From 6a85fce0694b1b63ab58997b6e40f95475c25b2c Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Sat, 7 Jan 2023 13:35:52 +1100 Subject: [PATCH 01/43] hardhat and forge working update goerli arb and mainnet --- contracts/ExternalBribe.sol | 269 +- contracts/Gauge.sol | 559 +- contracts/InternalBribe.sol | 488 +- contracts/Minter.sol | 73 +- contracts/Pair.sol | 615 +- contracts/RewardsDistributor.sol | 283 +- contracts/Router.sol | 541 +- contracts/WrappedExternalBribe.sol | 196 +- contracts/libraries/Math.sol | 36 +- gitsubmodules.sh | 11 + hardhat.config.ts | 90 +- lib/LayerZero | 1 + lib/ds-test | 1 + lib/forge-std | 1 + lib/openzeppelin-contracts | 1 + lib/solmate | 1 + scripts/k.js | 120 +- scripts/minterSolid.js | 46 +- scripts/minterVelo.js | 96 +- tasks/deploy/arb.ts | 214 + tasks/deploy/arbHardhat.ts | 212 + tasks/deploy/arbTest.ts | 207 + tasks/deploy/constants/arbConfig.ts | 91 + tasks/deploy/constants/arbHardhatConfig.ts | 91 + tasks/deploy/constants/arbTestnetConfig.ts | 91 + tasks/deploy/index.ts | 9 +- test/NFTVote.t.sol | 118 +- yarn.lock | 8520 ++++++++++++++++++++ 28 files changed, 11751 insertions(+), 1230 deletions(-) create mode 100644 gitsubmodules.sh create mode 160000 lib/LayerZero create mode 160000 lib/ds-test create mode 160000 lib/forge-std create mode 160000 lib/openzeppelin-contracts create mode 160000 lib/solmate create mode 100644 tasks/deploy/arb.ts create mode 100644 tasks/deploy/arbHardhat.ts create mode 100644 tasks/deploy/arbTest.ts create mode 100644 tasks/deploy/constants/arbConfig.ts create mode 100644 tasks/deploy/constants/arbHardhatConfig.ts create mode 100644 tasks/deploy/constants/arbTestnetConfig.ts create mode 100644 yarn.lock diff --git a/contracts/ExternalBribe.sol b/contracts/ExternalBribe.sol index e7bfe393..be4ef619 100644 --- a/contracts/ExternalBribe.sol +++ b/contracts/ExternalBribe.sol @@ -1,63 +1,72 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.13; -import 'contracts/libraries/Math.sol'; -import 'contracts/interfaces/IBribe.sol'; -import 'contracts/interfaces/IERC20.sol'; -import 'contracts/interfaces/IGauge.sol'; -import 'contracts/interfaces/IVoter.sol'; -import 'contracts/interfaces/IVotingEscrow.sol'; +import "contracts/libraries/Math.sol"; +import "contracts/interfaces/IBribe.sol"; +import "contracts/interfaces/IERC20.sol"; +import "contracts/interfaces/IGauge.sol"; +import "contracts/interfaces/IVoter.sol"; +import "contracts/interfaces/IVotingEscrow.sol"; // Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote()) contract ExternalBribe is IBribe { address public immutable voter; // only voter can modify balances (since it only happens on vote()) address public immutable _ve; // 天使のたまご - uint internal constant DURATION = 7 days; // rewards are released over the voting period - uint internal constant MAX_REWARD_TOKENS = 16; + uint256 internal constant DURATION = 7 days; // rewards are released over the voting period + uint256 internal constant MAX_REWARD_TOKENS = 16; - uint internal constant PRECISION = 10 ** 18; + uint256 internal constant PRECISION = 10**18; - uint public totalSupply; - mapping(uint => uint) public balanceOf; - mapping(address => mapping(uint => uint)) public tokenRewardsPerEpoch; - mapping(address => uint) public periodFinish; - mapping(address => mapping(uint => uint)) public lastEarn; + uint256 public totalSupply; + mapping(uint256 => uint256) public balanceOf; + mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch; + mapping(address => uint256) public periodFinish; + mapping(address => mapping(uint256 => uint256)) public lastEarn; address[] public rewards; mapping(address => bool) public isReward; /// @notice A checkpoint for marking balance struct Checkpoint { - uint timestamp; - uint balanceOf; + uint256 timestamp; + uint256 balanceOf; } /// @notice A checkpoint for marking supply struct SupplyCheckpoint { - uint timestamp; - uint supply; + uint256 timestamp; + uint256 supply; } /// @notice A record of balance checkpoints for each account, by index - mapping (uint => mapping (uint => Checkpoint)) public checkpoints; + mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints; /// @notice The number of checkpoints for each account - mapping (uint => uint) public numCheckpoints; + mapping(uint256 => uint256) public numCheckpoints; /// @notice A record of balance checkpoints for each token, by index - mapping (uint => SupplyCheckpoint) public supplyCheckpoints; + mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints; /// @notice The number of checkpoints - uint public supplyNumCheckpoints; - - event Deposit(address indexed from, uint tokenId, uint amount); - event Withdraw(address indexed from, uint tokenId, uint amount); - event NotifyReward(address indexed from, address indexed reward, uint epoch, uint amount); - event ClaimRewards(address indexed from, address indexed reward, uint amount); + uint256 public supplyNumCheckpoints; + + event Deposit(address indexed from, uint256 tokenId, uint256 amount); + event Withdraw(address indexed from, uint256 tokenId, uint256 amount); + event NotifyReward( + address indexed from, + address indexed reward, + uint256 epoch, + uint256 amount + ); + event ClaimRewards( + address indexed from, + address indexed reward, + uint256 amount + ); constructor(address _voter, address[] memory _allowedRewardTokens) { voter = _voter; _ve = IVoter(_voter)._ve(); - for (uint i; i < _allowedRewardTokens.length; i++) { + for (uint256 i; i < _allowedRewardTokens.length; i++) { if (_allowedRewardTokens[i] != address(0)) { isReward[_allowedRewardTokens[i]] = true; rewards.push(_allowedRewardTokens[i]); @@ -66,7 +75,7 @@ contract ExternalBribe is IBribe { } // simple re-entrancy check - uint internal _unlocked = 1; + uint256 internal _unlocked = 1; modifier lock() { require(_unlocked == 1); _unlocked = 2; @@ -74,25 +83,29 @@ contract ExternalBribe is IBribe { _unlocked = 1; } - function _bribeStart(uint timestamp) internal pure returns (uint) { + function _bribeStart(uint256 timestamp) internal pure returns (uint256) { return timestamp - (timestamp % (7 days)); } - function getEpochStart(uint timestamp) public pure returns (uint) { - uint bribeStart = _bribeStart(timestamp); - uint bribeEnd = bribeStart + DURATION; + function getEpochStart(uint256 timestamp) public pure returns (uint256) { + uint256 bribeStart = _bribeStart(timestamp); + uint256 bribeEnd = bribeStart + DURATION; return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days; } /** - * @notice Determine the prior balance for an account as of a block number - * @dev Block number must be a finalized block or else this function will revert to prevent misinformation. - * @param tokenId The token of the NFT to check - * @param timestamp The timestamp to get the balance at - * @return The balance the account had as of the given block - */ - function getPriorBalanceIndex(uint tokenId, uint timestamp) public view returns (uint) { - uint nCheckpoints = numCheckpoints[tokenId]; + * @notice Determine the prior balance for an account as of a block number + * @dev Block number must be a finalized block or else this function will revert to prevent misinformation. + * @param tokenId The token of the NFT to check + * @param timestamp The timestamp to get the balance at + * @return The balance the account had as of the given block + */ + function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp) + public + view + returns (uint256) + { + uint256 nCheckpoints = numCheckpoints[tokenId]; if (nCheckpoints == 0) { return 0; } @@ -105,10 +118,10 @@ contract ExternalBribe is IBribe { return 0; } - uint lower = 0; - uint upper = nCheckpoints - 1; + uint256 lower = 0; + uint256 upper = nCheckpoints - 1; while (upper > lower) { - uint center = upper - (upper - lower) / 2; // ceil, avoiding overflow + uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow Checkpoint memory cp = checkpoints[tokenId][center]; if (cp.timestamp == timestamp) { return center; @@ -121,8 +134,12 @@ contract ExternalBribe is IBribe { return lower; } - function getPriorSupplyIndex(uint timestamp) public view returns (uint) { - uint nCheckpoints = supplyNumCheckpoints; + function getPriorSupplyIndex(uint256 timestamp) + public + view + returns (uint256) + { + uint256 nCheckpoints = supplyNumCheckpoints; if (nCheckpoints == 0) { return 0; } @@ -137,10 +154,10 @@ contract ExternalBribe is IBribe { return 0; } - uint lower = 0; - uint upper = nCheckpoints - 1; + uint256 lower = 0; + uint256 upper = nCheckpoints - 1; while (upper > lower) { - uint center = upper - (upper - lower) / 2; // ceil, avoiding overflow + uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow SupplyCheckpoint memory cp = supplyCheckpoints[center]; if (cp.timestamp == timestamp) { return center; @@ -153,43 +170,59 @@ contract ExternalBribe is IBribe { return lower; } - function _writeCheckpoint(uint tokenId, uint balance) internal { - uint _timestamp = block.timestamp; - uint _nCheckPoints = numCheckpoints[tokenId]; - if (_nCheckPoints > 0 && checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp) { + function _writeCheckpoint(uint256 tokenId, uint256 balance) internal { + uint256 _timestamp = block.timestamp; + uint256 _nCheckPoints = numCheckpoints[tokenId]; + if ( + _nCheckPoints > 0 && + checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp + ) { checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance; } else { - checkpoints[tokenId][_nCheckPoints] = Checkpoint(_timestamp, balance); + checkpoints[tokenId][_nCheckPoints] = Checkpoint( + _timestamp, + balance + ); numCheckpoints[tokenId] = _nCheckPoints + 1; } } function _writeSupplyCheckpoint() internal { - uint _nCheckPoints = supplyNumCheckpoints; - uint _timestamp = block.timestamp; + uint256 _nCheckPoints = supplyNumCheckpoints; + uint256 _timestamp = block.timestamp; - if (_nCheckPoints > 0 && supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp) { + if ( + _nCheckPoints > 0 && + supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp + ) { supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply; } else { - supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(_timestamp, totalSupply); + supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint( + _timestamp, + totalSupply + ); supplyNumCheckpoints = _nCheckPoints + 1; } } - function rewardsListLength() external view returns (uint) { + function rewardsListLength() external view returns (uint256) { return rewards.length; } // returns the last time the reward was modified or periodFinish if the reward has ended - function lastTimeRewardApplicable(address token) public view returns (uint) { - return Math.min(block.timestamp, periodFinish[token]); + function lastTimeRewardApplicable(address token) + public + view + returns (uint256) + { + return MathDunks.min(block.timestamp, periodFinish[token]); } // allows a user to claim rewards for a given token - function getReward(uint tokenId, address[] memory tokens) external lock { + function getReward(uint256 tokenId, address[] memory tokens) external lock { require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId)); - for (uint i = 0; i < tokens.length; i++) { - uint _reward = earned(tokens[i], tokenId); + for (uint256 i = 0; i < tokens.length; i++) { + uint256 _reward = earned(tokens[i], tokenId); lastEarn[tokens[i]][tokenId] = block.timestamp; if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward); @@ -198,11 +231,14 @@ contract ExternalBribe is IBribe { } // used by Voter to allow batched reward claims - function getRewardForOwner(uint tokenId, address[] memory tokens) external lock { + function getRewardForOwner(uint256 tokenId, address[] memory tokens) + external + lock + { require(msg.sender == voter); address _owner = IVotingEscrow(_ve).ownerOf(tokenId); - for (uint i = 0; i < tokens.length; i++) { - uint _reward = earned(tokens[i], tokenId); + for (uint256 i = 0; i < tokens.length; i++) { + uint256 _reward = earned(tokens[i], tokenId); lastEarn[tokens[i]][tokenId] = block.timestamp; if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward); @@ -210,50 +246,61 @@ contract ExternalBribe is IBribe { } } - function earned(address token, uint tokenId) public view returns (uint) { - uint _startTimestamp = lastEarn[token][tokenId]; + function earned(address token, uint256 tokenId) + public + view + returns (uint256) + { + uint256 _startTimestamp = lastEarn[token][tokenId]; if (numCheckpoints[tokenId] == 0) { return 0; } - uint _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp); - uint _endIndex = numCheckpoints[tokenId]-1; + uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp); + uint256 _endIndex = numCheckpoints[tokenId] - 1; - uint reward = 0; + uint256 reward = 0; // you only earn once per epoch (after it's over) Checkpoint memory prevRewards; // reuse struct to avoid stack too deep prevRewards.timestamp = _bribeStart(_startTimestamp); - uint _prevSupply = 1; + uint256 _prevSupply = 1; if (_endIndex > 0) { - for (uint i = _startIndex; i <= _endIndex - 1; i++) { + for (uint256 i = _startIndex; i <= _endIndex - 1; i++) { Checkpoint memory cp0 = checkpoints[tokenId][i]; - uint _nextEpochStart = _bribeStart(cp0.timestamp); + uint256 _nextEpochStart = _bribeStart(cp0.timestamp); // check that you've earned it // this won't happen until a week has passed if (_nextEpochStart > prevRewards.timestamp) { - reward += prevRewards.balanceOf; + reward += prevRewards.balanceOf; } prevRewards.timestamp = _nextEpochStart; - _prevSupply = supplyCheckpoints[getPriorSupplyIndex(_nextEpochStart + DURATION)].supply; - prevRewards.balanceOf = cp0.balanceOf * tokenRewardsPerEpoch[token][_nextEpochStart] / _prevSupply; + _prevSupply = supplyCheckpoints[ + getPriorSupplyIndex(_nextEpochStart + DURATION) + ].supply; + prevRewards.balanceOf = + (cp0.balanceOf * + tokenRewardsPerEpoch[token][_nextEpochStart]) / + _prevSupply; } } Checkpoint memory cp = checkpoints[tokenId][_endIndex]; - uint _lastEpochStart = _bribeStart(cp.timestamp); - uint _lastEpochEnd = _lastEpochStart + DURATION; + uint256 _lastEpochStart = _bribeStart(cp.timestamp); + uint256 _lastEpochEnd = _lastEpochStart + DURATION; if (block.timestamp > _lastEpochEnd) { - reward += cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart] / supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply; + reward += + (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) / + supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply; } return reward; } // This is an external function, but internal notation is used since it can only be called "internally" from Gauges - function _deposit(uint amount, uint tokenId) external { + function _deposit(uint256 amount, uint256 tokenId) external { require(msg.sender == voter); totalSupply += amount; @@ -265,7 +312,7 @@ contract ExternalBribe is IBribe { emit Deposit(msg.sender, tokenId, amount); } - function _withdraw(uint amount, uint tokenId) external { + function _withdraw(uint256 amount, uint256 tokenId) external { require(msg.sender == voter); totalSupply -= amount; @@ -277,20 +324,26 @@ contract ExternalBribe is IBribe { emit Withdraw(msg.sender, tokenId, amount); } - function left(address token) external view returns (uint) { - uint adjustedTstamp = getEpochStart(block.timestamp); + function left(address token) external view returns (uint256) { + uint256 adjustedTstamp = getEpochStart(block.timestamp); return tokenRewardsPerEpoch[token][adjustedTstamp]; } - function notifyRewardAmount(address token, uint amount) external lock { + function notifyRewardAmount(address token, uint256 amount) external lock { require(amount > 0); if (!isReward[token]) { - require(IVoter(voter).isWhitelisted(token), "bribe tokens must be whitelisted"); - require(rewards.length < MAX_REWARD_TOKENS, "too many rewards tokens"); + require( + IVoter(voter).isWhitelisted(token), + "bribe tokens must be whitelisted" + ); + require( + rewards.length < MAX_REWARD_TOKENS, + "too many rewards tokens" + ); } // bribes kick in at the start of next bribe period - uint adjustedTstamp = getEpochStart(block.timestamp); - uint epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp]; + uint256 adjustedTstamp = getEpochStart(block.timestamp); + uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp]; _safeTransferFrom(token, msg.sender, address(this), amount); tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount; @@ -305,25 +358,45 @@ contract ExternalBribe is IBribe { emit NotifyReward(msg.sender, token, adjustedTstamp, amount); } - function swapOutRewardToken(uint i, address oldToken, address newToken) external { - require(msg.sender == IVotingEscrow(_ve).team(), 'only team'); + function swapOutRewardToken( + uint256 i, + address oldToken, + address newToken + ) external { + require(msg.sender == IVotingEscrow(_ve).team(), "only team"); require(rewards[i] == oldToken); isReward[oldToken] = false; isReward[newToken] = true; rewards[i] = newToken; } - function _safeTransfer(address token, address to, uint256 value) internal { + function _safeTransfer( + address token, + address to, + uint256 value + ) internal { require(token.code.length > 0); - (bool success, bytes memory data) = - token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value)); + (bool success, bytes memory data) = token.call( + abi.encodeWithSelector(IERC20.transfer.selector, to, value) + ); require(success && (data.length == 0 || abi.decode(data, (bool)))); } - function _safeTransferFrom(address token, address from, address to, uint256 value) internal { + function _safeTransferFrom( + address token, + address from, + address to, + uint256 value + ) internal { require(token.code.length > 0); - (bool success, bytes memory data) = - token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value)); + (bool success, bytes memory data) = token.call( + abi.encodeWithSelector( + IERC20.transferFrom.selector, + from, + to, + value + ) + ); require(success && (data.length == 0 || abi.decode(data, (bool)))); } } diff --git a/contracts/Gauge.sol b/contracts/Gauge.sol index 611e35df..c7bbfdb5 100644 --- a/contracts/Gauge.sol +++ b/contracts/Gauge.sol @@ -1,90 +1,107 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.13; -import 'contracts/libraries/Math.sol'; -import 'contracts/interfaces/IBribe.sol'; -import 'contracts/interfaces/IERC20.sol'; -import 'contracts/interfaces/IGauge.sol'; -import 'contracts/interfaces/IPair.sol'; -import 'contracts/interfaces/IVoter.sol'; -import 'contracts/interfaces/IVotingEscrow.sol'; +import "contracts/libraries/Math.sol"; +import "contracts/interfaces/IBribe.sol"; +import "contracts/interfaces/IERC20.sol"; +import "contracts/interfaces/IGauge.sol"; +import "contracts/interfaces/IPair.sol"; +import "contracts/interfaces/IVoter.sol"; +import "contracts/interfaces/IVotingEscrow.sol"; // Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens contract Gauge is IGauge { - address public immutable stake; // the LP token that needs to be staked for rewards address public immutable _ve; // the ve token used for gauges address public immutable internal_bribe; address public immutable external_bribe; address public immutable voter; - uint public derivedSupply; - mapping(address => uint) public derivedBalances; + uint256 public derivedSupply; + mapping(address => uint256) public derivedBalances; bool public isForPair; - uint internal constant DURATION = 7 days; // rewards are released over 7 days - uint internal constant PRECISION = 10 ** 18; - uint internal constant MAX_REWARD_TOKENS = 16; + uint256 internal constant DURATION = 7 days; // rewards are released over 7 days + uint256 internal constant PRECISION = 10**18; + uint256 internal constant MAX_REWARD_TOKENS = 16; // default snx staking contract implementation - mapping(address => uint) public rewardRate; - mapping(address => uint) public periodFinish; - mapping(address => uint) public lastUpdateTime; - mapping(address => uint) public rewardPerTokenStored; + mapping(address => uint256) public rewardRate; + mapping(address => uint256) public periodFinish; + mapping(address => uint256) public lastUpdateTime; + mapping(address => uint256) public rewardPerTokenStored; - mapping(address => mapping(address => uint)) public lastEarn; - mapping(address => mapping(address => uint)) public userRewardPerTokenStored; + mapping(address => mapping(address => uint256)) public lastEarn; + mapping(address => mapping(address => uint256)) + public userRewardPerTokenStored; - mapping(address => uint) public tokenIds; + mapping(address => uint256) public tokenIds; - uint public totalSupply; - mapping(address => uint) public balanceOf; + uint256 public totalSupply; + mapping(address => uint256) public balanceOf; address[] public rewards; mapping(address => bool) public isReward; /// @notice A checkpoint for marking balance struct Checkpoint { - uint timestamp; - uint balanceOf; + uint256 timestamp; + uint256 balanceOf; } /// @notice A checkpoint for marking reward rate struct RewardPerTokenCheckpoint { - uint timestamp; - uint rewardPerToken; + uint256 timestamp; + uint256 rewardPerToken; } /// @notice A checkpoint for marking supply struct SupplyCheckpoint { - uint timestamp; - uint supply; + uint256 timestamp; + uint256 supply; } /// @notice A record of balance checkpoints for each account, by index - mapping (address => mapping (uint => Checkpoint)) public checkpoints; + mapping(address => mapping(uint256 => Checkpoint)) public checkpoints; /// @notice The number of checkpoints for each account - mapping (address => uint) public numCheckpoints; + mapping(address => uint256) public numCheckpoints; /// @notice A record of balance checkpoints for each token, by index - mapping (uint => SupplyCheckpoint) public supplyCheckpoints; + mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints; /// @notice The number of checkpoints - uint public supplyNumCheckpoints; + uint256 public supplyNumCheckpoints; /// @notice A record of balance checkpoints for each token, by index - mapping (address => mapping (uint => RewardPerTokenCheckpoint)) public rewardPerTokenCheckpoints; + mapping(address => mapping(uint256 => RewardPerTokenCheckpoint)) + public rewardPerTokenCheckpoints; /// @notice The number of checkpoints for each token - mapping (address => uint) public rewardPerTokenNumCheckpoints; - - uint public fees0; - uint public fees1; - - event Deposit(address indexed from, uint tokenId, uint amount); - event Withdraw(address indexed from, uint tokenId, uint amount); - event NotifyReward(address indexed from, address indexed reward, uint amount); - event ClaimFees(address indexed from, uint claimed0, uint claimed1); - event ClaimRewards(address indexed from, address indexed reward, uint amount); - - constructor(address _stake, address _internal_bribe, address _external_bribe, address __ve, address _voter, bool _forPair, address[] memory _allowedRewardTokens) { + mapping(address => uint256) public rewardPerTokenNumCheckpoints; + + uint256 public fees0; + uint256 public fees1; + + event Deposit(address indexed from, uint256 tokenId, uint256 amount); + event Withdraw(address indexed from, uint256 tokenId, uint256 amount); + event NotifyReward( + address indexed from, + address indexed reward, + uint256 amount + ); + event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1); + event ClaimRewards( + address indexed from, + address indexed reward, + uint256 amount + ); + + constructor( + address _stake, + address _internal_bribe, + address _external_bribe, + address __ve, + address _voter, + bool _forPair, + address[] memory _allowedRewardTokens + ) { stake = _stake; internal_bribe = _internal_bribe; external_bribe = _external_bribe; @@ -92,7 +109,7 @@ contract Gauge is IGauge { voter = _voter; isForPair = _forPair; - for (uint i; i < _allowedRewardTokens.length; i++) { + for (uint256 i; i < _allowedRewardTokens.length; i++) { if (_allowedRewardTokens[i] != address(0)) { isReward[_allowedRewardTokens[i]] = true; rewards.push(_allowedRewardTokens[i]); @@ -101,7 +118,7 @@ contract Gauge is IGauge { } // simple re-entrancy check - uint internal _unlocked = 1; + uint256 internal _unlocked = 1; modifier lock() { require(_unlocked == 1); _unlocked = 2; @@ -109,27 +126,40 @@ contract Gauge is IGauge { _unlocked = 1; } - function claimFees() external lock returns (uint claimed0, uint claimed1) { + function claimFees() + external + lock + returns (uint256 claimed0, uint256 claimed1) + { return _claimFees(); } - function _claimFees() internal returns (uint claimed0, uint claimed1) { + function _claimFees() + internal + returns (uint256 claimed0, uint256 claimed1) + { if (!isForPair) { return (0, 0); } (claimed0, claimed1) = IPair(stake).claimFees(); if (claimed0 > 0 || claimed1 > 0) { - uint _fees0 = fees0 + claimed0; - uint _fees1 = fees1 + claimed1; + uint256 _fees0 = fees0 + claimed0; + uint256 _fees1 = fees1 + claimed1; (address _token0, address _token1) = IPair(stake).tokens(); - if (_fees0 > IBribe(internal_bribe).left(_token0) && _fees0 / DURATION > 0) { + if ( + _fees0 > IBribe(internal_bribe).left(_token0) && + _fees0 / DURATION > 0 + ) { fees0 = 0; _safeApprove(_token0, internal_bribe, _fees0); IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0); } else { fees0 = _fees0; } - if (_fees1 > IBribe(internal_bribe).left(_token1) && _fees1 / DURATION > 0) { + if ( + _fees1 > IBribe(internal_bribe).left(_token1) && + _fees1 / DURATION > 0 + ) { fees1 = 0; _safeApprove(_token1, internal_bribe, _fees1); IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1); @@ -142,14 +172,18 @@ contract Gauge is IGauge { } /** - * @notice Determine the prior balance for an account as of a block number - * @dev Block number must be a finalized block or else this function will revert to prevent misinformation. - * @param account The address of the account to check - * @param timestamp The timestamp to get the balance at - * @return The balance the account had as of the given block - */ - function getPriorBalanceIndex(address account, uint timestamp) public view returns (uint) { - uint nCheckpoints = numCheckpoints[account]; + * @notice Determine the prior balance for an account as of a block number + * @dev Block number must be a finalized block or else this function will revert to prevent misinformation. + * @param account The address of the account to check + * @param timestamp The timestamp to get the balance at + * @return The balance the account had as of the given block + */ + function getPriorBalanceIndex(address account, uint256 timestamp) + public + view + returns (uint256) + { + uint256 nCheckpoints = numCheckpoints[account]; if (nCheckpoints == 0) { return 0; } @@ -164,10 +198,10 @@ contract Gauge is IGauge { return 0; } - uint lower = 0; - uint upper = nCheckpoints - 1; + uint256 lower = 0; + uint256 upper = nCheckpoints - 1; while (upper > lower) { - uint center = upper - (upper - lower) / 2; // ceil, avoiding overflow + uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow Checkpoint memory cp = checkpoints[account][center]; if (cp.timestamp == timestamp) { return center; @@ -180,8 +214,12 @@ contract Gauge is IGauge { return lower; } - function getPriorSupplyIndex(uint timestamp) public view returns (uint) { - uint nCheckpoints = supplyNumCheckpoints; + function getPriorSupplyIndex(uint256 timestamp) + public + view + returns (uint256) + { + uint256 nCheckpoints = supplyNumCheckpoints; if (nCheckpoints == 0) { return 0; } @@ -196,10 +234,10 @@ contract Gauge is IGauge { return 0; } - uint lower = 0; - uint upper = nCheckpoints - 1; + uint256 lower = 0; + uint256 upper = nCheckpoints - 1; while (upper > lower) { - uint center = upper - (upper - lower) / 2; // ceil, avoiding overflow + uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow SupplyCheckpoint memory cp = supplyCheckpoints[center]; if (cp.timestamp == timestamp) { return center; @@ -212,27 +250,40 @@ contract Gauge is IGauge { return lower; } - function getPriorRewardPerToken(address token, uint timestamp) public view returns (uint, uint) { - uint nCheckpoints = rewardPerTokenNumCheckpoints[token]; + function getPriorRewardPerToken(address token, uint256 timestamp) + public + view + returns (uint256, uint256) + { + uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token]; if (nCheckpoints == 0) { - return (0,0); + return (0, 0); } // First check most recent balance - if (rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <= timestamp) { - return (rewardPerTokenCheckpoints[token][nCheckpoints - 1].rewardPerToken, rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp); + if ( + rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <= + timestamp + ) { + return ( + rewardPerTokenCheckpoints[token][nCheckpoints - 1] + .rewardPerToken, + rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp + ); } // Next check implicit zero balance if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) { - return (0,0); + return (0, 0); } - uint lower = 0; - uint upper = nCheckpoints - 1; + uint256 lower = 0; + uint256 upper = nCheckpoints - 1; while (upper > lower) { - uint center = upper - (upper - lower) / 2; // ceil, avoiding overflow - RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[token][center]; + uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow + RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[ + token + ][center]; if (cp.timestamp == timestamp) { return (cp.rewardPerToken, cp.timestamp); } else if (cp.timestamp < timestamp) { @@ -241,51 +292,81 @@ contract Gauge is IGauge { upper = center - 1; } } - return (rewardPerTokenCheckpoints[token][lower].rewardPerToken, rewardPerTokenCheckpoints[token][lower].timestamp); + return ( + rewardPerTokenCheckpoints[token][lower].rewardPerToken, + rewardPerTokenCheckpoints[token][lower].timestamp + ); } - function _writeCheckpoint(address account, uint balance) internal { - uint _timestamp = block.timestamp; - uint _nCheckPoints = numCheckpoints[account]; + function _writeCheckpoint(address account, uint256 balance) internal { + uint256 _timestamp = block.timestamp; + uint256 _nCheckPoints = numCheckpoints[account]; - if (_nCheckPoints > 0 && checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp) { + if ( + _nCheckPoints > 0 && + checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp + ) { checkpoints[account][_nCheckPoints - 1].balanceOf = balance; } else { - checkpoints[account][_nCheckPoints] = Checkpoint(_timestamp, balance); + checkpoints[account][_nCheckPoints] = Checkpoint( + _timestamp, + balance + ); numCheckpoints[account] = _nCheckPoints + 1; } } - function _writeRewardPerTokenCheckpoint(address token, uint reward, uint timestamp) internal { - uint _nCheckPoints = rewardPerTokenNumCheckpoints[token]; + function _writeRewardPerTokenCheckpoint( + address token, + uint256 reward, + uint256 timestamp + ) internal { + uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token]; - if (_nCheckPoints > 0 && rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp == timestamp) { - rewardPerTokenCheckpoints[token][_nCheckPoints - 1].rewardPerToken = reward; + if ( + _nCheckPoints > 0 && + rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp == + timestamp + ) { + rewardPerTokenCheckpoints[token][_nCheckPoints - 1] + .rewardPerToken = reward; } else { - rewardPerTokenCheckpoints[token][_nCheckPoints] = RewardPerTokenCheckpoint(timestamp, reward); + rewardPerTokenCheckpoints[token][ + _nCheckPoints + ] = RewardPerTokenCheckpoint(timestamp, reward); rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1; } } function _writeSupplyCheckpoint() internal { - uint _nCheckPoints = supplyNumCheckpoints; - uint _timestamp = block.timestamp; + uint256 _nCheckPoints = supplyNumCheckpoints; + uint256 _timestamp = block.timestamp; - if (_nCheckPoints > 0 && supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp) { + if ( + _nCheckPoints > 0 && + supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp + ) { supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply; } else { - supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(_timestamp, derivedSupply); + supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint( + _timestamp, + derivedSupply + ); supplyNumCheckpoints = _nCheckPoints + 1; } } - function rewardsListLength() external view returns (uint) { + function rewardsListLength() external view returns (uint256) { return rewards.length; } // returns the last time the reward was modified or periodFinish if the reward has ended - function lastTimeRewardApplicable(address token) public view returns (uint) { - return Math.min(block.timestamp, periodFinish[token]); + function lastTimeRewardApplicable(address token) + public + view + returns (uint256) + { + return MathDunks.min(block.timestamp, periodFinish[token]); } function getReward(address account, address[] memory tokens) external lock { @@ -294,18 +375,23 @@ contract Gauge is IGauge { IVoter(voter).distribute(address(this)); _unlocked = 2; - for (uint i = 0; i < tokens.length; i++) { - (rewardPerTokenStored[tokens[i]], lastUpdateTime[tokens[i]]) = _updateRewardPerToken(tokens[i], type(uint).max, true); + for (uint256 i = 0; i < tokens.length; i++) { + ( + rewardPerTokenStored[tokens[i]], + lastUpdateTime[tokens[i]] + ) = _updateRewardPerToken(tokens[i], type(uint256).max, true); - uint _reward = earned(tokens[i], account); + uint256 _reward = earned(tokens[i], account); lastEarn[tokens[i]][account] = block.timestamp; - userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[tokens[i]]; + userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[ + tokens[i] + ]; if (_reward > 0) _safeTransfer(tokens[i], account, _reward); emit ClaimRewards(msg.sender, tokens[i], _reward); } - uint _derivedBalance = derivedBalances[account]; + uint256 _derivedBalance = derivedBalances[account]; derivedSupply -= _derivedBalance; _derivedBalance = derivedBalance(account); derivedBalances[account] = _derivedBalance; @@ -315,25 +401,35 @@ contract Gauge is IGauge { _writeSupplyCheckpoint(); } - - function rewardPerToken(address token) public view returns (uint) { + function rewardPerToken(address token) public view returns (uint256) { if (derivedSupply == 0) { return rewardPerTokenStored[token]; } - return rewardPerTokenStored[token] + ((lastTimeRewardApplicable(token) - Math.min(lastUpdateTime[token], periodFinish[token])) * rewardRate[token] * PRECISION / derivedSupply); + return + rewardPerTokenStored[token] + + (((lastTimeRewardApplicable(token) - + MathDunks.min(lastUpdateTime[token], periodFinish[token])) * + rewardRate[token] * + PRECISION) / derivedSupply); } - function derivedBalance(address account) public view returns (uint) { + function derivedBalance(address account) public view returns (uint256) { return balanceOf[account]; } - function batchRewardPerToken(address token, uint maxRuns) external { - (rewardPerTokenStored[token], lastUpdateTime[token]) = _batchRewardPerToken(token, maxRuns); + function batchRewardPerToken(address token, uint256 maxRuns) external { + ( + rewardPerTokenStored[token], + lastUpdateTime[token] + ) = _batchRewardPerToken(token, maxRuns); } - function _batchRewardPerToken(address token, uint maxRuns) internal returns (uint, uint) { - uint _startTimestamp = lastUpdateTime[token]; - uint reward = rewardPerTokenStored[token]; + function _batchRewardPerToken(address token, uint256 maxRuns) + internal + returns (uint256, uint256) + { + uint256 _startTimestamp = lastUpdateTime[token]; + uint256 reward = rewardPerTokenStored[token]; if (supplyNumCheckpoints == 0) { return (reward, _startTimestamp); @@ -343,14 +439,20 @@ contract Gauge is IGauge { return (reward, block.timestamp); } - uint _startIndex = getPriorSupplyIndex(_startTimestamp); - uint _endIndex = Math.min(supplyNumCheckpoints-1, maxRuns); + uint256 _startIndex = getPriorSupplyIndex(_startTimestamp); + uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns); - for (uint i = _startIndex; i < _endIndex; i++) { + for (uint256 i = _startIndex; i < _endIndex; i++) { SupplyCheckpoint memory sp0 = supplyCheckpoints[i]; if (sp0.supply > 0) { - SupplyCheckpoint memory sp1 = supplyCheckpoints[i+1]; - (uint _reward, uint _endTime) = _calcRewardPerToken(token, sp1.timestamp, sp0.timestamp, sp0.supply, _startTimestamp); + SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1]; + (uint256 _reward, uint256 _endTime) = _calcRewardPerToken( + token, + sp1.timestamp, + sp0.timestamp, + sp0.supply, + _startTimestamp + ); reward += _reward; _writeRewardPerTokenCheckpoint(token, reward, _endTime); _startTimestamp = _endTime; @@ -360,28 +462,55 @@ contract Gauge is IGauge { return (reward, _startTimestamp); } - function _calcRewardPerToken(address token, uint timestamp1, uint timestamp0, uint supply, uint startTimestamp) internal view returns (uint, uint) { - uint endTime = Math.max(timestamp1, startTimestamp); - return (((Math.min(endTime, periodFinish[token]) - Math.min(Math.max(timestamp0, startTimestamp), periodFinish[token])) * rewardRate[token] * PRECISION / supply), endTime); + function _calcRewardPerToken( + address token, + uint256 timestamp1, + uint256 timestamp0, + uint256 supply, + uint256 startTimestamp + ) internal view returns (uint256, uint256) { + uint256 endTime = MathDunks.max(timestamp1, startTimestamp); + return ( + (((MathDunks.min(endTime, periodFinish[token]) - + MathDunks.min( + MathDunks.max(timestamp0, startTimestamp), + periodFinish[token] + )) * + rewardRate[token] * + PRECISION) / supply), + endTime + ); } /// @dev Update stored rewardPerToken values without the last one snapshot /// If the contract will get "out of gas" error on users actions this will be helpful - function batchUpdateRewardPerToken(address token, uint maxRuns) external { - (rewardPerTokenStored[token], lastUpdateTime[token]) = _updateRewardPerToken(token, maxRuns, false); + function batchUpdateRewardPerToken(address token, uint256 maxRuns) + external + { + ( + rewardPerTokenStored[token], + lastUpdateTime[token] + ) = _updateRewardPerToken(token, maxRuns, false); } function _updateRewardForAllTokens() internal { - uint length = rewards.length; - for (uint i; i < length; i++) { - address token = rewards[i]; - (rewardPerTokenStored[token], lastUpdateTime[token]) = _updateRewardPerToken(token, type(uint).max, true); - } + uint256 length = rewards.length; + for (uint256 i; i < length; i++) { + address token = rewards[i]; + ( + rewardPerTokenStored[token], + lastUpdateTime[token] + ) = _updateRewardPerToken(token, type(uint256).max, true); + } } - function _updateRewardPerToken(address token, uint maxRuns, bool actualLast) internal returns (uint, uint) { - uint _startTimestamp = lastUpdateTime[token]; - uint reward = rewardPerTokenStored[token]; + function _updateRewardPerToken( + address token, + uint256 maxRuns, + bool actualLast + ) internal returns (uint256, uint256) { + uint256 _startTimestamp = lastUpdateTime[token]; + uint256 reward = rewardPerTokenStored[token]; if (supplyNumCheckpoints == 0) { return (reward, _startTimestamp); @@ -391,15 +520,21 @@ contract Gauge is IGauge { return (reward, block.timestamp); } - uint _startIndex = getPriorSupplyIndex(_startTimestamp); - uint _endIndex = Math.min(supplyNumCheckpoints - 1, maxRuns); + uint256 _startIndex = getPriorSupplyIndex(_startTimestamp); + uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns); if (_endIndex > 0) { - for (uint i = _startIndex; i <= _endIndex - 1; i++) { + for (uint256 i = _startIndex; i <= _endIndex - 1; i++) { SupplyCheckpoint memory sp0 = supplyCheckpoints[i]; if (sp0.supply > 0) { - SupplyCheckpoint memory sp1 = supplyCheckpoints[i+1]; - (uint _reward, uint _endTime) = _calcRewardPerToken(token, sp1.timestamp, sp0.timestamp, sp0.supply, _startTimestamp); + SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1]; + (uint256 _reward, uint256 _endTime) = _calcRewardPerToken( + token, + sp1.timestamp, + sp0.timestamp, + sp0.supply, + _startTimestamp + ); reward += _reward; _writeRewardPerTokenCheckpoint(token, reward, _endTime); _startTimestamp = _endTime; @@ -411,7 +546,13 @@ contract Gauge is IGauge { if (actualLast) { SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex]; if (sp.supply > 0) { - (uint _reward,) = _calcRewardPerToken(token, lastTimeRewardApplicable(token), Math.max(sp.timestamp, _startTimestamp), sp.supply, _startTimestamp); + (uint256 _reward, ) = _calcRewardPerToken( + token, + lastTimeRewardApplicable(token), + MathDunks.max(sp.timestamp, _startTimestamp), + sp.supply, + _startTimestamp + ); reward += _reward; _writeRewardPerTokenCheckpoint(token, reward, block.timestamp); _startTimestamp = block.timestamp; @@ -422,39 +563,65 @@ contract Gauge is IGauge { } // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run - function earned(address token, address account) public view returns (uint) { - uint _startTimestamp = Math.max(lastEarn[token][account], rewardPerTokenCheckpoints[token][0].timestamp); + function earned(address token, address account) + public + view + returns (uint256) + { + uint256 _startTimestamp = MathDunks.max( + lastEarn[token][account], + rewardPerTokenCheckpoints[token][0].timestamp + ); if (numCheckpoints[account] == 0) { return 0; } - uint _startIndex = getPriorBalanceIndex(account, _startTimestamp); - uint _endIndex = numCheckpoints[account]-1; + uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp); + uint256 _endIndex = numCheckpoints[account] - 1; - uint reward = 0; + uint256 reward = 0; if (_endIndex > 0) { - for (uint i = _startIndex; i <= _endIndex-1; i++) { + for (uint256 i = _startIndex; i <= _endIndex - 1; i++) { Checkpoint memory cp0 = checkpoints[account][i]; - Checkpoint memory cp1 = checkpoints[account][i+1]; - (uint _rewardPerTokenStored0,) = getPriorRewardPerToken(token, cp0.timestamp); - (uint _rewardPerTokenStored1,) = getPriorRewardPerToken(token, cp1.timestamp); - reward += cp0.balanceOf * (_rewardPerTokenStored1 - _rewardPerTokenStored0) / PRECISION; + Checkpoint memory cp1 = checkpoints[account][i + 1]; + (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken( + token, + cp0.timestamp + ); + (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken( + token, + cp1.timestamp + ); + reward += + (cp0.balanceOf * + (_rewardPerTokenStored1 - _rewardPerTokenStored0)) / + PRECISION; } } Checkpoint memory cp = checkpoints[account][_endIndex]; - (uint _rewardPerTokenStored,) = getPriorRewardPerToken(token, cp.timestamp); - reward += cp.balanceOf * (rewardPerToken(token) - Math.max(_rewardPerTokenStored, userRewardPerTokenStored[token][account])) / PRECISION; + (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken( + token, + cp.timestamp + ); + reward += + (cp.balanceOf * + (rewardPerToken(token) - + MathDunks.max( + _rewardPerTokenStored, + userRewardPerTokenStored[token][account] + ))) / + PRECISION; return reward; } - function depositAll(uint tokenId) external { + function depositAll(uint256 tokenId) external { deposit(IERC20(stake).balanceOf(msg.sender), tokenId); } - function deposit(uint amount, uint tokenId) public lock { + function deposit(uint256 amount, uint256 tokenId) public lock { require(amount > 0); _updateRewardForAllTokens(); @@ -473,7 +640,7 @@ contract Gauge is IGauge { tokenId = tokenIds[msg.sender]; } - uint _derivedBalance = derivedBalances[msg.sender]; + uint256 _derivedBalance = derivedBalances[msg.sender]; derivedSupply -= _derivedBalance; _derivedBalance = derivedBalance(msg.sender); derivedBalances[msg.sender] = _derivedBalance; @@ -490,15 +657,15 @@ contract Gauge is IGauge { withdraw(balanceOf[msg.sender]); } - function withdraw(uint amount) public { - uint tokenId = 0; + function withdraw(uint256 amount) public { + uint256 tokenId = 0; if (amount == balanceOf[msg.sender]) { tokenId = tokenIds[msg.sender]; } withdrawToken(amount, tokenId); } - function withdrawToken(uint amount, uint tokenId) public lock { + function withdrawToken(uint256 amount, uint256 tokenId) public lock { _updateRewardForAllTokens(); totalSupply -= amount; @@ -513,7 +680,7 @@ contract Gauge is IGauge { tokenId = tokenIds[msg.sender]; } - uint _derivedBalance = derivedBalances[msg.sender]; + uint256 _derivedBalance = derivedBalances[msg.sender]; derivedSupply -= _derivedBalance; _derivedBalance = derivedBalance(msg.sender); derivedBalances[msg.sender] = _derivedBalance; @@ -526,36 +693,49 @@ contract Gauge is IGauge { emit Withdraw(msg.sender, tokenId, amount); } - function left(address token) external view returns (uint) { + function left(address token) external view returns (uint256) { if (block.timestamp >= periodFinish[token]) return 0; - uint _remaining = periodFinish[token] - block.timestamp; + uint256 _remaining = periodFinish[token] - block.timestamp; return _remaining * rewardRate[token]; } - function notifyRewardAmount(address token, uint amount) external lock { + function notifyRewardAmount(address token, uint256 amount) external lock { require(token != stake); require(amount > 0); if (!isReward[token]) { - require(IVoter(voter).isWhitelisted(token), "rewards tokens must be whitelisted"); - require(rewards.length < MAX_REWARD_TOKENS, "too many rewards tokens"); - } - if (rewardRate[token] == 0) _writeRewardPerTokenCheckpoint(token, 0, block.timestamp); - (rewardPerTokenStored[token], lastUpdateTime[token]) = _updateRewardPerToken(token, type(uint).max, true); + require( + IVoter(voter).isWhitelisted(token), + "rewards tokens must be whitelisted" + ); + require( + rewards.length < MAX_REWARD_TOKENS, + "too many rewards tokens" + ); + } + if (rewardRate[token] == 0) + _writeRewardPerTokenCheckpoint(token, 0, block.timestamp); + ( + rewardPerTokenStored[token], + lastUpdateTime[token] + ) = _updateRewardPerToken(token, type(uint256).max, true); _claimFees(); if (block.timestamp >= periodFinish[token]) { _safeTransferFrom(token, msg.sender, address(this), amount); rewardRate[token] = amount / DURATION; } else { - uint _remaining = periodFinish[token] - block.timestamp; - uint _left = _remaining * rewardRate[token]; + uint256 _remaining = periodFinish[token] - block.timestamp; + uint256 _left = _remaining * rewardRate[token]; require(amount > _left); _safeTransferFrom(token, msg.sender, address(this), amount); rewardRate[token] = (amount + _left) / DURATION; } require(rewardRate[token] > 0); - uint balance = IERC20(token).balanceOf(address(this)); - require(rewardRate[token] <= balance / DURATION, "Provided reward too high"); + uint256 balance = IERC20(token).balanceOf(address(this)); + require( + rewardRate[token] <= balance / DURATION, + "Provided reward too high" + ); periodFinish[token] = block.timestamp + DURATION; if (!isReward[token]) { isReward[token] = true; @@ -565,32 +745,57 @@ contract Gauge is IGauge { emit NotifyReward(msg.sender, token, amount); } - function swapOutRewardToken(uint i, address oldToken, address newToken) external { - require(msg.sender == IVotingEscrow(_ve).team(), 'only team'); + function swapOutRewardToken( + uint256 i, + address oldToken, + address newToken + ) external { + require(msg.sender == IVotingEscrow(_ve).team(), "only team"); require(rewards[i] == oldToken); isReward[oldToken] = false; isReward[newToken] = true; rewards[i] = newToken; } - function _safeTransfer(address token, address to, uint256 value) internal { + function _safeTransfer( + address token, + address to, + uint256 value + ) internal { require(token.code.length > 0); - (bool success, bytes memory data) = - token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value)); + (bool success, bytes memory data) = token.call( + abi.encodeWithSelector(IERC20.transfer.selector, to, value) + ); require(success && (data.length == 0 || abi.decode(data, (bool)))); } - function _safeTransferFrom(address token, address from, address to, uint256 value) internal { + function _safeTransferFrom( + address token, + address from, + address to, + uint256 value + ) internal { require(token.code.length > 0); - (bool success, bytes memory data) = - token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value)); + (bool success, bytes memory data) = token.call( + abi.encodeWithSelector( + IERC20.transferFrom.selector, + from, + to, + value + ) + ); require(success && (data.length == 0 || abi.decode(data, (bool)))); } - function _safeApprove(address token, address spender, uint256 value) internal { + function _safeApprove( + address token, + address spender, + uint256 value + ) internal { require(token.code.length > 0); - (bool success, bytes memory data) = - token.call(abi.encodeWithSelector(IERC20.approve.selector, spender, value)); + (bool success, bytes memory data) = token.call( + abi.encodeWithSelector(IERC20.approve.selector, spender, value) + ); require(success && (data.length == 0 || abi.decode(data, (bool)))); } } diff --git a/contracts/InternalBribe.sol b/contracts/InternalBribe.sol index cae81540..82ccd34d 100644 --- a/contracts/InternalBribe.sol +++ b/contracts/InternalBribe.sol @@ -1,78 +1,87 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.13; -import 'contracts/libraries/Math.sol'; -import 'contracts/interfaces/IBribe.sol'; -import 'contracts/interfaces/IERC20.sol'; -import 'contracts/interfaces/IVoter.sol'; -import 'contracts/interfaces/IVotingEscrow.sol'; +import "contracts/libraries/Math.sol"; +import "contracts/interfaces/IBribe.sol"; +import "contracts/interfaces/IERC20.sol"; +import "contracts/interfaces/IVoter.sol"; +import "contracts/interfaces/IVotingEscrow.sol"; // Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote()) contract InternalBribe is IBribe { - address public immutable voter; // only voter can modify balances (since it only happens on vote()) address public immutable _ve; - uint public constant DURATION = 7 days; // rewards are released over 7 days - uint public constant PRECISION = 10 ** 18; - uint internal constant MAX_REWARD_TOKENS = 16; + uint256 public constant DURATION = 7 days; // rewards are released over 7 days + uint256 public constant PRECISION = 10**18; + uint256 internal constant MAX_REWARD_TOKENS = 16; // default snx staking contract implementation - mapping(address => uint) public rewardRate; - mapping(address => uint) public periodFinish; - mapping(address => uint) public lastUpdateTime; - mapping(address => uint) public rewardPerTokenStored; + mapping(address => uint256) public rewardRate; + mapping(address => uint256) public periodFinish; + mapping(address => uint256) public lastUpdateTime; + mapping(address => uint256) public rewardPerTokenStored; - mapping(address => mapping(uint => uint)) public lastEarn; - mapping(address => mapping(uint => uint)) public userRewardPerTokenStored; + mapping(address => mapping(uint256 => uint256)) public lastEarn; + mapping(address => mapping(uint256 => uint256)) + public userRewardPerTokenStored; address[] public rewards; mapping(address => bool) public isReward; - uint public totalSupply; - mapping(uint => uint) public balanceOf; + uint256 public totalSupply; + mapping(uint256 => uint256) public balanceOf; /// @notice A checkpoint for marking balance struct Checkpoint { - uint timestamp; - uint balanceOf; + uint256 timestamp; + uint256 balanceOf; } /// @notice A checkpoint for marking reward rate struct RewardPerTokenCheckpoint { - uint timestamp; - uint rewardPerToken; + uint256 timestamp; + uint256 rewardPerToken; } /// @notice A checkpoint for marking supply struct SupplyCheckpoint { - uint timestamp; - uint supply; + uint256 timestamp; + uint256 supply; } /// @notice A record of balance checkpoints for each account, by index - mapping (uint => mapping (uint => Checkpoint)) public checkpoints; + mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints; /// @notice The number of checkpoints for each account - mapping (uint => uint) public numCheckpoints; + mapping(uint256 => uint256) public numCheckpoints; /// @notice A record of balance checkpoints for each token, by index - mapping (uint => SupplyCheckpoint) public supplyCheckpoints; + mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints; /// @notice The number of checkpoints - uint public supplyNumCheckpoints; + uint256 public supplyNumCheckpoints; /// @notice A record of balance checkpoints for each token, by index - mapping (address => mapping (uint => RewardPerTokenCheckpoint)) public rewardPerTokenCheckpoints; + mapping(address => mapping(uint256 => RewardPerTokenCheckpoint)) + public rewardPerTokenCheckpoints; /// @notice The number of checkpoints for each token - mapping (address => uint) public rewardPerTokenNumCheckpoints; - - event Deposit(address indexed from, uint tokenId, uint amount); - event Withdraw(address indexed from, uint tokenId, uint amount); - event NotifyReward(address indexed from, address indexed reward, uint amount); - event ClaimRewards(address indexed from, address indexed reward, uint amount); + mapping(address => uint256) public rewardPerTokenNumCheckpoints; + + event Deposit(address indexed from, uint256 tokenId, uint256 amount); + event Withdraw(address indexed from, uint256 tokenId, uint256 amount); + event NotifyReward( + address indexed from, + address indexed reward, + uint256 amount + ); + event ClaimRewards( + address indexed from, + address indexed reward, + uint256 amount + ); constructor(address _voter, address[] memory _allowedRewardTokens) { voter = _voter; _ve = IVoter(_voter)._ve(); - for (uint i; i < _allowedRewardTokens.length; i++) { + for (uint256 i; i < _allowedRewardTokens.length; i++) { if (_allowedRewardTokens[i] != address(0)) { isReward[_allowedRewardTokens[i]] = true; rewards.push(_allowedRewardTokens[i]); @@ -81,7 +90,7 @@ contract InternalBribe is IBribe { } // simple re-entrancy check - uint internal _unlocked = 1; + uint256 internal _unlocked = 1; modifier lock() { require(_unlocked == 1); _unlocked = 2; @@ -90,14 +99,18 @@ contract InternalBribe is IBribe { } /** - * @notice Determine the prior balance for an account as of a block number - * @dev Block number must be a finalized block or else this function will revert to prevent misinformation. - * @param tokenId The token of the NFT to check - * @param timestamp The timestamp to get the balance at - * @return The balance the account had as of the given block - */ - function getPriorBalanceIndex(uint tokenId, uint timestamp) public view returns (uint) { - uint nCheckpoints = numCheckpoints[tokenId]; + * @notice Determine the prior balance for an account as of a block number + * @dev Block number must be a finalized block or else this function will revert to prevent misinformation. + * @param tokenId The token of the NFT to check + * @param timestamp The timestamp to get the balance at + * @return The balance the account had as of the given block + */ + function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp) + public + view + returns (uint256) + { + uint256 nCheckpoints = numCheckpoints[tokenId]; if (nCheckpoints == 0) { return 0; } @@ -112,10 +125,10 @@ contract InternalBribe is IBribe { return 0; } - uint lower = 0; - uint upper = nCheckpoints - 1; + uint256 lower = 0; + uint256 upper = nCheckpoints - 1; while (upper > lower) { - uint center = upper - (upper - lower) / 2; // ceil, avoiding overflow + uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow Checkpoint memory cp = checkpoints[tokenId][center]; if (cp.timestamp == timestamp) { return center; @@ -128,8 +141,12 @@ contract InternalBribe is IBribe { return lower; } - function getPriorSupplyIndex(uint timestamp) public view returns (uint) { - uint nCheckpoints = supplyNumCheckpoints; + function getPriorSupplyIndex(uint256 timestamp) + public + view + returns (uint256) + { + uint256 nCheckpoints = supplyNumCheckpoints; if (nCheckpoints == 0) { return 0; } @@ -144,10 +161,10 @@ contract InternalBribe is IBribe { return 0; } - uint lower = 0; - uint upper = nCheckpoints - 1; + uint256 lower = 0; + uint256 upper = nCheckpoints - 1; while (upper > lower) { - uint center = upper - (upper - lower) / 2; // ceil, avoiding overflow + uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow SupplyCheckpoint memory cp = supplyCheckpoints[center]; if (cp.timestamp == timestamp) { return center; @@ -160,27 +177,40 @@ contract InternalBribe is IBribe { return lower; } - function getPriorRewardPerToken(address token, uint timestamp) public view returns (uint, uint) { - uint nCheckpoints = rewardPerTokenNumCheckpoints[token]; + function getPriorRewardPerToken(address token, uint256 timestamp) + public + view + returns (uint256, uint256) + { + uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token]; if (nCheckpoints == 0) { - return (0,0); + return (0, 0); } // First check most recent balance - if (rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <= timestamp) { - return (rewardPerTokenCheckpoints[token][nCheckpoints - 1].rewardPerToken, rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp); + if ( + rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <= + timestamp + ) { + return ( + rewardPerTokenCheckpoints[token][nCheckpoints - 1] + .rewardPerToken, + rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp + ); } // Next check implicit zero balance if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) { - return (0,0); + return (0, 0); } - uint lower = 0; - uint upper = nCheckpoints - 1; + uint256 lower = 0; + uint256 upper = nCheckpoints - 1; while (upper > lower) { - uint center = upper - (upper - lower) / 2; // ceil, avoiding overflow - RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[token][center]; + uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow + RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[ + token + ][center]; if (cp.timestamp == timestamp) { return (cp.rewardPerToken, cp.timestamp); } else if (cp.timestamp < timestamp) { @@ -189,62 +219,97 @@ contract InternalBribe is IBribe { upper = center - 1; } } - return (rewardPerTokenCheckpoints[token][lower].rewardPerToken, rewardPerTokenCheckpoints[token][lower].timestamp); + return ( + rewardPerTokenCheckpoints[token][lower].rewardPerToken, + rewardPerTokenCheckpoints[token][lower].timestamp + ); } - function _writeCheckpoint(uint tokenId, uint balance) internal { - uint _timestamp = block.timestamp; - uint _nCheckPoints = numCheckpoints[tokenId]; + function _writeCheckpoint(uint256 tokenId, uint256 balance) internal { + uint256 _timestamp = block.timestamp; + uint256 _nCheckPoints = numCheckpoints[tokenId]; - if (_nCheckPoints > 0 && checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp) { + if ( + _nCheckPoints > 0 && + checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp + ) { checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance; } else { - checkpoints[tokenId][_nCheckPoints] = Checkpoint(_timestamp, balance); + checkpoints[tokenId][_nCheckPoints] = Checkpoint( + _timestamp, + balance + ); numCheckpoints[tokenId] = _nCheckPoints + 1; } } - function _writeRewardPerTokenCheckpoint(address token, uint reward, uint timestamp) internal { - uint _nCheckPoints = rewardPerTokenNumCheckpoints[token]; - - if (_nCheckPoints > 0 && rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp == timestamp) { - rewardPerTokenCheckpoints[token][_nCheckPoints - 1].rewardPerToken = reward; + function _writeRewardPerTokenCheckpoint( + address token, + uint256 reward, + uint256 timestamp + ) internal { + uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token]; + + if ( + _nCheckPoints > 0 && + rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp == + timestamp + ) { + rewardPerTokenCheckpoints[token][_nCheckPoints - 1] + .rewardPerToken = reward; } else { - rewardPerTokenCheckpoints[token][_nCheckPoints] = RewardPerTokenCheckpoint(timestamp, reward); + rewardPerTokenCheckpoints[token][ + _nCheckPoints + ] = RewardPerTokenCheckpoint(timestamp, reward); rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1; } } function _writeSupplyCheckpoint() internal { - uint _nCheckPoints = supplyNumCheckpoints; - uint _timestamp = block.timestamp; + uint256 _nCheckPoints = supplyNumCheckpoints; + uint256 _timestamp = block.timestamp; - if (_nCheckPoints > 0 && supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp) { + if ( + _nCheckPoints > 0 && + supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp + ) { supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply; } else { - supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(_timestamp, totalSupply); + supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint( + _timestamp, + totalSupply + ); supplyNumCheckpoints = _nCheckPoints + 1; } } - function rewardsListLength() external view returns (uint) { + function rewardsListLength() external view returns (uint256) { return rewards.length; } // returns the last time the reward was modified or periodFinish if the reward has ended - function lastTimeRewardApplicable(address token) public view returns (uint) { - return Math.min(block.timestamp, periodFinish[token]); + function lastTimeRewardApplicable(address token) + public + view + returns (uint256) + { + return MathDunks.min(block.timestamp, periodFinish[token]); } // allows a user to claim rewards for a given token - function getReward(uint tokenId, address[] memory tokens) external lock { + function getReward(uint256 tokenId, address[] memory tokens) external lock { require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId)); - for (uint i = 0; i < tokens.length; i++) { - (rewardPerTokenStored[tokens[i]], lastUpdateTime[tokens[i]]) = _updateRewardPerToken(tokens[i], type(uint).max, true); + for (uint256 i = 0; i < tokens.length; i++) { + ( + rewardPerTokenStored[tokens[i]], + lastUpdateTime[tokens[i]] + ) = _updateRewardPerToken(tokens[i], type(uint256).max, true); - uint _reward = earned(tokens[i], tokenId); + uint256 _reward = earned(tokens[i], tokenId); lastEarn[tokens[i]][tokenId] = block.timestamp; - userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[tokens[i]]; + userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[ + tokens[i] + ]; if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward); emit ClaimRewards(msg.sender, tokens[i], _reward); @@ -252,35 +317,54 @@ contract InternalBribe is IBribe { } // used by Voter to allow batched reward claims - function getRewardForOwner(uint tokenId, address[] memory tokens) external lock { + function getRewardForOwner(uint256 tokenId, address[] memory tokens) + external + lock + { require(msg.sender == voter); address _owner = IVotingEscrow(_ve).ownerOf(tokenId); - for (uint i = 0; i < tokens.length; i++) { - (rewardPerTokenStored[tokens[i]], lastUpdateTime[tokens[i]]) = _updateRewardPerToken(tokens[i], type(uint).max, true); + for (uint256 i = 0; i < tokens.length; i++) { + ( + rewardPerTokenStored[tokens[i]], + lastUpdateTime[tokens[i]] + ) = _updateRewardPerToken(tokens[i], type(uint256).max, true); - uint _reward = earned(tokens[i], tokenId); + uint256 _reward = earned(tokens[i], tokenId); lastEarn[tokens[i]][tokenId] = block.timestamp; - userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[tokens[i]]; + userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[ + tokens[i] + ]; if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward); emit ClaimRewards(_owner, tokens[i], _reward); } } - function rewardPerToken(address token) public view returns (uint) { + function rewardPerToken(address token) public view returns (uint256) { if (totalSupply == 0) { return rewardPerTokenStored[token]; } - return rewardPerTokenStored[token] + ((lastTimeRewardApplicable(token) - Math.min(lastUpdateTime[token], periodFinish[token])) * rewardRate[token] * PRECISION / totalSupply); + return + rewardPerTokenStored[token] + + (((lastTimeRewardApplicable(token) - + MathDunks.min(lastUpdateTime[token], periodFinish[token])) * + rewardRate[token] * + PRECISION) / totalSupply); } - function batchRewardPerToken(address token, uint maxRuns) external { - (rewardPerTokenStored[token], lastUpdateTime[token]) = _batchRewardPerToken(token, maxRuns); + function batchRewardPerToken(address token, uint256 maxRuns) external { + ( + rewardPerTokenStored[token], + lastUpdateTime[token] + ) = _batchRewardPerToken(token, maxRuns); } - function _batchRewardPerToken(address token, uint maxRuns) internal returns (uint, uint) { - uint _startTimestamp = lastUpdateTime[token]; - uint reward = rewardPerTokenStored[token]; + function _batchRewardPerToken(address token, uint256 maxRuns) + internal + returns (uint256, uint256) + { + uint256 _startTimestamp = lastUpdateTime[token]; + uint256 reward = rewardPerTokenStored[token]; if (supplyNumCheckpoints == 0) { return (reward, _startTimestamp); @@ -290,14 +374,20 @@ contract InternalBribe is IBribe { return (reward, block.timestamp); } - uint _startIndex = getPriorSupplyIndex(_startTimestamp); - uint _endIndex = Math.min(supplyNumCheckpoints-1, maxRuns); + uint256 _startIndex = getPriorSupplyIndex(_startTimestamp); + uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns); - for (uint i = _startIndex; i < _endIndex; i++) { + for (uint256 i = _startIndex; i < _endIndex; i++) { SupplyCheckpoint memory sp0 = supplyCheckpoints[i]; if (sp0.supply > 0) { - SupplyCheckpoint memory sp1 = supplyCheckpoints[i+1]; - (uint _reward, uint endTime) = _calcRewardPerToken(token, sp1.timestamp, sp0.timestamp, sp0.supply, _startTimestamp); + SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1]; + (uint256 _reward, uint256 endTime) = _calcRewardPerToken( + token, + sp1.timestamp, + sp0.timestamp, + sp0.supply, + _startTimestamp + ); reward += _reward; _writeRewardPerTokenCheckpoint(token, reward, endTime); _startTimestamp = endTime; @@ -307,28 +397,55 @@ contract InternalBribe is IBribe { return (reward, _startTimestamp); } - function _calcRewardPerToken(address token, uint timestamp1, uint timestamp0, uint supply, uint startTimestamp) internal view returns (uint, uint) { - uint endTime = Math.max(timestamp1, startTimestamp); - return (((Math.min(endTime, periodFinish[token]) - Math.min(Math.max(timestamp0, startTimestamp), periodFinish[token])) * rewardRate[token] * PRECISION / supply), endTime); + function _calcRewardPerToken( + address token, + uint256 timestamp1, + uint256 timestamp0, + uint256 supply, + uint256 startTimestamp + ) internal view returns (uint256, uint256) { + uint256 endTime = MathDunks.max(timestamp1, startTimestamp); + return ( + (((MathDunks.min(endTime, periodFinish[token]) - + MathDunks.min( + MathDunks.max(timestamp0, startTimestamp), + periodFinish[token] + )) * + rewardRate[token] * + PRECISION) / supply), + endTime + ); } /// @dev Update stored rewardPerToken values without the last one snapshot /// If the contract will get "out of gas" error on users actions this will be helpful - function batchUpdateRewardPerToken(address token, uint maxRuns) external { - (rewardPerTokenStored[token], lastUpdateTime[token]) = _updateRewardPerToken(token, maxRuns, false); + function batchUpdateRewardPerToken(address token, uint256 maxRuns) + external + { + ( + rewardPerTokenStored[token], + lastUpdateTime[token] + ) = _updateRewardPerToken(token, maxRuns, false); } function _updateRewardForAllTokens() internal { - uint length = rewards.length; - for (uint i; i < length; i++) { - address token = rewards[i]; - (rewardPerTokenStored[token], lastUpdateTime[token]) = _updateRewardPerToken(token, type(uint).max, true); - } + uint256 length = rewards.length; + for (uint256 i; i < length; i++) { + address token = rewards[i]; + ( + rewardPerTokenStored[token], + lastUpdateTime[token] + ) = _updateRewardPerToken(token, type(uint256).max, true); + } } - function _updateRewardPerToken(address token, uint maxRuns, bool actualLast) internal returns (uint, uint) { - uint _startTimestamp = lastUpdateTime[token]; - uint reward = rewardPerTokenStored[token]; + function _updateRewardPerToken( + address token, + uint256 maxRuns, + bool actualLast + ) internal returns (uint256, uint256) { + uint256 _startTimestamp = lastUpdateTime[token]; + uint256 reward = rewardPerTokenStored[token]; if (supplyNumCheckpoints == 0) { return (reward, _startTimestamp); @@ -338,15 +455,21 @@ contract InternalBribe is IBribe { return (reward, block.timestamp); } - uint _startIndex = getPriorSupplyIndex(_startTimestamp); - uint _endIndex = Math.min(supplyNumCheckpoints - 1, maxRuns); + uint256 _startIndex = getPriorSupplyIndex(_startTimestamp); + uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns); if (_endIndex > 0) { - for (uint i = _startIndex; i <= _endIndex - 1; i++) { + for (uint256 i = _startIndex; i <= _endIndex - 1; i++) { SupplyCheckpoint memory sp0 = supplyCheckpoints[i]; if (sp0.supply > 0) { - SupplyCheckpoint memory sp1 = supplyCheckpoints[i+1]; - (uint _reward, uint _endTime) = _calcRewardPerToken(token, sp1.timestamp, sp0.timestamp, sp0.supply, _startTimestamp); + SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1]; + (uint256 _reward, uint256 _endTime) = _calcRewardPerToken( + token, + sp1.timestamp, + sp0.timestamp, + sp0.supply, + _startTimestamp + ); reward += _reward; _writeRewardPerTokenCheckpoint(token, reward, _endTime); _startTimestamp = _endTime; @@ -357,7 +480,13 @@ contract InternalBribe is IBribe { if (actualLast) { SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex]; if (sp.supply > 0) { - (uint _reward,) = _calcRewardPerToken(token, lastTimeRewardApplicable(token), Math.max(sp.timestamp, _startTimestamp), sp.supply, _startTimestamp); + (uint256 _reward, ) = _calcRewardPerToken( + token, + lastTimeRewardApplicable(token), + MathDunks.max(sp.timestamp, _startTimestamp), + sp.supply, + _startTimestamp + ); reward += _reward; _writeRewardPerTokenCheckpoint(token, reward, block.timestamp); _startTimestamp = block.timestamp; @@ -367,36 +496,62 @@ contract InternalBribe is IBribe { return (reward, _startTimestamp); } - function earned(address token, uint tokenId) public view returns (uint) { - uint _startTimestamp = Math.max(lastEarn[token][tokenId], rewardPerTokenCheckpoints[token][0].timestamp); + function earned(address token, uint256 tokenId) + public + view + returns (uint256) + { + uint256 _startTimestamp = MathDunks.max( + lastEarn[token][tokenId], + rewardPerTokenCheckpoints[token][0].timestamp + ); if (numCheckpoints[tokenId] == 0) { return 0; } - uint _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp); - uint _endIndex = numCheckpoints[tokenId]-1; + uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp); + uint256 _endIndex = numCheckpoints[tokenId] - 1; - uint reward = 0; + uint256 reward = 0; if (_endIndex > 0) { - for (uint i = _startIndex; i <= _endIndex-1; i++) { + for (uint256 i = _startIndex; i <= _endIndex - 1; i++) { Checkpoint memory cp0 = checkpoints[tokenId][i]; - Checkpoint memory cp1 = checkpoints[tokenId][i+1]; - (uint _rewardPerTokenStored0,) = getPriorRewardPerToken(token, cp0.timestamp); - (uint _rewardPerTokenStored1,) = getPriorRewardPerToken(token, cp1.timestamp); - reward += cp0.balanceOf * (_rewardPerTokenStored1 - _rewardPerTokenStored0) / PRECISION; + Checkpoint memory cp1 = checkpoints[tokenId][i + 1]; + (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken( + token, + cp0.timestamp + ); + (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken( + token, + cp1.timestamp + ); + reward += + (cp0.balanceOf * + (_rewardPerTokenStored1 - _rewardPerTokenStored0)) / + PRECISION; } } Checkpoint memory cp = checkpoints[tokenId][_endIndex]; - (uint _rewardPerTokenStored,) = getPriorRewardPerToken(token, cp.timestamp); - reward += cp.balanceOf * (rewardPerToken(token) - Math.max(_rewardPerTokenStored, userRewardPerTokenStored[token][tokenId])) / PRECISION; + (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken( + token, + cp.timestamp + ); + reward += + (cp.balanceOf * + (rewardPerToken(token) - + MathDunks.max( + _rewardPerTokenStored, + userRewardPerTokenStored[token][tokenId] + ))) / + PRECISION; return reward; } // This is an external function, but internal notation is used since it can only be called "internally" from Gauges - function _deposit(uint amount, uint tokenId) external { + function _deposit(uint256 amount, uint256 tokenId) external { require(msg.sender == voter); _updateRewardForAllTokens(); @@ -409,7 +564,7 @@ contract InternalBribe is IBribe { emit Deposit(msg.sender, tokenId, amount); } - function _withdraw(uint amount, uint tokenId) external { + function _withdraw(uint256 amount, uint256 tokenId) external { require(msg.sender == voter); _updateRewardForAllTokens(); @@ -422,57 +577,84 @@ contract InternalBribe is IBribe { emit Withdraw(msg.sender, tokenId, amount); } - function left(address token) external view returns (uint) { + function left(address token) external view returns (uint256) { if (block.timestamp >= periodFinish[token]) return 0; - uint _remaining = periodFinish[token] - block.timestamp; + uint256 _remaining = periodFinish[token] - block.timestamp; return _remaining * rewardRate[token]; } // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards - function notifyRewardAmount(address token, uint amount) external lock { + function notifyRewardAmount(address token, uint256 amount) external lock { require(amount > 0); require(isReward[token]); - if (rewardRate[token] == 0) _writeRewardPerTokenCheckpoint(token, 0, block.timestamp); - (rewardPerTokenStored[token], lastUpdateTime[token]) = _updateRewardPerToken(token, type(uint).max, true); + if (rewardRate[token] == 0) + _writeRewardPerTokenCheckpoint(token, 0, block.timestamp); + ( + rewardPerTokenStored[token], + lastUpdateTime[token] + ) = _updateRewardPerToken(token, type(uint256).max, true); if (block.timestamp >= periodFinish[token]) { _safeTransferFrom(token, msg.sender, address(this), amount); rewardRate[token] = amount / DURATION; } else { - uint _remaining = periodFinish[token] - block.timestamp; - uint _left = _remaining * rewardRate[token]; + uint256 _remaining = periodFinish[token] - block.timestamp; + uint256 _left = _remaining * rewardRate[token]; require(amount > _left); _safeTransferFrom(token, msg.sender, address(this), amount); rewardRate[token] = (amount + _left) / DURATION; } require(rewardRate[token] > 0); - uint balance = IERC20(token).balanceOf(address(this)); - require(rewardRate[token] <= balance / DURATION, "Provided reward too high"); + uint256 balance = IERC20(token).balanceOf(address(this)); + require( + rewardRate[token] <= balance / DURATION, + "Provided reward too high" + ); periodFinish[token] = block.timestamp + DURATION; emit NotifyReward(msg.sender, token, amount); } - function swapOutRewardToken(uint i, address oldToken, address newToken) external { - require(msg.sender == IVotingEscrow(_ve).team(), 'only team'); + function swapOutRewardToken( + uint256 i, + address oldToken, + address newToken + ) external { + require(msg.sender == IVotingEscrow(_ve).team(), "only team"); require(rewards[i] == oldToken); isReward[oldToken] = false; isReward[newToken] = true; rewards[i] = newToken; } - function _safeTransfer(address token, address to, uint256 value) internal { + function _safeTransfer( + address token, + address to, + uint256 value + ) internal { require(token.code.length > 0); - (bool success, bytes memory data) = - token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value)); + (bool success, bytes memory data) = token.call( + abi.encodeWithSelector(IERC20.transfer.selector, to, value) + ); require(success && (data.length == 0 || abi.decode(data, (bool)))); } - function _safeTransferFrom(address token, address from, address to, uint256 value) internal { + function _safeTransferFrom( + address token, + address from, + address to, + uint256 value + ) internal { require(token.code.length > 0); - (bool success, bytes memory data) = - token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value)); + (bool success, bytes memory data) = token.call( + abi.encodeWithSelector( + IERC20.transferFrom.selector, + from, + to, + value + ) + ); require(success && (data.length == 0 || abi.decode(data, (bool)))); } } diff --git a/contracts/Minter.sol b/contracts/Minter.sol index 75d476fb..712a3255 100644 --- a/contracts/Minter.sol +++ b/contracts/Minter.sol @@ -11,25 +11,30 @@ import "contracts/interfaces/IVotingEscrow.sol"; // codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting contract Minter is IMinter { - uint internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC) - uint internal constant EMISSION = 990; - uint internal constant TAIL_EMISSION = 2; - uint internal constant PRECISION = 1000; + uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC) + uint256 internal constant EMISSION = 990; + uint256 internal constant TAIL_EMISSION = 2; + uint256 internal constant PRECISION = 1000; IVelo public immutable _velo; IVoter public immutable _voter; IVotingEscrow public immutable _ve; IRewardsDistributor public immutable _rewards_distributor; - uint public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals) - uint public active_period; - uint internal constant LOCK = 86400 * 7 * 52 * 4; + uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals) + uint256 public active_period; + uint256 internal constant LOCK = 86400 * 7 * 52 * 4; address internal initializer; address public team; address public pendingTeam; - uint public teamRate; - uint public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05% + uint256 public teamRate; + uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05% - event Mint(address indexed sender, uint weekly, uint circulating_supply, uint circulating_emission); + event Mint( + address indexed sender, + uint256 weekly, + uint256 circulating_supply, + uint256 circulating_emission + ); constructor( address __voter, // the voting & distribution system @@ -48,13 +53,13 @@ contract Minter is IMinter { function initialize( address[] memory claimants, - uint[] memory amounts, - uint max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m + uint256[] memory amounts, + uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m ) external { require(initializer == msg.sender); _velo.mint(address(this), max); - _velo.approve(address(_ve), type(uint).max); - for (uint i = 0; i < claimants.length; i++) { + _velo.approve(address(_ve), type(uint256).max); + for (uint256 i = 0; i < claimants.length; i++) { _ve.create_lock_for(amounts[i], LOCK, claimants[i]); } initializer = address(0); @@ -71,36 +76,36 @@ contract Minter is IMinter { team = pendingTeam; } - function setTeamRate(uint _teamRate) external { + function setTeamRate(uint256 _teamRate) external { require(msg.sender == team, "not team"); require(_teamRate <= MAX_TEAM_RATE, "rate too high"); teamRate = _teamRate; } // calculate circulating supply as total token supply - locked supply - function circulating_supply() public view returns (uint) { + function circulating_supply() public view returns (uint256) { return _velo.totalSupply() - _ve.totalSupply(); } // emission calculation is 1% of available supply to mint adjusted by circulating / total supply - function calculate_emission() public view returns (uint) { + function calculate_emission() public view returns (uint256) { return (weekly * EMISSION) / PRECISION; } // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission - function weekly_emission() public view returns (uint) { - return Math.max(calculate_emission(), circulating_emission()); + function weekly_emission() public view returns (uint256) { + return MathDunks.max(calculate_emission(), circulating_emission()); } // calculates tail end (infinity) emissions as 0.2% of total supply - function circulating_emission() public view returns (uint) { + function circulating_emission() public view returns (uint256) { return (circulating_supply() * TAIL_EMISSION) / PRECISION; } // calculate inflation and adjust ve balances accordingly - function calculate_growth(uint _minted) public view returns (uint) { - uint _veTotal = _ve.totalSupply(); - uint _veloTotal = _velo.totalSupply(); + function calculate_growth(uint256 _minted) public view returns (uint256) { + uint256 _veTotal = _ve.totalSupply(); + uint256 _veloTotal = _velo.totalSupply(); return (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) * _veTotal) / @@ -109,18 +114,19 @@ contract Minter is IMinter { } // update period can only be called once per cycle (1 week) - function update_period() external returns (uint) { - uint _period = active_period; - if (block.timestamp >= _period + WEEK && initializer == address(0)) { // only trigger if new week + function update_period() external returns (uint256) { + uint256 _period = active_period; + if (block.timestamp >= _period + WEEK && initializer == address(0)) { + // only trigger if new week _period = (block.timestamp / WEEK) * WEEK; active_period = _period; weekly = weekly_emission(); - uint _growth = calculate_growth(weekly); - uint _teamEmissions = (teamRate * (_growth + weekly)) / + uint256 _growth = calculate_growth(weekly); + uint256 _teamEmissions = (teamRate * (_growth + weekly)) / (PRECISION - teamRate); - uint _required = _growth + weekly + _teamEmissions; - uint _balanceOf = _velo.balanceOf(address(this)); + uint256 _required = _growth + weekly + _teamEmissions; + uint256 _balanceOf = _velo.balanceOf(address(this)); if (_balanceOf < _required) { _velo.mint(address(this), _required - _balanceOf); } @@ -133,7 +139,12 @@ contract Minter is IMinter { _velo.approve(address(_voter), weekly); _voter.notifyRewardAmount(weekly); - emit Mint(msg.sender, weekly, circulating_supply(), circulating_emission()); + emit Mint( + msg.sender, + weekly, + circulating_supply(), + circulating_emission() + ); } return _period; } diff --git a/contracts/Pair.sol b/contracts/Pair.sol index fc33938f..d908d6a6 100644 --- a/contracts/Pair.sol +++ b/contracts/Pair.sol @@ -1,16 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.13; -import 'contracts/libraries/Math.sol'; -import 'contracts/interfaces/IERC20.sol'; -import 'contracts/interfaces/IPair.sol'; -import 'contracts/interfaces/IPairCallee.sol'; -import 'contracts/factories/PairFactory.sol'; -import 'contracts/PairFees.sol'; +import "contracts/libraries/Math.sol"; +import "contracts/interfaces/IERC20.sol"; +import "contracts/interfaces/IPair.sol"; +import "contracts/interfaces/IPairCallee.sol"; +import "contracts/factories/PairFactory.sol"; +import "contracts/PairFees.sol"; // The base pair of pools, either stable or volatile contract Pair is IPair { - string public name; string public symbol; uint8 public constant decimals = 18; @@ -18,17 +17,18 @@ contract Pair is IPair { // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses bool public immutable stable; - uint public totalSupply = 0; + uint256 public totalSupply = 0; - mapping(address => mapping (address => uint)) public allowance; - mapping(address => uint) public balanceOf; + mapping(address => mapping(address => uint256)) public allowance; + mapping(address => uint256) public balanceOf; bytes32 internal DOMAIN_SEPARATOR; // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); - bytes32 internal constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; - mapping(address => uint) public nonces; + bytes32 internal constant PERMIT_TYPEHASH = + 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; + mapping(address => uint256) public nonces; - uint internal constant MINIMUM_LIQUIDITY = 10**3; + uint256 internal constant MINIMUM_LIQUIDITY = 10**3; address public immutable token0; address public immutable token1; @@ -37,67 +37,111 @@ contract Pair is IPair { // Structure to capture time period obervations every 30 minutes, used for local oracles struct Observation { - uint timestamp; - uint reserve0Cumulative; - uint reserve1Cumulative; + uint256 timestamp; + uint256 reserve0Cumulative; + uint256 reserve1Cumulative; } // Capture oracle reading every 30 minutes - uint constant periodSize = 1800; + uint256 constant periodSize = 1800; Observation[] public observations; - uint internal immutable decimals0; - uint internal immutable decimals1; + uint256 internal immutable decimals0; + uint256 internal immutable decimals1; - uint public reserve0; - uint public reserve1; - uint public blockTimestampLast; + uint256 public reserve0; + uint256 public reserve1; + uint256 public blockTimestampLast; - uint public reserve0CumulativeLast; - uint public reserve1CumulativeLast; + uint256 public reserve0CumulativeLast; + uint256 public reserve1CumulativeLast; // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap "clean" // this further allows LP holders to easily claim fees for tokens they have/staked - uint public index0 = 0; - uint public index1 = 0; + uint256 public index0 = 0; + uint256 public index1 = 0; // position assigned to each LP to track their current index0 & index1 vs the global position - mapping(address => uint) public supplyIndex0; - mapping(address => uint) public supplyIndex1; + mapping(address => uint256) public supplyIndex0; + mapping(address => uint256) public supplyIndex1; // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1 - mapping(address => uint) public claimable0; - mapping(address => uint) public claimable1; + mapping(address => uint256) public claimable0; + mapping(address => uint256) public claimable1; - event Fees(address indexed sender, uint amount0, uint amount1); - event Mint(address indexed sender, uint amount0, uint amount1); - event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); + event Fees(address indexed sender, uint256 amount0, uint256 amount1); + event Mint(address indexed sender, uint256 amount0, uint256 amount1); + event Burn( + address indexed sender, + uint256 amount0, + uint256 amount1, + address indexed to + ); event Swap( address indexed sender, - uint amount0In, - uint amount1In, - uint amount0Out, - uint amount1Out, + uint256 amount0In, + uint256 amount1In, + uint256 amount0Out, + uint256 amount1Out, address indexed to ); - event Sync(uint reserve0, uint reserve1); - event Claim(address indexed sender, address indexed recipient, uint amount0, uint amount1); + event Sync(uint256 reserve0, uint256 reserve1); + event Claim( + address indexed sender, + address indexed recipient, + uint256 amount0, + uint256 amount1 + ); - event Transfer(address indexed from, address indexed to, uint amount); - event Approval(address indexed owner, address indexed spender, uint amount); + event Transfer(address indexed from, address indexed to, uint256 amount); + event Approval( + address indexed owner, + address indexed spender, + uint256 amount + ); constructor() { factory = msg.sender; - (address _token0, address _token1, bool _stable) = PairFactory(msg.sender).getInitializable(); + (address _token0, address _token1, bool _stable) = PairFactory( + msg.sender + ).getInitializable(); (token0, token1, stable) = (_token0, _token1, _stable); fees = address(new PairFees(_token0, _token1)); if (_stable) { - name = string(abi.encodePacked("StableV1 AMM - ", IERC20(_token0).symbol(), "/", IERC20(_token1).symbol())); - symbol = string(abi.encodePacked("sAMM-", IERC20(_token0).symbol(), "/", IERC20(_token1).symbol())); + name = string( + abi.encodePacked( + "StableV1 AMM - ", + IERC20(_token0).symbol(), + "/", + IERC20(_token1).symbol() + ) + ); + symbol = string( + abi.encodePacked( + "sAMM-", + IERC20(_token0).symbol(), + "/", + IERC20(_token1).symbol() + ) + ); } else { - name = string(abi.encodePacked("VolatileV1 AMM - ", IERC20(_token0).symbol(), "/", IERC20(_token1).symbol())); - symbol = string(abi.encodePacked("vAMM-", IERC20(_token0).symbol(), "/", IERC20(_token1).symbol())); + name = string( + abi.encodePacked( + "VolatileV1 AMM - ", + IERC20(_token0).symbol(), + "/", + IERC20(_token1).symbol() + ) + ); + symbol = string( + abi.encodePacked( + "vAMM-", + IERC20(_token0).symbol(), + "/", + IERC20(_token1).symbol() + ) + ); } decimals0 = 10**IERC20(_token0).decimals(); @@ -107,7 +151,7 @@ contract Pair is IPair { } // simple re-entrancy check - uint internal _unlocked = 1; + uint256 internal _unlocked = 1; modifier lock() { require(_unlocked == 1); _unlocked = 2; @@ -115,16 +159,36 @@ contract Pair is IPair { _unlocked = 1; } - function observationLength() external view returns (uint) { + function observationLength() external view returns (uint256) { return observations.length; } function lastObservation() public view returns (Observation memory) { - return observations[observations.length-1]; - } - - function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1) { - return (decimals0, decimals1, reserve0, reserve1, stable, token0, token1); + return observations[observations.length - 1]; + } + + function metadata() + external + view + returns ( + uint256 dec0, + uint256 dec1, + uint256 r0, + uint256 r1, + bool st, + address t0, + address t1 + ) + { + return ( + decimals0, + decimals1, + reserve0, + reserve1, + stable, + token0, + token1 + ); } function tokens() external view returns (address, address) { @@ -132,7 +196,7 @@ contract Pair is IPair { } // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1) - function claimFees() external returns (uint claimed0, uint claimed1) { + function claimFees() external returns (uint256 claimed0, uint256 claimed1) { _updateFor(msg.sender); claimed0 = claimable0[msg.sender]; @@ -149,9 +213,9 @@ contract Pair is IPair { } // Accrue fees on token0 - function _update0(uint amount) internal { + function _update0(uint256 amount) internal { _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees - uint256 _ratio = amount * 1e18 / totalSupply; // 1e18 adjustment is removed during claim + uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim if (_ratio > 0) { index0 += _ratio; } @@ -159,9 +223,9 @@ contract Pair is IPair { } // Accrue fees on token1 - function _update1(uint amount) internal { + function _update1(uint256 amount) internal { _safeTransfer(token1, fees, amount); - uint256 _ratio = amount * 1e18 / totalSupply; + uint256 _ratio = (amount * 1e18) / totalSupply; if (_ratio > 0) { index1 += _ratio; } @@ -171,22 +235,22 @@ contract Pair is IPair { // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees // Fees are segregated from core funds, so fees can never put liquidity at risk function _updateFor(address recipient) internal { - uint _supplied = balanceOf[recipient]; // get LP balance of `recipient` + uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient` if (_supplied > 0) { - uint _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient - uint _supplyIndex1 = supplyIndex1[recipient]; - uint _index0 = index0; // get global index0 for accumulated fees - uint _index1 = index1; + uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient + uint256 _supplyIndex1 = supplyIndex1[recipient]; + uint256 _index0 = index0; // get global index0 for accumulated fees + uint256 _index1 = index1; supplyIndex0[recipient] = _index0; // update user current position to global position supplyIndex1[recipient] = _index1; - uint _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued - uint _delta1 = _index1 - _supplyIndex1; + uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued + uint256 _delta1 = _index1 - _supplyIndex1; if (_delta0 > 0) { - uint _share = _supplied * _delta0 / 1e18; // add accrued difference for each supplied token + uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token claimable0[recipient] += _share; } if (_delta1 > 0) { - uint _share = _supplied * _delta1 / 1e18; + uint256 _share = (_supplied * _delta1) / 1e18; claimable1[recipient] += _share; } } else { @@ -195,16 +259,29 @@ contract Pair is IPair { } } - function getReserves() public view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast) { + function getReserves() + public + view + returns ( + uint256 _reserve0, + uint256 _reserve1, + uint256 _blockTimestampLast + ) + { _reserve0 = reserve0; _reserve1 = reserve1; _blockTimestampLast = blockTimestampLast; } // update reserves and, on the first call per block, price accumulators - function _update(uint balance0, uint balance1, uint _reserve0, uint _reserve1) internal { - uint blockTimestamp = block.timestamp; - uint timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired + function _update( + uint256 balance0, + uint256 balance1, + uint256 _reserve0, + uint256 _reserve1 + ) internal { + uint256 blockTimestamp = block.timestamp; + uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) { reserve0CumulativeLast += _reserve0 * timeElapsed; reserve1CumulativeLast += _reserve1 * timeElapsed; @@ -213,7 +290,13 @@ contract Pair is IPair { Observation memory _point = lastObservation(); timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event if (timeElapsed > periodSize) { - observations.push(Observation(blockTimestamp, reserve0CumulativeLast, reserve1CumulativeLast)); + observations.push( + Observation( + blockTimestamp, + reserve0CumulativeLast, + reserve1CumulativeLast + ) + ); } reserve0 = balance0; reserve1 = balance1; @@ -222,64 +305,107 @@ contract Pair is IPair { } // produces the cumulative price using counterfactuals to save gas and avoid a call to sync. - function currentCumulativePrices() public view returns (uint reserve0Cumulative, uint reserve1Cumulative, uint blockTimestamp) { + function currentCumulativePrices() + public + view + returns ( + uint256 reserve0Cumulative, + uint256 reserve1Cumulative, + uint256 blockTimestamp + ) + { blockTimestamp = block.timestamp; reserve0Cumulative = reserve0CumulativeLast; reserve1Cumulative = reserve1CumulativeLast; // if time has elapsed since the last update on the pair, mock the accumulated price values - (uint _reserve0, uint _reserve1, uint _blockTimestampLast) = getReserves(); + ( + uint256 _reserve0, + uint256 _reserve1, + uint256 _blockTimestampLast + ) = getReserves(); if (_blockTimestampLast != blockTimestamp) { // subtraction overflow is desired - uint timeElapsed = blockTimestamp - _blockTimestampLast; + uint256 timeElapsed = blockTimestamp - _blockTimestampLast; reserve0Cumulative += _reserve0 * timeElapsed; reserve1Cumulative += _reserve1 * timeElapsed; } } // gives the current twap price measured from amountIn * tokenIn gives amountOut - function current(address tokenIn, uint amountIn) external view returns (uint amountOut) { + function current(address tokenIn, uint256 amountIn) + external + view + returns (uint256 amountOut) + { Observation memory _observation = lastObservation(); - (uint reserve0Cumulative, uint reserve1Cumulative,) = currentCumulativePrices(); + ( + uint256 reserve0Cumulative, + uint256 reserve1Cumulative, + + ) = currentCumulativePrices(); if (block.timestamp == _observation.timestamp) { - _observation = observations[observations.length-2]; + _observation = observations[observations.length - 2]; } - uint timeElapsed = block.timestamp - _observation.timestamp; - uint _reserve0 = (reserve0Cumulative - _observation.reserve0Cumulative) / timeElapsed; - uint _reserve1 = (reserve1Cumulative - _observation.reserve1Cumulative) / timeElapsed; + uint256 timeElapsed = block.timestamp - _observation.timestamp; + uint256 _reserve0 = (reserve0Cumulative - + _observation.reserve0Cumulative) / timeElapsed; + uint256 _reserve1 = (reserve1Cumulative - + _observation.reserve1Cumulative) / timeElapsed; amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1); } // as per `current`, however allows user configured granularity, up to the full window size - function quote(address tokenIn, uint amountIn, uint granularity) external view returns (uint amountOut) { - uint [] memory _prices = sample(tokenIn, amountIn, granularity, 1); - uint priceAverageCumulative; - for (uint i = 0; i < _prices.length; i++) { + function quote( + address tokenIn, + uint256 amountIn, + uint256 granularity + ) external view returns (uint256 amountOut) { + uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1); + uint256 priceAverageCumulative; + for (uint256 i = 0; i < _prices.length; i++) { priceAverageCumulative += _prices[i]; } return priceAverageCumulative / granularity; } // returns a memory set of twap prices - function prices(address tokenIn, uint amountIn, uint points) external view returns (uint[] memory) { + function prices( + address tokenIn, + uint256 amountIn, + uint256 points + ) external view returns (uint256[] memory) { return sample(tokenIn, amountIn, points, 1); } - function sample(address tokenIn, uint amountIn, uint points, uint window) public view returns (uint[] memory) { - uint[] memory _prices = new uint[](points); + function sample( + address tokenIn, + uint256 amountIn, + uint256 points, + uint256 window + ) public view returns (uint256[] memory) { + uint256[] memory _prices = new uint256[](points); - uint length = observations.length-1; - uint i = length - (points * window); - uint nextIndex = 0; - uint index = 0; + uint256 length = observations.length - 1; + uint256 i = length - (points * window); + uint256 nextIndex = 0; + uint256 index = 0; - for (; i < length; i+=window) { + for (; i < length; i += window) { nextIndex = i + window; - uint timeElapsed = observations[nextIndex].timestamp - observations[i].timestamp; - uint _reserve0 = (observations[nextIndex].reserve0Cumulative - observations[i].reserve0Cumulative) / timeElapsed; - uint _reserve1 = (observations[nextIndex].reserve1Cumulative - observations[i].reserve1Cumulative) / timeElapsed; - _prices[index] = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1); + uint256 timeElapsed = observations[nextIndex].timestamp - + observations[i].timestamp; + uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative - + observations[i].reserve0Cumulative) / timeElapsed; + uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative - + observations[i].reserve1Cumulative) / timeElapsed; + _prices[index] = _getAmountOut( + amountIn, + tokenIn, + _reserve0, + _reserve1 + ); // index < length; length cannot overflow unchecked { index = index + 1; @@ -290,21 +416,24 @@ contract Pair is IPair { // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks // standard uniswap v2 implementation - function mint(address to) external lock returns (uint liquidity) { - (uint _reserve0, uint _reserve1) = (reserve0, reserve1); - uint _balance0 = IERC20(token0).balanceOf(address(this)); - uint _balance1 = IERC20(token1).balanceOf(address(this)); - uint _amount0 = _balance0 - _reserve0; - uint _amount1 = _balance1 - _reserve1; - - uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee + function mint(address to) external lock returns (uint256 liquidity) { + (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1); + uint256 _balance0 = IERC20(token0).balanceOf(address(this)); + uint256 _balance1 = IERC20(token1).balanceOf(address(this)); + uint256 _amount0 = _balance0 - _reserve0; + uint256 _amount1 = _balance1 - _reserve1; + + uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee if (_totalSupply == 0) { - liquidity = Math.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY; + liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY; _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens } else { - liquidity = Math.min(_amount0 * _totalSupply / _reserve0, _amount1 * _totalSupply / _reserve1); + liquidity = MathDunks.min( + (_amount0 * _totalSupply) / _reserve0, + (_amount1 * _totalSupply) / _reserve1 + ); } - require(liquidity > 0, 'ILM'); // Pair: INSUFFICIENT_LIQUIDITY_MINTED + require(liquidity > 0, "ILM"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED _mint(to, liquidity); _update(_balance0, _balance1, _reserve0, _reserve1); @@ -313,17 +442,21 @@ contract Pair is IPair { // this low-level function should be called from a contract which performs important safety checks // standard uniswap v2 implementation - function burn(address to) external lock returns (uint amount0, uint amount1) { - (uint _reserve0, uint _reserve1) = (reserve0, reserve1); + function burn(address to) + external + lock + returns (uint256 amount0, uint256 amount1) + { + (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1); (address _token0, address _token1) = (token0, token1); - uint _balance0 = IERC20(_token0).balanceOf(address(this)); - uint _balance1 = IERC20(_token1).balanceOf(address(this)); - uint _liquidity = balanceOf[address(this)]; - - uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee - amount0 = _liquidity * _balance0 / _totalSupply; // using balances ensures pro-rata distribution - amount1 = _liquidity * _balance1 / _totalSupply; // using balances ensures pro-rata distribution - require(amount0 > 0 && amount1 > 0, 'ILB'); // Pair: INSUFFICIENT_LIQUIDITY_BURNED + uint256 _balance0 = IERC20(_token0).balanceOf(address(this)); + uint256 _balance1 = IERC20(_token1).balanceOf(address(this)); + uint256 _liquidity = balanceOf[address(this)]; + + uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee + amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution + amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution + require(amount0 > 0 && amount1 > 0, "ILB"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED _burn(address(this), _liquidity); _safeTransfer(_token0, to, amount0); _safeTransfer(_token1, to, amount1); @@ -335,34 +468,52 @@ contract Pair is IPair { } // this low-level function should be called from a contract which performs important safety checks - function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock { + function swap( + uint256 amount0Out, + uint256 amount1Out, + address to, + bytes calldata data + ) external lock { require(!PairFactory(factory).isPaused()); - require(amount0Out > 0 || amount1Out > 0, 'IOA'); // Pair: INSUFFICIENT_OUTPUT_AMOUNT - (uint _reserve0, uint _reserve1) = (reserve0, reserve1); - require(amount0Out < _reserve0 && amount1Out < _reserve1, 'IL'); // Pair: INSUFFICIENT_LIQUIDITY - - uint _balance0; - uint _balance1; - { // scope for _token{0,1}, avoids stack too deep errors - (address _token0, address _token1) = (token0, token1); - require(to != _token0 && to != _token1, 'IT'); // Pair: INVALID_TO - if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens - if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens - if (data.length > 0) IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans - _balance0 = IERC20(_token0).balanceOf(address(this)); - _balance1 = IERC20(_token1).balanceOf(address(this)); + require(amount0Out > 0 || amount1Out > 0, "IOA"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT + (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1); + require(amount0Out < _reserve0 && amount1Out < _reserve1, "IL"); // Pair: INSUFFICIENT_LIQUIDITY + + uint256 _balance0; + uint256 _balance1; + { + // scope for _token{0,1}, avoids stack too deep errors + (address _token0, address _token1) = (token0, token1); + require(to != _token0 && to != _token1, "IT"); // Pair: INVALID_TO + if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens + if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens + if (data.length > 0) + IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans + _balance0 = IERC20(_token0).balanceOf(address(this)); + _balance1 = IERC20(_token1).balanceOf(address(this)); } - uint amount0In = _balance0 > _reserve0 - amount0Out ? _balance0 - (_reserve0 - amount0Out) : 0; - uint amount1In = _balance1 > _reserve1 - amount1Out ? _balance1 - (_reserve1 - amount1Out) : 0; - require(amount0In > 0 || amount1In > 0, 'IIA'); // Pair: INSUFFICIENT_INPUT_AMOUNT - { // scope for reserve{0,1}Adjusted, avoids stack too deep errors - (address _token0, address _token1) = (token0, token1); - if (amount0In > 0) _update0(amount0In * PairFactory(factory).getFee(stable) / 10000); // accrue fees for token0 and move them out of pool - if (amount1In > 0) _update1(amount1In * PairFactory(factory).getFee(stable) / 10000); // accrue fees for token1 and move them out of pool - _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check - _balance1 = IERC20(_token1).balanceOf(address(this)); - // The curve, either x3y+y3x for stable pools, or x*y for volatile pools - require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), 'K'); // Pair: K + uint256 amount0In = _balance0 > _reserve0 - amount0Out + ? _balance0 - (_reserve0 - amount0Out) + : 0; + uint256 amount1In = _balance1 > _reserve1 - amount1Out + ? _balance1 - (_reserve1 - amount1Out) + : 0; + require(amount0In > 0 || amount1In > 0, "IIA"); // Pair: INSUFFICIENT_INPUT_AMOUNT + { + // scope for reserve{0,1}Adjusted, avoids stack too deep errors + (address _token0, address _token1) = (token0, token1); + if (amount0In > 0) + _update0( + (amount0In * PairFactory(factory).getFee(stable)) / 10000 + ); // accrue fees for token0 and move them out of pool + if (amount1In > 0) + _update1( + (amount1In * PairFactory(factory).getFee(stable)) / 10000 + ); // accrue fees for token1 and move them out of pool + _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check + _balance1 = IERC20(_token1).balanceOf(address(this)); + // The curve, either x3y+y3x for stable pools, or x*y for volatile pools + require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), "K"); // Pair: K } _update(_balance0, _balance1, _reserve0, _reserve1); @@ -372,32 +523,56 @@ contract Pair is IPair { // force balances to match reserves function skim(address to) external lock { (address _token0, address _token1) = (token0, token1); - _safeTransfer(_token0, to, IERC20(_token0).balanceOf(address(this)) - (reserve0)); - _safeTransfer(_token1, to, IERC20(_token1).balanceOf(address(this)) - (reserve1)); + _safeTransfer( + _token0, + to, + IERC20(_token0).balanceOf(address(this)) - (reserve0) + ); + _safeTransfer( + _token1, + to, + IERC20(_token1).balanceOf(address(this)) - (reserve1) + ); } // force reserves to match balances function sync() external lock { - _update(IERC20(token0).balanceOf(address(this)), IERC20(token1).balanceOf(address(this)), reserve0, reserve1); + _update( + IERC20(token0).balanceOf(address(this)), + IERC20(token1).balanceOf(address(this)), + reserve0, + reserve1 + ); } - function _f(uint x0, uint y) internal pure returns (uint) { - return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18; + function _f(uint256 x0, uint256 y) internal pure returns (uint256) { + return + (x0 * ((((y * y) / 1e18) * y) / 1e18)) / + 1e18 + + (((((x0 * x0) / 1e18) * x0) / 1e18) * y) / + 1e18; } - function _d(uint x0, uint y) internal pure returns (uint) { - return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18); + function _d(uint256 x0, uint256 y) internal pure returns (uint256) { + return + (3 * x0 * ((y * y) / 1e18)) / + 1e18 + + ((((x0 * x0) / 1e18) * x0) / 1e18); } - function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) { - for (uint i = 0; i < 255; i++) { - uint y_prev = y; - uint k = _f(x0, y); + function _get_y( + uint256 x0, + uint256 xy, + uint256 y + ) internal pure returns (uint256) { + for (uint256 i = 0; i < 255; i++) { + uint256 y_prev = y; + uint256 k = _f(x0, y); if (k < xy) { - uint dy = (xy - k)*1e18/_d(x0, y); + uint256 dy = ((xy - k) * 1e18) / _d(x0, y); y = y + dy; } else { - uint dy = (k - xy)*1e18/_d(x0, y); + uint256 dy = ((k - xy) * 1e18) / _d(x0, y); y = y - dy; } if (y > y_prev) { @@ -413,96 +588,137 @@ contract Pair is IPair { return y; } - function getAmountOut(uint amountIn, address tokenIn) external view returns (uint) { - (uint _reserve0, uint _reserve1) = (reserve0, reserve1); - amountIn -= amountIn * PairFactory(factory).getFee(stable) / 10000; // remove fee from amount received + function getAmountOut(uint256 amountIn, address tokenIn) + external + view + returns (uint256) + { + (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1); + amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1); } - function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1) internal view returns (uint) { + function _getAmountOut( + uint256 amountIn, + address tokenIn, + uint256 _reserve0, + uint256 _reserve1 + ) internal view returns (uint256) { if (stable) { - uint xy = _k(_reserve0, _reserve1); - _reserve0 = _reserve0 * 1e18 / decimals0; - _reserve1 = _reserve1 * 1e18 / decimals1; - (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0); - amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1; - uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB); - return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18; + uint256 xy = _k(_reserve0, _reserve1); + _reserve0 = (_reserve0 * 1e18) / decimals0; + _reserve1 = (_reserve1 * 1e18) / decimals1; + (uint256 reserveA, uint256 reserveB) = tokenIn == token0 + ? (_reserve0, _reserve1) + : (_reserve1, _reserve0); + amountIn = tokenIn == token0 + ? (amountIn * 1e18) / decimals0 + : (amountIn * 1e18) / decimals1; + uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB); + return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18; } else { - (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0); - return amountIn * reserveB / (reserveA + amountIn); + (uint256 reserveA, uint256 reserveB) = tokenIn == token0 + ? (_reserve0, _reserve1) + : (_reserve1, _reserve0); + return (amountIn * reserveB) / (reserveA + amountIn); } } - function _k(uint x, uint y) internal view returns (uint) { + function _k(uint256 x, uint256 y) internal view returns (uint256) { if (stable) { - uint _x = x * 1e18 / decimals0; - uint _y = y * 1e18 / decimals1; - uint _a = (_x * _y) / 1e18; - uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18); - return _a * _b / 1e18; // x3y+y3x >= k + uint256 _x = (x * 1e18) / decimals0; + uint256 _y = (y * 1e18) / decimals1; + uint256 _a = (_x * _y) / 1e18; + uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18); + return (_a * _b) / 1e18; // x3y+y3x >= k } else { return x * y; // xy >= k } } - function _mint(address dst, uint amount) internal { + function _mint(address dst, uint256 amount) internal { _updateFor(dst); // balances must be updated on mint/burn/transfer totalSupply += amount; balanceOf[dst] += amount; emit Transfer(address(0), dst, amount); } - function _burn(address dst, uint amount) internal { + function _burn(address dst, uint256 amount) internal { _updateFor(dst); totalSupply -= amount; balanceOf[dst] -= amount; emit Transfer(dst, address(0), amount); } - function approve(address spender, uint amount) external returns (bool) { + function approve(address spender, uint256 amount) external returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } - function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external { - require(deadline >= block.timestamp, 'Pair: EXPIRED'); + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) external { + require(deadline >= block.timestamp, "Pair: EXPIRED"); DOMAIN_SEPARATOR = keccak256( abi.encode( - keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'), + keccak256( + "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" + ), keccak256(bytes(name)), - keccak256(bytes('1')), + keccak256(bytes("1")), block.chainid, address(this) ) ); bytes32 digest = keccak256( abi.encodePacked( - '\x19\x01', + "\x19\x01", DOMAIN_SEPARATOR, - keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline)) + keccak256( + abi.encode( + PERMIT_TYPEHASH, + owner, + spender, + value, + nonces[owner]++, + deadline + ) + ) ) ); address recoveredAddress = ecrecover(digest, v, r, s); - require(recoveredAddress != address(0) && recoveredAddress == owner, 'Pair: INVALID_SIGNATURE'); + require( + recoveredAddress != address(0) && recoveredAddress == owner, + "Pair: INVALID_SIGNATURE" + ); allowance[owner][spender] = value; emit Approval(owner, spender, value); } - function transfer(address dst, uint amount) external returns (bool) { + function transfer(address dst, uint256 amount) external returns (bool) { _transferTokens(msg.sender, dst, amount); return true; } - function transferFrom(address src, address dst, uint amount) external returns (bool) { + function transferFrom( + address src, + address dst, + uint256 amount + ) external returns (bool) { address spender = msg.sender; - uint spenderAllowance = allowance[src][spender]; + uint256 spenderAllowance = allowance[src][spender]; - if (spender != src && spenderAllowance != type(uint).max) { - uint newAllowance = spenderAllowance - amount; + if (spender != src && spenderAllowance != type(uint256).max) { + uint256 newAllowance = spenderAllowance - amount; allowance[src][spender] = newAllowance; emit Approval(src, spender, newAllowance); @@ -512,7 +728,11 @@ contract Pair is IPair { return true; } - function _transferTokens(address src, address dst, uint amount) internal { + function _transferTokens( + address src, + address dst, + uint256 amount + ) internal { _updateFor(src); // update fee position for src _updateFor(dst); // update fee position for dst @@ -522,10 +742,15 @@ contract Pair is IPair { emit Transfer(src, dst, amount); } - function _safeTransfer(address token,address to,uint256 value) internal { + function _safeTransfer( + address token, + address to, + uint256 value + ) internal { require(token.code.length > 0); - (bool success, bytes memory data) = - token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value)); + (bool success, bytes memory data) = token.call( + abi.encodeWithSelector(IERC20.transfer.selector, to, value) + ); require(success && (data.length == 0 || abi.decode(data, (bool)))); } } diff --git a/contracts/RewardsDistributor.sol b/contracts/RewardsDistributor.sol index 0ad5bac6..f742d719 100644 --- a/contracts/RewardsDistributor.sol +++ b/contracts/RewardsDistributor.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.13; -import 'contracts/libraries/Math.sol'; -import 'contracts/interfaces/IERC20.sol'; -import 'contracts/interfaces/IRewardsDistributor.sol'; -import 'contracts/interfaces/IVotingEscrow.sol'; +import "contracts/libraries/Math.sol"; +import "contracts/interfaces/IERC20.sol"; +import "contracts/interfaces/IRewardsDistributor.sol"; +import "contracts/interfaces/IVotingEscrow.sol"; /* @@ -15,39 +15,35 @@ import 'contracts/interfaces/IVotingEscrow.sol'; */ contract RewardsDistributor is IRewardsDistributor { - - event CheckpointToken( - uint time, - uint tokens - ); + event CheckpointToken(uint256 time, uint256 tokens); event Claimed( - uint tokenId, - uint amount, - uint claim_epoch, - uint max_epoch + uint256 tokenId, + uint256 amount, + uint256 claim_epoch, + uint256 max_epoch ); - uint constant WEEK = 7 * 86400; + uint256 constant WEEK = 7 * 86400; - uint public start_time; - uint public time_cursor; - mapping(uint => uint) public time_cursor_of; - mapping(uint => uint) public user_epoch_of; + uint256 public start_time; + uint256 public time_cursor; + mapping(uint256 => uint256) public time_cursor_of; + mapping(uint256 => uint256) public user_epoch_of; - uint public last_token_time; - uint[1000000000000000] public tokens_per_week; + uint256 public last_token_time; + uint256[1000000000000000] public tokens_per_week; address public voting_escrow; address public token; - uint public token_last_balance; + uint256 public token_last_balance; - uint[1000000000000000] public ve_supply; + uint256[1000000000000000] public ve_supply; address public depositor; constructor(address _voting_escrow) { - uint _t = block.timestamp / WEEK * WEEK; + uint256 _t = (block.timestamp / WEEK) * WEEK; start_time = _t; last_token_time = _t; time_cursor = _t; @@ -55,38 +51,42 @@ contract RewardsDistributor is IRewardsDistributor { token = _token; voting_escrow = _voting_escrow; depositor = msg.sender; - require(IERC20(_token).approve(_voting_escrow, type(uint).max)); + require(IERC20(_token).approve(_voting_escrow, type(uint256).max)); } - function timestamp() external view returns (uint) { - return block.timestamp / WEEK * WEEK; + function timestamp() external view returns (uint256) { + return (block.timestamp / WEEK) * WEEK; } function _checkpoint_token() internal { - uint token_balance = IERC20(token).balanceOf(address(this)); - uint to_distribute = token_balance - token_last_balance; + uint256 token_balance = IERC20(token).balanceOf(address(this)); + uint256 to_distribute = token_balance - token_last_balance; token_last_balance = token_balance; - uint t = last_token_time; - uint since_last = block.timestamp - t; + uint256 t = last_token_time; + uint256 since_last = block.timestamp - t; last_token_time = block.timestamp; - uint this_week = t / WEEK * WEEK; - uint next_week = 0; + uint256 this_week = (t / WEEK) * WEEK; + uint256 next_week = 0; - for (uint i = 0; i < 20; i++) { + for (uint256 i = 0; i < 20; i++) { next_week = this_week + WEEK; if (block.timestamp < next_week) { if (since_last == 0 && block.timestamp == t) { tokens_per_week[this_week] += to_distribute; } else { - tokens_per_week[this_week] += to_distribute * (block.timestamp - t) / since_last; + tokens_per_week[this_week] += + (to_distribute * (block.timestamp - t)) / + since_last; } break; } else { if (since_last == 0 && next_week == t) { tokens_per_week[this_week] += to_distribute; } else { - tokens_per_week[this_week] += to_distribute * (next_week - t) / since_last; + tokens_per_week[this_week] += + (to_distribute * (next_week - t)) / + since_last; } } t = next_week; @@ -100,13 +100,19 @@ contract RewardsDistributor is IRewardsDistributor { _checkpoint_token(); } - function _find_timestamp_epoch(address ve, uint _timestamp) internal view returns (uint) { - uint _min = 0; - uint _max = IVotingEscrow(ve).epoch(); - for (uint i = 0; i < 128; i++) { + function _find_timestamp_epoch(address ve, uint256 _timestamp) + internal + view + returns (uint256) + { + uint256 _min = 0; + uint256 _max = IVotingEscrow(ve).epoch(); + for (uint256 i = 0; i < 128; i++) { if (_min >= _max) break; - uint _mid = (_min + _max + 2) / 2; - IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(_mid); + uint256 _mid = (_min + _max + 2) / 2; + IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history( + _mid + ); if (pt.ts <= _timestamp) { _min = _mid; } else { @@ -116,47 +122,80 @@ contract RewardsDistributor is IRewardsDistributor { return _min; } - function _find_timestamp_user_epoch(address ve, uint tokenId, uint _timestamp, uint max_user_epoch) internal view returns (uint) { - uint _min = 0; - uint _max = max_user_epoch; - for (uint i = 0; i < 128; i++) { + function _find_timestamp_user_epoch( + address ve, + uint256 tokenId, + uint256 _timestamp, + uint256 max_user_epoch + ) internal view returns (uint256) { + uint256 _min = 0; + uint256 _max = max_user_epoch; + for (uint256 i = 0; i < 128; i++) { if (_min >= _max) break; - uint _mid = (_min + _max + 2) / 2; - IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(tokenId, _mid); + uint256 _mid = (_min + _max + 2) / 2; + IVotingEscrow.Point memory pt = IVotingEscrow(ve) + .user_point_history(tokenId, _mid); if (pt.ts <= _timestamp) { _min = _mid; } else { - _max = _mid -1; + _max = _mid - 1; } } return _min; } - function ve_for_at(uint _tokenId, uint _timestamp) external view returns (uint) { + function ve_for_at(uint256 _tokenId, uint256 _timestamp) + external + view + returns (uint256) + { address ve = voting_escrow; - uint max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId); - uint epoch = _find_timestamp_user_epoch(ve, _tokenId, _timestamp, max_user_epoch); - IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(_tokenId, epoch); - return Math.max(uint(int256(pt.bias - pt.slope * (int128(int256(_timestamp - pt.ts))))), 0); + uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId); + uint256 epoch = _find_timestamp_user_epoch( + ve, + _tokenId, + _timestamp, + max_user_epoch + ); + IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history( + _tokenId, + epoch + ); + return + MathDunks.max( + uint256( + int256( + pt.bias - + pt.slope * + (int128(int256(_timestamp - pt.ts))) + ) + ), + 0 + ); } function _checkpoint_total_supply() internal { address ve = voting_escrow; - uint t = time_cursor; - uint rounded_timestamp = block.timestamp / WEEK * WEEK; + uint256 t = time_cursor; + uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK; IVotingEscrow(ve).checkpoint(); - for (uint i = 0; i < 20; i++) { + for (uint256 i = 0; i < 20; i++) { if (t > rounded_timestamp) { break; } else { - uint epoch = _find_timestamp_epoch(ve, t); - IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(epoch); + uint256 epoch = _find_timestamp_epoch(ve, t); + IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history( + epoch + ); int128 dt = 0; if (t > pt.ts) { dt = int128(int256(t - pt.ts)); } - ve_supply[t] = Math.max(uint(int256(pt.bias - pt.slope * dt)), 0); + ve_supply[t] = MathDunks.max( + uint256(int256(pt.bias - pt.slope * dt)), + 0 + ); } t += WEEK; } @@ -167,55 +206,76 @@ contract RewardsDistributor is IRewardsDistributor { _checkpoint_total_supply(); } - function _claim(uint _tokenId, address ve, uint _last_token_time) internal returns (uint) { - uint user_epoch = 0; - uint to_distribute = 0; + function _claim( + uint256 _tokenId, + address ve, + uint256 _last_token_time + ) internal returns (uint256) { + uint256 user_epoch = 0; + uint256 to_distribute = 0; - uint max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId); - uint _start_time = start_time; + uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId); + uint256 _start_time = start_time; if (max_user_epoch == 0) return 0; - uint week_cursor = time_cursor_of[_tokenId]; + uint256 week_cursor = time_cursor_of[_tokenId]; if (week_cursor == 0) { - user_epoch = _find_timestamp_user_epoch(ve, _tokenId, _start_time, max_user_epoch); + user_epoch = _find_timestamp_user_epoch( + ve, + _tokenId, + _start_time, + max_user_epoch + ); } else { user_epoch = user_epoch_of[_tokenId]; } if (user_epoch == 0) user_epoch = 1; - IVotingEscrow.Point memory user_point = IVotingEscrow(ve).user_point_history(_tokenId, user_epoch); + IVotingEscrow.Point memory user_point = IVotingEscrow(ve) + .user_point_history(_tokenId, user_epoch); - if (week_cursor == 0) week_cursor = (user_point.ts + WEEK - 1) / WEEK * WEEK; + if (week_cursor == 0) + week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK; if (week_cursor >= last_token_time) return 0; if (week_cursor < _start_time) week_cursor = _start_time; IVotingEscrow.Point memory old_user_point; - for (uint i = 0; i < 50; i++) { + for (uint256 i = 0; i < 50; i++) { if (week_cursor >= _last_token_time) break; if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) { user_epoch += 1; old_user_point = user_point; if (user_epoch > max_user_epoch) { - user_point = IVotingEscrow.Point(0,0,0,0); + user_point = IVotingEscrow.Point(0, 0, 0, 0); } else { - user_point = IVotingEscrow(ve).user_point_history(_tokenId, user_epoch); + user_point = IVotingEscrow(ve).user_point_history( + _tokenId, + user_epoch + ); } } else { int128 dt = int128(int256(week_cursor - old_user_point.ts)); - uint balance_of = Math.max(uint(int256(old_user_point.bias - dt * old_user_point.slope)), 0); + uint256 balance_of = MathDunks.max( + uint256( + int256(old_user_point.bias - dt * old_user_point.slope) + ), + 0 + ); if (balance_of == 0 && user_epoch > max_user_epoch) break; if (balance_of != 0) { - to_distribute += balance_of * tokens_per_week[week_cursor] / ve_supply[week_cursor]; + to_distribute += + (balance_of * tokens_per_week[week_cursor]) / + ve_supply[week_cursor]; } week_cursor += WEEK; } } - user_epoch = Math.min(max_user_epoch, user_epoch - 1); + user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1); user_epoch_of[_tokenId] = user_epoch; time_cursor_of[_tokenId] = week_cursor; @@ -224,49 +284,70 @@ contract RewardsDistributor is IRewardsDistributor { return to_distribute; } - function _claimable(uint _tokenId, address ve, uint _last_token_time) internal view returns (uint) { - uint user_epoch = 0; - uint to_distribute = 0; + function _claimable( + uint256 _tokenId, + address ve, + uint256 _last_token_time + ) internal view returns (uint256) { + uint256 user_epoch = 0; + uint256 to_distribute = 0; - uint max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId); - uint _start_time = start_time; + uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId); + uint256 _start_time = start_time; if (max_user_epoch == 0) return 0; - uint week_cursor = time_cursor_of[_tokenId]; + uint256 week_cursor = time_cursor_of[_tokenId]; if (week_cursor == 0) { - user_epoch = _find_timestamp_user_epoch(ve, _tokenId, _start_time, max_user_epoch); + user_epoch = _find_timestamp_user_epoch( + ve, + _tokenId, + _start_time, + max_user_epoch + ); } else { user_epoch = user_epoch_of[_tokenId]; } if (user_epoch == 0) user_epoch = 1; - IVotingEscrow.Point memory user_point = IVotingEscrow(ve).user_point_history(_tokenId, user_epoch); + IVotingEscrow.Point memory user_point = IVotingEscrow(ve) + .user_point_history(_tokenId, user_epoch); - if (week_cursor == 0) week_cursor = (user_point.ts + WEEK - 1) / WEEK * WEEK; + if (week_cursor == 0) + week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK; if (week_cursor >= last_token_time) return 0; if (week_cursor < _start_time) week_cursor = _start_time; IVotingEscrow.Point memory old_user_point; - for (uint i = 0; i < 50; i++) { + for (uint256 i = 0; i < 50; i++) { if (week_cursor >= _last_token_time) break; if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) { user_epoch += 1; old_user_point = user_point; if (user_epoch > max_user_epoch) { - user_point = IVotingEscrow.Point(0,0,0,0); + user_point = IVotingEscrow.Point(0, 0, 0, 0); } else { - user_point = IVotingEscrow(ve).user_point_history(_tokenId, user_epoch); + user_point = IVotingEscrow(ve).user_point_history( + _tokenId, + user_epoch + ); } } else { int128 dt = int128(int256(week_cursor - old_user_point.ts)); - uint balance_of = Math.max(uint(int256(old_user_point.bias - dt * old_user_point.slope)), 0); + uint256 balance_of = MathDunks.max( + uint256( + int256(old_user_point.bias - dt * old_user_point.slope) + ), + 0 + ); if (balance_of == 0 && user_epoch > max_user_epoch) break; if (balance_of != 0) { - to_distribute += balance_of * tokens_per_week[week_cursor] / ve_supply[week_cursor]; + to_distribute += + (balance_of * tokens_per_week[week_cursor]) / + ve_supply[week_cursor]; } week_cursor += WEEK; } @@ -275,16 +356,16 @@ contract RewardsDistributor is IRewardsDistributor { return to_distribute; } - function claimable(uint _tokenId) external view returns (uint) { - uint _last_token_time = last_token_time / WEEK * WEEK; + function claimable(uint256 _tokenId) external view returns (uint256) { + uint256 _last_token_time = (last_token_time / WEEK) * WEEK; return _claimable(_tokenId, voting_escrow, _last_token_time); } - function claim(uint _tokenId) external returns (uint) { + function claim(uint256 _tokenId) external returns (uint256) { if (block.timestamp >= time_cursor) _checkpoint_total_supply(); - uint _last_token_time = last_token_time; - _last_token_time = _last_token_time / WEEK * WEEK; - uint amount = _claim(_tokenId, voting_escrow, _last_token_time); + uint256 _last_token_time = last_token_time; + _last_token_time = (_last_token_time / WEEK) * WEEK; + uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time); if (amount != 0) { IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount); token_last_balance -= amount; @@ -292,17 +373,17 @@ contract RewardsDistributor is IRewardsDistributor { return amount; } - function claim_many(uint[] memory _tokenIds) external returns (bool) { + function claim_many(uint256[] memory _tokenIds) external returns (bool) { if (block.timestamp >= time_cursor) _checkpoint_total_supply(); - uint _last_token_time = last_token_time; - _last_token_time = _last_token_time / WEEK * WEEK; + uint256 _last_token_time = last_token_time; + _last_token_time = (_last_token_time / WEEK) * WEEK; address _voting_escrow = voting_escrow; - uint total = 0; + uint256 total = 0; - for (uint i = 0; i < _tokenIds.length; i++) { - uint _tokenId = _tokenIds[i]; + for (uint256 i = 0; i < _tokenIds.length; i++) { + uint256 _tokenId = _tokenIds[i]; if (_tokenId == 0) break; - uint amount = _claim(_tokenId, _voting_escrow, _last_token_time); + uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time); if (amount != 0) { IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount); total += amount; diff --git a/contracts/Router.sol b/contracts/Router.sol index c6866d27..d9b616b6 100644 --- a/contracts/Router.sol +++ b/contracts/Router.sol @@ -2,15 +2,14 @@ pragma solidity 0.8.13; -import 'contracts/libraries/Math.sol'; -import 'contracts/interfaces/IERC20.sol'; -import 'contracts/interfaces/IPair.sol'; -import 'contracts/interfaces/IPairFactory.sol'; -import 'contracts/interfaces/IRouter.sol'; -import 'contracts/interfaces/IWETH.sol'; +import "contracts/libraries/Math.sol"; +import "contracts/interfaces/IERC20.sol"; +import "contracts/interfaces/IPair.sol"; +import "contracts/interfaces/IPairFactory.sol"; +import "contracts/interfaces/IRouter.sol"; +import "contracts/interfaces/IWETH.sol"; contract Router is IRouter { - struct route { address from; address to; @@ -19,11 +18,11 @@ contract Router is IRouter { address public immutable factory; IWETH public immutable weth; - uint internal constant MINIMUM_LIQUIDITY = 10**3; + uint256 internal constant MINIMUM_LIQUIDITY = 10**3; bytes32 immutable pairCodeHash; - modifier ensure(uint deadline) { - require(deadline >= block.timestamp, 'Router: EXPIRED'); + modifier ensure(uint256 deadline) { + require(deadline >= block.timestamp, "Router: EXPIRED"); _; } @@ -37,42 +36,76 @@ contract Router is IRouter { assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract } - function sortTokens(address tokenA, address tokenB) public pure returns (address token0, address token1) { - require(tokenA != tokenB, 'Router: IDENTICAL_ADDRESSES'); - (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); - require(token0 != address(0), 'Router: ZERO_ADDRESS'); + function sortTokens(address tokenA, address tokenB) + public + pure + returns (address token0, address token1) + { + require(tokenA != tokenB, "Router: IDENTICAL_ADDRESSES"); + (token0, token1) = tokenA < tokenB + ? (tokenA, tokenB) + : (tokenB, tokenA); + require(token0 != address(0), "Router: ZERO_ADDRESS"); } // calculates the CREATE2 address for a pair without making any external calls - function pairFor(address tokenA, address tokenB, bool stable) public view returns (address pair) { + function pairFor( + address tokenA, + address tokenB, + bool stable + ) public view returns (address pair) { (address token0, address token1) = sortTokens(tokenA, tokenB); - pair = address(uint160(uint256(keccak256(abi.encodePacked( - hex'ff', - factory, - keccak256(abi.encodePacked(token0, token1, stable)), - pairCodeHash // init code hash - ))))); + pair = address( + uint160( + uint256( + keccak256( + abi.encodePacked( + hex"ff", + factory, + keccak256(abi.encodePacked(token0, token1, stable)), + pairCodeHash // init code hash + ) + ) + ) + ) + ); } // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset - function quoteLiquidity(uint amountA, uint reserveA, uint reserveB) internal pure returns (uint amountB) { - require(amountA > 0, 'Router: INSUFFICIENT_AMOUNT'); - require(reserveA > 0 && reserveB > 0, 'Router: INSUFFICIENT_LIQUIDITY'); - amountB = amountA * reserveB / reserveA; + function quoteLiquidity( + uint256 amountA, + uint256 reserveA, + uint256 reserveB + ) internal pure returns (uint256 amountB) { + require(amountA > 0, "Router: INSUFFICIENT_AMOUNT"); + require(reserveA > 0 && reserveB > 0, "Router: INSUFFICIENT_LIQUIDITY"); + amountB = (amountA * reserveB) / reserveA; } // fetches and sorts the reserves for a pair - function getReserves(address tokenA, address tokenB, bool stable) public view returns (uint reserveA, uint reserveB) { - (address token0,) = sortTokens(tokenA, tokenB); - (uint reserve0, uint reserve1,) = IPair(pairFor(tokenA, tokenB, stable)).getReserves(); - (reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0); + function getReserves( + address tokenA, + address tokenB, + bool stable + ) public view returns (uint256 reserveA, uint256 reserveB) { + (address token0, ) = sortTokens(tokenA, tokenB); + (uint256 reserve0, uint256 reserve1, ) = IPair( + pairFor(tokenA, tokenB, stable) + ).getReserves(); + (reserveA, reserveB) = tokenA == token0 + ? (reserve0, reserve1) + : (reserve1, reserve0); } // performs chained getAmountOut calculations on any number of pairs - function getAmountOut(uint amountIn, address tokenIn, address tokenOut) external view returns (uint amount, bool stable) { + function getAmountOut( + uint256 amountIn, + address tokenIn, + address tokenOut + ) external view returns (uint256 amount, bool stable) { address pair = pairFor(tokenIn, tokenOut, true); - uint amountStable; - uint amountVolatile; + uint256 amountStable; + uint256 amountVolatile; if (IPairFactory(factory).isPair(pair)) { amountStable = IPair(pair).getAmountOut(amountIn, tokenIn); } @@ -80,18 +113,32 @@ contract Router is IRouter { if (IPairFactory(factory).isPair(pair)) { amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn); } - return amountStable > amountVolatile ? (amountStable, true) : (amountVolatile, false); + return + amountStable > amountVolatile + ? (amountStable, true) + : (amountVolatile, false); } // performs chained getAmountOut calculations on any number of pairs - function getAmountsOut(uint amountIn, route[] memory routes) public view returns (uint[] memory amounts) { - require(routes.length >= 1, 'Router: INVALID_PATH'); - amounts = new uint[](routes.length+1); + function getAmountsOut(uint256 amountIn, route[] memory routes) + public + view + returns (uint256[] memory amounts) + { + require(routes.length >= 1, "Router: INVALID_PATH"); + amounts = new uint256[](routes.length + 1); amounts[0] = amountIn; - for (uint i = 0; i < routes.length; i++) { - address pair = pairFor(routes[i].from, routes[i].to, routes[i].stable); + for (uint256 i = 0; i < routes.length; i++) { + address pair = pairFor( + routes[i].from, + routes[i].to, + routes[i].stable + ); if (IPairFactory(factory).isPair(pair)) { - amounts[i+1] = IPair(pair).getAmountOut(amounts[i], routes[i].from); + amounts[i + 1] = IPair(pair).getAmountOut( + amounts[i], + routes[i].from + ); } } } @@ -104,30 +151,51 @@ contract Router is IRouter { address tokenA, address tokenB, bool stable, - uint amountADesired, - uint amountBDesired - ) external view returns (uint amountA, uint amountB, uint liquidity) { + uint256 amountADesired, + uint256 amountBDesired + ) + external + view + returns ( + uint256 amountA, + uint256 amountB, + uint256 liquidity + ) + { // create the pair if it doesn't exist yet address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable); - (uint reserveA, uint reserveB) = (0,0); - uint _totalSupply = 0; + (uint256 reserveA, uint256 reserveB) = (0, 0); + uint256 _totalSupply = 0; if (_pair != address(0)) { _totalSupply = IERC20(_pair).totalSupply(); (reserveA, reserveB) = getReserves(tokenA, tokenB, stable); } if (reserveA == 0 && reserveB == 0) { (amountA, amountB) = (amountADesired, amountBDesired); - liquidity = Math.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY; + liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY; } else { - - uint amountBOptimal = quoteLiquidity(amountADesired, reserveA, reserveB); + uint256 amountBOptimal = quoteLiquidity( + amountADesired, + reserveA, + reserveB + ); if (amountBOptimal <= amountBDesired) { (amountA, amountB) = (amountADesired, amountBOptimal); - liquidity = Math.min(amountA * _totalSupply / reserveA, amountB * _totalSupply / reserveB); + liquidity = MathDunks.min( + (amountA * _totalSupply) / reserveA, + (amountB * _totalSupply) / reserveB + ); } else { - uint amountAOptimal = quoteLiquidity(amountBDesired, reserveB, reserveA); + uint256 amountAOptimal = quoteLiquidity( + amountBDesired, + reserveB, + reserveA + ); (amountA, amountB) = (amountAOptimal, amountBDesired); - liquidity = Math.min(amountA * _totalSupply / reserveA, amountB * _totalSupply / reserveB); + liquidity = MathDunks.min( + (amountA * _totalSupply) / reserveA, + (amountB * _totalSupply) / reserveB + ); } } } @@ -136,32 +204,35 @@ contract Router is IRouter { address tokenA, address tokenB, bool stable, - uint liquidity - ) external view returns (uint amountA, uint amountB) { + uint256 liquidity + ) external view returns (uint256 amountA, uint256 amountB) { // create the pair if it doesn't exist yet address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable); if (_pair == address(0)) { - return (0,0); + return (0, 0); } - (uint reserveA, uint reserveB) = getReserves(tokenA, tokenB, stable); - uint _totalSupply = IERC20(_pair).totalSupply(); - - amountA = liquidity * reserveA / _totalSupply; // using balances ensures pro-rata distribution - amountB = liquidity * reserveB / _totalSupply; // using balances ensures pro-rata distribution + (uint256 reserveA, uint256 reserveB) = getReserves( + tokenA, + tokenB, + stable + ); + uint256 _totalSupply = IERC20(_pair).totalSupply(); + amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution + amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution } function _addLiquidity( address tokenA, address tokenB, bool stable, - uint amountADesired, - uint amountBDesired, - uint amountAMin, - uint amountBMin - ) internal returns (uint amountA, uint amountB) { + uint256 amountADesired, + uint256 amountBDesired, + uint256 amountAMin, + uint256 amountBMin + ) internal returns (uint256 amountA, uint256 amountB) { require(amountADesired >= amountAMin); require(amountBDesired >= amountBMin); // create the pair if it doesn't exist yet @@ -169,18 +240,36 @@ contract Router is IRouter { if (_pair == address(0)) { _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable); } - (uint reserveA, uint reserveB) = getReserves(tokenA, tokenB, stable); + (uint256 reserveA, uint256 reserveB) = getReserves( + tokenA, + tokenB, + stable + ); if (reserveA == 0 && reserveB == 0) { (amountA, amountB) = (amountADesired, amountBDesired); } else { - uint amountBOptimal = quoteLiquidity(amountADesired, reserveA, reserveB); + uint256 amountBOptimal = quoteLiquidity( + amountADesired, + reserveA, + reserveB + ); if (amountBOptimal <= amountBDesired) { - require(amountBOptimal >= amountBMin, 'Router: INSUFFICIENT_B_AMOUNT'); + require( + amountBOptimal >= amountBMin, + "Router: INSUFFICIENT_B_AMOUNT" + ); (amountA, amountB) = (amountADesired, amountBOptimal); } else { - uint amountAOptimal = quoteLiquidity(amountBDesired, reserveB, reserveA); + uint256 amountAOptimal = quoteLiquidity( + amountBDesired, + reserveB, + reserveA + ); assert(amountAOptimal <= amountADesired); - require(amountAOptimal >= amountAMin, 'Router: INSUFFICIENT_A_AMOUNT'); + require( + amountAOptimal >= amountAMin, + "Router: INSUFFICIENT_A_AMOUNT" + ); (amountA, amountB) = (amountAOptimal, amountBDesired); } } @@ -190,14 +279,30 @@ contract Router is IRouter { address tokenA, address tokenB, bool stable, - uint amountADesired, - uint amountBDesired, - uint amountAMin, - uint amountBMin, + uint256 amountADesired, + uint256 amountBDesired, + uint256 amountAMin, + uint256 amountBMin, address to, - uint deadline - ) external ensure(deadline) returns (uint amountA, uint amountB, uint liquidity) { - (amountA, amountB) = _addLiquidity(tokenA, tokenB, stable, amountADesired, amountBDesired, amountAMin, amountBMin); + uint256 deadline + ) + external + ensure(deadline) + returns ( + uint256 amountA, + uint256 amountB, + uint256 liquidity + ) + { + (amountA, amountB) = _addLiquidity( + tokenA, + tokenB, + stable, + amountADesired, + amountBDesired, + amountAMin, + amountBMin + ); address pair = pairFor(tokenA, tokenB, stable); _safeTransferFrom(tokenA, msg.sender, pair, amountA); _safeTransferFrom(tokenB, msg.sender, pair, amountB); @@ -207,12 +312,21 @@ contract Router is IRouter { function addLiquidityETH( address token, bool stable, - uint amountTokenDesired, - uint amountTokenMin, - uint amountETHMin, + uint256 amountTokenDesired, + uint256 amountTokenMin, + uint256 amountETHMin, address to, - uint deadline - ) external payable ensure(deadline) returns (uint amountToken, uint amountETH, uint liquidity) { + uint256 deadline + ) + external + payable + ensure(deadline) + returns ( + uint256 amountToken, + uint256 amountETH, + uint256 liquidity + ) + { (amountToken, amountETH) = _addLiquidity( token, address(weth), @@ -228,7 +342,8 @@ contract Router is IRouter { assert(weth.transfer(pair, amountETH)); liquidity = IPair(pair).mint(to); // refund dust eth, if any - if (msg.value > amountETH) _safeTransferETH(msg.sender, msg.value - amountETH); + if (msg.value > amountETH) + _safeTransferETH(msg.sender, msg.value - amountETH); } // **** REMOVE LIQUIDITY **** @@ -236,30 +351,32 @@ contract Router is IRouter { address tokenA, address tokenB, bool stable, - uint liquidity, - uint amountAMin, - uint amountBMin, + uint256 liquidity, + uint256 amountAMin, + uint256 amountBMin, address to, - uint deadline - ) public ensure(deadline) returns (uint amountA, uint amountB) { + uint256 deadline + ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) { address pair = pairFor(tokenA, tokenB, stable); require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair - (uint amount0, uint amount1) = IPair(pair).burn(to); - (address token0,) = sortTokens(tokenA, tokenB); - (amountA, amountB) = tokenA == token0 ? (amount0, amount1) : (amount1, amount0); - require(amountA >= amountAMin, 'Router: INSUFFICIENT_A_AMOUNT'); - require(amountB >= amountBMin, 'Router: INSUFFICIENT_B_AMOUNT'); + (uint256 amount0, uint256 amount1) = IPair(pair).burn(to); + (address token0, ) = sortTokens(tokenA, tokenB); + (amountA, amountB) = tokenA == token0 + ? (amount0, amount1) + : (amount1, amount0); + require(amountA >= amountAMin, "Router: INSUFFICIENT_A_AMOUNT"); + require(amountB >= amountBMin, "Router: INSUFFICIENT_B_AMOUNT"); } function removeLiquidityETH( address token, bool stable, - uint liquidity, - uint amountTokenMin, - uint amountETHMin, + uint256 liquidity, + uint256 amountTokenMin, + uint256 amountETHMin, address to, - uint deadline - ) public ensure(deadline) returns (uint amountToken, uint amountETH) { + uint256 deadline + ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) { (amountToken, amountETH) = removeLiquidity( token, address(weth), @@ -279,112 +396,189 @@ contract Router is IRouter { address tokenA, address tokenB, bool stable, - uint liquidity, - uint amountAMin, - uint amountBMin, + uint256 liquidity, + uint256 amountAMin, + uint256 amountBMin, address to, - uint deadline, - bool approveMax, uint8 v, bytes32 r, bytes32 s - ) external returns (uint amountA, uint amountB) { + uint256 deadline, + bool approveMax, + uint8 v, + bytes32 r, + bytes32 s + ) external returns (uint256 amountA, uint256 amountB) { address pair = pairFor(tokenA, tokenB, stable); { - uint value = approveMax ? type(uint).max : liquidity; - IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s); + uint256 value = approveMax ? type(uint256).max : liquidity; + IPair(pair).permit( + msg.sender, + address(this), + value, + deadline, + v, + r, + s + ); } - (amountA, amountB) = removeLiquidity(tokenA, tokenB, stable, liquidity, amountAMin, amountBMin, to, deadline); + (amountA, amountB) = removeLiquidity( + tokenA, + tokenB, + stable, + liquidity, + amountAMin, + amountBMin, + to, + deadline + ); } function removeLiquidityETHWithPermit( address token, bool stable, - uint liquidity, - uint amountTokenMin, - uint amountETHMin, + uint256 liquidity, + uint256 amountTokenMin, + uint256 amountETHMin, address to, - uint deadline, - bool approveMax, uint8 v, bytes32 r, bytes32 s - ) external returns (uint amountToken, uint amountETH) { + uint256 deadline, + bool approveMax, + uint8 v, + bytes32 r, + bytes32 s + ) external returns (uint256 amountToken, uint256 amountETH) { address pair = pairFor(token, address(weth), stable); - uint value = approveMax ? type(uint).max : liquidity; + uint256 value = approveMax ? type(uint256).max : liquidity; IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s); - (amountToken, amountETH) = removeLiquidityETH(token, stable, liquidity, amountTokenMin, amountETHMin, to, deadline); + (amountToken, amountETH) = removeLiquidityETH( + token, + stable, + liquidity, + amountTokenMin, + amountETHMin, + to, + deadline + ); } // **** SWAP **** // requires the initial amount to have already been sent to the first pair - function _swap(uint[] memory amounts, route[] memory routes, address _to) internal virtual { - for (uint i = 0; i < routes.length; i++) { - (address token0,) = sortTokens(routes[i].from, routes[i].to); - uint amountOut = amounts[i + 1]; - (uint amount0Out, uint amount1Out) = routes[i].from == token0 ? (uint(0), amountOut) : (amountOut, uint(0)); - address to = i < routes.length - 1 ? pairFor(routes[i+1].from, routes[i+1].to, routes[i+1].stable) : _to; + function _swap( + uint256[] memory amounts, + route[] memory routes, + address _to + ) internal virtual { + for (uint256 i = 0; i < routes.length; i++) { + (address token0, ) = sortTokens(routes[i].from, routes[i].to); + uint256 amountOut = amounts[i + 1]; + (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0 + ? (uint256(0), amountOut) + : (amountOut, uint256(0)); + address to = i < routes.length - 1 + ? pairFor( + routes[i + 1].from, + routes[i + 1].to, + routes[i + 1].stable + ) + : _to; IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap( - amount0Out, amount1Out, to, new bytes(0) - ); + amount0Out, + amount1Out, + to, + new bytes(0) + ); } } function swapExactTokensForTokensSimple( - uint amountIn, - uint amountOutMin, + uint256 amountIn, + uint256 amountOutMin, address tokenFrom, address tokenTo, bool stable, address to, - uint deadline - ) external ensure(deadline) returns (uint[] memory amounts) { + uint256 deadline + ) external ensure(deadline) returns (uint256[] memory amounts) { route[] memory routes = new route[](1); routes[0].from = tokenFrom; routes[0].to = tokenTo; routes[0].stable = stable; amounts = getAmountsOut(amountIn, routes); - require(amounts[amounts.length - 1] >= amountOutMin, 'Router: INSUFFICIENT_OUTPUT_AMOUNT'); + require( + amounts[amounts.length - 1] >= amountOutMin, + "Router: INSUFFICIENT_OUTPUT_AMOUNT" + ); _safeTransferFrom( - routes[0].from, msg.sender, pairFor(routes[0].from, routes[0].to, routes[0].stable), amounts[0] + routes[0].from, + msg.sender, + pairFor(routes[0].from, routes[0].to, routes[0].stable), + amounts[0] ); _swap(amounts, routes, to); } function swapExactTokensForTokens( - uint amountIn, - uint amountOutMin, + uint256 amountIn, + uint256 amountOutMin, route[] calldata routes, address to, - uint deadline - ) external ensure(deadline) returns (uint[] memory amounts) { + uint256 deadline + ) external ensure(deadline) returns (uint256[] memory amounts) { amounts = getAmountsOut(amountIn, routes); - require(amounts[amounts.length - 1] >= amountOutMin, 'Router: INSUFFICIENT_OUTPUT_AMOUNT'); + require( + amounts[amounts.length - 1] >= amountOutMin, + "Router: INSUFFICIENT_OUTPUT_AMOUNT" + ); _safeTransferFrom( - routes[0].from, msg.sender, pairFor(routes[0].from, routes[0].to, routes[0].stable), amounts[0] + routes[0].from, + msg.sender, + pairFor(routes[0].from, routes[0].to, routes[0].stable), + amounts[0] ); _swap(amounts, routes, to); } - function swapExactETHForTokens(uint amountOutMin, route[] calldata routes, address to, uint deadline) - external - payable - ensure(deadline) - returns (uint[] memory amounts) - { - require(routes[0].from == address(weth), 'Router: INVALID_PATH'); + function swapExactETHForTokens( + uint256 amountOutMin, + route[] calldata routes, + address to, + uint256 deadline + ) external payable ensure(deadline) returns (uint256[] memory amounts) { + require(routes[0].from == address(weth), "Router: INVALID_PATH"); amounts = getAmountsOut(msg.value, routes); - require(amounts[amounts.length - 1] >= amountOutMin, 'Router: INSUFFICIENT_OUTPUT_AMOUNT'); + require( + amounts[amounts.length - 1] >= amountOutMin, + "Router: INSUFFICIENT_OUTPUT_AMOUNT" + ); weth.deposit{value: amounts[0]}(); - assert(weth.transfer(pairFor(routes[0].from, routes[0].to, routes[0].stable), amounts[0])); + assert( + weth.transfer( + pairFor(routes[0].from, routes[0].to, routes[0].stable), + amounts[0] + ) + ); _swap(amounts, routes, to); } - function swapExactTokensForETH(uint amountIn, uint amountOutMin, route[] calldata routes, address to, uint deadline) - external - ensure(deadline) - returns (uint[] memory amounts) - { - require(routes[routes.length - 1].to == address(weth), 'Router: INVALID_PATH'); + function swapExactTokensForETH( + uint256 amountIn, + uint256 amountOutMin, + route[] calldata routes, + address to, + uint256 deadline + ) external ensure(deadline) returns (uint256[] memory amounts) { + require( + routes[routes.length - 1].to == address(weth), + "Router: INVALID_PATH" + ); amounts = getAmountsOut(amountIn, routes); - require(amounts[amounts.length - 1] >= amountOutMin, 'Router: INSUFFICIENT_OUTPUT_AMOUNT'); + require( + amounts[amounts.length - 1] >= amountOutMin, + "Router: INSUFFICIENT_OUTPUT_AMOUNT" + ); _safeTransferFrom( - routes[0].from, msg.sender, pairFor(routes[0].from, routes[0].to, routes[0].stable), amounts[0] + routes[0].from, + msg.sender, + pairFor(routes[0].from, routes[0].to, routes[0].stable), + amounts[0] ); _swap(amounts, routes, address(this)); weth.withdraw(amounts[amounts.length - 1]); @@ -392,32 +586,53 @@ contract Router is IRouter { } function UNSAFE_swapExactTokensForTokens( - uint[] memory amounts, + uint256[] memory amounts, route[] calldata routes, address to, - uint deadline - ) external ensure(deadline) returns (uint[] memory) { - _safeTransferFrom(routes[0].from, msg.sender, pairFor(routes[0].from, routes[0].to, routes[0].stable), amounts[0]); + uint256 deadline + ) external ensure(deadline) returns (uint256[] memory) { + _safeTransferFrom( + routes[0].from, + msg.sender, + pairFor(routes[0].from, routes[0].to, routes[0].stable), + amounts[0] + ); _swap(amounts, routes, to); return amounts; } - function _safeTransferETH(address to, uint value) internal { - (bool success,) = to.call{value:value}(new bytes(0)); - require(success, 'TransferHelper: ETH_TRANSFER_FAILED'); + function _safeTransferETH(address to, uint256 value) internal { + (bool success, ) = to.call{value: value}(new bytes(0)); + require(success, "TransferHelper: ETH_TRANSFER_FAILED"); } - function _safeTransfer(address token, address to, uint256 value) internal { + function _safeTransfer( + address token, + address to, + uint256 value + ) internal { require(token.code.length > 0); - (bool success, bytes memory data) = - token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value)); + (bool success, bytes memory data) = token.call( + abi.encodeWithSelector(IERC20.transfer.selector, to, value) + ); require(success && (data.length == 0 || abi.decode(data, (bool)))); } - function _safeTransferFrom(address token, address from, address to, uint256 value) internal { + function _safeTransferFrom( + address token, + address from, + address to, + uint256 value + ) internal { require(token.code.length > 0); - (bool success, bytes memory data) = - token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value)); + (bool success, bytes memory data) = token.call( + abi.encodeWithSelector( + IERC20.transferFrom.selector, + from, + to, + value + ) + ); require(success && (data.length == 0 || abi.decode(data, (bool)))); } } diff --git a/contracts/WrappedExternalBribe.sol b/contracts/WrappedExternalBribe.sol index 9017f9a3..4df09a08 100644 --- a/contracts/WrappedExternalBribe.sol +++ b/contracts/WrappedExternalBribe.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.13; -import 'contracts/libraries/Math.sol'; -import 'contracts/ExternalBribe.sol'; -import 'contracts/interfaces/IERC20.sol'; -import 'contracts/interfaces/IGauge.sol'; -import 'contracts/interfaces/IVoter.sol'; -import 'contracts/interfaces/IVotingEscrow.sol'; +import "contracts/libraries/Math.sol"; +import "contracts/ExternalBribe.sol"; +import "contracts/interfaces/IERC20.sol"; +import "contracts/interfaces/IGauge.sol"; +import "contracts/interfaces/IVoter.sol"; +import "contracts/interfaces/IVotingEscrow.sol"; // Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote()) contract WrappedExternalBribe { @@ -14,33 +14,42 @@ contract WrappedExternalBribe { address public immutable _ve; ExternalBribe public underlying_bribe; - uint internal constant DURATION = 7 days; // rewards are released over the voting period - uint internal constant MAX_REWARD_TOKENS = 16; + uint256 internal constant DURATION = 7 days; // rewards are released over the voting period + uint256 internal constant MAX_REWARD_TOKENS = 16; - uint internal constant PRECISION = 10 ** 18; + uint256 internal constant PRECISION = 10**18; - mapping(address => mapping(uint => uint)) public tokenRewardsPerEpoch; - mapping(address => uint) public periodFinish; - mapping(address => mapping(uint => uint)) public lastEarn; + mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch; + mapping(address => uint256) public periodFinish; + mapping(address => mapping(uint256 => uint256)) public lastEarn; address[] public rewards; mapping(address => bool) public isReward; /// @notice A checkpoint for marking balance struct RewardCheckpoint { - uint timestamp; - uint balance; + uint256 timestamp; + uint256 balance; } - event NotifyReward(address indexed from, address indexed reward, uint epoch, uint amount); - event ClaimRewards(address indexed from, address indexed reward, uint amount); + event NotifyReward( + address indexed from, + address indexed reward, + uint256 epoch, + uint256 amount + ); + event ClaimRewards( + address indexed from, + address indexed reward, + uint256 amount + ); constructor(address _voter, address _old_bribe) { voter = _voter; _ve = IVoter(_voter)._ve(); underlying_bribe = ExternalBribe(_old_bribe); - for (uint i; i < underlying_bribe.rewardsListLength(); i++) { + for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) { address underlying_reward = underlying_bribe.rewards(i); if (underlying_reward != address(0)) { isReward[underlying_reward] = true; @@ -50,7 +59,7 @@ contract WrappedExternalBribe { } // simple re-entrancy check - uint internal _unlocked = 1; + uint256 internal _unlocked = 1; modifier lock() { require(_unlocked == 1); _unlocked = 2; @@ -58,30 +67,34 @@ contract WrappedExternalBribe { _unlocked = 1; } - function _bribeStart(uint timestamp) internal pure returns (uint) { + function _bribeStart(uint256 timestamp) internal pure returns (uint256) { return timestamp - (timestamp % (7 days)); } - function getEpochStart(uint timestamp) public pure returns (uint) { - uint bribeStart = _bribeStart(timestamp); - uint bribeEnd = bribeStart + DURATION; + function getEpochStart(uint256 timestamp) public pure returns (uint256) { + uint256 bribeStart = _bribeStart(timestamp); + uint256 bribeEnd = bribeStart + DURATION; return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days; } - function rewardsListLength() external view returns (uint) { + function rewardsListLength() external view returns (uint256) { return rewards.length; } // returns the last time the reward was modified or periodFinish if the reward has ended - function lastTimeRewardApplicable(address token) public view returns (uint) { - return Math.min(block.timestamp, periodFinish[token]); + function lastTimeRewardApplicable(address token) + public + view + returns (uint256) + { + return MathDunks.min(block.timestamp, periodFinish[token]); } // allows a user to claim rewards for a given token - function getReward(uint tokenId, address[] memory tokens) external lock { + function getReward(uint256 tokenId, address[] memory tokens) external lock { require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId)); - for (uint i = 0; i < tokens.length; i++) { - uint _reward = earned(tokens[i], tokenId); + for (uint256 i = 0; i < tokens.length; i++) { + uint256 _reward = earned(tokens[i], tokenId); lastEarn[tokens[i]][tokenId] = block.timestamp; if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward); @@ -90,11 +103,14 @@ contract WrappedExternalBribe { } // used by Voter to allow batched reward claims - function getRewardForOwner(uint tokenId, address[] memory tokens) external lock { + function getRewardForOwner(uint256 tokenId, address[] memory tokens) + external + lock + { require(msg.sender == voter); address _owner = IVotingEscrow(_ve).ownerOf(tokenId); - for (uint i = 0; i < tokens.length; i++) { - uint _reward = earned(tokens[i], tokenId); + for (uint256 i = 0; i < tokens.length; i++) { + uint256 _reward = earned(tokens[i], tokenId); lastEarn[tokens[i]][tokenId] = block.timestamp; if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward); @@ -102,66 +118,90 @@ contract WrappedExternalBribe { } } - function earned(address token, uint tokenId) public view returns (uint) { - uint _startTimestamp = lastEarn[token][tokenId]; + function earned(address token, uint256 tokenId) + public + view + returns (uint256) + { + uint256 _startTimestamp = lastEarn[token][tokenId]; if (underlying_bribe.numCheckpoints(tokenId) == 0) { return 0; } - uint _startIndex = underlying_bribe.getPriorBalanceIndex(tokenId, _startTimestamp); - uint _endIndex = underlying_bribe.numCheckpoints(tokenId)-1; + uint256 _startIndex = underlying_bribe.getPriorBalanceIndex( + tokenId, + _startTimestamp + ); + uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1; - uint reward = 0; + uint256 reward = 0; // you only earn once per epoch (after it's over) RewardCheckpoint memory prevRewards; prevRewards.timestamp = _bribeStart(_startTimestamp); - uint _prevTs = 0; - uint _prevBal = 0; - uint _prevSupply = 1; - + uint256 _prevTs = 0; + uint256 _prevBal = 0; + uint256 _prevSupply = 1; if (_endIndex > 0) { - for (uint i = _startIndex; i <= _endIndex - 1; i++) { - (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId,i); - uint _nextEpochStart = _bribeStart(_prevTs); + for (uint256 i = _startIndex; i <= _endIndex - 1; i++) { + (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i); + uint256 _nextEpochStart = _bribeStart(_prevTs); // check that you've earned it // this won't happen until a week has passed if (_nextEpochStart > prevRewards.timestamp) { - reward += prevRewards.balance; + reward += prevRewards.balance; } prevRewards.timestamp = _nextEpochStart; - (, _prevSupply) = underlying_bribe.supplyCheckpoints(underlying_bribe.getPriorSupplyIndex(_nextEpochStart + DURATION)); - prevRewards.balance = _prevBal * tokenRewardsPerEpoch[token][_nextEpochStart] / _prevSupply; + (, _prevSupply) = underlying_bribe.supplyCheckpoints( + underlying_bribe.getPriorSupplyIndex( + _nextEpochStart + DURATION + ) + ); + prevRewards.balance = + (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) / + _prevSupply; } } - (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId,_endIndex); - uint _lastEpochStart = _bribeStart(_prevTs); - uint _lastEpochEnd = _lastEpochStart + DURATION; - - if (block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd) { - (, _prevSupply) = underlying_bribe.supplyCheckpoints(underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)); - reward += _prevBal * tokenRewardsPerEpoch[token][_lastEpochStart] / _prevSupply; + (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex); + uint256 _lastEpochStart = _bribeStart(_prevTs); + uint256 _lastEpochEnd = _lastEpochStart + DURATION; + + if ( + block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd + ) { + (, _prevSupply) = underlying_bribe.supplyCheckpoints( + underlying_bribe.getPriorSupplyIndex(_lastEpochEnd) + ); + reward += + (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) / + _prevSupply; } return reward; } - function left(address token) external view returns (uint) { - uint adjustedTstamp = getEpochStart(block.timestamp); + function left(address token) external view returns (uint256) { + uint256 adjustedTstamp = getEpochStart(block.timestamp); return tokenRewardsPerEpoch[token][adjustedTstamp]; } - function notifyRewardAmount(address token, uint amount) external lock { + function notifyRewardAmount(address token, uint256 amount) external lock { require(amount > 0); if (!isReward[token]) { - require(IVoter(voter).isWhitelisted(token), "bribe tokens must be whitelisted"); - require(rewards.length < MAX_REWARD_TOKENS, "too many rewards tokens"); + require( + IVoter(voter).isWhitelisted(token), + "bribe tokens must be whitelisted" + ); + require( + rewards.length < MAX_REWARD_TOKENS, + "too many rewards tokens" + ); } // bribes kick in at the start of next bribe period - uint adjustedTstamp = getEpochStart(block.timestamp); - uint epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp]; + uint256 adjustedTstamp = getEpochStart(block.timestamp); + uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp]; _safeTransferFrom(token, msg.sender, address(this), amount); tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount; @@ -176,25 +216,45 @@ contract WrappedExternalBribe { emit NotifyReward(msg.sender, token, adjustedTstamp, amount); } - function swapOutRewardToken(uint i, address oldToken, address newToken) external { - require(msg.sender == IVotingEscrow(_ve).team(), 'only team'); + function swapOutRewardToken( + uint256 i, + address oldToken, + address newToken + ) external { + require(msg.sender == IVotingEscrow(_ve).team(), "only team"); require(rewards[i] == oldToken); isReward[oldToken] = false; isReward[newToken] = true; rewards[i] = newToken; } - function _safeTransfer(address token, address to, uint256 value) internal { + function _safeTransfer( + address token, + address to, + uint256 value + ) internal { require(token.code.length > 0); - (bool success, bytes memory data) = - token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value)); + (bool success, bytes memory data) = token.call( + abi.encodeWithSelector(IERC20.transfer.selector, to, value) + ); require(success && (data.length == 0 || abi.decode(data, (bool)))); } - function _safeTransferFrom(address token, address from, address to, uint256 value) internal { + function _safeTransferFrom( + address token, + address from, + address to, + uint256 value + ) internal { require(token.code.length > 0); - (bool success, bytes memory data) = - token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value)); + (bool success, bytes memory data) = token.call( + abi.encodeWithSelector( + IERC20.transferFrom.selector, + from, + to, + value + ) + ); require(success && (data.length == 0 || abi.decode(data, (bool)))); } } diff --git a/contracts/libraries/Math.sol b/contracts/libraries/Math.sol index bb315bee..fe5b2aa0 100644 --- a/contracts/libraries/Math.sol +++ b/contracts/libraries/Math.sol @@ -1,16 +1,19 @@ pragma solidity 0.8.13; -library Math { - function max(uint a, uint b) internal pure returns (uint) { +// this causes issue with forge test as there is already a Math.sol in the forge repo +library MathDunks { + function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } - function min(uint a, uint b) internal pure returns (uint) { + + function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } - function sqrt(uint y) internal pure returns (uint z) { + + function sqrt(uint256 y) internal pure returns (uint256 z) { if (y > 3) { z = y; - uint x = y / 2 + 1; + uint256 x = y / 2 + 1; while (x < z) { z = x; x = (y / x + x) / 2; @@ -19,16 +22,19 @@ library Math { z = 1; } } - function cbrt(uint256 n) internal pure returns (uint256) { unchecked { - uint256 x = 0; - for (uint256 y = 1 << 255; y > 0; y >>= 3) { - x <<= 1; - uint256 z = 3 * x * (x + 1) + 1; - if (n / y >= z) { - n -= y * z; - x += 1; + + function cbrt(uint256 n) internal pure returns (uint256) { + unchecked { + uint256 x = 0; + for (uint256 y = 1 << 255; y > 0; y >>= 3) { + x <<= 1; + uint256 z = 3 * x * (x + 1) + 1; + if (n / y >= z) { + n -= y * z; + x += 1; + } } + return x; } - return x; - }} + } } diff --git a/gitsubmodules.sh b/gitsubmodules.sh new file mode 100644 index 00000000..fa2958a8 --- /dev/null +++ b/gitsubmodules.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +set -e + +git config -f .gitmodules --get-regexp '^submodule\..*\.path$' | + while read path_key path + do + url_key=$(echo $path_key | sed 's/\.path/.url/') + url=$(git config -f .gitmodules --get "$url_key") + git submodule add $url $path + done \ No newline at end of file diff --git a/hardhat.config.ts b/hardhat.config.ts index ef75274c..b42388ba 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -1,79 +1,90 @@ -import "@nomiclabs/hardhat-ethers"; -import "@nomiclabs/hardhat-etherscan"; -import "@nomiclabs/hardhat-waffle"; -import "@typechain/hardhat"; -import "hardhat-preprocessor"; -import "hardhat-abi-exporter"; +import '@nomiclabs/hardhat-ethers' +import '@nomiclabs/hardhat-etherscan' +import '@nomiclabs/hardhat-waffle' +import '@typechain/hardhat' +import 'hardhat-preprocessor' +import 'hardhat-abi-exporter' -import "./tasks/accounts"; -import "./tasks/deploy"; +import './tasks/accounts' +import './tasks/deploy' -import fs from "fs"; -import { resolve } from "path"; +import fs from 'fs' +import { resolve } from 'path' -import { config as dotenvConfig } from "dotenv"; -import { HardhatUserConfig, task } from "hardhat/config"; +import { config as dotenvConfig } from 'dotenv' +import { HardhatUserConfig, task } from 'hardhat/config' -dotenvConfig({ path: resolve(__dirname, "./.env") }); +dotenvConfig({ path: resolve(__dirname, './.env') }) const remappings = fs - .readFileSync("remappings.txt", "utf8") - .split("\n") + .readFileSync('remappings.txt', 'utf8') + .split('\n') .filter(Boolean) - .map((line) => line.trim().split("=")); + .map(line => line.trim().split('=')) const config: HardhatUserConfig = { networks: { hardhat: { initialBaseFeePerGas: 0, forking: { - url: `https://opt-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_API_KEY}`, + url: `https://arb-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY}`, blockNumber: 16051852 } }, opera: { - url: "https://rpc.fantom.network", + url: 'https://rpc.fantom.network', + accounts: [process.env.PRIVATE_KEY!] + }, + arbitrum: { + url: `https://arb-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY}`, accounts: [process.env.PRIVATE_KEY!], + chainId: 42161 }, - ftmTestnet: { - url: "https://rpc.testnet.fantom.network", + arbitrumGoerli: { + url: 'https://arb-goerli.g.alchemy.com/v2/JW-n2dVWqUeU-bdj_MKeq2qs3LupK8CS', accounts: [process.env.PRIVATE_KEY!], + chainId: 421613 + }, + + ftmTestnet: { + url: 'https://rpc.testnet.fantom.network', + accounts: [process.env.PRIVATE_KEY!] }, optimisticEthereum: { - url: "https://mainnet.optimism.io", - accounts: [process.env.PRIVATE_KEY!], + url: 'https://mainnet.optimism.io', + accounts: [process.env.PRIVATE_KEY!] }, optimisticKovan: { - url: "https://kovan.optimism.io", - accounts: [process.env.PRIVATE_KEY!], - }, + url: 'https://kovan.optimism.io', + accounts: [process.env.PRIVATE_KEY!] + } }, solidity: { - version: "0.8.13", + version: '0.8.13', settings: { optimizer: { enabled: true, - runs: 200, - }, - }, + runs: 200 + } + } }, // This fully resolves paths for imports in the ./lib directory for Hardhat preprocess: { - eachLine: (hre) => ({ + eachLine: hre => ({ transform: (line: string) => { if (!line.match(/^\s*import /i)) { - return line; + return line } - const remapping = remappings.find(([find]) => line.match('"' + find)); + const remapping = remappings.find(([find]) => line.match('"' + find)) if (!remapping) { - return line; + return line } - const [find, replace] = remapping; - return line.replace('"' + find, '"' + replace); - }, - }), + const [find, replace] = remapping + return line.replace('"' + find, '"' + replace) + } + }) }, etherscan: { apiKey: { @@ -81,8 +92,9 @@ const config: HardhatUserConfig = { ftmTestnet: process.env.FTM_SCAN_API_KEY!, optimisticEthereum: process.env.OP_SCAN_API_KEY!, optimisticKovan: process.env.OP_SCAN_API_KEY!, + arbitrum: process.env.ARB_SCAN_API_KEY! } } -}; +} -export default config; +export default config diff --git a/lib/LayerZero b/lib/LayerZero new file mode 160000 index 00000000..3fb8f696 --- /dev/null +++ b/lib/LayerZero @@ -0,0 +1 @@ +Subproject commit 3fb8f6962c1346eefa7e12f2cd8c299f0cfba944 diff --git a/lib/ds-test b/lib/ds-test new file mode 160000 index 00000000..cd98eff2 --- /dev/null +++ b/lib/ds-test @@ -0,0 +1 @@ +Subproject commit cd98eff28324bfac652e63a239a60632a761790b diff --git a/lib/forge-std b/lib/forge-std new file mode 160000 index 00000000..b78fdb5a --- /dev/null +++ b/lib/forge-std @@ -0,0 +1 @@ +Subproject commit b78fdb5aed571e20c8b1f52a67566ed5bac0be59 diff --git a/lib/openzeppelin-contracts b/lib/openzeppelin-contracts new file mode 160000 index 00000000..a28aafdc --- /dev/null +++ b/lib/openzeppelin-contracts @@ -0,0 +1 @@ +Subproject commit a28aafdc85a592776544f7978c6b1a462d28ede2 diff --git a/lib/solmate b/lib/solmate new file mode 160000 index 00000000..3998897a --- /dev/null +++ b/lib/solmate @@ -0,0 +1 @@ +Subproject commit 3998897acb502fa7b480f505138a6ae1842e8d10 diff --git a/scripts/k.js b/scripts/k.js index 9ab02728..652f9abb 100644 --- a/scripts/k.js +++ b/scripts/k.js @@ -1,102 +1,102 @@ -const xIn = 1000000000000; -const _x = 100000001000000000000000000; -const _y = 100000001000000000000000000; +const xIn = 1000000000000 +const _x = 100000001000000000000000000 +const _y = 100000001000000000000000000 -yOut = get_y(xIn,_x,_y); +yOut = get_y(xIn, _x, _y) -const a = 100000001000000000000000000; +const a = 100000001000000000000000000 -console.log(a*a/1e18*a/1e18) +console.log((((a * a) / 1e18) * a) / 1e18) - -function get_y(xIn, a, b) { - x = xIn + a; - a3 = a*a/1e18*a/1e18 - x2 = x*x/1e18 - b3 = b*b/1e18*b/1e18 - c0 = 27*a3*b/1e18*x2/1e18+27*a*b3/1e18*x2/1e18; - console.log("c0",c0) - console.log("c0*c0",c0*c0) - _c1 = (Math.sqrt(c0*c0+108*x**12)+c0) +function get_y (xIn, a, b) { + x = xIn + a + a3 = (((a * a) / 1e18) * a) / 1e18 + x2 = (x * x) / 1e18 + b3 = (((b * b) / 1e18) * b) / 1e18 + c0 = + (((27 * a3 * b) / 1e18) * x2) / 1e18 + (((27 * a * b3) / 1e18) * x2) / 1e18 + console.log('c0', c0) + console.log('c0*c0', c0 * c0) + _c1 = MathDunks.sqrt(c0 * c0 + 108 * x ** 12) + c0 console.log(_c1) - c1 = Math.cbrt(_c1) - b1 = (3*2**(1/3)*x) - b1 = 3*Math.cbrt(2)*x - b2 = ((2**(1/3))*(x**3)) - console.log("c1", c1); - console.log("b1", b1); - console.log("b2", b2); - console.log("c1/b1 %s", c1/b1); - console.log("b2/c1 %s", b2/c1); - y = c1/b1-b2/c1 - console.log("y", b-y) + c1 = MathDunks.cbrt(_c1) + b1 = 3 * 2 ** (1 / 3) * x + b1 = 3 * MathDunks.cbrt(2) * x + b2 = 2 ** (1 / 3) * x ** 3 + console.log('c1', c1) + console.log('b1', b1) + console.log('b2', b2) + console.log('c1/b1 %s', c1 / b1) + console.log('b2/c1 %s', b2 / c1) + y = c1 / b1 - b2 / c1 + console.log('y', b - y) } /*function get_y(xIn, a, b) { x = xIn + a; - y0 = Math.cbrt(Math.sqrt(((27*(a**3)*b*(x**2)+27*a*(b**3)*(x**2))**2)+108*x**12)+27*(a**3)*b*(x**2)+27*a*(b**3)*(x**2)) - y1 = y0 / 3*Math.cbrt(2)*x - y2 = Math.cbrt(2)*(x**3) / y0 + y0 = MathDunks.cbrt(MathDunks.sqrt(((27*(a**3)*b*(x**2)+27*a*(b**3)*(x**2))**2)+108*x**12)+27*(a**3)*b*(x**2)+27*a*(b**3)*(x**2)) + y1 = y0 / 3*MathDunks.cbrt(2)*x + y2 = MathDunks.cbrt(2)*(x**3) / y0 y = y1 - y2 console.log(y) console.log(b-y) }*/ // getAmountOut gives the amount that will be returned given the amountIn for tokenIn -function getAmountOut(xIn, x, y) { - console.log("_k1",_k(x,y)); - _kB = Math.sqrt(Math.sqrt(_k(x, y))) * 2; - console.log("_kB", _kB); - _kA1 = Math.sqrt(Math.sqrt(_k(x+xIn, y))) * 2; - yOutAbove = (_kA1 - _kB); +function getAmountOut (xIn, x, y) { + console.log('_k1', _k(x, y)) + _kB = MathDunks.sqrt(MathDunks.sqrt(_k(x, y))) * 2 + console.log('_kB', _kB) + _kA1 = MathDunks.sqrt(MathDunks.sqrt(_k(x + xIn, y))) * 2 + yOutAbove = _kA1 - _kB - _kA2 = Math.sqrt(Math.sqrt(_k(x+xIn, y-yOutAbove))) * 2; + _kA2 = MathDunks.sqrt(MathDunks.sqrt(_k(x + xIn, y - yOutAbove))) * 2 while (_kA2 < _kB) { - diff = _kB - _kA2; + diff = _kB - _kA2 yOutAbove = yOutAbove - diff - console.log("yOutAbove", yOutAbove); - _kA2 = Math.sqrt(Math.sqrt(_k(x+xIn, y-yOutAbove))) * 2; + console.log('yOutAbove', yOutAbove) + _kA2 = MathDunks.sqrt(MathDunks.sqrt(_k(x + xIn, y - yOutAbove))) * 2 } - yOutBelow = yOutAbove; - _kA2 = Math.sqrt(Math.sqrt(_k(x+xIn, y-yOutAbove))) * 2; + yOutBelow = yOutAbove + _kA2 = MathDunks.sqrt(MathDunks.sqrt(_k(x + xIn, y - yOutAbove))) * 2 - console.log("_kA2", _kA2); + console.log('_kA2', _kA2) while (_kA2 > _kB) { - diff = _kA2 - _kB; + diff = _kA2 - _kB yOutBelow = yOutBelow + diff - _kA2 = Math.sqrt(Math.sqrt(_k(x+xIn, y-yOutBelow))) * 2; + _kA2 = MathDunks.sqrt(MathDunks.sqrt(_k(x + xIn, y - yOutBelow))) * 2 } - console.log(yOutAbove); - console.log(yOutBelow); - yOut = (yOutBelow+yOutAbove)/2; - _kA2 = Math.sqrt(Math.sqrt(_k(x+xIn, y-yOut))) * 2; + console.log(yOutAbove) + console.log(yOutBelow) + yOut = (yOutBelow + yOutAbove) / 2 + _kA2 = MathDunks.sqrt(MathDunks.sqrt(_k(x + xIn, y - yOut))) * 2 /*while (_kA2 != _kB) { diff = _kA2 - _kB; yOut = (yOutBelow+yOutAbove)/2; console.log(yOut); - _kA2 = Math.sqrt(Math.sqrt(_k(x+xIn, y-yOut))) * 2; + _kA2 = MathDunks.sqrt(MathDunks.sqrt(_k(x+xIn, y-yOut))) * 2; }*/ for (i = 0; i < 255; i++) { - _kA2 = Math.sqrt(Math.sqrt(_k(x+xIn, y-yOut))) * 2; + _kA2 = MathDunks.sqrt(MathDunks.sqrt(_k(x + xIn, y - yOut))) * 2 if (_kA2 > _kB) { - yOut = (yOut+yOutBelow)/2 + yOut = (yOut + yOutBelow) / 2 } else if (_kA2 < _kB) { - yOut = (yOut+yOutAbove)/2 + yOut = (yOut + yOutAbove) / 2 } else { return yOut } } - console.log("_k2 yOutAbove",_k(x+xIn,y-yOutAbove)); - console.log("_k2 yOutBelow",_k(x+xIn,y-yOutBelow)); - console.log("_k2 yOut",_k(x+xIn,y-yOut)); + console.log('_k2 yOutAbove', _k(x + xIn, y - yOutAbove)) + console.log('_k2 yOutBelow', _k(x + xIn, y - yOutBelow)) + console.log('_k2 yOut', _k(x + xIn, y - yOut)) } -function _k(_x, _y) { - _a = (_x * _y) ; - _b = ((_x * _x) + (_y * _y) ); - return _a * _b / 2; // x3y+y3x >= k +function _k (_x, _y) { + _a = _x * _y + _b = _x * _x + _y * _y + return (_a * _b) / 2 // x3y+y3x >= k } diff --git a/scripts/minterSolid.js b/scripts/minterSolid.js index 585cc9ad..c8a7e700 100644 --- a/scripts/minterSolid.js +++ b/scripts/minterSolid.js @@ -1,39 +1,39 @@ -let week = 1; -const emission = 98; -const tail_emission = 2; -const target_base = 100; -const tail_base = 1000; -let weekly = 20000000; -let totalSupply = 0; +let week = 1 +const emission = 98 +const tail_emission = 2 +const target_base = 100 +const tail_base = 1000 +let weekly = 20000000 +let totalSupply = 0 -function circulating_supply() { - return totalSupply; +function circulating_supply () { + return totalSupply } -function calculate_emission() { - return (weekly * emission) / target_base; +function calculate_emission () { + return (weekly * emission) / target_base } -function weekly_emission() { - return Math.max(calculate_emission(), circulating_emission()); +function weekly_emission () { + return MathDunks.max(calculate_emission(), circulating_emission()) } -function circulating_emission() { - return (circulating_supply() * tail_emission) / tail_base; +function circulating_emission () { + return (circulating_supply() * tail_emission) / tail_base } while (week < 50) { - weekly = weekly_emission(); - totalSupply += weekly; + weekly = weekly_emission() + totalSupply += weekly console.log( - "week: ", + 'week: ', week, - " minted: ", + ' minted: ', weekly, - " weekly: ", + ' weekly: ', weekly, - " totalSupply: ", + ' totalSupply: ', totalSupply - ); - week++; + ) + week++ } diff --git a/scripts/minterVelo.js b/scripts/minterVelo.js index 30e9cbf6..77b6963a 100644 --- a/scripts/minterVelo.js +++ b/scripts/minterVelo.js @@ -1,87 +1,87 @@ -let week = 1; -const emission = 99; -const tail_emission = 2; -const target_base = 100; // 2% per week target emission -const tail_base = 1000; // 0.2% per week target emission -let weekly = 15000000; -const lock = 86400 * 7 * 52 * 4; -let balanceOfContract = 0; -let veSupply = 140000000; -let totalSupply = 400000000; -let lockrate = 0.5; -let actualCirc = totalSupply - balanceOfContract - veSupply; +let week = 1 +const emission = 99 +const tail_emission = 2 +const target_base = 100 // 2% per week target emission +const tail_base = 1000 // 0.2% per week target emission +let weekly = 15000000 +const lock = 86400 * 7 * 52 * 4 +let balanceOfContract = 0 +let veSupply = 140000000 +let totalSupply = 400000000 +let lockrate = 0.5 +let actualCirc = totalSupply - balanceOfContract - veSupply // calculate circulating supply as total token supply - locked supply -function circulating_supply() { - return totalSupply - veSupply; +function circulating_supply () { + return totalSupply - veSupply } // emission calculation is 1% of available supply to mint adjusted by circulating / total supply -function calculate_emission() { - return weekly * (emission / target_base); +function calculate_emission () { + return weekly * (emission / target_base) } // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission -function weekly_emission() { - return Math.max(calculate_emission(), circulating_emission()); +function weekly_emission () { + return MathDunks.max(calculate_emission(), circulating_emission()) } -function circulating_emission() { - return circulating_supply() * (tail_emission / tail_base); +function circulating_emission () { + return circulating_supply() * (tail_emission / tail_base) } -function calculate_growth(minted) { +function calculate_growth (minted) { return ( minted * (veSupply / totalSupply) * (veSupply / totalSupply) * (veSupply / totalSupply) * 0.5 - ); + ) } -let data = []; +let data = [] while (week < 900) { - weekly = weekly_emission(); - _growth = calculate_growth(weekly); - _required = weekly + _growth; - _balanceOf = balanceOfContract; + weekly = weekly_emission() + _growth = calculate_growth(weekly) + _required = weekly + _growth + _balanceOf = balanceOfContract if (_balanceOf < _required) { - totalSupply += _required; + totalSupply += _required } else { - balanceOfContract -= _required; + balanceOfContract -= _required } //adjust for ve balance - veSupply += _growth + weekly * lockrate; - emissionRate = weekly / totalSupply; - actualCirc = totalSupply - balanceOfContract - veSupply; + veSupply += _growth + weekly * lockrate + emissionRate = weekly / totalSupply + actualCirc = totalSupply - balanceOfContract - veSupply data.push([ - "week", + 'week', week, - "totalWeeklyEmissions", + 'totalWeeklyEmissions', _required, - "LPemissions", + 'LPemissions', weekly, - "veLockerRebase", + 'veLockerRebase', _growth, - "veSupply", + 'veSupply', veSupply, - "locked", + 'locked', veSupply / totalSupply, - "totalSupply", + 'totalSupply', totalSupply, - "actual circ", - actualCirc + veSupply, - ]); + 'actual circ', + actualCirc + veSupply + ]) console.log( - "week: ", + 'week: ', week, - " minted: ", + ' minted: ', weekly, - " weekly: ", + ' weekly: ', weekly, - " totalSupply: ", + ' totalSupply: ', totalSupply - ); - week++; + ) + week++ } diff --git a/tasks/deploy/arb.ts b/tasks/deploy/arb.ts new file mode 100644 index 00000000..e61be7f7 --- /dev/null +++ b/tasks/deploy/arb.ts @@ -0,0 +1,214 @@ +import { task } from 'hardhat/config' +import arbConfig from './constants/arbConfig' +import arbTestnetConfig from './constants/arbTestnetConfig' +import arbHardhatConfig from './constants/arbHardhatConfig' + +import optimismConfig from './constants/optimismConfig' +import testOptimismConfig from './constants/testOptimismConfig' + +import fantomConfig from './constants/fantomConfig' +import testFantomConfig from './constants/testFantomConfig' + +task('deploy:arb', 'Deploys Arbitrum contracts').setAction(async function ( + taskArguments, + { ethers } +) { + const mainnet = true + + const ARB_CONFIG = mainnet ? arbConfig : arbTestnetConfig + const FTM_CONFIG = mainnet ? fantomConfig : testFantomConfig + + console.log( + 'ALCHEMY_MAINNET_ARBITRUM_API_KEY: ', + process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY + ) + + // Load + const [ + Velo, + GaugeFactory, + BribeFactory, + PairFactory, + Router, + Library, + VeArtProxy, + VotingEscrow, + RewardsDistributor, + Voter, + Minter, + VeloGovernor, + RedemptionReceiver, + MerkleClaim + ] = await Promise.all([ + ethers.getContractFactory('Velo'), + ethers.getContractFactory('GaugeFactory'), + ethers.getContractFactory('BribeFactory'), + ethers.getContractFactory('PairFactory'), + ethers.getContractFactory('Router'), + ethers.getContractFactory('VelodromeLibrary'), + ethers.getContractFactory('VeArtProxy'), + ethers.getContractFactory('VotingEscrow'), + ethers.getContractFactory('RewardsDistributor'), + ethers.getContractFactory('Voter'), + ethers.getContractFactory('Minter'), + ethers.getContractFactory('VeloGovernor'), + ethers.getContractFactory('RedemptionReceiver'), + ethers.getContractFactory('MerkleClaim') + ]) + + const velo = await Velo.deploy() + await velo.deployed() + console.log('Velo deployed to dunks: ', velo.address) + + const gaugeFactory = await GaugeFactory.deploy() + await gaugeFactory.deployed() + console.log('GaugeFactory deployed to: ', gaugeFactory.address) + + const bribeFactory = await BribeFactory.deploy() + await bribeFactory.deployed() + console.log('BribeFactory deployed to: ', bribeFactory.address) + + const pairFactory = await PairFactory.deploy() + await pairFactory.deployed() + console.log('PairFactory deployed to: ', pairFactory.address) + + const router = await Router.deploy(pairFactory.address, ARB_CONFIG.WETH) + await router.deployed() + console.log('Router deployed to: ', router.address) + console.log('Args: ', pairFactory.address, ARB_CONFIG.WETH, '\n') + + const library = await Library.deploy(router.address) + await library.deployed() + console.log('VelodromeLibrary deployed to: ', library.address) + console.log('Args: ', router.address, '\n') + + const artProxy = await VeArtProxy.deploy() + await artProxy.deployed() + console.log('VeArtProxy deployed to: ', artProxy.address) + + const escrow = await VotingEscrow.deploy(velo.address, artProxy.address) + await escrow.deployed() + console.log('VotingEscrow deployed to: ', escrow.address) + console.log('Args: ', velo.address, artProxy.address, '\n') + + const distributor = await RewardsDistributor.deploy(escrow.address) + await distributor.deployed() + console.log('RewardsDistributor deployed to: ', distributor.address) + console.log('Args: ', escrow.address, '\n') + + const voter = await Voter.deploy( + escrow.address, + pairFactory.address, + gaugeFactory.address, + bribeFactory.address + ) + await voter.deployed() + console.log('Voter deployed to: ', voter.address) + console.log( + 'Args: ', + escrow.address, + pairFactory.address, + gaugeFactory.address, + bribeFactory.address, + '\n' + ) + + const minter = await Minter.deploy( + voter.address, + escrow.address, + distributor.address + ) + await minter.deployed() + console.log('Minter deployed to: ', minter.address) + console.log( + 'Args: ', + voter.address, + escrow.address, + distributor.address, + '\n' + ) + + const receiver = await RedemptionReceiver.deploy( + ARB_CONFIG.USDC, + velo.address, + FTM_CONFIG.lzChainId, + ARB_CONFIG.lzEndpoint + ) + await receiver.deployed() + console.log('RedemptionReceiver deployed to: ', receiver.address) + console.log( + 'Args: ', + ARB_CONFIG.USDC, + velo.address, + FTM_CONFIG.lzChainId, + ARB_CONFIG.lzEndpoint, + '\n' + ) + + const governor = await VeloGovernor.deploy(escrow.address) + await governor.deployed() + console.log('VeloGovernor deployed to: ', governor.address) + console.log('Args: ', escrow.address, '\n') + + // Airdrop + const claim = await MerkleClaim.deploy(velo.address, ARB_CONFIG.merkleRoot) + await claim.deployed() + console.log('MerkleClaim deployed to: ', claim.address) + console.log('Args: ', velo.address, ARB_CONFIG.merkleRoot, '\n') + + // Initialize + await velo.initialMint(ARB_CONFIG.teamEOA) + console.log('Initial minted') + + await velo.setRedemptionReceiver(receiver.address) + console.log('RedemptionReceiver set') + + await velo.setMerkleClaim(claim.address) + console.log('MerkleClaim set') + + await velo.setMinter(minter.address) + console.log('Minter set') + + await pairFactory.setPauser(ARB_CONFIG.teamMultisig) + console.log('Pauser set') + + await escrow.setVoter(voter.address) + console.log('Voter set') + + await escrow.setTeam(ARB_CONFIG.teamMultisig) + console.log('Team set for escrow') + + await voter.setGovernor(ARB_CONFIG.teamMultisig) + console.log('Governor set') + + await voter.setEmergencyCouncil(ARB_CONFIG.teamMultisig) + console.log('Emergency Council set') + + await distributor.setDepositor(minter.address) + console.log('Depositor set') + + await receiver.setTeam(ARB_CONFIG.teamMultisig) + console.log('Team set for receiver') + + await governor.setTeam(ARB_CONFIG.teamMultisig) + console.log('Team set for governor') + + // Whitelist + const nativeToken = [velo.address] + const tokenWhitelist = nativeToken.concat(ARB_CONFIG.tokenWhitelist) + await voter.initialize(tokenWhitelist, minter.address) + console.log('Whitelist set') + + // Initial veVELO distro + await minter.initialize( + ARB_CONFIG.partnerAddrs, + ARB_CONFIG.partnerAmts, + ARB_CONFIG.partnerMax + ) + console.log('veVELO distributed') + + await minter.setTeam(ARB_CONFIG.teamMultisig) + console.log('Team set for minter') + + console.log('Arbitrum contracts deployed') +}) diff --git a/tasks/deploy/arbHardhat.ts b/tasks/deploy/arbHardhat.ts new file mode 100644 index 00000000..701ae98b --- /dev/null +++ b/tasks/deploy/arbHardhat.ts @@ -0,0 +1,212 @@ +import { task } from 'hardhat/config' +import arbConfig from './constants/arbConfig' +import arbTestnetConfig from './constants/arbTestnetConfig' +import arbHardhatConfig from './constants/arbHardhatConfig' +import optimismConfig from './constants/optimismConfig' +import testOptimismConfig from './constants/testOptimismConfig' + +import fantomConfig from './constants/fantomConfig' +import testFantomConfig from './constants/testFantomConfig' + +task('deploy:arbHardhat', 'Deploys Arbitrum forked chain contracts').setAction( + async function (taskArguments, { ethers }) { + const mainnet = false + + const ARB_CONFIG = mainnet ? arbConfig : arbHardhatConfig + const FTM_CONFIG = mainnet ? fantomConfig : testFantomConfig + + console.log( + 'ALCHEMY_MAINNET_ARBITRUM_API_KEY: ', + process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY + ) + + // Load + const [ + Velo, + GaugeFactory, + BribeFactory, + PairFactory, + Router, + Library, + VeArtProxy, + VotingEscrow, + RewardsDistributor, + Voter, + Minter, + VeloGovernor, + RedemptionReceiver, + MerkleClaim + ] = await Promise.all([ + ethers.getContractFactory('Velo'), + ethers.getContractFactory('GaugeFactory'), + ethers.getContractFactory('BribeFactory'), + ethers.getContractFactory('PairFactory'), + ethers.getContractFactory('Router'), + ethers.getContractFactory('VelodromeLibrary'), + ethers.getContractFactory('VeArtProxy'), + ethers.getContractFactory('VotingEscrow'), + ethers.getContractFactory('RewardsDistributor'), + ethers.getContractFactory('Voter'), + ethers.getContractFactory('Minter'), + ethers.getContractFactory('VeloGovernor'), + ethers.getContractFactory('RedemptionReceiver'), + ethers.getContractFactory('MerkleClaim') + ]) + + const velo = await Velo.deploy() + await velo.deployed() + console.log('Velo deployed to dunks: ', velo.address) + + const gaugeFactory = await GaugeFactory.deploy() + await gaugeFactory.deployed() + console.log('GaugeFactory deployed to: ', gaugeFactory.address) + + const bribeFactory = await BribeFactory.deploy() + await bribeFactory.deployed() + console.log('BribeFactory deployed to: ', bribeFactory.address) + + const pairFactory = await PairFactory.deploy() + await pairFactory.deployed() + console.log('PairFactory deployed to: ', pairFactory.address) + + const router = await Router.deploy(pairFactory.address, ARB_CONFIG.WETH) + await router.deployed() + console.log('Router deployed to: ', router.address) + console.log('Args: ', pairFactory.address, ARB_CONFIG.WETH, '\n') + + const library = await Library.deploy(router.address) + await library.deployed() + console.log('VelodromeLibrary deployed to: ', library.address) + console.log('Args: ', router.address, '\n') + + const artProxy = await VeArtProxy.deploy() + await artProxy.deployed() + console.log('VeArtProxy deployed to: ', artProxy.address) + + const escrow = await VotingEscrow.deploy(velo.address, artProxy.address) + await escrow.deployed() + console.log('VotingEscrow deployed to: ', escrow.address) + console.log('Args: ', velo.address, artProxy.address, '\n') + + const distributor = await RewardsDistributor.deploy(escrow.address) + await distributor.deployed() + console.log('RewardsDistributor deployed to: ', distributor.address) + console.log('Args: ', escrow.address, '\n') + + const voter = await Voter.deploy( + escrow.address, + pairFactory.address, + gaugeFactory.address, + bribeFactory.address + ) + await voter.deployed() + console.log('Voter deployed to: ', voter.address) + console.log( + 'Args: ', + escrow.address, + pairFactory.address, + gaugeFactory.address, + bribeFactory.address, + '\n' + ) + + const minter = await Minter.deploy( + voter.address, + escrow.address, + distributor.address + ) + await minter.deployed() + console.log('Minter deployed to: ', minter.address) + console.log( + 'Args: ', + voter.address, + escrow.address, + distributor.address, + '\n' + ) + + const receiver = await RedemptionReceiver.deploy( + ARB_CONFIG.USDC, + velo.address, + FTM_CONFIG.lzChainId, + ARB_CONFIG.lzEndpoint + ) + await receiver.deployed() + console.log('RedemptionReceiver deployed to: ', receiver.address) + console.log( + 'Args: ', + ARB_CONFIG.USDC, + velo.address, + FTM_CONFIG.lzChainId, + ARB_CONFIG.lzEndpoint, + '\n' + ) + + const governor = await VeloGovernor.deploy(escrow.address) + await governor.deployed() + console.log('VeloGovernor deployed to: ', governor.address) + console.log('Args: ', escrow.address, '\n') + + // Airdrop + const claim = await MerkleClaim.deploy(velo.address, ARB_CONFIG.merkleRoot) + await claim.deployed() + console.log('MerkleClaim deployed to: ', claim.address) + console.log('Args: ', velo.address, ARB_CONFIG.merkleRoot, '\n') + + // Initialize + await velo.initialMint(ARB_CONFIG.teamEOA) + console.log('Initial minted') + + await velo.setRedemptionReceiver(receiver.address) + console.log('RedemptionReceiver set') + + await velo.setMerkleClaim(claim.address) + console.log('MerkleClaim set') + + await velo.setMinter(minter.address) + console.log('Minter set') + + await pairFactory.setPauser(ARB_CONFIG.teamMultisig) + console.log('Pauser set') + + await escrow.setVoter(voter.address) + console.log('Voter set') + + await escrow.setTeam(ARB_CONFIG.teamMultisig) + console.log('Team set for escrow') + + await voter.setGovernor(ARB_CONFIG.teamMultisig) + console.log('Governor set') + + await voter.setEmergencyCouncil(ARB_CONFIG.teamMultisig) + console.log('Emergency Council set') + + await distributor.setDepositor(minter.address) + console.log('Depositor set') + + await receiver.setTeam(ARB_CONFIG.teamMultisig) + console.log('Team set for receiver') + + await governor.setTeam(ARB_CONFIG.teamMultisig) + console.log('Team set for governor') + + // Whitelist + const nativeToken = [velo.address] + const tokenWhitelist = nativeToken.concat(ARB_CONFIG.tokenWhitelist) + await voter.initialize(tokenWhitelist, minter.address) + console.log('Whitelist set') + + // Initial veVELO distro + await minter.initialize( + ARB_CONFIG.partnerAddrs, + ARB_CONFIG.partnerAmts, + ARB_CONFIG.partnerMax + ) + console.log('veVELO distributed') + + await minter.setTeam(ARB_CONFIG.teamMultisig) + console.log('Team set for minter') + + console.log('Arbitrum Forked Chain contracts deployed') + } +) diff --git a/tasks/deploy/arbTest.ts b/tasks/deploy/arbTest.ts new file mode 100644 index 00000000..2c30b177 --- /dev/null +++ b/tasks/deploy/arbTest.ts @@ -0,0 +1,207 @@ +import { task } from 'hardhat/config' + +import optimismConfig from './constants/optimismConfig' +import testOptimismConfig from './constants/testOptimismConfig' +import arbTestnetConfig from './constants/arbTestnetConfig' + +import fantomConfig from './constants/fantomConfig' +import testFantomConfig from './constants/testFantomConfig' + +task('deploy:arbTest', 'Deploys Optimism contracts').setAction(async function ( + taskArguments, + { ethers } +) { + const mainnet = false + + const OP_CONFIG = mainnet ? optimismConfig : testOptimismConfig + const FTM_CONFIG = mainnet ? fantomConfig : testFantomConfig + + // Load + const [ + Velo, + GaugeFactory, + BribeFactory, + PairFactory, + Router, + Library, + VeArtProxy, + VotingEscrow, + RewardsDistributor, + Voter, + Minter, + VeloGovernor, + RedemptionReceiver, + MerkleClaim + ] = await Promise.all([ + ethers.getContractFactory('Velo'), + ethers.getContractFactory('GaugeFactory'), + ethers.getContractFactory('BribeFactory'), + ethers.getContractFactory('PairFactory'), + ethers.getContractFactory('Router'), + ethers.getContractFactory('VelodromeLibrary'), + ethers.getContractFactory('VeArtProxy'), + ethers.getContractFactory('VotingEscrow'), + ethers.getContractFactory('RewardsDistributor'), + ethers.getContractFactory('Voter'), + ethers.getContractFactory('Minter'), + ethers.getContractFactory('VeloGovernor'), + ethers.getContractFactory('RedemptionReceiver'), + ethers.getContractFactory('MerkleClaim') + ]) + + const velo = await Velo.deploy() + await velo.deployed() + console.log('Velo deployed to: ', velo.address) + + const gaugeFactory = await GaugeFactory.deploy() + await gaugeFactory.deployed() + console.log('GaugeFactory deployed to: ', gaugeFactory.address) + + const bribeFactory = await BribeFactory.deploy() + await bribeFactory.deployed() + console.log('BribeFactory deployed to: ', bribeFactory.address) + + const pairFactory = await PairFactory.deploy() + await pairFactory.deployed() + console.log('PairFactory deployed to: ', pairFactory.address) + + const router = await Router.deploy(pairFactory.address, OP_CONFIG.WETH) + await router.deployed() + console.log('Router deployed to: ', router.address) + console.log('Args: ', pairFactory.address, OP_CONFIG.WETH, '\n') + + const library = await Library.deploy(router.address) + await library.deployed() + console.log('VelodromeLibrary deployed to: ', library.address) + console.log('Args: ', router.address, '\n') + + const artProxy = await VeArtProxy.deploy() + await artProxy.deployed() + console.log('VeArtProxy deployed to: ', artProxy.address) + + const escrow = await VotingEscrow.deploy(velo.address, artProxy.address) + await escrow.deployed() + console.log('VotingEscrow deployed to: ', escrow.address) + console.log('Args: ', velo.address, artProxy.address, '\n') + + const distributor = await RewardsDistributor.deploy(escrow.address) + await distributor.deployed() + console.log('RewardsDistributor deployed to: ', distributor.address) + console.log('Args: ', escrow.address, '\n') + + const voter = await Voter.deploy( + escrow.address, + pairFactory.address, + gaugeFactory.address, + bribeFactory.address + ) + await voter.deployed() + console.log('Voter deployed to: ', voter.address) + console.log( + 'Args: ', + escrow.address, + pairFactory.address, + gaugeFactory.address, + bribeFactory.address, + '\n' + ) + + const minter = await Minter.deploy( + voter.address, + escrow.address, + distributor.address + ) + await minter.deployed() + console.log('Minter deployed to: ', minter.address) + console.log( + 'Args: ', + voter.address, + escrow.address, + distributor.address, + '\n' + ) + + const receiver = await RedemptionReceiver.deploy( + OP_CONFIG.USDC, + velo.address, + FTM_CONFIG.lzChainId, + OP_CONFIG.lzEndpoint + ) + await receiver.deployed() + console.log('RedemptionReceiver deployed to: ', receiver.address) + console.log( + 'Args: ', + OP_CONFIG.USDC, + velo.address, + FTM_CONFIG.lzChainId, + OP_CONFIG.lzEndpoint, + '\n' + ) + + const governor = await VeloGovernor.deploy(escrow.address) + await governor.deployed() + console.log('VeloGovernor deployed to: ', governor.address) + console.log('Args: ', escrow.address, '\n') + + // Airdrop + // const claim = await MerkleClaim.deploy(velo.address, OP_CONFIG.merkleRoot) + // await claim.deployed() + // console.log('MerkleClaim deployed to: ', claim.address) + // console.log('Args: ', velo.address, OP_CONFIG.merkleRoot, '\n') + + // Initialize + await velo.initialMint(OP_CONFIG.teamEOA) + console.log('Initial minted') + + // await velo.setRedemptionReceiver(receiver.address) + // console.log('RedemptionReceiver set') + + // await velo.setMerkleClaim(claim.address) + // console.log('MerkleClaim set') + + await velo.setMinter(minter.address) + console.log('Minter set') + + await pairFactory.setPauser(OP_CONFIG.teamMultisig) + console.log('Pauser set') + + await escrow.setVoter(voter.address) + console.log('Voter set') + + await escrow.setTeam(OP_CONFIG.teamMultisig) + console.log('Team set for escrow') + + await voter.setGovernor(OP_CONFIG.teamMultisig) + console.log('Governor set') + + await voter.setEmergencyCouncil(OP_CONFIG.teamMultisig) + console.log('Emergency Council set') + + await distributor.setDepositor(minter.address) + console.log('Depositor set') + + await receiver.setTeam(OP_CONFIG.teamMultisig) + console.log('Team set for receiver') + + await governor.setTeam(OP_CONFIG.teamMultisig) + console.log('Team set for governor') + + // Whitelist + const nativeToken = [velo.address] + const tokenWhitelist = nativeToken.concat(OP_CONFIG.tokenWhitelist) + await voter.initialize(tokenWhitelist, minter.address) + console.log('Whitelist set') + + // Initial veVELO distro + await minter.initialize( + OP_CONFIG.partnerAddrs, + OP_CONFIG.partnerAmts, + OP_CONFIG.partnerMax + ) + console.log('veVELO distributed') + + await minter.setTeam(OP_CONFIG.teamMultisig) + console.log('Team set for minter') + + console.log('Arbitrum Goerli Velocimeter Instruments deployed') +}) diff --git a/tasks/deploy/constants/arbConfig.ts b/tasks/deploy/constants/arbConfig.ts new file mode 100644 index 00000000..d8c03b76 --- /dev/null +++ b/tasks/deploy/constants/arbConfig.ts @@ -0,0 +1,91 @@ +import { ethers } from 'ethers' + +const TOKEN_DECIMALS = ethers.BigNumber.from('10').pow( + ethers.BigNumber.from('18') +) +const MILLION = ethers.BigNumber.from('10').pow(ethers.BigNumber.from('6')) + +const FOUR_MILLION = ethers.BigNumber.from('4').mul(MILLION).mul(TOKEN_DECIMALS) +const TEN_MILLION = ethers.BigNumber.from('10').mul(MILLION).mul(TOKEN_DECIMALS) +const TWENTY_MILLION = ethers.BigNumber.from('20') + .mul(MILLION) + .mul(TOKEN_DECIMALS) +const PARTNER_MAX = ethers.BigNumber.from('78').mul(MILLION).mul(TOKEN_DECIMALS) + +const TEAM_MULTISIG = '0x069e85D4F1010DD961897dC8C095FBB5FF297434' +const TEAM_EOA = '0x069e85D4F1010DD961897dC8C095FBB5FF297434' + +const arbConfig = { + // Chain const + lzChainId: 110, + lzEndpoint: '0x3c2269811836af69497E5F486A85D7316753cf62', + + // Tokens + WETH: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', + USDC: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', + + // Addresses + teamEOA: TEAM_EOA, + teamMultisig: TEAM_MULTISIG, + emergencyCouncil: '0xcC2D01030eC2cd187346F70bFc483F24488C32E8', + + merkleRoot: + '0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f', + tokenWhitelist: [ + '0x4200000000000000000000000000000000000042', // OP + '0x4200000000000000000000000000000000000006', // WETH + '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', // USDC + '0x2E3D870790dC77A83DD1d18184Acc7439A53f475', // FRAX + '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', // DAI + '0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9', // sUSD + '0x217D47011b23BB961eB6D93cA9945B7501a5BB11', // THALES + '0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb', // LYRA + '0x67CCEA5bb16181E7b4109c9c2143c24a1c2205Be', // FXS + '0x9e1028F5F1D5eDE59748FFceE5532509976840E0', // PERP + '0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4', // SNX + '0xCB8FA9a76b8e203D8C3797bF438d8FB81Ea3326A', // alUSD + '0x3E29D3A9316dAB217754d13b28646B76607c5f04', // alETH + '0x8aE125E8653821E851F12A49F7765db9a9ce7384', // DOLA + '0x10010078a54396F62c96dF8532dc2B4847d47ED3', // HND + // "", // BTRFLY -- N/A + // "", // pxVELO -- N/A + '0xc40F949F8a4e094D1b49a23ea9241D289B7b2819' // LUSD + // "", // wstETH -- N/A + // "", // HOP -- N/A + ], + partnerAddrs: [ + TEAM_EOA, // VELO + '0x4a84675512949f81EBFEAAcC6C00D03eDd329de5', // OP + TEAM_EOA, // SNX -- custodied + '0xa283139017a2f5BAdE8d8e25412C600055D318F8', // INV + '0xDcf664d0f76E99eaA2DBD569474d0E75dC899FCD', // PERP + '0x489863b61C625a15C74FB4C21486baCb4A3937AB', // THALES + '0x641f26c67A5D0829Ae61019131093B6a7c7d18a3', // HND + '0xC224bf25Dcc99236F00843c7D8C4194abE8AA94a', // ALCX + '0xB6DACAE4eF97b4817d54df8e005269f509f803f9', // LYRA + TEAM_EOA, // MKR -- custodied + TEAM_EOA, // HOP -- custodied + '0x0dF840dCbf1229262A4125C1fc559bd338eC9491', // FRAX + '0x2E33A660742e813aD948fB9f7d682FE461E5fbf3', // BTRFLY + '0xd2D4e9024D8C90aB52032a9F1e0d92D4cE20191B' // LUSD + ], + partnerAmts: [ + TEN_MILLION, + TWENTY_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION + ], + partnerMax: PARTNER_MAX +} + +export default arbConfig diff --git a/tasks/deploy/constants/arbHardhatConfig.ts b/tasks/deploy/constants/arbHardhatConfig.ts new file mode 100644 index 00000000..1d1aa733 --- /dev/null +++ b/tasks/deploy/constants/arbHardhatConfig.ts @@ -0,0 +1,91 @@ +import { ethers } from 'ethers' + +const TOKEN_DECIMALS = ethers.BigNumber.from('10').pow( + ethers.BigNumber.from('18') +) +const MILLION = ethers.BigNumber.from('10').pow(ethers.BigNumber.from('6')) + +const FOUR_MILLION = ethers.BigNumber.from('4').mul(MILLION).mul(TOKEN_DECIMALS) +const TEN_MILLION = ethers.BigNumber.from('10').mul(MILLION).mul(TOKEN_DECIMALS) +const TWENTY_MILLION = ethers.BigNumber.from('20') + .mul(MILLION) + .mul(TOKEN_DECIMALS) +const PARTNER_MAX = ethers.BigNumber.from('78').mul(MILLION).mul(TOKEN_DECIMALS) + +const TEAM_MULTISIG = '0x069e85D4F1010DD961897dC8C095FBB5FF297434' +const TEAM_EOA = '0x069e85D4F1010DD961897dC8C095FBB5FF297434' + +const arbHardhatConfig = { + // Chain const + lzChainId: 110, + lzEndpoint: '0x3c2269811836af69497E5F486A85D7316753cf62', + + // Tokens + WETH: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', + USDC: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', + + // Addresses + teamEOA: TEAM_EOA, + teamMultisig: TEAM_MULTISIG, + emergencyCouncil: '0xcC2D01030eC2cd187346F70bFc483F24488C32E8', + + merkleRoot: + '0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f', + tokenWhitelist: [ + '0x4200000000000000000000000000000000000042', // OP + '0x4200000000000000000000000000000000000006', // WETH + '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', // USDC + '0x2E3D870790dC77A83DD1d18184Acc7439A53f475', // FRAX + '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', // DAI + '0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9', // sUSD + '0x217D47011b23BB961eB6D93cA9945B7501a5BB11', // THALES + '0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb', // LYRA + '0x67CCEA5bb16181E7b4109c9c2143c24a1c2205Be', // FXS + '0x9e1028F5F1D5eDE59748FFceE5532509976840E0', // PERP + '0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4', // SNX + '0xCB8FA9a76b8e203D8C3797bF438d8FB81Ea3326A', // alUSD + '0x3E29D3A9316dAB217754d13b28646B76607c5f04', // alETH + '0x8aE125E8653821E851F12A49F7765db9a9ce7384', // DOLA + '0x10010078a54396F62c96dF8532dc2B4847d47ED3', // HND + // "", // BTRFLY -- N/A + // "", // pxVELO -- N/A + '0xc40F949F8a4e094D1b49a23ea9241D289B7b2819' // LUSD + // "", // wstETH -- N/A + // "", // HOP -- N/A + ], + partnerAddrs: [ + TEAM_EOA, // VELO + '0x4a84675512949f81EBFEAAcC6C00D03eDd329de5', // OP + TEAM_EOA, // SNX -- custodied + '0xa283139017a2f5BAdE8d8e25412C600055D318F8', // INV + '0xDcf664d0f76E99eaA2DBD569474d0E75dC899FCD', // PERP + '0x489863b61C625a15C74FB4C21486baCb4A3937AB', // THALES + '0x641f26c67A5D0829Ae61019131093B6a7c7d18a3', // HND + '0xC224bf25Dcc99236F00843c7D8C4194abE8AA94a', // ALCX + '0xB6DACAE4eF97b4817d54df8e005269f509f803f9', // LYRA + TEAM_EOA, // MKR -- custodied + TEAM_EOA, // HOP -- custodied + '0x0dF840dCbf1229262A4125C1fc559bd338eC9491', // FRAX + '0x2E33A660742e813aD948fB9f7d682FE461E5fbf3', // BTRFLY + '0xd2D4e9024D8C90aB52032a9F1e0d92D4cE20191B' // LUSD + ], + partnerAmts: [ + TEN_MILLION, + TWENTY_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION + ], + partnerMax: PARTNER_MAX +} + +export default arbHardhatConfig diff --git a/tasks/deploy/constants/arbTestnetConfig.ts b/tasks/deploy/constants/arbTestnetConfig.ts new file mode 100644 index 00000000..752a5642 --- /dev/null +++ b/tasks/deploy/constants/arbTestnetConfig.ts @@ -0,0 +1,91 @@ +import { ethers } from 'ethers' + +const TOKEN_DECIMALS = ethers.BigNumber.from('10').pow( + ethers.BigNumber.from('18') +) +const MILLION = ethers.BigNumber.from('10').pow(ethers.BigNumber.from('6')) + +const FOUR_MILLION = ethers.BigNumber.from('4').mul(MILLION).mul(TOKEN_DECIMALS) +const TEN_MILLION = ethers.BigNumber.from('10').mul(MILLION).mul(TOKEN_DECIMALS) +const TWENTY_MILLION = ethers.BigNumber.from('20') + .mul(MILLION) + .mul(TOKEN_DECIMALS) +const PARTNER_MAX = ethers.BigNumber.from('78').mul(MILLION).mul(TOKEN_DECIMALS) + +const TEAM_MULTISIG = '0xb074ec6c37659525EEf2Fb44478077901F878012' +const TEAM_EOA = '0xe247340f06FCB7eb904F16a48C548221375b5b96' + +const arbTestnetConfig = { + // Chain const + lzChainId: 11, + lzEndpoint: '0x3c2269811836af69497E5F486A85D7316753cf62', + + // Tokens + WETH: '0x4200000000000000000000000000000000000006', + USDC: '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', + + // Addresses + teamEOA: TEAM_EOA, + teamMultisig: TEAM_MULTISIG, + emergencyCouncil: '0xcC2D01030eC2cd187346F70bFc483F24488C32E8', + + merkleRoot: + '0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f', + tokenWhitelist: [ + '0x4200000000000000000000000000000000000042', // OP + '0x4200000000000000000000000000000000000006', // WETH + '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', // USDC + '0x2E3D870790dC77A83DD1d18184Acc7439A53f475', // FRAX + '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', // DAI + '0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9', // sUSD + '0x217D47011b23BB961eB6D93cA9945B7501a5BB11', // THALES + '0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb', // LYRA + '0x67CCEA5bb16181E7b4109c9c2143c24a1c2205Be', // FXS + '0x9e1028F5F1D5eDE59748FFceE5532509976840E0', // PERP + '0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4', // SNX + '0xCB8FA9a76b8e203D8C3797bF438d8FB81Ea3326A', // alUSD + '0x3E29D3A9316dAB217754d13b28646B76607c5f04', // alETH + '0x8aE125E8653821E851F12A49F7765db9a9ce7384', // DOLA + '0x10010078a54396F62c96dF8532dc2B4847d47ED3', // HND + // "", // BTRFLY -- N/A + // "", // pxVELO -- N/A + '0xc40F949F8a4e094D1b49a23ea9241D289B7b2819' // LUSD + // "", // wstETH -- N/A + // "", // HOP -- N/A + ], + partnerAddrs: [ + TEAM_EOA, // VELO + '0x4a84675512949f81EBFEAAcC6C00D03eDd329de5', // OP + TEAM_EOA, // SNX -- custodied + '0xa283139017a2f5BAdE8d8e25412C600055D318F8', // INV + '0xDcf664d0f76E99eaA2DBD569474d0E75dC899FCD', // PERP + '0x489863b61C625a15C74FB4C21486baCb4A3937AB', // THALES + '0x641f26c67A5D0829Ae61019131093B6a7c7d18a3', // HND + '0xC224bf25Dcc99236F00843c7D8C4194abE8AA94a', // ALCX + '0xB6DACAE4eF97b4817d54df8e005269f509f803f9', // LYRA + TEAM_EOA, // MKR -- custodied + TEAM_EOA, // HOP -- custodied + '0x0dF840dCbf1229262A4125C1fc559bd338eC9491', // FRAX + '0x2E33A660742e813aD948fB9f7d682FE461E5fbf3', // BTRFLY + '0xd2D4e9024D8C90aB52032a9F1e0d92D4cE20191B' // LUSD + ], + partnerAmts: [ + TEN_MILLION, + TWENTY_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION + ], + partnerMax: PARTNER_MAX +} + +export default arbTestnetConfig diff --git a/tasks/deploy/index.ts b/tasks/deploy/index.ts index 2be5165e..34b725f6 100644 --- a/tasks/deploy/index.ts +++ b/tasks/deploy/index.ts @@ -1,3 +1,6 @@ -import "./op.ts"; -import "./ftm.ts"; -import "./init.ts"; \ No newline at end of file +import './op.ts' +import './ftm.ts' +import './init.ts' +import './arb.ts' +import './arbHardhat.ts' +import './arbTest.ts' diff --git a/test/NFTVote.t.sol b/test/NFTVote.t.sol index 2b032673..67444a8f 100644 --- a/test/NFTVote.t.sol +++ b/test/NFTVote.t.sol @@ -4,75 +4,81 @@ import "openzeppelin-contracts/contracts/access/Ownable.sol"; import "./BaseTest.sol"; import "utils/TestL2Governance.sol"; +// fix using two versions of same thing contract FlagCondition is Ownable { - bool public flag; + bool public flag; - function setFlag(bool _to) public onlyOwner { - flag = _to; - } + function setFlag(bool _to) public onlyOwner { + flag = _to; + } } contract NFTVoteTest is BaseTest { - VotingEscrow escrow; - TestL2Governance gov; - FlagCondition flag; + VotingEscrow escrow; + TestL2Governance gov; + FlagCondition flag; - function setUp() public { - deployCoins(); + function setUp() public { + deployCoins(); - VeArtProxy artProxy = new VeArtProxy(); - escrow = new VotingEscrow(address(VELO), address(artProxy)); - gov = new TestL2Governance(escrow); + VeArtProxy artProxy = new VeArtProxy(); + escrow = new VotingEscrow(address(VELO), address(artProxy)); + gov = new TestL2Governance(escrow); - // test variable to vote on - flag = new FlagCondition(); - flag.transferOwnership(address(gov)); + // test variable to vote on + flag = new FlagCondition(); + flag.transferOwnership(address(gov)); - VELO.mint(address(this), 1e21); - vm.roll(block.number + 1); - } + VELO.mint(address(this), 1e21); + vm.roll(block.number + 1); + } - function testLockAndPropose() public { - uint256 fourYears = 4 * 365 * 24 * 3600; - VELO.approve(address(escrow), 1e21); - escrow.create_lock(1e21, fourYears); - uint256 quorum = gov.quorum(block.timestamp); - uint256 numVotes = gov.getVotes(address(this), block.timestamp); - uint256 thresh = gov.proposalThreshold(); // 0 for now - assertGt(numVotes, thresh); - assertGt(numVotes, quorum); // owner will win + function testLockAndPropose() public { + uint256 fourYears = 4 * 365 * 24 * 3600; + VELO.approve(address(escrow), 1e21); + escrow.create_lock(1e21, fourYears); + uint256 quorum = gov.quorum(block.timestamp); + uint256 numVotes = gov.getVotes(address(this), block.timestamp); + uint256 thresh = gov.proposalThreshold(); // 0 for now + assertGt(numVotes, thresh); + assertGt(numVotes, quorum); // owner will win - // vote to set the flag to true - address[] memory targets = new address[](1); - targets[0] = address(flag); - uint256[] memory values = new uint256[](1); - values[0] = 0; - bytes[] memory calldatas = new bytes[](1); - bytes memory data = abi.encodeCall(flag.setFlag, (true)); - calldatas[0] = data; - string memory description = "no description"; + // vote to set the flag to true + address[] memory targets = new address[](1); + targets[0] = address(flag); + uint256[] memory values = new uint256[](1); + values[0] = 0; + bytes[] memory calldatas = new bytes[](1); + bytes memory data = abi.encodeCall(flag.setFlag, (true)); + calldatas[0] = data; + string memory description = "no description"; - uint256 proposal_id = gov.propose(targets, values, calldatas, description); + uint256 proposal_id = gov.propose( + targets, + values, + calldatas, + description + ); - // start block is at 2 - vm.warp(block.timestamp + 2); - vm.roll(block.number + 1); - gov.castVote( - proposal_id, - uint8(L2GovernorCountingSimple.VoteType.For) // 1 - ); + // start block is at 2 + vm.warp(block.timestamp + 2); + vm.roll(block.number + 1); + gov.castVote( + proposal_id, + uint8(L2GovernorCountingSimple.VoteType.For) // 1 + ); - vm.warp(block.timestamp + 7); - vm.roll(block.number + 1); // voting period over - assertEq(uint8(gov.state(proposal_id)), 4); // 3 = defeated, 4 = succeeded + vm.warp(block.timestamp + 7); + vm.roll(block.number + 1); // voting period over + assertEq(uint8(gov.state(proposal_id)), 4); // 3 = defeated, 4 = succeeded - uint256 executed_proposal_id = gov.execute( - targets, - values, - calldatas, - keccak256(bytes(description)) - ); - assertEq(executed_proposal_id, proposal_id); - assertTrue(flag.flag()); - } + uint256 executed_proposal_id = gov.execute( + targets, + values, + calldatas, + keccak256(bytes(description)) + ); + assertEq(executed_proposal_id, proposal_id); + assertTrue(flag.flag()); + } } diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 00000000..e5270bfd --- /dev/null +++ b/yarn.lock @@ -0,0 +1,8520 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@ensdomains/ens@^0.4.4": + version "0.4.5" + resolved "https://registry.yarnpkg.com/@ensdomains/ens/-/ens-0.4.5.tgz#e0aebc005afdc066447c6e22feb4eda89a5edbfc" + integrity sha512-JSvpj1iNMFjK6K+uVl4unqMoa9rf5jopb8cya5UGBWz23Nw8hSNT7efgUx4BTlAPAgpNlEioUfeTyQ6J9ZvTVw== + dependencies: + bluebird "^3.5.2" + eth-ens-namehash "^2.0.8" + solc "^0.4.20" + testrpc "0.0.1" + web3-utils "^1.0.0-beta.31" + +"@ensdomains/resolver@^0.2.4": + version "0.2.4" + resolved "https://registry.yarnpkg.com/@ensdomains/resolver/-/resolver-0.2.4.tgz#c10fe28bf5efbf49bff4666d909aed0265efbc89" + integrity sha512-bvaTH34PMCbv6anRa9I/0zjLJgY4EuznbEMgbV77JBCQ9KNC46rzi0avuxpOfu+xDjPEtSFGqVEOr5GlUSGudA== + +"@ethereum-waffle/chai@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/chai/-/chai-3.4.4.tgz#16c4cc877df31b035d6d92486dfdf983df9138ff" + integrity sha512-/K8czydBtXXkcM9X6q29EqEkc5dN3oYenyH2a9hF7rGAApAJUpH8QBtojxOY/xQ2up5W332jqgxwp0yPiYug1g== + dependencies: + "@ethereum-waffle/provider" "^3.4.4" + ethers "^5.5.2" + +"@ethereum-waffle/compiler@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/compiler/-/compiler-3.4.4.tgz#d568ee0f6029e68b5c645506079fbf67d0dfcf19" + integrity sha512-RUK3axJ8IkD5xpWjWoJgyHclOeEzDLQFga6gKpeGxiS/zBu+HB0W2FvsrrLalTFIaPw/CGYACRBSIxqiCqwqTQ== + dependencies: + "@resolver-engine/imports" "^0.3.3" + "@resolver-engine/imports-fs" "^0.3.3" + "@typechain/ethers-v5" "^2.0.0" + "@types/mkdirp" "^0.5.2" + "@types/node-fetch" "^2.5.5" + ethers "^5.0.1" + mkdirp "^0.5.1" + node-fetch "^2.6.1" + solc "^0.6.3" + ts-generator "^0.1.1" + typechain "^3.0.0" + +"@ethereum-waffle/ens@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/ens/-/ens-3.4.4.tgz#db97ea2c9decbb70b9205d53de2ccbd6f3182ba1" + integrity sha512-0m4NdwWxliy3heBYva1Wr4WbJKLnwXizmy5FfSSr5PMbjI7SIGCdCB59U7/ZzY773/hY3bLnzLwvG5mggVjJWg== + dependencies: + "@ensdomains/ens" "^0.4.4" + "@ensdomains/resolver" "^0.2.4" + ethers "^5.5.2" + +"@ethereum-waffle/mock-contract@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/mock-contract/-/mock-contract-3.4.4.tgz#fc6ffa18813546f4950a69f5892d4dd54b2c685a" + integrity sha512-Mp0iB2YNWYGUV+VMl5tjPsaXKbKo8MDH9wSJ702l9EBjdxFf/vBvnMBAC1Fub1lLtmD0JHtp1pq+mWzg/xlLnA== + dependencies: + "@ethersproject/abi" "^5.5.0" + ethers "^5.5.2" + +"@ethereum-waffle/provider@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/provider/-/provider-3.4.4.tgz#398fc1f7eb91cc2df7d011272eacba8af0c7fffb" + integrity sha512-GK8oKJAM8+PKy2nK08yDgl4A80mFuI8zBkE0C9GqTRYQqvuxIyXoLmJ5NZU9lIwyWVv5/KsoA11BgAv2jXE82g== + dependencies: + "@ethereum-waffle/ens" "^3.4.4" + ethers "^5.5.2" + ganache-core "^2.13.2" + patch-package "^6.2.2" + postinstall-postinstall "^2.1.0" + +"@ethersproject/abi@5.0.0-beta.153": + version "5.0.0-beta.153" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.0-beta.153.tgz#43a37172b33794e4562999f6e2d555b7599a8eee" + integrity sha512-aXweZ1Z7vMNzJdLpR1CZUAIgnwjrZeUSvN9syCwlBaEBUFJmFY+HHnfuTI5vIhVs/mRkfJVrbEyl51JZQqyjAg== + dependencies: + "@ethersproject/address" ">=5.0.0-beta.128" + "@ethersproject/bignumber" ">=5.0.0-beta.130" + "@ethersproject/bytes" ">=5.0.0-beta.129" + "@ethersproject/constants" ">=5.0.0-beta.128" + "@ethersproject/hash" ">=5.0.0-beta.128" + "@ethersproject/keccak256" ">=5.0.0-beta.127" + "@ethersproject/logger" ">=5.0.0-beta.129" + "@ethersproject/properties" ">=5.0.0-beta.131" + "@ethersproject/strings" ">=5.0.0-beta.130" + +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.5.0", "@ethersproject/abi@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" + integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" + integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + +"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" + integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/address@5.7.0", "@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" + integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + +"@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" + integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + +"@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" + integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" + integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + bn.js "^5.2.1" + +"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" + integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/constants@5.7.0", "@ethersproject/constants@>=5.0.0-beta.128", "@ethersproject/constants@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" + integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + +"@ethersproject/contracts@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" + integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== + dependencies: + "@ethersproject/abi" "^5.7.0" + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + +"@ethersproject/hash@5.7.0", "@ethersproject/hash@>=5.0.0-beta.128", "@ethersproject/hash@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" + integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" + integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" + integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + aes-js "3.0.0" + scrypt-js "3.0.1" + +"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@>=5.0.0-beta.127", "@ethersproject/keccak256@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" + integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + js-sha3 "0.8.0" + +"@ethersproject/logger@5.7.0", "@ethersproject/logger@>=5.0.0-beta.129", "@ethersproject/logger@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" + integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== + +"@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" + integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" + integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + +"@ethersproject/properties@5.7.0", "@ethersproject/properties@>=5.0.0-beta.131", "@ethersproject/properties@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" + integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/providers@5.7.2": + version "5.7.2" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" + integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + bech32 "1.1.4" + ws "7.4.6" + +"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" + integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" + integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" + integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + hash.js "1.1.7" + +"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" + integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + bn.js "^5.2.1" + elliptic "6.5.4" + hash.js "1.1.7" + +"@ethersproject/solidity@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" + integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/strings@5.7.0", "@ethersproject/strings@>=5.0.0-beta.130", "@ethersproject/strings@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" + integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.0.0-beta.135", "@ethersproject/transactions@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" + integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + +"@ethersproject/units@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" + integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/wallet@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" + integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/json-wallets" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" + integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== + dependencies: + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" + integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@metamask/eth-sig-util@^4.0.0": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz#3ad61f6ea9ad73ba5b19db780d40d9aae5157088" + integrity sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ== + dependencies: + ethereumjs-abi "^0.6.8" + ethereumjs-util "^6.2.1" + ethjs-util "^0.1.6" + tweetnacl "^1.0.3" + tweetnacl-util "^0.15.1" + +"@noble/hashes@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.2.tgz#e9e035b9b166ca0af657a7848eb2718f0f22f183" + integrity sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA== + +"@noble/hashes@~1.1.1": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.5.tgz#1a0377f3b9020efe2fae03290bd2a12140c95c11" + integrity sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ== + +"@noble/secp256k1@1.6.3", "@noble/secp256k1@~1.6.0": + version "1.6.3" + resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.6.3.tgz#7eed12d9f4404b416999d0c87686836c4c5c9b94" + integrity sha512-T04e4iTurVy7I8Sw4+c5OSN9/RkPlo1uKxAomtxQNLq8j1uPAqnsqG1bqvY3Jv7c13gyr6dui0zmh/I3+f/JaQ== + +"@nomicfoundation/ethereumjs-block@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-4.0.0.tgz#fdd5c045e7baa5169abeed0e1202bf94e4481c49" + integrity sha512-bk8uP8VuexLgyIZAHExH1QEovqx0Lzhc9Ntm63nCRKLHXIZkobaFaeCVwTESV7YkPKUk7NiK11s8ryed4CS9yA== + dependencies: + "@nomicfoundation/ethereumjs-common" "^3.0.0" + "@nomicfoundation/ethereumjs-rlp" "^4.0.0" + "@nomicfoundation/ethereumjs-trie" "^5.0.0" + "@nomicfoundation/ethereumjs-tx" "^4.0.0" + "@nomicfoundation/ethereumjs-util" "^8.0.0" + ethereum-cryptography "0.1.3" + +"@nomicfoundation/ethereumjs-blockchain@^6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-6.0.0.tgz#1a8c243a46d4d3691631f139bfb3a4a157187b0c" + integrity sha512-pLFEoea6MWd81QQYSReLlLfH7N9v7lH66JC/NMPN848ySPPQA5renWnE7wPByfQFzNrPBuDDRFFULMDmj1C0xw== + dependencies: + "@nomicfoundation/ethereumjs-block" "^4.0.0" + "@nomicfoundation/ethereumjs-common" "^3.0.0" + "@nomicfoundation/ethereumjs-ethash" "^2.0.0" + "@nomicfoundation/ethereumjs-rlp" "^4.0.0" + "@nomicfoundation/ethereumjs-trie" "^5.0.0" + "@nomicfoundation/ethereumjs-util" "^8.0.0" + abstract-level "^1.0.3" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + level "^8.0.0" + lru-cache "^5.1.1" + memory-level "^1.0.0" + +"@nomicfoundation/ethereumjs-common@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-3.0.0.tgz#f6bcc7753994555e49ab3aa517fc8bcf89c280b9" + integrity sha512-WS7qSshQfxoZOpHG/XqlHEGRG1zmyjYrvmATvc4c62+gZXgre1ymYP8ZNgx/3FyZY0TWe9OjFlKOfLqmgOeYwA== + dependencies: + "@nomicfoundation/ethereumjs-util" "^8.0.0" + crc-32 "^1.2.0" + +"@nomicfoundation/ethereumjs-ethash@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-2.0.0.tgz#11539c32fe0990e1122ff987d1b84cfa34774e81" + integrity sha512-WpDvnRncfDUuXdsAXlI4lXbqUDOA+adYRQaEezIkxqDkc+LDyYDbd/xairmY98GnQzo1zIqsIL6GB5MoMSJDew== + dependencies: + "@nomicfoundation/ethereumjs-block" "^4.0.0" + "@nomicfoundation/ethereumjs-rlp" "^4.0.0" + "@nomicfoundation/ethereumjs-util" "^8.0.0" + abstract-level "^1.0.3" + bigint-crypto-utils "^3.0.23" + ethereum-cryptography "0.1.3" + +"@nomicfoundation/ethereumjs-evm@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-1.0.0.tgz#99cd173c03b59107c156a69c5e215409098a370b" + integrity sha512-hVS6qRo3V1PLKCO210UfcEQHvlG7GqR8iFzp0yyjTg2TmJQizcChKgWo8KFsdMw6AyoLgLhHGHw4HdlP8a4i+Q== + dependencies: + "@nomicfoundation/ethereumjs-common" "^3.0.0" + "@nomicfoundation/ethereumjs-util" "^8.0.0" + "@types/async-eventemitter" "^0.2.1" + async-eventemitter "^0.2.4" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + mcl-wasm "^0.7.1" + rustbn.js "~0.2.0" + +"@nomicfoundation/ethereumjs-rlp@^4.0.0", "@nomicfoundation/ethereumjs-rlp@^4.0.0-beta.2": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-4.0.0.tgz#d9a9c5f0f10310c8849b6525101de455a53e771d" + integrity sha512-GaSOGk5QbUk4eBP5qFbpXoZoZUj/NrW7MRa0tKY4Ew4c2HAS0GXArEMAamtFrkazp0BO4K5p2ZCG3b2FmbShmw== + +"@nomicfoundation/ethereumjs-statemanager@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-1.0.0.tgz#14a9d4e1c828230368f7ab520c144c34d8721e4b" + integrity sha512-jCtqFjcd2QejtuAMjQzbil/4NHf5aAWxUc+CvS0JclQpl+7M0bxMofR2AJdtz+P3u0ke2euhYREDiE7iSO31vQ== + dependencies: + "@nomicfoundation/ethereumjs-common" "^3.0.0" + "@nomicfoundation/ethereumjs-rlp" "^4.0.0" + "@nomicfoundation/ethereumjs-trie" "^5.0.0" + "@nomicfoundation/ethereumjs-util" "^8.0.0" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + functional-red-black-tree "^1.0.1" + +"@nomicfoundation/ethereumjs-trie@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-5.0.0.tgz#dcfbe3be53a94bc061c9767a396c16702bc2f5b7" + integrity sha512-LIj5XdE+s+t6WSuq/ttegJzZ1vliwg6wlb+Y9f4RlBpuK35B9K02bO7xU+E6Rgg9RGptkWd6TVLdedTI4eNc2A== + dependencies: + "@nomicfoundation/ethereumjs-rlp" "^4.0.0" + "@nomicfoundation/ethereumjs-util" "^8.0.0" + ethereum-cryptography "0.1.3" + readable-stream "^3.6.0" + +"@nomicfoundation/ethereumjs-tx@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-4.0.0.tgz#59dc7452b0862b30342966f7052ab9a1f7802f52" + integrity sha512-Gg3Lir2lNUck43Kp/3x6TfBNwcWC9Z1wYue9Nz3v4xjdcv6oDW9QSMJxqsKw9QEGoBBZ+gqwpW7+F05/rs/g1w== + dependencies: + "@nomicfoundation/ethereumjs-common" "^3.0.0" + "@nomicfoundation/ethereumjs-rlp" "^4.0.0" + "@nomicfoundation/ethereumjs-util" "^8.0.0" + ethereum-cryptography "0.1.3" + +"@nomicfoundation/ethereumjs-util@^8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-8.0.0.tgz#deb2b15d2c308a731e82977aefc4e61ca0ece6c5" + integrity sha512-2emi0NJ/HmTG+CGY58fa+DQuAoroFeSH9gKu9O6JnwTtlzJtgfTixuoOqLEgyyzZVvwfIpRueuePb8TonL1y+A== + dependencies: + "@nomicfoundation/ethereumjs-rlp" "^4.0.0-beta.2" + ethereum-cryptography "0.1.3" + +"@nomicfoundation/ethereumjs-vm@^6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-6.0.0.tgz#2bb50d332bf41790b01a3767ffec3987585d1de6" + integrity sha512-JMPxvPQ3fzD063Sg3Tp+UdwUkVxMoo1uML6KSzFhMH3hoQi/LMuXBoEHAoW83/vyNS9BxEe6jm6LmT5xdeEJ6w== + dependencies: + "@nomicfoundation/ethereumjs-block" "^4.0.0" + "@nomicfoundation/ethereumjs-blockchain" "^6.0.0" + "@nomicfoundation/ethereumjs-common" "^3.0.0" + "@nomicfoundation/ethereumjs-evm" "^1.0.0" + "@nomicfoundation/ethereumjs-rlp" "^4.0.0" + "@nomicfoundation/ethereumjs-statemanager" "^1.0.0" + "@nomicfoundation/ethereumjs-trie" "^5.0.0" + "@nomicfoundation/ethereumjs-tx" "^4.0.0" + "@nomicfoundation/ethereumjs-util" "^8.0.0" + "@types/async-eventemitter" "^0.2.1" + async-eventemitter "^0.2.4" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + functional-red-black-tree "^1.0.1" + mcl-wasm "^0.7.1" + rustbn.js "~0.2.0" + +"@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.0.tgz#83a7367342bd053a76d04bbcf4f373fef07cf760" + integrity sha512-vEF3yKuuzfMHsZecHQcnkUrqm8mnTWfJeEVFHpg+cO+le96xQA4lAJYdUan8pXZohQxv1fSReQsn4QGNuBNuCw== + +"@nomicfoundation/solidity-analyzer-darwin-x64@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.0.tgz#1225f7da647ae1ad25a87125664704ecc0af6ccc" + integrity sha512-dlHeIg0pTL4dB1l9JDwbi/JG6dHQaU1xpDK+ugYO8eJ1kxx9Dh2isEUtA4d02cQAl22cjOHTvifAk96A+ItEHA== + +"@nomicfoundation/solidity-analyzer-freebsd-x64@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-freebsd-x64/-/solidity-analyzer-freebsd-x64-0.1.0.tgz#dbc052dcdfd50ae50fd5ae1788b69b4e0fa40040" + integrity sha512-WFCZYMv86WowDA4GiJKnebMQRt3kCcFqHeIomW6NMyqiKqhK1kIZCxSLDYsxqlx396kKLPN1713Q1S8tu68GKg== + +"@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.0.tgz#e6b2eea633995b557e74e881d2a43eab4760903d" + integrity sha512-DTw6MNQWWlCgc71Pq7CEhEqkb7fZnS7oly13pujs4cMH1sR0JzNk90Mp1zpSCsCs4oKan2ClhMlLKtNat/XRKQ== + +"@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.0.tgz#af81107f5afa794f19988a368647727806e18dc4" + integrity sha512-wUpUnR/3GV5Da88MhrxXh/lhb9kxh9V3Jya2NpBEhKDIRCDmtXMSqPMXHZmOR9DfCwCvG6vLFPr/+YrPCnUN0w== + +"@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.0.tgz#6877e1da1a06a9f08446070ab6e0a5347109f868" + integrity sha512-lR0AxK1x/MeKQ/3Pt923kPvwigmGX3OxeU5qNtQ9pj9iucgk4PzhbS3ruUeSpYhUxG50jN4RkIGwUMoev5lguw== + +"@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.0.tgz#bb6cd83a0c259eccef4183796b6329a66cf7ebd9" + integrity sha512-A1he/8gy/JeBD3FKvmI6WUJrGrI5uWJNr5Xb9WdV+DK0F8msuOqpEByLlnTdLkXMwW7nSl3awvLezOs9xBHJEg== + +"@nomicfoundation/solidity-analyzer-win32-arm64-msvc@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-arm64-msvc/-/solidity-analyzer-win32-arm64-msvc-0.1.0.tgz#9d4bca1cc9a1333fde985675083b0b7d165f6076" + integrity sha512-7x5SXZ9R9H4SluJZZP8XPN+ju7Mx+XeUMWZw7ZAqkdhP5mK19I4vz3x0zIWygmfE8RT7uQ5xMap0/9NPsO+ykw== + +"@nomicfoundation/solidity-analyzer-win32-ia32-msvc@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-ia32-msvc/-/solidity-analyzer-win32-ia32-msvc-0.1.0.tgz#0db5bfc6aa952bea4098d8d2c8947b4e5c4337ee" + integrity sha512-m7w3xf+hnE774YRXu+2mGV7RiF3QJtUoiYU61FascCkQhX3QMQavh7saH/vzb2jN5D24nT/jwvaHYX/MAM9zUw== + +"@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.0.tgz#2e0f39a2924dcd77db6b419828595e984fabcb33" + integrity sha512-xCuybjY0sLJQnJhupiFAXaek2EqF0AP0eBjgzaalPXSNvCEN6ZYHvUzdA50ENDVeSYFXcUsYf3+FsD3XKaeptA== + +"@nomicfoundation/solidity-analyzer@^0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.0.tgz#e5ddc43ad5c0aab96e5054520d8e16212e125f50" + integrity sha512-xGWAiVCGOycvGiP/qrlf9f9eOn7fpNbyJygcB0P21a1MDuVPlKt0Srp7rvtBEutYQ48ouYnRXm33zlRnlTOPHg== + optionalDependencies: + "@nomicfoundation/solidity-analyzer-darwin-arm64" "0.1.0" + "@nomicfoundation/solidity-analyzer-darwin-x64" "0.1.0" + "@nomicfoundation/solidity-analyzer-freebsd-x64" "0.1.0" + "@nomicfoundation/solidity-analyzer-linux-arm64-gnu" "0.1.0" + "@nomicfoundation/solidity-analyzer-linux-arm64-musl" "0.1.0" + "@nomicfoundation/solidity-analyzer-linux-x64-gnu" "0.1.0" + "@nomicfoundation/solidity-analyzer-linux-x64-musl" "0.1.0" + "@nomicfoundation/solidity-analyzer-win32-arm64-msvc" "0.1.0" + "@nomicfoundation/solidity-analyzer-win32-ia32-msvc" "0.1.0" + "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.0" + +"@nomiclabs/hardhat-ethers@^2.0.6": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.2.1.tgz#8057b43566a0e41abeb8142064a3c0d3f23dca86" + integrity sha512-RHWYwnxryWR8hzRmU4Jm/q4gzvXpetUOJ4OPlwH2YARcDB+j79+yAYCwO0lN1SUOb4++oOTJEe6AWLEc42LIvg== + +"@nomiclabs/hardhat-etherscan@^3.0.4": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.1.4.tgz#970e57fabc6060489c93b3f646ca790db36ffee0" + integrity sha512-fw8JCfukf6MdIGoySRmSftlM2wBgoaSbWQZgiYfD/KTeaSFEWCdMpuPZcLSBXtwtnQyyWDs07Lo7fL8HSqtD2Q== + dependencies: + "@ethersproject/abi" "^5.1.2" + "@ethersproject/address" "^5.0.2" + cbor "^8.1.0" + chalk "^2.4.2" + debug "^4.1.1" + fs-extra "^7.0.1" + lodash "^4.17.11" + semver "^6.3.0" + table "^6.8.0" + undici "^5.4.0" + +"@nomiclabs/hardhat-waffle@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.3.tgz#9c538a09c5ed89f68f5fd2dc3f78f16ed1d6e0b1" + integrity sha512-049PHSnI1CZq6+XTbrMbMv5NaL7cednTfPenx02k3cEh8wBMLa6ys++dBETJa6JjfwgA9nBhhHQ173LJv6k2Pg== + dependencies: + "@types/sinon-chai" "^3.2.3" + "@types/web3" "1.0.19" + +"@resolver-engine/core@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/core/-/core-0.3.3.tgz#590f77d85d45bc7ecc4e06c654f41345db6ca967" + integrity sha512-eB8nEbKDJJBi5p5SrvrvILn4a0h42bKtbCTri3ZxCGt6UvoQyp7HnGOfki944bUjBSHKK3RvgfViHn+kqdXtnQ== + dependencies: + debug "^3.1.0" + is-url "^1.2.4" + request "^2.85.0" + +"@resolver-engine/fs@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/fs/-/fs-0.3.3.tgz#fbf83fa0c4f60154a82c817d2fe3f3b0c049a973" + integrity sha512-wQ9RhPUcny02Wm0IuJwYMyAG8fXVeKdmhm8xizNByD4ryZlx6PP6kRen+t/haF43cMfmaV7T3Cx6ChOdHEhFUQ== + dependencies: + "@resolver-engine/core" "^0.3.3" + debug "^3.1.0" + +"@resolver-engine/imports-fs@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/imports-fs/-/imports-fs-0.3.3.tgz#4085db4b8d3c03feb7a425fbfcf5325c0d1e6c1b" + integrity sha512-7Pjg/ZAZtxpeyCFlZR5zqYkz+Wdo84ugB5LApwriT8XFeQoLwGUj4tZFFvvCuxaNCcqZzCYbonJgmGObYBzyCA== + dependencies: + "@resolver-engine/fs" "^0.3.3" + "@resolver-engine/imports" "^0.3.3" + debug "^3.1.0" + +"@resolver-engine/imports@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/imports/-/imports-0.3.3.tgz#badfb513bb3ff3c1ee9fd56073e3144245588bcc" + integrity sha512-anHpS4wN4sRMwsAbMXhMfOD/y4a4Oo0Cw/5+rue7hSwGWsDOQaAU1ClK1OxjUC35/peazxEl8JaSRRS+Xb8t3Q== + dependencies: + "@resolver-engine/core" "^0.3.3" + debug "^3.1.0" + hosted-git-info "^2.6.0" + path-browserify "^1.0.0" + url "^0.11.0" + +"@scure/base@~1.1.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" + integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA== + +"@scure/bip32@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.0.tgz#dea45875e7fbc720c2b4560325f1cf5d2246d95b" + integrity sha512-ftTW3kKX54YXLCxH6BB7oEEoJfoE2pIgw7MINKAs5PsS6nqKPuKk1haTF/EuHmYqG330t5GSrdmtRuHaY1a62Q== + dependencies: + "@noble/hashes" "~1.1.1" + "@noble/secp256k1" "~1.6.0" + "@scure/base" "~1.1.0" + +"@scure/bip39@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.0.tgz#92f11d095bae025f166bef3defcc5bf4945d419a" + integrity sha512-pwrPOS16VeTKg98dYXQyIjJEcWfz7/1YJIwxUEPFfQPtc86Ym/1sVgQ2RLoD43AazMk2l/unK4ITySSpW2+82w== + dependencies: + "@noble/hashes" "~1.1.1" + "@scure/base" "~1.1.0" + +"@sentry/core@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" + integrity sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/minimal" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/hub@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.30.0.tgz#2453be9b9cb903404366e198bd30c7ca74cdc100" + integrity sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ== + dependencies: + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/minimal@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.30.0.tgz#ce3d3a6a273428e0084adcb800bc12e72d34637b" + integrity sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/types" "5.30.0" + tslib "^1.9.3" + +"@sentry/node@^5.18.1": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.30.0.tgz#4ca479e799b1021285d7fe12ac0858951c11cd48" + integrity sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg== + dependencies: + "@sentry/core" "5.30.0" + "@sentry/hub" "5.30.0" + "@sentry/tracing" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + cookie "^0.4.1" + https-proxy-agent "^5.0.0" + lru_map "^0.3.3" + tslib "^1.9.3" + +"@sentry/tracing@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-5.30.0.tgz#501d21f00c3f3be7f7635d8710da70d9419d4e1f" + integrity sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/minimal" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/types@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.30.0.tgz#19709bbe12a1a0115bc790b8942917da5636f402" + integrity sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw== + +"@sentry/utils@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.30.0.tgz#9a5bd7ccff85ccfe7856d493bffa64cabc41e980" + integrity sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww== + dependencies: + "@sentry/types" "5.30.0" + tslib "^1.9.3" + +"@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + +"@sindresorhus/is@^4.0.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" + integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== + +"@solidity-parser/parser@^0.14.5": + version "0.14.5" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.14.5.tgz#87bc3cc7b068e08195c219c91cd8ddff5ef1a804" + integrity sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg== + dependencies: + antlr4ts "^0.5.0-alpha.4" + +"@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + dependencies: + defer-to-connect "^1.0.1" + +"@szmarczak/http-timer@^4.0.5": + version "4.0.6" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807" + integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w== + dependencies: + defer-to-connect "^2.0.0" + +"@tsconfig/node10@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" + integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" + integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== + +"@typechain/ethers-v5@^10.0.0": + version "10.2.0" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-10.2.0.tgz#68f5963efb5214cb2d881477228e4b5b315473e1" + integrity sha512-ikaq0N/w9fABM+G01OFmU3U3dNnyRwEahkdvi9mqy1a3XwKiPZaF/lu54OcNaEWnpvEYyhhS0N7buCtLQqC92w== + dependencies: + lodash "^4.17.15" + ts-essentials "^7.0.1" + +"@typechain/ethers-v5@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-2.0.0.tgz#cd3ca1590240d587ca301f4c029b67bfccd08810" + integrity sha512-0xdCkyGOzdqh4h5JSf+zoWx85IusEjDcPIwNEHP8mrWSnCae4rvrqB+/gtpdNfX7zjlFlZiMeePn2r63EI3Lrw== + dependencies: + ethers "^5.0.2" + +"@typechain/hardhat@^6.0.0": + version "6.1.5" + resolved "https://registry.yarnpkg.com/@typechain/hardhat/-/hardhat-6.1.5.tgz#caad58a1d3e9cd88061a584eb4f4fa763d5dcad1" + integrity sha512-lg7LW4qDZpxFMknp3Xool61Fg6Lays8F8TXdFGBG+MxyYcYU5795P1U2XdStuzGq9S2Dzdgh+1jGww9wvZ6r4Q== + dependencies: + fs-extra "^9.1.0" + +"@types/async-eventemitter@^0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@types/async-eventemitter/-/async-eventemitter-0.2.1.tgz#f8e6280e87e8c60b2b938624b0a3530fb3e24712" + integrity sha512-M2P4Ng26QbAeITiH7w1d7OxtldgfAe0wobpyJzVK/XOb0cUGKU2R4pfAhqcJBXAe2ife5ZOhSv4wk7p+ffURtg== + +"@types/bn.js@*", "@types/bn.js@^5.1.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" + integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== + dependencies: + "@types/node" "*" + +"@types/bn.js@^4.11.3", "@types/bn.js@^4.11.5": + version "4.11.6" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" + integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== + dependencies: + "@types/node" "*" + +"@types/cacheable-request@^6.0.1": + version "6.0.3" + resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183" + integrity sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw== + dependencies: + "@types/http-cache-semantics" "*" + "@types/keyv" "^3.1.4" + "@types/node" "*" + "@types/responselike" "^1.0.0" + +"@types/chai@*", "@types/chai@^4.3.0": + version "4.3.4" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.4.tgz#e913e8175db8307d78b4e8fa690408ba6b65dee4" + integrity sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw== + +"@types/http-cache-semantics@*": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812" + integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ== + +"@types/keyv@^3.1.4": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6" + integrity sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg== + dependencies: + "@types/node" "*" + +"@types/lru-cache@^5.1.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" + integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw== + +"@types/mkdirp@^0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-0.5.2.tgz#503aacfe5cc2703d5484326b1b27efa67a339c1f" + integrity sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg== + dependencies: + "@types/node" "*" + +"@types/mocha@^9.1.0": + version "9.1.1" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4" + integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== + +"@types/node-fetch@^2.5.5": + version "2.6.2" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.2.tgz#d1a9c5fd049d9415dce61571557104dec3ec81da" + integrity sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + +"@types/node@*": + version "18.11.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.18.tgz#8dfb97f0da23c2293e554c5a50d61ef134d7697f" + integrity sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA== + +"@types/node@^12.12.6": + version "12.20.55" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" + integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== + +"@types/node@^17.0.35": + version "17.0.45" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190" + integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw== + +"@types/pbkdf2@^3.0.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.0.tgz#039a0e9b67da0cdc4ee5dab865caa6b267bb66b1" + integrity sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ== + dependencies: + "@types/node" "*" + +"@types/prettier@^2.1.1": + version "2.7.2" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.2.tgz#6c2324641cc4ba050a8c710b2b251b377581fbf0" + integrity sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg== + +"@types/resolve@^0.0.8": + version "0.0.8" + resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194" + integrity sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ== + dependencies: + "@types/node" "*" + +"@types/responselike@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" + integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA== + dependencies: + "@types/node" "*" + +"@types/secp256k1@^4.0.1": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.3.tgz#1b8e55d8e00f08ee7220b4d59a6abe89c37a901c" + integrity sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w== + dependencies: + "@types/node" "*" + +"@types/sinon-chai@^3.2.3": + version "3.2.9" + resolved "https://registry.yarnpkg.com/@types/sinon-chai/-/sinon-chai-3.2.9.tgz#71feb938574bbadcb176c68e5ff1a6014c5e69d4" + integrity sha512-/19t63pFYU0ikrdbXKBWj9PCdnKyTd0Qkz0X91Ta081cYsq90OxYdcWwK/dwEoDa6dtXgj2HJfmzgq+QZTHdmQ== + dependencies: + "@types/chai" "*" + "@types/sinon" "*" + +"@types/sinon@*": + version "10.0.13" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.13.tgz#60a7a87a70d9372d0b7b38cc03e825f46981fb83" + integrity sha512-UVjDqJblVNQYvVNUsj0PuYYw0ELRmgt1Nt5Vk0pT5f16ROGfcKJY8o1HVuMOJOpD727RrGB9EGvoaTQE5tgxZQ== + dependencies: + "@types/sinonjs__fake-timers" "*" + +"@types/sinonjs__fake-timers@*": + version "8.1.2" + resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz#bf2e02a3dbd4aecaf95942ecd99b7402e03fad5e" + integrity sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA== + +"@types/underscore@*": + version "1.11.4" + resolved "https://registry.yarnpkg.com/@types/underscore/-/underscore-1.11.4.tgz#62e393f8bc4bd8a06154d110c7d042a93751def3" + integrity sha512-uO4CD2ELOjw8tasUrAhvnn2W4A0ZECOvMjCivJr4gA9pGgjv+qxKWY9GLTMVEK8ej85BxQOocUyE7hImmSQYcg== + +"@types/web3@1.0.19": + version "1.0.19" + resolved "https://registry.yarnpkg.com/@types/web3/-/web3-1.0.19.tgz#46b85d91d398ded9ab7c85a5dd57cb33ac558924" + integrity sha512-fhZ9DyvDYDwHZUp5/STa9XW2re0E8GxoioYJ4pEUZ13YHpApSagixj7IAdoYH5uAK+UalGq6Ml8LYzmgRA/q+A== + dependencies: + "@types/bn.js" "*" + "@types/underscore" "*" + +"@yarnpkg/lockfile@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" + integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== + +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + +abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/abstract-level/-/abstract-level-1.0.3.tgz#78a67d3d84da55ee15201486ab44c09560070741" + integrity sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA== + dependencies: + buffer "^6.0.3" + catering "^2.1.0" + is-buffer "^2.0.5" + level-supports "^4.0.0" + level-transcoder "^1.0.1" + module-error "^1.0.1" + queue-microtask "^1.2.3" + +abstract-leveldown@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-3.0.0.tgz#5cb89f958a44f526779d740d1440e743e0c30a57" + integrity sha512-KUWx9UWGQD12zsmLNj64/pndaz4iJh/Pj7nopgkfDG6RlCcbMZvT6+9l7dchK4idog2Is8VdC/PvNbFuFmalIQ== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@^2.4.1, abstract-leveldown@~2.7.1: + version "2.7.2" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz#87a44d7ebebc341d59665204834c8b7e0932cc93" + integrity sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@^5.0.0, abstract-leveldown@~5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz#f7128e1f86ccabf7d2893077ce5d06d798e386c6" + integrity sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@~2.6.0: + version "2.6.3" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz#1c5e8c6a5ef965ae8c35dfb3a8770c476b82c4b8" + integrity sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA== + dependencies: + xtend "~4.0.0" + +accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +acorn-walk@^8.1.1: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + +acorn@^8.4.1: + version "8.8.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.1.tgz#0a3f9cbecc4ec3bea6f0a80b66ae8dd2da250b73" + integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA== + +adm-zip@^0.4.16: + version "0.4.16" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365" + integrity sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg== + +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== + +aes-js@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" + integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ajv@^6.12.3: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.0.1: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +ansi-colors@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-colors@^4.1.0, ansi-colors@^4.1.1: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== + +ansi-escapes@^4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +antlr4ts@^0.5.0-alpha.4: + version "0.5.0-alpha.4" + resolved "https://registry.yarnpkg.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz#71702865a87478ed0b40c0709f422cf14d51652a" + integrity sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ== + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA== + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q== + +array-back@^1.0.3, array-back@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-1.0.4.tgz#644ba7f095f7ffcf7c43b5f0dc39d3c1f03c063b" + integrity sha512-1WxbZvrmyhkNoeYcizokbmh5oiOCIfyvGtcqbK3Ls1v1fKcquzxnQSceOx6tzq7jmai2kFLWIpGND2cLhH6TPw== + dependencies: + typical "^2.6.0" + +array-back@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-2.0.0.tgz#6877471d51ecc9c9bfa6136fb6c7d5fe69748022" + integrity sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw== + dependencies: + typical "^2.6.1" + +array-back@^3.0.1, array-back@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" + integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== + +array-back@^4.0.1, array-back@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e" + integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg== + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ== + +array.prototype.reduce@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz#6b20b0daa9d9734dd6bc7ea66b5bbce395471eac" + integrity sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-array-method-boxes-properly "^1.0.0" + is-string "^1.0.7" + +asn1.js@^5.2.0: + version "5.4.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" + integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + safer-buffer "^2.1.0" + +asn1@~0.2.3: + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== + +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw== + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + +async-eventemitter@^0.2.2, async-eventemitter@^0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" + integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw== + dependencies: + async "^2.4.0" + +async-limiter@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" + integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + +async@2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381" + integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg== + dependencies: + lodash "^4.17.11" + +async@^1.4.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + integrity sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w== + +async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.5.0, async@^2.6.1: + version "2.6.4" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" + integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== + dependencies: + lodash "^4.17.14" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + +atob@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +available-typed-arrays@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" + integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== + +aws4@^1.8.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" + integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== + +babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + integrity sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g== + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-core@^6.0.14, babel-core@^6.26.0: + version "6.26.3" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" + integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== + dependencies: + babel-code-frame "^6.26.0" + babel-generator "^6.26.0" + babel-helpers "^6.24.1" + babel-messages "^6.23.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + convert-source-map "^1.5.1" + debug "^2.6.9" + json5 "^0.5.1" + lodash "^4.17.4" + minimatch "^3.0.4" + path-is-absolute "^1.0.1" + private "^0.1.8" + slash "^1.0.0" + source-map "^0.5.7" + +babel-generator@^6.26.0: + version "6.26.1" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" + integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.17.4" + source-map "^0.5.7" + trim-right "^1.0.1" + +babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" + integrity sha512-gCtfYORSG1fUMX4kKraymq607FWgMWg+j42IFPc18kFQEsmtaibP4UrqsXt8FlEJle25HUd4tsoDR7H2wDhe9Q== + dependencies: + babel-helper-explode-assignable-expression "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-call-delegate@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" + integrity sha512-RL8n2NiEj+kKztlrVJM9JT1cXzzAdvWFh76xh/H1I4nKwunzE4INBXn8ieCZ+wh4zWszZk7NBS1s/8HR5jDkzQ== + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-define-map@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" + integrity sha512-bHkmjcC9lM1kmZcVpA5t2om2nzT/xiZpo6TJq7UlZ3wqKfzia4veeXbIhKvJXAMzhhEBd3cR1IElL5AenWEUpA== + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-explode-assignable-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" + integrity sha512-qe5csbhbvq6ccry9G7tkXbzNtcDiH4r51rrPUbwwoTzZ18AqxWYRZT6AOmxrpxKnQBW0pYlBI/8vh73Z//78nQ== + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-function-name@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" + integrity sha512-Oo6+e2iX+o9eVvJ9Y5eKL5iryeRdsIkwRYheCuhYdVHsdEQysbc2z2QkqCLIYnNxkT5Ss3ggrHdXiDI7Dhrn4Q== + dependencies: + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-get-function-arity@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" + integrity sha512-WfgKFX6swFB1jS2vo+DwivRN4NB8XUdM3ij0Y1gnC21y1tdBoe6xjVnd7NSI6alv+gZXCtJqvrTeMW3fR/c0ng== + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-hoist-variables@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" + integrity sha512-zAYl3tqerLItvG5cKYw7f1SpvIxS9zi7ohyGHaI9cgDUjAT6YcY9jIEH5CstetP5wHIVSceXwNS7Z5BpJg+rOw== + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-optimise-call-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" + integrity sha512-Op9IhEaxhbRT8MDXx2iNuMgciu2V8lDvYCNQbDGjdBNCjaMvyLf4wl4A3b8IgndCyQF8TwfgsQ8T3VD8aX1/pA== + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-regex@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" + integrity sha512-VlPiWmqmGJp0x0oK27Out1D+71nVVCTSdlbhIVoaBAj2lUgrNjBCRR9+llO4lTSb2O4r7PJg+RobRkhBrf6ofg== + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-remap-async-to-generator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" + integrity sha512-RYqaPD0mQyQIFRu7Ho5wE2yvA/5jxqCIj/Lv4BXNq23mHYu/vxikOy2JueLiBxQknwapwrJeNCesvY0ZcfnlHg== + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-replace-supers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" + integrity sha512-sLI+u7sXJh6+ToqDr57Bv973kCepItDhMou0xCP2YPVmR1jkHSCY+p1no8xErbV1Siz5QE8qKT1WIwybSWlqjw== + dependencies: + babel-helper-optimise-call-expression "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helpers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" + integrity sha512-n7pFrqQm44TCYvrCDb0MqabAF+JUBq+ijBvNMUxpkLjJaAu32faIexewMumrH5KLLJ1HDyT0PTEqRyAe/GwwuQ== + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + integrity sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-check-es2015-constants@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" + integrity sha512-B1M5KBP29248dViEo1owyY32lk1ZSH2DaNNrXLGt8lyjjHm7pBqAdQ7VKUPR6EEDO323+OvT3MQXbCin8ooWdA== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-syntax-async-functions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" + integrity sha512-4Zp4unmHgw30A1eWI5EpACji2qMocisdXhAftfhXoSV9j0Tvj6nRFE3tOmRY912E0FMRm/L5xWE7MGVT2FoLnw== + +babel-plugin-syntax-exponentiation-operator@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" + integrity sha512-Z/flU+T9ta0aIEKl1tGEmN/pZiI1uXmCiGFRegKacQfEJzp7iNsKloZmyJlQr+75FCJtiFfGIK03SiCvCt9cPQ== + +babel-plugin-syntax-trailing-function-commas@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" + integrity sha512-Gx9CH3Q/3GKbhs07Bszw5fPTlU+ygrOGfAhEt7W2JICwufpC4SuO0mG0+4NykPBSYPMJhqvVlDBU17qB1D+hMQ== + +babel-plugin-transform-async-to-generator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" + integrity sha512-7BgYJujNCg0Ti3x0c/DL3tStvnKS6ktIYOmo9wginv/dfZOrbSZ+qG4IRRHMBOzZ5Awb1skTiAsQXg/+IWkZYw== + dependencies: + babel-helper-remap-async-to-generator "^6.24.1" + babel-plugin-syntax-async-functions "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-arrow-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" + integrity sha512-PCqwwzODXW7JMrzu+yZIaYbPQSKjDTAsNNlK2l5Gg9g4rz2VzLnZsStvp/3c46GfXpwkyufb3NCyG9+50FF1Vg== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" + integrity sha512-2+ujAT2UMBzYFm7tidUsYh+ZoIutxJ3pN9IYrF1/H6dCKtECfhmB8UkHVpyxDwkj0CYbQG35ykoz925TUnBc3A== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoping@^6.23.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" + integrity sha512-YiN6sFAQ5lML8JjCmr7uerS5Yc/EMbgg9G8ZNmk2E3nYX4ckHR01wrkeeMijEf5WHNK5TW0Sl0Uu3pv3EdOJWw== + dependencies: + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-plugin-transform-es2015-classes@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" + integrity sha512-5Dy7ZbRinGrNtmWpquZKZ3EGY8sDgIVB4CU8Om8q8tnMLrD/m94cKglVcHps0BCTdZ0TJeeAWOq2TK9MIY6cag== + dependencies: + babel-helper-define-map "^6.24.1" + babel-helper-function-name "^6.24.1" + babel-helper-optimise-call-expression "^6.24.1" + babel-helper-replace-supers "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-computed-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" + integrity sha512-C/uAv4ktFP/Hmh01gMTvYvICrKze0XVX9f2PdIXuriCSvUmV9j+u+BB9f5fJK3+878yMK6dkdcq+Ymr9mrcLzw== + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-destructuring@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" + integrity sha512-aNv/GDAW0j/f4Uy1OEPZn1mqD+Nfy9viFGBfQ5bZyT35YqOiqx7/tXdyfZkJ1sC21NyEsBdfDY6PYmLHF4r5iA== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-duplicate-keys@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" + integrity sha512-ossocTuPOssfxO2h+Z3/Ea1Vo1wWx31Uqy9vIiJusOP4TbF7tPs9U0sJ9pX9OJPf4lXRGj5+6Gkl/HHKiAP5ug== + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-for-of@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" + integrity sha512-DLuRwoygCoXx+YfxHLkVx5/NpeSbVwfoTeBykpJK7JhYWlL/O8hgAK/reforUnZDlxasOrVPPJVI/guE3dCwkw== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-function-name@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" + integrity sha512-iFp5KIcorf11iBqu/y/a7DK3MN5di3pNCzto61FqCNnUX4qeBwcV1SLqe10oXNnCaxBUImX3SckX2/o1nsrTcg== + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" + integrity sha512-tjFl0cwMPpDYyoqYA9li1/7mGFit39XiNX5DKC/uCNjBctMxyL1/PT/l4rSlbvBG1pOKI88STRdUsWXB3/Q9hQ== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" + integrity sha512-LnIIdGWIKdw7zwckqx+eGjcS8/cl8D74A3BpJbGjKTFFNJSMrjN4bIh22HY1AlkUbeLG6X6OZj56BDvWD+OeFA== + dependencies: + babel-plugin-transform-es2015-modules-commonjs "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: + version "6.26.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" + integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== + dependencies: + babel-plugin-transform-strict-mode "^6.24.1" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-types "^6.26.0" + +babel-plugin-transform-es2015-modules-systemjs@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" + integrity sha512-ONFIPsq8y4bls5PPsAWYXH/21Hqv64TBxdje0FvU3MhIV6QM2j5YS7KvAzg/nTIVLot2D2fmFQrFWCbgHlFEjg== + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-umd@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" + integrity sha512-LpVbiT9CLsuAIp3IG0tfbVo81QIhn6pE8xBJ7XSeCtFlMltuar5VuBV6y6Q45tpui9QWcy5i0vLQfCfrnF7Kiw== + dependencies: + babel-plugin-transform-es2015-modules-amd "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-object-super@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" + integrity sha512-8G5hpZMecb53vpD3mjs64NhI1au24TAmokQ4B+TBFBjN9cVoGoOvotdrMMRmHvVZUEvqGUPWL514woru1ChZMA== + dependencies: + babel-helper-replace-supers "^6.24.1" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-parameters@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" + integrity sha512-8HxlW+BB5HqniD+nLkQ4xSAVq3bR/pcYW9IigY+2y0dI+Y7INFeTbfAQr+63T3E4UDsZGjyb+l9txUnABWxlOQ== + dependencies: + babel-helper-call-delegate "^6.24.1" + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-shorthand-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" + integrity sha512-mDdocSfUVm1/7Jw/FIRNw9vPrBQNePy6wZJlR8HAUBLybNp1w/6lr6zZ2pjMShee65t/ybR5pT8ulkLzD1xwiw== + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-spread@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" + integrity sha512-3Ghhi26r4l3d0Js933E5+IhHwk0A1yiutj9gwvzmFbVV0sPMYk2lekhOufHBswX7NCoSeF4Xrl3sCIuSIa+zOg== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-sticky-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" + integrity sha512-CYP359ADryTo3pCsH0oxRo/0yn6UsEZLqYohHmvLQdfS9xkf+MbCzE3/Kolw9OYIY4ZMilH25z/5CbQbwDD+lQ== + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-template-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" + integrity sha512-x8b9W0ngnKzDMHimVtTfn5ryimars1ByTqsfBDwAqLibmuuQY6pgBQi5z1ErIsUOWBdw1bW9FSz5RZUojM4apg== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-typeof-symbol@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" + integrity sha512-fz6J2Sf4gYN6gWgRZaoFXmq93X+Li/8vf+fb0sGDVtdeWvxC9y5/bTD7bvfWMEq6zetGEHpWjtzRGSugt5kNqw== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-unicode-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" + integrity sha512-v61Dbbihf5XxnYjtBN04B/JBvsScY37R1cZT5r9permN1cp+b70DY3Ib3fIkgn1DI9U3tGgBJZVD8p/mE/4JbQ== + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + regexpu-core "^2.0.0" + +babel-plugin-transform-exponentiation-operator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" + integrity sha512-LzXDmbMkklvNhprr20//RStKVcT8Cu+SQtX18eMHLhjHf2yFzwtQ0S2f0jQ+89rokoNdmwoSqYzAhq86FxlLSQ== + dependencies: + babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" + babel-plugin-syntax-exponentiation-operator "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-regenerator@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" + integrity sha512-LS+dBkUGlNR15/5WHKe/8Neawx663qttS6AGqoOUhICc9d1KciBvtrQSuc0PI+CxQ2Q/S1aKuJ+u64GtLdcEZg== + dependencies: + regenerator-transform "^0.10.0" + +babel-plugin-transform-strict-mode@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" + integrity sha512-j3KtSpjyLSJxNoCDrhwiJad8kw0gJ9REGj8/CqL0HeRyLnvUNYV9zcqluL6QJSXh3nfsLEmSLvwRfGzrgR96Pw== + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-preset-env@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" + integrity sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg== + dependencies: + babel-plugin-check-es2015-constants "^6.22.0" + babel-plugin-syntax-trailing-function-commas "^6.22.0" + babel-plugin-transform-async-to-generator "^6.22.0" + babel-plugin-transform-es2015-arrow-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoping "^6.23.0" + babel-plugin-transform-es2015-classes "^6.23.0" + babel-plugin-transform-es2015-computed-properties "^6.22.0" + babel-plugin-transform-es2015-destructuring "^6.23.0" + babel-plugin-transform-es2015-duplicate-keys "^6.22.0" + babel-plugin-transform-es2015-for-of "^6.23.0" + babel-plugin-transform-es2015-function-name "^6.22.0" + babel-plugin-transform-es2015-literals "^6.22.0" + babel-plugin-transform-es2015-modules-amd "^6.22.0" + babel-plugin-transform-es2015-modules-commonjs "^6.23.0" + babel-plugin-transform-es2015-modules-systemjs "^6.23.0" + babel-plugin-transform-es2015-modules-umd "^6.23.0" + babel-plugin-transform-es2015-object-super "^6.22.0" + babel-plugin-transform-es2015-parameters "^6.23.0" + babel-plugin-transform-es2015-shorthand-properties "^6.22.0" + babel-plugin-transform-es2015-spread "^6.22.0" + babel-plugin-transform-es2015-sticky-regex "^6.22.0" + babel-plugin-transform-es2015-template-literals "^6.22.0" + babel-plugin-transform-es2015-typeof-symbol "^6.23.0" + babel-plugin-transform-es2015-unicode-regex "^6.22.0" + babel-plugin-transform-exponentiation-operator "^6.22.0" + babel-plugin-transform-regenerator "^6.22.0" + browserslist "^3.2.6" + invariant "^2.2.2" + semver "^5.3.0" + +babel-register@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" + integrity sha512-veliHlHX06wjaeY8xNITbveXSiI+ASFnOqvne/LaIJIqOWi2Ogmj91KOugEz/hoh/fwMhXNBJPCv8Xaz5CyM4A== + dependencies: + babel-core "^6.26.0" + babel-runtime "^6.26.0" + core-js "^2.5.0" + home-or-tmp "^2.0.0" + lodash "^4.17.4" + mkdirp "^0.5.1" + source-map-support "^0.4.15" + +babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + integrity sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g== + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-template@^6.24.1, babel-template@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + integrity sha512-PCOcLFW7/eazGUKIoqH97sO9A2UYMahsn/yRQ7uOk37iutwjq7ODtcTNF+iFDSHNfkctqsLRjLP7URnOx0T1fg== + dependencies: + babel-runtime "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + lodash "^4.17.4" + +babel-traverse@^6.24.1, babel-traverse@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + integrity sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA== + dependencies: + babel-code-frame "^6.26.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + debug "^2.6.8" + globals "^9.18.0" + invariant "^2.2.2" + lodash "^4.17.4" + +babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + integrity sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g== + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babelify@^7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/babelify/-/babelify-7.3.0.tgz#aa56aede7067fd7bd549666ee16dc285087e88e5" + integrity sha512-vID8Fz6pPN5pJMdlUnNFSfrlcx5MUule4k9aKs/zbZPyXxMTcRrB0M4Tarw22L8afr8eYSWxDPYCob3TdrqtlA== + dependencies: + babel-core "^6.0.14" + object-assign "^4.0.0" + +babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== + +backoff@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f" + integrity sha512-wC5ihrnUXmR2douXmXLCe5O3zg3GKIyvRi/hi58a/XyRxVI+3/yM0PYueQOZXPXQ9pxBislYkw+sF9b7C/RuMA== + dependencies: + precond "0.2" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base-x@^3.0.2, base-x@^3.0.8: + version "3.0.9" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" + integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== + dependencies: + safe-buffer "^5.0.1" + +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== + dependencies: + tweetnacl "^0.14.3" + +bech32@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== + +bigint-crypto-utils@^3.0.23: + version "3.1.8" + resolved "https://registry.yarnpkg.com/bigint-crypto-utils/-/bigint-crypto-utils-3.1.8.tgz#e2e0f40cf45488f9d7f0e32ff84152aa73819d5d" + integrity sha512-+VMV9Laq8pXLBKKKK49nOoq9bfR3j7NNQAtbA617a4nw9bVLo8rsqkKMBgM2AJWlNX9fEIyYaYX+d0laqYV4tw== + dependencies: + bigint-mod-arith "^3.1.0" + +bigint-mod-arith@^3.1.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bigint-mod-arith/-/bigint-mod-arith-3.1.2.tgz#658e416bc593a463d97b59766226d0a3021a76b1" + integrity sha512-nx8J8bBeiRR+NlsROFH9jHswW5HO8mgfOSqW0AmjicMMvaONDa8AO+5ViKDUUNytBPWiwfvZP4/Bj4Y3lUfvgQ== + +bignumber.js@^9.0.0: + version "9.1.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.1.tgz#c4df7dc496bd849d4c9464344c1aa74228b4dac6" + integrity sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +bip39@2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.5.0.tgz#51cbd5179460504a63ea3c000db3f787ca051235" + integrity sha512-xwIx/8JKoT2+IPJpFEfXoWdYwP7UVAoUxxLNfGCfVowaJE7yg1Y5B1BVPqlUNsBq5/nGwmFkwRJ8xDW4sX8OdA== + dependencies: + create-hash "^1.1.0" + pbkdf2 "^3.0.9" + randombytes "^2.0.1" + safe-buffer "^5.0.1" + unorm "^1.3.3" + +blakejs@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" + integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== + +bluebird@^3.5.0, bluebird@^3.5.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + +bn.js@4.11.6: + version "4.11.6" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" + integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA== + +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.11.9, bn.js@^4.8.0: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^5.0.0, bn.js@^5.1.1, bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + +body-parser@1.20.1, body-parser@^1.16.0: + version "1.20.1" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" + integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== + dependencies: + bytes "3.1.2" + content-type "~1.0.4" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.11.0" + raw-body "2.5.1" + type-is "~1.6.18" + unpipe "1.0.0" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +braces@^3.0.2, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +brorand@^1.0.1, brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== + +browser-level@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browser-level/-/browser-level-1.0.1.tgz#36e8c3183d0fe1c405239792faaab5f315871011" + integrity sha512-XECYKJ+Dbzw0lbydyQuJzwNXtOpbMSq737qxJN11sIRTErOMShvDpbzTlgju7orJKvx4epULolZAuJGLzCmWRQ== + dependencies: + abstract-level "^1.0.2" + catering "^2.1.1" + module-error "^1.0.2" + run-parallel-limit "^1.1.0" + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" + integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== + dependencies: + bn.js "^5.0.0" + randombytes "^2.0.1" + +browserify-sign@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" + integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== + dependencies: + bn.js "^5.1.1" + browserify-rsa "^4.0.1" + create-hash "^1.2.0" + create-hmac "^1.1.7" + elliptic "^6.5.3" + inherits "^2.0.4" + parse-asn1 "^5.1.5" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +browserslist@^3.2.6: + version "3.2.8" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" + integrity sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ== + dependencies: + caniuse-lite "^1.0.30000844" + electron-to-chromium "^1.3.47" + +bs58@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" + integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== + dependencies: + base-x "^3.0.2" + +bs58check@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" + integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== + dependencies: + bs58 "^4.0.0" + create-hash "^1.1.0" + safe-buffer "^5.1.2" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer-to-arraybuffer@^0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz#6064a40fa76eb43c723aba9ef8f6e1216d10511a" + integrity sha512-3dthu5CYiVB1DEJp61FtApNnNndTckcqe4pFcLdvHtrpG+kcyekCJKg4MRiDcFW7A6AODnXB9U4dwQiCW5kzJQ== + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== + +buffer-xor@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-2.0.2.tgz#34f7c64f04c777a1f8aac5e661273bb9dd320289" + integrity sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ== + dependencies: + safe-buffer "^5.1.1" + +buffer@^5.0.5, buffer@^5.2.1, buffer@^5.5.0, buffer@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + +bufferutil@^4.0.1: + version "4.0.7" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.7.tgz#60c0d19ba2c992dd8273d3f73772ffc894c153ad" + integrity sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw== + dependencies: + node-gyp-build "^4.3.0" + +busboy@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" + integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== + dependencies: + streamsearch "^1.1.0" + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +bytewise-core@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/bytewise-core/-/bytewise-core-1.2.3.tgz#3fb410c7e91558eb1ab22a82834577aa6bd61d42" + integrity sha512-nZD//kc78OOxeYtRlVk8/zXqTB4gf/nlguL1ggWA8FuchMyOxcyHR4QPQZMUmA7czC+YnaBrPUCubqAWe50DaA== + dependencies: + typewise-core "^1.2" + +bytewise@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/bytewise/-/bytewise-1.1.0.tgz#1d13cbff717ae7158094aa881b35d081b387253e" + integrity sha512-rHuuseJ9iQ0na6UDhnrRVDh8YnWVlU6xM3VH6q/+yHDeUH2zIhUzP+2/h3LIrhLDBtTqzWpE3p3tP/boefskKQ== + dependencies: + bytewise-core "^1.2.2" + typewise "^1.0.3" + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +cacheable-lookup@^5.0.3: + version "5.0.4" + resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" + integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA== + +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" + integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^1.0.2" + +cacheable-request@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.2.tgz#ea0d0b889364a25854757301ca12b2da77f91d27" + integrity sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^4.0.0" + lowercase-keys "^2.0.0" + normalize-url "^6.0.1" + responselike "^2.0.0" + +cachedown@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cachedown/-/cachedown-1.0.0.tgz#d43f036e4510696b31246d7db31ebf0f7ac32d15" + integrity sha512-t+yVk82vQWCJF3PsWHMld+jhhjkkWjcAzz8NbFx1iULOXWl8Tm/FdM4smZNVw3MRr0X+lVTx9PKzvEn4Ng19RQ== + dependencies: + abstract-leveldown "^2.4.1" + lru-cache "^3.2.0" + +call-bind@^1.0.0, call-bind@^1.0.2, call-bind@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +camelcase@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" + integrity sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg== + +camelcase@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-lite@^1.0.30000844: + version "1.0.30001442" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001442.tgz#40337f1cf3be7c637b061e2f78582dc1daec0614" + integrity sha512-239m03Pqy0hwxYPYR5JwOIxRJfLTWtle9FV8zosfV5pHg+/51uD4nxcUlM8+mWWGfwKtt8lJNHnD3cWw9VZ6ow== + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== + +catering@^2.1.0, catering@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/catering/-/catering-2.1.1.tgz#66acba06ed5ee28d5286133982a927de9a04b510" + integrity sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w== + +cbor@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/cbor/-/cbor-8.1.0.tgz#cfc56437e770b73417a2ecbfc9caf6b771af60d5" + integrity sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg== + dependencies: + nofilter "^3.1.0" + +chai@^4.3.6: + version "4.3.7" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" + integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^4.1.2" + get-func-name "^2.0.0" + loupe "^2.3.1" + pathval "^1.1.1" + type-detect "^4.0.5" + +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.4.1, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.1.0, chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +check-error@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== + +checkpoint-store@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06" + integrity sha512-J/NdY2WvIx654cc6LWSq/IYFFCUf75fFTgwzFnmbqyORH4MwgiQCgswLLKBGzmsyTI5V7i5bp/So6sMbDWhedg== + dependencies: + functional-red-black-tree "^1.0.1" + +chokidar@3.5.3, chokidar@^3.4.0: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chownr@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +cids@^0.7.1: + version "0.7.5" + resolved "https://registry.yarnpkg.com/cids/-/cids-0.7.5.tgz#60a08138a99bfb69b6be4ceb63bfef7a396b28b2" + integrity sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA== + dependencies: + buffer "^5.5.0" + class-is "^1.1.0" + multibase "~0.6.0" + multicodec "^1.0.0" + multihashes "~0.4.15" + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +class-is@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/class-is/-/class-is-1.1.0.tgz#9d3c0fba0440d211d843cec3dedfa48055005825" + integrity sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw== + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +classic-level@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/classic-level/-/classic-level-1.2.0.tgz#2d52bdec8e7a27f534e67fdeb890abef3e643c27" + integrity sha512-qw5B31ANxSluWz9xBzklRWTUAJ1SXIdaVKTVS7HcTGKOAmExx65Wo5BUICW+YGORe2FOUaDghoI9ZDxj82QcFg== + dependencies: + abstract-level "^1.0.2" + catering "^2.1.0" + module-error "^1.0.1" + napi-macros "~2.0.0" + node-gyp-build "^4.3.0" + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cliui@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + integrity sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w== + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +clone-response@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3" + integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA== + dependencies: + mimic-response "^1.0.0" + +clone@2.1.2, clone@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w== + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA== + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw== + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +command-exists@^1.2.8: + version "1.2.9" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== + +command-line-args@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-4.0.7.tgz#f8d1916ecb90e9e121eda6428e41300bfb64cc46" + integrity sha512-aUdPvQRAyBvQd2n7jXcsMDz68ckBJELXNzBybCHOibUWEg0mWTnaYCSRU8h9R+aNRSvDihJtssSRCiDRpLaezA== + dependencies: + array-back "^2.0.0" + find-replace "^1.0.3" + typical "^2.6.1" + +command-line-args@^5.1.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.1.tgz#c44c32e437a57d7c51157696893c5909e9cec42e" + integrity sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg== + dependencies: + array-back "^3.1.0" + find-replace "^3.0.0" + lodash.camelcase "^4.3.0" + typical "^4.0.0" + +command-line-usage@^6.1.0: + version "6.1.3" + resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-6.1.3.tgz#428fa5acde6a838779dfa30e44686f4b6761d957" + integrity sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw== + dependencies: + array-back "^4.0.2" + chalk "^2.4.2" + table-layout "^1.0.2" + typical "^5.2.0" + +commander@3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" + integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== + +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +concat-stream@^1.5.1: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-hash@^2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/content-hash/-/content-hash-2.5.2.tgz#bbc2655e7c21f14fd3bfc7b7d4bfe6e454c9e211" + integrity sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw== + dependencies: + cids "^0.7.1" + multicodec "^0.5.5" + multihashes "^0.4.15" + +content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== + +convert-source-map@^1.5.1: + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + +cookie@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== + +cookie@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + +cookiejar@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.3.tgz#fc7a6216e408e74414b90230050842dacda75acc" + integrity sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ== + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== + +core-js-pure@^3.0.1: + version "3.27.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.27.1.tgz#ede4a6b8440585c7190062757069c01d37a19dca" + integrity sha512-BS2NHgwwUppfeoqOXqi08mUqS5FiZpuRuJJpKsaME7kJz0xxuk0xkhDdfMIlP/zLa80krBqss1LtD7f889heAw== + +core-js@^2.4.0, core-js@^2.5.0: + version "2.6.12" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" + integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== + +core-util-is@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cors@^2.8.1: + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + +crc-32@^1.2.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" + integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== + +create-ecdh@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" + integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== + dependencies: + bn.js "^4.1.0" + elliptic "^6.5.3" + +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +cross-fetch@^2.1.0, cross-fetch@^2.1.1: + version "2.2.6" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-2.2.6.tgz#2ef0bb39a24ac034787965c457368a28730e220a" + integrity sha512-9JZz+vXCmfKUZ68zAptS7k4Nu8e2qcibe7WVZYps7sAgk5R8GYTc+T1WR0v1rlP9HxgARmOX1UTIJZFytajpNA== + dependencies: + node-fetch "^2.6.7" + whatwg-fetch "^2.0.4" + +cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +crypto-browserify@3.12.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== + dependencies: + browserify-cipher "^1.0.0" + browserify-sign "^4.0.0" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "^3.0.3" + public-encrypt "^4.0.0" + randombytes "^2.0.0" + randomfill "^1.0.3" + +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== + dependencies: + assert-plus "^1.0.0" + +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +debug@4, debug@4.3.4, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +debug@^3.1.0: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +decamelize@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +decode-uri-component@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== + +decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA== + dependencies: + mimic-response "^1.0.0" + +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== + dependencies: + mimic-response "^3.1.0" + +deep-eql@^4.1.2: + version "4.1.3" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" + integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== + dependencies: + type-detect "^4.0.0" + +deep-equal@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" + integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== + dependencies: + is-arguments "^1.0.4" + is-date-object "^1.0.1" + is-regex "^1.0.4" + object-is "^1.0.1" + object-keys "^1.1.1" + regexp.prototype.flags "^1.2.0" + +deep-extend@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +defer-to-connect@^1.0.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" + integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== + +defer-to-connect@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" + integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== + +deferred-leveldown@~1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz#3acd2e0b75d1669924bc0a4b642851131173e1eb" + integrity sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA== + dependencies: + abstract-leveldown "~2.6.0" + +deferred-leveldown@~4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz#0b0570087827bf480a23494b398f04c128c19a20" + integrity sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww== + dependencies: + abstract-leveldown "~5.0.0" + inherits "^2.0.3" + +define-properties@^1.1.3, define-properties@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" + integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== + dependencies: + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA== + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA== + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +defined@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.1.tgz#c0b9db27bfaffd95d6f61399419b893df0f91ebf" + integrity sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q== + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +delete-empty@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/delete-empty/-/delete-empty-3.0.0.tgz#f8040f2669f26fa7060bc2304e9859c593b685e8" + integrity sha512-ZUyiwo76W+DYnKsL3Kim6M/UOavPdBJgDYWOmuQhYaZvJH0AXAHbUNyEDtRbBra8wqqr686+63/0azfEk1ebUQ== + dependencies: + ansi-colors "^4.1.0" + minimist "^1.2.0" + path-starts-with "^2.0.0" + rimraf "^2.6.2" + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +des.js@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" + integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + integrity sha512-BDKtmHlOzwI7iRuEkhzsnPoi5ypEhWAJB5RvHWe1kMr06js3uK5B3734i3ui5Yd+wOJV1cpE4JnivPD283GU/A== + dependencies: + repeating "^2.0.0" + +diff@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +diffie-hellman@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +dom-walk@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" + integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w== + +dotenv@^16.0.0: + version "16.0.3" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" + integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== + +dotignore@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/dotignore/-/dotignore-0.1.2.tgz#f942f2200d28c3a76fbdd6f0ee9f3257c8a2e905" + integrity sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw== + dependencies: + minimatch "^3.0.4" + +duplexer3@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e" + integrity sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA== + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +electron-to-chromium@^1.3.47: + version "1.4.284" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" + integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== + +elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5.4: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +encode-utf8@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda" + integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +encoding-down@5.0.4, encoding-down@~5.0.0: + version "5.0.4" + resolved "https://registry.yarnpkg.com/encoding-down/-/encoding-down-5.0.4.tgz#1e477da8e9e9d0f7c8293d320044f8b2cd8e9614" + integrity sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw== + dependencies: + abstract-leveldown "^5.0.0" + inherits "^2.0.3" + level-codec "^9.0.0" + level-errors "^2.0.0" + xtend "^4.0.1" + +encoding@^0.1.11: + version "0.1.13" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" + integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== + dependencies: + iconv-lite "^0.6.2" + +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +enquirer@^2.3.0: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + +env-paths@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + +errno@~0.1.1: + version "0.1.8" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" + integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== + dependencies: + prr "~1.0.1" + +error-ex@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.19.0, es-abstract@^1.20.4: + version "1.21.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.0.tgz#dd1b69ea5bfc3c27199c9753efd4de015102c252" + integrity sha512-GUGtW7eXQay0c+PRq0sGIKSdaBorfVqsCMhGHo4elP7YVqZu9nCZS4UkK4gv71gOWNMra/PaSKD3ao1oWExO0g== + dependencies: + call-bind "^1.0.2" + es-set-tostringtag "^2.0.0" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + function.prototype.name "^1.1.5" + get-intrinsic "^1.1.3" + get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" + has "^1.0.3" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.4" + is-array-buffer "^3.0.0" + is-callable "^1.2.7" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-typed-array "^1.1.10" + is-weakref "^1.0.2" + object-inspect "^1.12.2" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.4.3" + safe-regex-test "^1.0.0" + string.prototype.trimend "^1.0.6" + string.prototype.trimstart "^1.0.6" + typed-array-length "^1.0.4" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.9" + +es-array-method-boxes-properly@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" + integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== + +es-set-tostringtag@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" + integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + has-tostringtag "^1.0.0" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +es5-ext@^0.10.35, es5-ext@^0.10.50: + version "0.10.62" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.62.tgz#5e6adc19a6da524bf3d1e02bbc8960e5eb49a9a5" + integrity sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA== + dependencies: + es6-iterator "^2.0.3" + es6-symbol "^3.1.3" + next-tick "^1.1.0" + +es6-iterator@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@^3.1.1, es6-symbol@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" + integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== + dependencies: + d "^1.0.1" + ext "^1.1.2" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +escape-string-regexp@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +eth-block-tracker@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-3.0.1.tgz#95cd5e763c7293e0b1b2790a2a39ac2ac188a5e1" + integrity sha512-WUVxWLuhMmsfenfZvFO5sbl1qFY2IqUlw/FPVmjjdElpqLsZtSG+wPe9Dz7W/sB6e80HgFKknOmKk2eNlznHug== + dependencies: + eth-query "^2.1.0" + ethereumjs-tx "^1.3.3" + ethereumjs-util "^5.1.3" + ethjs-util "^0.1.3" + json-rpc-engine "^3.6.0" + pify "^2.3.0" + tape "^4.6.3" + +eth-ens-namehash@2.0.8, eth-ens-namehash@^2.0.8: + version "2.0.8" + resolved "https://registry.yarnpkg.com/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz#229ac46eca86d52e0c991e7cb2aef83ff0f68bcf" + integrity sha512-VWEI1+KJfz4Km//dadyvBBoBeSQ0MHTXPvr8UIXiLW6IanxvAV+DmlZAijZwAyggqGUfwQBeHf7tc9wzc1piSw== + dependencies: + idna-uts46-hx "^2.3.1" + js-sha3 "^0.5.7" + +eth-json-rpc-infura@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/eth-json-rpc-infura/-/eth-json-rpc-infura-3.2.1.tgz#26702a821067862b72d979c016fd611502c6057f" + integrity sha512-W7zR4DZvyTn23Bxc0EWsq4XGDdD63+XPUCEhV2zQvQGavDVC4ZpFDK4k99qN7bd7/fjj37+rxmuBOBeIqCA5Mw== + dependencies: + cross-fetch "^2.1.1" + eth-json-rpc-middleware "^1.5.0" + json-rpc-engine "^3.4.0" + json-rpc-error "^2.0.0" + +eth-json-rpc-middleware@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz#5c9d4c28f745ccb01630f0300ba945f4bef9593f" + integrity sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q== + dependencies: + async "^2.5.0" + eth-query "^2.1.2" + eth-tx-summary "^3.1.2" + ethereumjs-block "^1.6.0" + ethereumjs-tx "^1.3.3" + ethereumjs-util "^5.1.2" + ethereumjs-vm "^2.1.0" + fetch-ponyfill "^4.0.0" + json-rpc-engine "^3.6.0" + json-rpc-error "^2.0.0" + json-stable-stringify "^1.0.1" + promise-to-callback "^1.0.0" + tape "^4.6.3" + +eth-lib@0.2.8: + version "0.2.8" + resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.8.tgz#b194058bef4b220ad12ea497431d6cb6aa0623c8" + integrity sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw== + dependencies: + bn.js "^4.11.6" + elliptic "^6.4.0" + xhr-request-promise "^0.1.2" + +eth-lib@^0.1.26: + version "0.1.29" + resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.29.tgz#0c11f5060d42da9f931eab6199084734f4dbd1d9" + integrity sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ== + dependencies: + bn.js "^4.11.6" + elliptic "^6.4.0" + nano-json-stream-parser "^0.1.2" + servify "^0.1.12" + ws "^3.0.0" + xhr-request-promise "^0.1.2" + +eth-query@^2.0.2, eth-query@^2.1.0, eth-query@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/eth-query/-/eth-query-2.1.2.tgz#d6741d9000106b51510c72db92d6365456a6da5e" + integrity sha512-srES0ZcvwkR/wd5OQBRA1bIJMww1skfGS0s8wlwK3/oNP4+wnds60krvu5R1QbpRQjMmpG5OMIWro5s7gvDPsA== + dependencies: + json-rpc-random-id "^1.0.0" + xtend "^4.0.1" + +eth-sig-util@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-3.0.0.tgz#75133b3d7c20a5731af0690c385e184ab942b97e" + integrity sha512-4eFkMOhpGbTxBQ3AMzVf0haUX2uTur7DpWiHzWyTURa28BVJJtOkcb9Ok5TV0YvEPG61DODPW7ZUATbJTslioQ== + dependencies: + buffer "^5.2.1" + elliptic "^6.4.0" + ethereumjs-abi "0.6.5" + ethereumjs-util "^5.1.1" + tweetnacl "^1.0.0" + tweetnacl-util "^0.15.0" + +eth-sig-util@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.2.tgz#8d958202c7edbaae839707fba6f09ff327606210" + integrity sha512-iNZ576iTOGcfllftB73cPB5AN+XUQAT/T8xzsILsghXC1o8gJUqe3RHlcDqagu+biFpYQ61KQrZZJza8eRSYqw== + dependencies: + ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" + ethereumjs-util "^5.1.1" + +eth-tx-summary@^3.1.2: + version "3.2.4" + resolved "https://registry.yarnpkg.com/eth-tx-summary/-/eth-tx-summary-3.2.4.tgz#e10eb95eb57cdfe549bf29f97f1e4f1db679035c" + integrity sha512-NtlDnaVZah146Rm8HMRUNMgIwG/ED4jiqk0TME9zFheMl1jOp6jL1m0NKGjJwehXQ6ZKCPr16MTr+qspKpEXNg== + dependencies: + async "^2.1.2" + clone "^2.0.0" + concat-stream "^1.5.1" + end-of-stream "^1.1.0" + eth-query "^2.0.2" + ethereumjs-block "^1.4.1" + ethereumjs-tx "^1.1.1" + ethereumjs-util "^5.0.1" + ethereumjs-vm "^2.6.0" + through2 "^2.0.3" + +ethashjs@~0.0.7: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ethashjs/-/ethashjs-0.0.8.tgz#227442f1bdee409a548fb04136e24c874f3aa6f9" + integrity sha512-/MSbf/r2/Ld8o0l15AymjOTlPqpN8Cr4ByUEA9GtR4x0yAh3TdtDzEg29zMjXCNPI7u6E5fOQdj/Cf9Tc7oVNw== + dependencies: + async "^2.1.2" + buffer-xor "^2.0.1" + ethereumjs-util "^7.0.2" + miller-rabin "^4.0.0" + +ethereum-bloom-filters@^1.0.6: + version "1.0.10" + resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz#3ca07f4aed698e75bd134584850260246a5fed8a" + integrity sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA== + dependencies: + js-sha3 "^0.8.0" + +ethereum-common@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.2.0.tgz#13bf966131cce1eeade62a1b434249bb4cb120ca" + integrity sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA== + +ethereum-common@^0.0.18: + version "0.0.18" + resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" + integrity sha512-EoltVQTRNg2Uy4o84qpa2aXymXDJhxm7eos/ACOg0DG4baAbMjhbdAEsx9GeE8sC3XCxnYvrrzZDH8D8MtA2iQ== + +ethereum-cryptography@0.1.3, ethereum-cryptography@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" + integrity sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ== + dependencies: + "@types/pbkdf2" "^3.0.0" + "@types/secp256k1" "^4.0.1" + blakejs "^1.1.0" + browserify-aes "^1.2.0" + bs58check "^2.1.2" + create-hash "^1.2.0" + create-hmac "^1.1.7" + hash.js "^1.1.7" + keccak "^3.0.0" + pbkdf2 "^3.0.17" + randombytes "^2.1.0" + safe-buffer "^5.1.2" + scrypt-js "^3.0.0" + secp256k1 "^4.0.1" + setimmediate "^1.0.5" + +ethereum-cryptography@^1.0.3: + version "1.1.2" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-1.1.2.tgz#74f2ac0f0f5fe79f012c889b3b8446a9a6264e6d" + integrity sha512-XDSJlg4BD+hq9N2FjvotwUET9Tfxpxc3kWGE2AqUG5vcbeunnbImVk3cj6e/xT3phdW21mE8R5IugU4fspQDcQ== + dependencies: + "@noble/hashes" "1.1.2" + "@noble/secp256k1" "1.6.3" + "@scure/bip32" "1.1.0" + "@scure/bip39" "1.1.0" + +ethereum-waffle@^3.4.0: + version "3.4.4" + resolved "https://registry.yarnpkg.com/ethereum-waffle/-/ethereum-waffle-3.4.4.tgz#1378b72040697857b7f5e8f473ca8f97a37b5840" + integrity sha512-PA9+jCjw4WC3Oc5ocSMBj5sXvueWQeAbvCA+hUlb6oFgwwKyq5ka3bWQ7QZcjzIX+TdFkxP4IbFmoY2D8Dkj9Q== + dependencies: + "@ethereum-waffle/chai" "^3.4.4" + "@ethereum-waffle/compiler" "^3.4.4" + "@ethereum-waffle/mock-contract" "^3.4.4" + "@ethereum-waffle/provider" "^3.4.4" + ethers "^5.0.1" + +ethereumjs-abi@0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz#5a637ef16ab43473fa72a29ad90871405b3f5241" + integrity sha512-rCjJZ/AE96c/AAZc6O3kaog4FhOsAViaysBxqJNy2+LHP0ttH0zkZ7nXdVHOAyt6lFwLO0nlCwWszysG/ao1+g== + dependencies: + bn.js "^4.10.0" + ethereumjs-util "^4.3.0" + +ethereumjs-abi@0.6.8, ethereumjs-abi@^0.6.8: + version "0.6.8" + resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae" + integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== + dependencies: + bn.js "^4.11.8" + ethereumjs-util "^6.0.0" + +"ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git": + version "0.6.8" + resolved "git+https://github.com/ethereumjs/ethereumjs-abi.git#ee3994657fa7a427238e6ba92a84d0b529bbcde0" + dependencies: + bn.js "^4.11.8" + ethereumjs-util "^6.0.0" + +ethereumjs-account@3.0.0, ethereumjs-account@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-3.0.0.tgz#728f060c8e0c6e87f1e987f751d3da25422570a9" + integrity sha512-WP6BdscjiiPkQfF9PVfMcwx/rDvfZTjFKY0Uwc09zSQr9JfIVH87dYIJu0gNhBhpmovV4yq295fdllS925fnBA== + dependencies: + ethereumjs-util "^6.0.0" + rlp "^2.2.1" + safe-buffer "^5.1.1" + +ethereumjs-account@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz#eeafc62de544cb07b0ee44b10f572c9c49e00a84" + integrity sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA== + dependencies: + ethereumjs-util "^5.0.0" + rlp "^2.0.0" + safe-buffer "^5.1.1" + +ethereumjs-block@2.2.2, ethereumjs-block@^2.2.2, ethereumjs-block@~2.2.0, ethereumjs-block@~2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz#c7654be7e22df489fda206139ecd63e2e9c04965" + integrity sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg== + dependencies: + async "^2.0.1" + ethereumjs-common "^1.5.0" + ethereumjs-tx "^2.1.1" + ethereumjs-util "^5.0.0" + merkle-patricia-tree "^2.1.2" + +ethereumjs-block@^1.2.2, ethereumjs-block@^1.4.1, ethereumjs-block@^1.6.0: + version "1.7.1" + resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz#78b88e6cc56de29a6b4884ee75379b6860333c3f" + integrity sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg== + dependencies: + async "^2.0.1" + ethereum-common "0.2.0" + ethereumjs-tx "^1.2.2" + ethereumjs-util "^5.0.0" + merkle-patricia-tree "^2.1.2" + +ethereumjs-blockchain@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/ethereumjs-blockchain/-/ethereumjs-blockchain-4.0.4.tgz#30f2228dc35f6dcf94423692a6902604ae34960f" + integrity sha512-zCxaRMUOzzjvX78DTGiKjA+4h2/sF0OYL1QuPux0DHpyq8XiNoF5GYHtb++GUxVlMsMfZV7AVyzbtgcRdIcEPQ== + dependencies: + async "^2.6.1" + ethashjs "~0.0.7" + ethereumjs-block "~2.2.2" + ethereumjs-common "^1.5.0" + ethereumjs-util "^6.1.0" + flow-stoplight "^1.0.0" + level-mem "^3.0.1" + lru-cache "^5.1.1" + rlp "^2.2.2" + semaphore "^1.1.0" + +ethereumjs-common@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.0.tgz#d3e82fc7c47c0cef95047f431a99485abc9bb1cd" + integrity sha512-SZOjgK1356hIY7MRj3/ma5qtfr/4B5BL+G4rP/XSMYr2z1H5el4RX5GReYCKmQmYI/nSBmRnwrZ17IfHuG0viQ== + +ethereumjs-common@^1.1.0, ethereumjs-common@^1.3.2, ethereumjs-common@^1.5.0: + version "1.5.2" + resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz#2065dbe9214e850f2e955a80e650cb6999066979" + integrity sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA== + +ethereumjs-tx@2.1.2, ethereumjs-tx@^2.1.1, ethereumjs-tx@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz#5dfe7688bf177b45c9a23f86cf9104d47ea35fed" + integrity sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw== + dependencies: + ethereumjs-common "^1.5.0" + ethereumjs-util "^6.0.0" + +ethereumjs-tx@^1.1.1, ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.3: + version "1.3.7" + resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a" + integrity sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA== + dependencies: + ethereum-common "^0.0.18" + ethereumjs-util "^5.0.0" + +ethereumjs-util@6.2.1, ethereumjs-util@^6.0.0, ethereumjs-util@^6.1.0, ethereumjs-util@^6.2.0, ethereumjs-util@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" + integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== + dependencies: + "@types/bn.js" "^4.11.3" + bn.js "^4.11.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + ethjs-util "0.1.6" + rlp "^2.2.3" + +ethereumjs-util@^4.3.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.1.tgz#f4bf9b3b515a484e3cc8781d61d9d980f7c83bd0" + integrity sha512-WrckOZ7uBnei4+AKimpuF1B3Fv25OmoRgmYCpGsP7u8PFxXAmAgiJSYT2kRWnt6fVIlKaQlZvuwXp7PIrmn3/w== + dependencies: + bn.js "^4.8.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + rlp "^2.0.0" + +ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.2, ethereumjs-util@^5.1.3, ethereumjs-util@^5.1.5, ethereumjs-util@^5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz#a833f0e5fca7e5b361384dc76301a721f537bf65" + integrity sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ== + dependencies: + bn.js "^4.11.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + ethjs-util "^0.1.3" + rlp "^2.0.0" + safe-buffer "^5.1.1" + +ethereumjs-util@^7.0.2, ethereumjs-util@^7.1.0: + version "7.1.5" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" + integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== + dependencies: + "@types/bn.js" "^5.1.0" + bn.js "^5.1.2" + create-hash "^1.1.2" + ethereum-cryptography "^0.1.3" + rlp "^2.2.4" + +ethereumjs-vm@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-4.2.0.tgz#e885e861424e373dbc556278f7259ff3fca5edab" + integrity sha512-X6qqZbsY33p5FTuZqCnQ4+lo957iUJMM6Mpa6bL4UW0dxM6WmDSHuI4j/zOp1E2TDKImBGCJA9QPfc08PaNubA== + dependencies: + async "^2.1.2" + async-eventemitter "^0.2.2" + core-js-pure "^3.0.1" + ethereumjs-account "^3.0.0" + ethereumjs-block "^2.2.2" + ethereumjs-blockchain "^4.0.3" + ethereumjs-common "^1.5.0" + ethereumjs-tx "^2.1.2" + ethereumjs-util "^6.2.0" + fake-merkle-patricia-tree "^1.0.1" + functional-red-black-tree "^1.0.1" + merkle-patricia-tree "^2.3.2" + rustbn.js "~0.2.0" + safe-buffer "^5.1.1" + util.promisify "^1.0.0" + +ethereumjs-vm@^2.1.0, ethereumjs-vm@^2.3.4, ethereumjs-vm@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz#76243ed8de031b408793ac33907fb3407fe400c6" + integrity sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw== + dependencies: + async "^2.1.2" + async-eventemitter "^0.2.2" + ethereumjs-account "^2.0.3" + ethereumjs-block "~2.2.0" + ethereumjs-common "^1.1.0" + ethereumjs-util "^6.0.0" + fake-merkle-patricia-tree "^1.0.1" + functional-red-black-tree "^1.0.1" + merkle-patricia-tree "^2.3.2" + rustbn.js "~0.2.0" + safe-buffer "^5.1.1" + +ethereumjs-wallet@0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.5.tgz#685e9091645cee230ad125c007658833991ed474" + integrity sha512-MDwjwB9VQVnpp/Dc1XzA6J1a3wgHQ4hSvA1uWNatdpOrtCbPVuQSKSyRnjLvS0a+KKMw2pvQ9Ybqpb3+eW8oNA== + dependencies: + aes-js "^3.1.1" + bs58check "^2.1.2" + ethereum-cryptography "^0.1.3" + ethereumjs-util "^6.0.0" + randombytes "^2.0.6" + safe-buffer "^5.1.2" + scryptsy "^1.2.1" + utf8 "^3.0.0" + uuid "^3.3.2" + +ethers@^5.0.0, ethers@^5.0.1, ethers@^5.0.2, ethers@^5.5.2: + version "5.7.2" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" + integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/abstract-signer" "5.7.0" + "@ethersproject/address" "5.7.0" + "@ethersproject/base64" "5.7.0" + "@ethersproject/basex" "5.7.0" + "@ethersproject/bignumber" "5.7.0" + "@ethersproject/bytes" "5.7.0" + "@ethersproject/constants" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/hash" "5.7.0" + "@ethersproject/hdnode" "5.7.0" + "@ethersproject/json-wallets" "5.7.0" + "@ethersproject/keccak256" "5.7.0" + "@ethersproject/logger" "5.7.0" + "@ethersproject/networks" "5.7.1" + "@ethersproject/pbkdf2" "5.7.0" + "@ethersproject/properties" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@ethersproject/random" "5.7.0" + "@ethersproject/rlp" "5.7.0" + "@ethersproject/sha2" "5.7.0" + "@ethersproject/signing-key" "5.7.0" + "@ethersproject/solidity" "5.7.0" + "@ethersproject/strings" "5.7.0" + "@ethersproject/transactions" "5.7.0" + "@ethersproject/units" "5.7.0" + "@ethersproject/wallet" "5.7.0" + "@ethersproject/web" "5.7.1" + "@ethersproject/wordlists" "5.7.0" + +ethjs-unit@0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" + integrity sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw== + dependencies: + bn.js "4.11.6" + number-to-bn "1.7.0" + +ethjs-util@0.1.6, ethjs-util@^0.1.3, ethjs-util@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" + integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== + dependencies: + is-hex-prefixed "1.0.0" + strip-hex-prefix "1.0.0" + +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + +eventemitter3@4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" + integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== + +events@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA== + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +express@^4.14.0: + version "4.18.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" + integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.20.1" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.5.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "2.0.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.2.0" + fresh "0.5.2" + http-errors "2.0.0" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "2.4.1" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.7" + qs "6.11.0" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.18.0" + serve-static "1.15.0" + setprototypeof "1.2.0" + statuses "2.0.1" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +ext@^1.1.2: + version "1.7.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" + integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== + dependencies: + type "^2.7.2" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q== + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== + +extsprintf@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== + +fake-merkle-patricia-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz#4b8c3acfb520afadf9860b1f14cd8ce3402cddd3" + integrity sha512-Tgq37lkc9pUIgIKw5uitNUKcgcYL3R6JvXtKQbOf/ZSavXbidsksgp/pAY6p//uhw0I4yoMsvTSovvVIsk/qxA== + dependencies: + checkpoint-store "^1.1.0" + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fetch-ponyfill@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz#ae3ce5f732c645eab87e4ae8793414709b239893" + integrity sha512-knK9sGskIg2T7OnYLdZ2hZXn0CtDrAIBxYQLpmEf0BqfdWnwmM1weccUl5+4EdA44tzNSFAuxITPbXtPehUB3g== + dependencies: + node-fetch "~1.7.1" + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ== + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" + +find-replace@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-1.0.3.tgz#b88e7364d2d9c959559f388c66670d6130441fa0" + integrity sha512-KrUnjzDCD9426YnCP56zGYy/eieTnhtK6Vn++j+JJzmlsWWwEkDnsyVF575spT6HJ6Ow9tlbT3TQTDsa+O4UWA== + dependencies: + array-back "^1.0.4" + test-value "^2.1.0" + +find-replace@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" + integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ== + dependencies: + array-back "^3.0.1" + +find-up@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + integrity sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA== + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== + dependencies: + locate-path "^2.0.0" + +find-yarn-workspace-root@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz#40eb8e6e7c2502ddfaa2577c176f221422f860db" + integrity sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q== + dependencies: + fs-extra "^4.0.3" + micromatch "^3.1.4" + +find-yarn-workspace-root@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" + integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ== + dependencies: + micromatch "^4.0.2" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +flow-stoplight@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/flow-stoplight/-/flow-stoplight-1.0.0.tgz#4a292c5bcff8b39fa6cc0cb1a853d86f27eeff7b" + integrity sha512-rDjbZUKpN8OYhB0IE/vY/I8UWO/602IIJEU/76Tv4LvYnwHCk0BCsvz4eRr9n+FQcri7L5cyaXOo0+/Kh4HisA== + +fmix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/fmix/-/fmix-0.1.0.tgz#c7bbf124dec42c9d191cfb947d0a9778dd986c0c" + integrity sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w== + dependencies: + imul "^1.0.0" + +follow-redirects@^1.12.1: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + +for-each@^0.3.3, for-each@~0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ== + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== + +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fp-ts@1.19.3: + version "1.19.3" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.3.tgz#261a60d1088fbff01f91256f91d21d0caaaaa96f" + integrity sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg== + +fp-ts@^1.0.0: + version "1.19.5" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a" + integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A== + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA== + dependencies: + map-cache "^0.2.2" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +fs-extra@^0.30.0: + version "0.30.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" + integrity sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + klaw "^1.0.0" + path-is-absolute "^1.0.0" + rimraf "^2.2.8" + +fs-extra@^4.0.2, fs-extra@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" + integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^7.0.0, fs-extra@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^9.0.0, fs-extra@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-minipass@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" + integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== + dependencies: + minipass "^2.6.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +function.prototype.name@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" + integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + functions-have-names "^1.2.2" + +functional-red-black-tree@^1.0.1, functional-red-black-tree@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== + +functions-have-names@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + +ganache-core@^2.13.2: + version "2.13.2" + resolved "https://registry.yarnpkg.com/ganache-core/-/ganache-core-2.13.2.tgz#27e6fc5417c10e6e76e2e646671869d7665814a3" + integrity sha512-tIF5cR+ANQz0+3pHWxHjIwHqFXcVo0Mb+kcsNhglNFALcYo49aQpnS9dqHartqPfMFjiHh/qFoD3mYK0d/qGgw== + dependencies: + abstract-leveldown "3.0.0" + async "2.6.2" + bip39 "2.5.0" + cachedown "1.0.0" + clone "2.1.2" + debug "3.2.6" + encoding-down "5.0.4" + eth-sig-util "3.0.0" + ethereumjs-abi "0.6.8" + ethereumjs-account "3.0.0" + ethereumjs-block "2.2.2" + ethereumjs-common "1.5.0" + ethereumjs-tx "2.1.2" + ethereumjs-util "6.2.1" + ethereumjs-vm "4.2.0" + heap "0.2.6" + keccak "3.0.1" + level-sublevel "6.6.4" + levelup "3.1.1" + lodash "4.17.20" + lru-cache "5.1.1" + merkle-patricia-tree "3.0.0" + patch-package "6.2.2" + seedrandom "3.0.1" + source-map-support "0.5.12" + tmp "0.1.0" + web3-provider-engine "14.2.1" + websocket "1.0.32" + optionalDependencies: + ethereumjs-wallet "0.6.5" + web3 "1.2.11" + +get-caller-file@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig== + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" + integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.3" + +get-stream@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + +get-symbol-description@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" + integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== + dependencies: + assert-plus "^1.0.0" + +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@7.1.7: + version "7.1.7" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" + integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.2, glob@^7.1.3, glob@~7.2.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global@~4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" + integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w== + dependencies: + min-document "^2.19.0" + process "^0.11.10" + +globals@^9.18.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== + +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +got@9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" + integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + dependencies: + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" + +got@^11.8.5: + version "11.8.6" + resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a" + integrity sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g== + dependencies: + "@sindresorhus/is" "^4.0.0" + "@szmarczak/http-timer" "^4.0.5" + "@types/cacheable-request" "^6.0.1" + "@types/responselike" "^1.0.0" + cacheable-lookup "^5.0.3" + cacheable-request "^7.0.2" + decompress-response "^6.0.0" + http2-wrapper "^1.0.0-beta.5.2" + lowercase-keys "^2.0.0" + p-cancelable "^2.0.0" + responselike "^2.0.0" + +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== + +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + +hardhat-abi-exporter@^2.9.0: + version "2.10.1" + resolved "https://registry.yarnpkg.com/hardhat-abi-exporter/-/hardhat-abi-exporter-2.10.1.tgz#b14884e233c73fe3f43360f014ad7fd6df4b6d25" + integrity sha512-X8GRxUTtebMAd2k4fcPyVnCdPa6dYK4lBsrwzKP5yiSq4i+WadWPIumaLfce53TUf/o2TnLpLOduyO1ylE2NHQ== + dependencies: + "@ethersproject/abi" "^5.5.0" + delete-empty "^3.0.0" + +hardhat-preprocessor@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/hardhat-preprocessor/-/hardhat-preprocessor-0.1.5.tgz#75b22641fd6a680739c995d03bd5f7868eb72144" + integrity sha512-j8m44mmPxpxAAd0G8fPHRHOas/INZdzptSur0TNJvMEGcFdLDhbHHxBcqZVQ/bmiW42q4gC60AP4CXn9EF018g== + dependencies: + murmur-128 "^0.2.1" + +hardhat@^2.9.5: + version "2.12.5" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.12.5.tgz#e3cd4d6dae35cb9505055967bd7e15e6adf3aa03" + integrity sha512-f/t7+hLlhsnQZ6LDXyV+8rHGRZFZY1sgFvgrwr9fBjMdGp1Bu6hHq1KXS4/VFZfZcVdL1DAWWEkryinZhqce+A== + dependencies: + "@ethersproject/abi" "^5.1.2" + "@metamask/eth-sig-util" "^4.0.0" + "@nomicfoundation/ethereumjs-block" "^4.0.0" + "@nomicfoundation/ethereumjs-blockchain" "^6.0.0" + "@nomicfoundation/ethereumjs-common" "^3.0.0" + "@nomicfoundation/ethereumjs-evm" "^1.0.0" + "@nomicfoundation/ethereumjs-rlp" "^4.0.0" + "@nomicfoundation/ethereumjs-statemanager" "^1.0.0" + "@nomicfoundation/ethereumjs-trie" "^5.0.0" + "@nomicfoundation/ethereumjs-tx" "^4.0.0" + "@nomicfoundation/ethereumjs-util" "^8.0.0" + "@nomicfoundation/ethereumjs-vm" "^6.0.0" + "@nomicfoundation/solidity-analyzer" "^0.1.0" + "@sentry/node" "^5.18.1" + "@types/bn.js" "^5.1.0" + "@types/lru-cache" "^5.1.0" + abort-controller "^3.0.0" + adm-zip "^0.4.16" + aggregate-error "^3.0.0" + ansi-escapes "^4.3.0" + chalk "^2.4.2" + chokidar "^3.4.0" + ci-info "^2.0.0" + debug "^4.1.1" + enquirer "^2.3.0" + env-paths "^2.2.0" + ethereum-cryptography "^1.0.3" + ethereumjs-abi "^0.6.8" + find-up "^2.1.0" + fp-ts "1.19.3" + fs-extra "^7.0.1" + glob "7.2.0" + immutable "^4.0.0-rc.12" + io-ts "1.10.4" + keccak "^3.0.2" + lodash "^4.17.11" + mnemonist "^0.38.0" + mocha "^10.0.0" + p-map "^4.0.0" + qs "^6.7.0" + raw-body "^2.4.1" + resolve "1.17.0" + semver "^6.3.0" + solc "0.7.3" + source-map-support "^0.5.13" + stacktrace-parser "^0.1.10" + tsort "0.0.1" + undici "^5.4.0" + uuid "^8.3.2" + ws "^7.4.6" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg== + dependencies: + ansi-regex "^2.0.0" + +has-bigints@^1.0.1, has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + +has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q== + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw== + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ== + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ== + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has@^1.0.3, has@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +heap@0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.6.tgz#087e1f10b046932fc8594dd9e6d378afc9d1e5ac" + integrity sha512-MzzWcnfB1e4EG2vHi3dXHoBupmuXNZzx6pY6HldVS55JKKBoq3xOyzfSaZRkJp37HIhEYC78knabHff3zc4dQQ== + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +home-or-tmp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" + integrity sha512-ycURW7oUxE2sNiPVw1HVEFsW+ecOpJ5zaj7eC0RlwhibhRBod20muUN8qu/gzx956YrLolVvs1MTXwKgC2rVEg== + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.1" + +hosted-git-info@^2.1.4, hosted-git-info@^2.6.0: + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + +http-cache-semantics@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" + integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +http-https@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" + integrity sha512-o0PWwVCSp3O0wS6FvNr6xfBCHgt0m1tvPLFOCc2iFDKTRAXhB7m8klDf7ErowFH8POa6dVdGatKU5I1YYwzUyg== + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +http2-wrapper@^1.0.0-beta.5.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d" + integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg== + dependencies: + quick-lru "^5.1.1" + resolve-alpn "^1.0.0" + +https-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +iconv-lite@^0.6.2: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +idna-uts46-hx@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz#a1dc5c4df37eee522bf66d969cc980e00e8711f9" + integrity sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA== + dependencies: + punycode "2.1.0" + +ieee754@^1.1.13, ieee754@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +immediate@^3.2.3: + version "3.3.0" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" + integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q== + +immediate@~3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" + integrity sha512-RrGCXRm/fRVqMIhqXrGEX9rRADavPiDFSoMb/k64i9XMk8uH4r/Omi5Ctierj6XzNecwDbO4WuFbDD1zmpl3Tg== + +immutable@^4.0.0-rc.12: + version "4.2.1" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.2.1.tgz#8a4025691018c560a40c67e43d698f816edc44d4" + integrity sha512-7WYV7Q5BTs0nlQm7tl92rDYYoyELLKHoDMBKhrxEoiV4mrfVdRz8hzPiYOzH7yWjzoVEamxRuAqhxL2PLRwZYQ== + +imul@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/imul/-/imul-1.0.1.tgz#9d5867161e8b3de96c2c38d5dc7cb102f35e2ac9" + integrity sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA== + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +internal-slot@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.4.tgz#8551e7baf74a7a6ba5f749cfb16aa60722f0d6f3" + integrity sha512-tA8URYccNzMo94s5MQZgH8NB/XTa6HsOo0MLfXTKKEnHVVdegzaQoFZ7Jp44bdvLvY2waT5dc+j5ICEswhi7UQ== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + side-channel "^1.0.4" + +invariant@^2.2.2: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + integrity sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ== + +io-ts@1.10.4: + version "1.10.4" + resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-1.10.4.tgz#cd5401b138de88e4f920adbcb7026e2d1967e6e2" + integrity sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g== + dependencies: + fp-ts "^1.0.0" + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A== + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-arguments@^1.0.4: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" + integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-array-buffer@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.1.tgz#deb1db4fcae48308d54ef2442706c0393997052a" + integrity sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-typed-array "^1.1.10" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-buffer@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== + +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + +is-core-module@^2.9.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" + integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== + dependencies: + has "^1.0.3" + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg== + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-date-object@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-docker@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-finite@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" + integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== + +is-fn@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fn/-/is-fn-1.0.0.tgz#9543d5de7bcf5b08a22ec8a20bae6e286d510d8c" + integrity sha512-XoFPJQmsAShb3jEQRfzf2rqXavq7fIqF/jOekp308JlThqrODnMpweVSGilKTCXELfLhltGP2AGgbQGVP8F1dg== + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw== + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-function@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.2.tgz#4f097f30abf6efadac9833b17ca5dc03f8144e08" + integrity sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ== + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-hex-prefixed@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" + integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA== + +is-negative-zero@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + +is-number-object@^1.0.4: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" + integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== + dependencies: + has-tostringtag "^1.0.0" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg== + dependencies: + kind-of "^3.0.2" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-regex@^1.0.4, is-regex@^1.1.4, is-regex@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-shared-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" + integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== + dependencies: + call-bind "^1.0.2" + +is-stream@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ== + +is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + +is-symbol@^1.0.2, is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + +is-typed-array@^1.1.10, is-typed-array@^1.1.9: + version "1.1.10" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" + integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + +is-typedarray@^1.0.0, is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +is-url@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" + integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + integrity sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q== + +is-weakref@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +is-wsl@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== + +isarray@1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA== + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== + +js-sha3@0.8.0, js-sha3@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + +js-sha3@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" + integrity sha512-GII20kjaPX0zJ8wzkTbNDYMY7msuZcTWk8S5UOh6806Jq/wz1J8/bnr8uGU0DAUmYDjj2Mr4X1cW8v/GLYnR+g== + +"js-tokens@^3.0.0 || ^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + integrity sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg== + +js-yaml@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== + +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + integrity sha512-Mke0DA0QjUWuJlhsE0ZPPhYiJkRap642SmI/4ztCFaUs6V2AiH1sfecc+57NgaryfAA2VR3v6O+CSjC1jZJKOA== + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== + +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + integrity sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ== + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz#9d4ff447241792e1d0a232f6ef927302bb0c62a9" + integrity sha512-6QNcvm2gFuuK4TKU1uwfH0Qd/cOSb9c1lls0gbnIhciktIUQJwz6NQNAW4B1KiGPenv7IKu97V222Yo1bNhGuA== + dependencies: + async "^2.0.1" + babel-preset-env "^1.7.0" + babelify "^7.3.0" + json-rpc-error "^2.0.0" + promise-to-callback "^1.0.0" + safe-event-emitter "^1.0.1" + +json-rpc-error@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02" + integrity sha512-EwUeWP+KgAZ/xqFpaP6YDAXMtCJi+o/QQpCQFIYyxr01AdADi2y413eM8hSqJcoQym9WMePAJWoaODEJufC4Ug== + dependencies: + inherits "^2.0.1" + +json-rpc-random-id@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8" + integrity sha512-RJ9YYNCkhVDBuP4zN5BBtYAzEl03yq/jIIsyif0JY9qyJuQQZNeDK7anAPKKlyEtLSj2s8h6hNh2F8zO5q7ScA== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== + +json-stable-stringify@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz#e06f23128e0bbe342dc996ed5a19e28b57b580e0" + integrity sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g== + dependencies: + jsonify "^0.0.1" + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + +json5@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + integrity sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw== + +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + integrity sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw== + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +jsonify@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" + integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== + +jsprim@^1.2.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" + integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.4.0" + verror "1.10.0" + +keccak@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.1.tgz#ae30a0e94dbe43414f741375cff6d64c8bea0bff" + integrity sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA== + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + +keccak@^3.0.0, keccak@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.3.tgz#4bc35ad917be1ef54ff246f904c2bbbf9ac61276" + integrity sha512-JZrLIAJWuZxKbCilMpNz5Vj7Vtb4scDG3dMXLOsbzBmQGyjwE61BbW7bJkfKKCShXiQZt3T6sBgALRtmd+nZaQ== + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + readable-stream "^3.6.0" + +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" + integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + dependencies: + json-buffer "3.0.0" + +keyv@^4.0.0: + version "4.5.2" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.2.tgz#0e310ce73bf7851ec702f2eaf46ec4e3805cce56" + integrity sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g== + dependencies: + json-buffer "3.0.1" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw== + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +klaw-sync@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c" + integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ== + dependencies: + graceful-fs "^4.1.11" + +klaw@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" + integrity sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw== + optionalDependencies: + graceful-fs "^4.1.9" + +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + integrity sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw== + dependencies: + invert-kv "^1.0.0" + +level-codec@^9.0.0: + version "9.0.2" + resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-9.0.2.tgz#fd60df8c64786a80d44e63423096ffead63d8cbc" + integrity sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ== + dependencies: + buffer "^5.6.0" + +level-codec@~7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-7.0.1.tgz#341f22f907ce0f16763f24bddd681e395a0fb8a7" + integrity sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ== + +level-errors@^1.0.3: + version "1.1.2" + resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.1.2.tgz#4399c2f3d3ab87d0625f7e3676e2d807deff404d" + integrity sha512-Sw/IJwWbPKF5Ai4Wz60B52yj0zYeqzObLh8k1Tk88jVmD51cJSKWSYpRyhVIvFzZdvsPqlH5wfhp/yxdsaQH4w== + dependencies: + errno "~0.1.1" + +level-errors@^2.0.0, level-errors@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-2.0.1.tgz#2132a677bf4e679ce029f517c2f17432800c05c8" + integrity sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw== + dependencies: + errno "~0.1.1" + +level-errors@~1.0.3: + version "1.0.5" + resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.0.5.tgz#83dbfb12f0b8a2516bdc9a31c4876038e227b859" + integrity sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig== + dependencies: + errno "~0.1.1" + +level-iterator-stream@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-2.0.3.tgz#ccfff7c046dcf47955ae9a86f46dfa06a31688b4" + integrity sha512-I6Heg70nfF+e5Y3/qfthJFexhRw/Gi3bIymCoXAlijZdAcLaPuWSJs3KXyTYf23ID6g0o2QF62Yh+grOXY3Rig== + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.5" + xtend "^4.0.0" + +level-iterator-stream@~1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz#e43b78b1a8143e6fa97a4f485eb8ea530352f2ed" + integrity sha512-1qua0RHNtr4nrZBgYlpV0qHHeHpcRRWTxEZJ8xsemoHAXNL5tbooh4tPEEqIqsbWCAJBmUmkwYK/sW5OrFjWWw== + dependencies: + inherits "^2.0.1" + level-errors "^1.0.3" + readable-stream "^1.0.33" + xtend "^4.0.0" + +level-iterator-stream@~3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz#2c98a4f8820d87cdacab3132506815419077c730" + integrity sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g== + dependencies: + inherits "^2.0.1" + readable-stream "^2.3.6" + xtend "^4.0.0" + +level-mem@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/level-mem/-/level-mem-3.0.1.tgz#7ce8cf256eac40f716eb6489654726247f5a89e5" + integrity sha512-LbtfK9+3Ug1UmvvhR2DqLqXiPW1OJ5jEh0a3m9ZgAipiwpSxGj/qaVVy54RG5vAQN1nCuXqjvprCuKSCxcJHBg== + dependencies: + level-packager "~4.0.0" + memdown "~3.0.0" + +level-packager@~4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/level-packager/-/level-packager-4.0.1.tgz#7e7d3016af005be0869bc5fa8de93d2a7f56ffe6" + integrity sha512-svCRKfYLn9/4CoFfi+d8krOtrp6RoX8+xm0Na5cgXMqSyRru0AnDYdLl+YI8u1FyS6gGZ94ILLZDE5dh2but3Q== + dependencies: + encoding-down "~5.0.0" + levelup "^3.0.0" + +level-post@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/level-post/-/level-post-1.0.7.tgz#19ccca9441a7cc527879a0635000f06d5e8f27d0" + integrity sha512-PWYqG4Q00asOrLhX7BejSajByB4EmG2GaKHfj3h5UmmZ2duciXLPGYWIjBzLECFWUGOZWlm5B20h/n3Gs3HKew== + dependencies: + ltgt "^2.1.2" + +level-sublevel@6.6.4: + version "6.6.4" + resolved "https://registry.yarnpkg.com/level-sublevel/-/level-sublevel-6.6.4.tgz#f7844ae893919cd9d69ae19d7159499afd5352ba" + integrity sha512-pcCrTUOiO48+Kp6F1+UAzF/OtWqLcQVTVF39HLdZ3RO8XBoXt+XVPKZO1vVr1aUoxHZA9OtD2e1v7G+3S5KFDA== + dependencies: + bytewise "~1.1.0" + level-codec "^9.0.0" + level-errors "^2.0.0" + level-iterator-stream "^2.0.3" + ltgt "~2.1.1" + pull-defer "^0.2.2" + pull-level "^2.0.3" + pull-stream "^3.6.8" + typewiselite "~1.0.0" + xtend "~4.0.0" + +level-supports@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-4.0.1.tgz#431546f9d81f10ff0fea0e74533a0e875c08c66a" + integrity sha512-PbXpve8rKeNcZ9C1mUicC9auIYFyGpkV9/i6g76tLgANwWhtG2v7I4xNBUlkn3lE2/dZF3Pi0ygYGtLc4RXXdA== + +level-transcoder@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/level-transcoder/-/level-transcoder-1.0.1.tgz#f8cef5990c4f1283d4c86d949e73631b0bc8ba9c" + integrity sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w== + dependencies: + buffer "^6.0.3" + module-error "^1.0.1" + +level-ws@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-0.0.0.tgz#372e512177924a00424b0b43aef2bb42496d228b" + integrity sha512-XUTaO/+Db51Uiyp/t7fCMGVFOTdtLS/NIACxE/GHsij15mKzxksZifKVjlXDF41JMUP/oM1Oc4YNGdKnc3dVLw== + dependencies: + readable-stream "~1.0.15" + xtend "~2.1.1" + +level-ws@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-1.0.0.tgz#19a22d2d4ac57b18cc7c6ecc4bd23d899d8f603b" + integrity sha512-RXEfCmkd6WWFlArh3X8ONvQPm8jNpfA0s/36M4QzLqrLEIt1iJE9WBHLZ5vZJK6haMjJPJGJCQWfjMNnRcq/9Q== + dependencies: + inherits "^2.0.3" + readable-stream "^2.2.8" + xtend "^4.0.1" + +level@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/level/-/level-8.0.0.tgz#41b4c515dabe28212a3e881b61c161ffead14394" + integrity sha512-ypf0jjAk2BWI33yzEaaotpq7fkOPALKAgDBxggO6Q9HGX2MRXn0wbP1Jn/tJv1gtL867+YOjOB49WaUF3UoJNQ== + dependencies: + browser-level "^1.0.1" + classic-level "^1.2.0" + +levelup@3.1.1, levelup@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/levelup/-/levelup-3.1.1.tgz#c2c0b3be2b4dc316647c53b42e2f559e232d2189" + integrity sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg== + dependencies: + deferred-leveldown "~4.0.0" + level-errors "~2.0.0" + level-iterator-stream "~3.0.0" + xtend "~4.0.0" + +levelup@^1.2.1: + version "1.3.9" + resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.9.tgz#2dbcae845b2bb2b6bea84df334c475533bbd82ab" + integrity sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ== + dependencies: + deferred-leveldown "~1.2.1" + level-codec "~7.0.0" + level-errors "~1.0.3" + level-iterator-stream "~1.3.0" + prr "~1.0.1" + semver "~5.4.1" + xtend "~4.0.0" + +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + integrity sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A== + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.assign@^4.0.3, lodash.assign@^4.0.6: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" + integrity sha512-hFuH8TY+Yji7Eja3mGiuAxBqLagejScbG8GbG0j6o9vzn0YL14My+ktnqtZgFTosKymC9/44wP6s7xyuLfnClw== + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== + +lodash.truncate@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" + integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== + +lodash@4.17.20: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + +lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-symbols@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +looper@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/looper/-/looper-2.0.0.tgz#66cd0c774af3d4fedac53794f742db56da8f09ec" + integrity sha512-6DzMHJcjbQX/UPHc1rRCBfKlLwDkvuGZ715cIR36wSdYqWXFT35uLXq5P/2orl3tz+t+VOVPxw4yPinQlUDGDQ== + +looper@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/looper/-/looper-3.0.0.tgz#2efa54c3b1cbaba9b94aee2e5914b0be57fbb749" + integrity sha512-LJ9wplN/uSn72oJRsXTx+snxPet5c8XiZmOKCm906NVYu+ag6SB6vUcnJcWxgnl2NfbIyeobAn7Bwv6xRj2XJg== + +loose-envify@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +loupe@^2.3.1: + version "2.3.6" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53" + integrity sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA== + dependencies: + get-func-name "^2.0.0" + +lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + +lru-cache@5.1.1, lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +lru-cache@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-3.2.0.tgz#71789b3b7f5399bec8565dda38aa30d2a097efee" + integrity sha512-91gyOKTc2k66UG6kHiH4h3S2eltcPwE1STVfMYC/NG+nZwf8IIuiamfmpGZjpbbxzSyEJaLC0tNSmhjlQUTJow== + dependencies: + pseudomap "^1.0.1" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +lru_map@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" + integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== + +ltgt@^2.1.2, ltgt@~2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" + integrity sha512-AI2r85+4MquTw9ZYqabu4nMwy9Oftlfa/e/52t9IjtfG+mGBbTNdAoZ3RQKLHR6r0wQnwZnPIEh/Ya6XTWAKNA== + +ltgt@~2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.1.3.tgz#10851a06d9964b971178441c23c9e52698eece34" + integrity sha512-5VjHC5GsENtIi5rbJd+feEpDKhfr7j0odoUR2Uh978g+2p93nd5o34cTjQWohXsPsCZeqoDnIqEf88mPCe0Pfw== + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w== + dependencies: + object-visit "^1.0.0" + +mcl-wasm@^0.7.1: + version "0.7.9" + resolved "https://registry.yarnpkg.com/mcl-wasm/-/mcl-wasm-0.7.9.tgz#c1588ce90042a8700c3b60e40efb339fc07ab87f" + integrity sha512-iJIUcQWA88IJB/5L15GnJVnSQJmf/YaxxV6zRavv83HILHaJQb6y0iFyDMdDO0gN8X37tdxmAOrH/P8B6RB8sQ== + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + +memdown@^1.0.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215" + integrity sha512-iVrGHZB8i4OQfM155xx8akvG9FIj+ht14DX5CQkCTG4EHzZ3d3sgckIf/Lm9ivZalEsFuEVnWv2B2WZvbrro2w== + dependencies: + abstract-leveldown "~2.7.1" + functional-red-black-tree "^1.0.1" + immediate "^3.2.3" + inherits "~2.0.1" + ltgt "~2.2.0" + safe-buffer "~5.1.1" + +memdown@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/memdown/-/memdown-3.0.0.tgz#93aca055d743b20efc37492e9e399784f2958309" + integrity sha512-tbV02LfZMWLcHcq4tw++NuqMO+FZX8tNJEiD2aNRm48ZZusVg5N8NART+dmBkepJVye986oixErf7jfXboMGMA== + dependencies: + abstract-leveldown "~5.0.0" + functional-red-black-tree "~1.0.1" + immediate "~3.2.3" + inherits "~2.0.1" + ltgt "~2.2.0" + safe-buffer "~5.1.1" + +memory-level@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/memory-level/-/memory-level-1.0.0.tgz#7323c3fd368f9af2f71c3cd76ba403a17ac41692" + integrity sha512-UXzwewuWeHBz5krr7EvehKcmLFNoXxGcvuYhC41tRnkrTbJohtS7kVn9akmgirtRygg+f7Yjsfi8Uu5SGSQ4Og== + dependencies: + abstract-level "^1.0.0" + functional-red-black-tree "^1.0.1" + module-error "^1.0.1" + +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== + +merkle-patricia-tree@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-3.0.0.tgz#448d85415565df72febc33ca362b8b614f5a58f8" + integrity sha512-soRaMuNf/ILmw3KWbybaCjhx86EYeBbD8ph0edQCTed0JN/rxDt1EBN52Ajre3VyGo+91f8+/rfPIRQnnGMqmQ== + dependencies: + async "^2.6.1" + ethereumjs-util "^5.2.0" + level-mem "^3.0.1" + level-ws "^1.0.0" + readable-stream "^3.0.6" + rlp "^2.0.0" + semaphore ">=1.0.1" + +merkle-patricia-tree@^2.1.2, merkle-patricia-tree@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz#982ca1b5a0fde00eed2f6aeed1f9152860b8208a" + integrity sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g== + dependencies: + async "^1.4.2" + ethereumjs-util "^5.0.0" + level-ws "0.0.0" + levelup "^1.2.1" + memdown "^1.0.0" + readable-stream "^2.0.0" + rlp "^2.0.0" + semaphore ">=1.0.1" + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== + +micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +micromatch@^4.0.2: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mimic-response@^1.0.0, mimic-response@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== + +min-document@^2.19.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" + integrity sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ== + dependencies: + dom-walk "^0.1.0" + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== + +minimatch@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" + integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^3.0.4, minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.0, minimist@^1.2.6, minimist@~1.2.6: + version "1.2.7" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" + integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== + +minipass@^2.6.0, minipass@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" + integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" + integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== + dependencies: + minipass "^2.9.0" + +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp-promise@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" + integrity sha512-Hepn5kb1lJPtVW84RFT40YG1OddBNTOVUZR2bzQUHc+Z03en8/3uX0+060JDhcEzyO08HmipsN9DcnFMxhIL9w== + dependencies: + mkdirp "*" + +mkdirp@*, mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +mkdirp@^0.5.1, mkdirp@^0.5.5: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +mnemonist@^0.38.0: + version "0.38.5" + resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.38.5.tgz#4adc7f4200491237fe0fa689ac0b86539685cade" + integrity sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg== + dependencies: + obliterator "^2.0.0" + +mocha@^10.0.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8" + integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg== + dependencies: + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.3" + debug "4.3.4" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.2.0" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "5.0.1" + ms "2.1.3" + nanoid "3.3.3" + serialize-javascript "6.0.0" + strip-json-comments "3.1.1" + supports-color "8.1.1" + workerpool "6.2.1" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + +mock-fs@^4.1.0: + version "4.14.0" + resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.14.0.tgz#ce5124d2c601421255985e6e94da80a7357b1b18" + integrity sha512-qYvlv/exQ4+svI3UOvPUpLDF0OMX5euvUH0Ny4N5QyRyhNdgAgUrVH3iUINSzEPLvx0kbo/Bp28GJKIqvE7URw== + +module-error@^1.0.1, module-error@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/module-error/-/module-error-1.0.2.tgz#8d1a48897ca883f47a45816d4fb3e3c6ba404d86" + integrity sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3, ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +multibase@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.7.0.tgz#1adfc1c50abe05eefeb5091ac0c2728d6b84581b" + integrity sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg== + dependencies: + base-x "^3.0.8" + buffer "^5.5.0" + +multibase@~0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.6.1.tgz#b76df6298536cc17b9f6a6db53ec88f85f8cc12b" + integrity sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw== + dependencies: + base-x "^3.0.8" + buffer "^5.5.0" + +multicodec@^0.5.5: + version "0.5.7" + resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-0.5.7.tgz#1fb3f9dd866a10a55d226e194abba2dcc1ee9ffd" + integrity sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA== + dependencies: + varint "^5.0.0" + +multicodec@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-1.0.4.tgz#46ac064657c40380c28367c90304d8ed175a714f" + integrity sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg== + dependencies: + buffer "^5.6.0" + varint "^5.0.0" + +multihashes@^0.4.15, multihashes@~0.4.15: + version "0.4.21" + resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-0.4.21.tgz#dc02d525579f334a7909ade8a122dabb58ccfcb5" + integrity sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw== + dependencies: + buffer "^5.5.0" + multibase "^0.7.0" + varint "^5.0.0" + +murmur-128@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/murmur-128/-/murmur-128-0.2.1.tgz#a9f6568781d2350ecb1bf80c14968cadbeaa4b4d" + integrity sha512-WseEgiRkI6aMFBbj8Cg9yBj/y+OdipwVC7zUo3W2W1JAJITwouUOtpqsmGSg67EQmwwSyod7hsVsWY5LsrfQVg== + dependencies: + encode-utf8 "^1.0.2" + fmix "^0.1.0" + imul "^1.0.0" + +nano-json-stream-parser@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" + integrity sha512-9MqxMH/BSJC7dnLsEMPyfN5Dvoo49IsPFYMcHw3Bcfc2kN0lpHRBSzlMSVx4HGyJ7s9B31CyBTVehWJoQ8Ctew== + +nanoid@3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" + integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +napi-macros@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.0.0.tgz#2b6bae421e7b96eb687aa6c77a7858640670001b" + integrity sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg== + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +next-tick@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" + integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +node-addon-api@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" + integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== + +node-fetch@^2.6.1, node-fetch@^2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + +node-fetch@~1.7.1: + version "1.7.3" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" + integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== + dependencies: + encoding "^0.1.11" + is-stream "^1.0.1" + +node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" + integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== + +nofilter@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/nofilter/-/nofilter-3.1.0.tgz#c757ba68801d41ff930ba2ec55bab52ca184aa66" + integrity sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g== + +normalize-package-data@^2.3.2: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-url@^4.1.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" + integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== + +normalize-url@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" + integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ== + +number-to-bn@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" + integrity sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig== + dependencies: + bn.js "4.11.6" + strip-hex-prefix "1.0.0" + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +object-assign@^4, object-assign@^4.0.0, object-assign@^4.1.0, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ== + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-inspect@^1.12.2, object-inspect@^1.9.0, object-inspect@~1.12.2: + version "1.12.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" + integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== + +object-is@^1.0.1: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" + integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object-keys@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" + integrity sha512-ncrLw+X55z7bkl5PnUvHwFK9FcGuFYo9gtjws2XtSzL+aZ8tm830P60WJ0dSmFVaSalWieW5MD7kEdnXda9yJw== + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA== + dependencies: + isobject "^3.0.0" + +object.assign@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + has-symbols "^1.0.3" + object-keys "^1.1.1" + +object.getownpropertydescriptors@^2.1.1: + version "2.1.5" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.5.tgz#db5a9002489b64eef903df81d6623c07e5b4b4d3" + integrity sha512-yDNzckpM6ntyQiGTik1fKV1DcVDRS+w8bvpWNCBanvH5LfRX9O8WTHqQzG4RZwRAM4I0oU7TV11Lj5v0g20ibw== + dependencies: + array.prototype.reduce "^1.0.5" + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ== + dependencies: + isobject "^3.0.1" + +obliterator@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.4.tgz#fa650e019b2d075d745e44f1effeb13a2adbe816" + integrity sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ== + +oboe@2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.4.tgz#20c88cdb0c15371bb04119257d4fdd34b0aa49f6" + integrity sha512-ymBJ4xSC6GBXLT9Y7lirj+xbqBLa+jADGJldGEYG7u8sZbS9GyG+u1Xk9c5cbriKwSpCg41qUhPjvU5xOpvIyQ== + dependencies: + http-https "^1.0.0" + +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +open@^7.4.2: + version "7.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" + integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== + dependencies: + is-docker "^2.0.0" + is-wsl "^2.1.1" + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ== + +os-locale@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + integrity sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g== + dependencies: + lcid "^1.0.0" + +os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + +p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" + integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + +p-cancelable@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf" + integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg== + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== + dependencies: + p-limit "^1.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== + +parse-asn1@^5.0.0, parse-asn1@^5.1.5: + version "5.1.6" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" + integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== + dependencies: + asn1.js "^5.2.0" + browserify-aes "^1.0.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + safe-buffer "^5.1.1" + +parse-headers@^2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.5.tgz#069793f9356a54008571eb7f9761153e6c770da9" + integrity sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA== + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + integrity sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ== + dependencies: + error-ex "^1.2.0" + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw== + +patch-package@6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.2.2.tgz#71d170d650c65c26556f0d0fbbb48d92b6cc5f39" + integrity sha512-YqScVYkVcClUY0v8fF0kWOjDYopzIM8e3bj/RU1DPeEF14+dCGm6UeOYm4jvCyxqIEQ5/eJzmbWfDWnUleFNMg== + dependencies: + "@yarnpkg/lockfile" "^1.1.0" + chalk "^2.4.2" + cross-spawn "^6.0.5" + find-yarn-workspace-root "^1.2.1" + fs-extra "^7.0.1" + is-ci "^2.0.0" + klaw-sync "^6.0.0" + minimist "^1.2.0" + rimraf "^2.6.3" + semver "^5.6.0" + slash "^2.0.0" + tmp "^0.0.33" + +patch-package@^6.2.2: + version "6.5.1" + resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.5.1.tgz#3e5d00c16997e6160291fee06a521c42ac99b621" + integrity sha512-I/4Zsalfhc6bphmJTlrLoOcAF87jcxko4q0qsv4bGcurbr8IskEOtdnt9iCmsQVGL1B+iUhSQqweyTLJfCF9rA== + dependencies: + "@yarnpkg/lockfile" "^1.1.0" + chalk "^4.1.2" + cross-spawn "^6.0.5" + find-yarn-workspace-root "^2.0.0" + fs-extra "^9.0.0" + is-ci "^2.0.0" + klaw-sync "^6.0.0" + minimist "^1.2.6" + open "^7.4.2" + rimraf "^2.6.3" + semver "^5.6.0" + slash "^2.0.0" + tmp "^0.0.33" + yaml "^1.10.2" + +path-browserify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" + integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== + +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + integrity sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ== + dependencies: + pinkie-promise "^2.0.0" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== + +path-parse@^1.0.6, path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-starts-with@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-starts-with/-/path-starts-with-2.0.0.tgz#ffd6d51926cd497022b44d392196033d5451892f" + integrity sha512-3UHTHbJz5+NLkPafFR+2ycJOjoc4WV2e9qCZCnm71zHiWaFrm1XniLVTkZXvaRgxr1xFh9JsTdicpH2yM03nLA== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== + +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + integrity sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg== + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== + +pbkdf2@^3.0.17, pbkdf2@^3.0.3, pbkdf2@^3.0.9: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" + integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pify@^2.0.0, pify@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw== + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg== + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg== + +postinstall-postinstall@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz#4f7f77441ef539d1512c40bd04c71b06a4704ca3" + integrity sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ== + +precond@0.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" + integrity sha512-QCYG84SgGyGzqJ/vlMsxeXd/pgL/I94ixdNFyh1PusWmTCyVfPJjZ1K1jvHtsbfnXQs2TSkEP2fR7QiMZAnKFQ== + +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA== + +prettier-plugin-solidity@^1.0.0-beta.19: + version "1.1.1" + resolved "https://registry.yarnpkg.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.1.1.tgz#4d3375b85f97812ffcbe48d5a8b3fe914d69c91f" + integrity sha512-uD24KO26tAHF+zMN2nt1OUzfknzza5AgxjogQQrMLZc7j8xiQrDoNWNeOlfFC0YLTwo12CLD10b9niLyP6AqXg== + dependencies: + "@solidity-parser/parser" "^0.14.5" + semver "^7.3.8" + solidity-comments-extractor "^0.0.7" + +prettier@^2.1.2, prettier@^2.3.1, prettier@^2.6.2: + version "2.8.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.1.tgz#4e1fd11c34e2421bc1da9aea9bd8127cd0a35efc" + integrity sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg== + +private@^0.1.6, private@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== + +promise-to-callback@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/promise-to-callback/-/promise-to-callback-1.0.0.tgz#5d2a749010bfb67d963598fcd3960746a68feef7" + integrity sha512-uhMIZmKM5ZteDMfLgJnoSq9GCwsNKrYau73Awf1jIy6/eUcuuZ3P+CD9zUv0kJsIUbU+x6uLNIhXhLHDs1pNPA== + dependencies: + is-fn "^1.0.0" + set-immediate-shim "^1.0.1" + +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw== + +pseudomap@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== + +psl@^1.1.28: + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== + +public-encrypt@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + safe-buffer "^5.1.2" + +pull-cat@^1.1.9: + version "1.1.11" + resolved "https://registry.yarnpkg.com/pull-cat/-/pull-cat-1.1.11.tgz#b642dd1255da376a706b6db4fa962f5fdb74c31b" + integrity sha512-i3w+xZ3DCtTVz8S62hBOuNLRHqVDsHMNZmgrZsjPnsxXUgbWtXEee84lo1XswE7W2a3WHyqsNuDJTjVLAQR8xg== + +pull-defer@^0.2.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/pull-defer/-/pull-defer-0.2.3.tgz#4ee09c6d9e227bede9938db80391c3dac489d113" + integrity sha512-/An3KE7mVjZCqNhZsr22k1Tx8MACnUnHZZNPSJ0S62td8JtYr/AiRG42Vz7Syu31SoTLUzVIe61jtT/pNdjVYA== + +pull-level@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pull-level/-/pull-level-2.0.4.tgz#4822e61757c10bdcc7cf4a03af04c92734c9afac" + integrity sha512-fW6pljDeUThpq5KXwKbRG3X7Ogk3vc75d5OQU/TvXXui65ykm+Bn+fiktg+MOx2jJ85cd+sheufPL+rw9QSVZg== + dependencies: + level-post "^1.0.7" + pull-cat "^1.1.9" + pull-live "^1.0.1" + pull-pushable "^2.0.0" + pull-stream "^3.4.0" + pull-window "^2.1.4" + stream-to-pull-stream "^1.7.1" + +pull-live@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/pull-live/-/pull-live-1.0.1.tgz#a4ecee01e330155e9124bbbcf4761f21b38f51f5" + integrity sha512-tkNz1QT5gId8aPhV5+dmwoIiA1nmfDOzJDlOOUpU5DNusj6neNd3EePybJ5+sITr2FwyCs/FVpx74YMCfc8YeA== + dependencies: + pull-cat "^1.1.9" + pull-stream "^3.4.0" + +pull-pushable@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/pull-pushable/-/pull-pushable-2.2.0.tgz#5f2f3aed47ad86919f01b12a2e99d6f1bd776581" + integrity sha512-M7dp95enQ2kaHvfCt2+DJfyzgCSpWVR2h2kWYnVsW6ZpxQBx5wOu0QWOvQPVoPnBLUZYitYP2y7HyHkLQNeGXg== + +pull-stream@^3.2.3, pull-stream@^3.4.0, pull-stream@^3.6.8: + version "3.7.0" + resolved "https://registry.yarnpkg.com/pull-stream/-/pull-stream-3.7.0.tgz#85de0e44ff38a4d2ad08cc43fc458e1922f9bf0b" + integrity sha512-Eco+/R004UaCK2qEDE8vGklcTG2OeZSVm1kTUQNrykEjDwcFXDZhygFDsW49DbXyJMEhHeRL3z5cRVqPAhXlIw== + +pull-window@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/pull-window/-/pull-window-2.1.4.tgz#fc3b86feebd1920c7ae297691e23f705f88552f0" + integrity sha512-cbDzN76BMlcGG46OImrgpkMf/VkCnupj8JhsrpBw3aWBM9ye345aYnqitmZCgauBkc0HbbRRn9hCnsa3k2FNUg== + dependencies: + looper "^2.0.0" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + integrity sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw== + +punycode@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" + integrity sha512-Yxz2kRwT90aPiWEMHVYnEf4+rhwF1tBmmZ4KepCP+Wkium9JxtWnUm1nqGwpiAHr/tnTSeHqr3wb++jgSkXjhA== + +punycode@^2.1.0, punycode@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +qs@6.11.0, qs@^6.7.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" + +qs@~6.5.2: + version "6.5.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== + +query-string@^5.0.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" + integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== + dependencies: + decode-uri-component "^0.2.0" + object-assign "^4.1.0" + strict-uri-encode "^1.0.0" + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g== + +queue-microtask@^1.2.2, queue-microtask@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +quick-lru@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" + integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.0.6, randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.5.1, raw-body@^2.4.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" + integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + integrity sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A== + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + integrity sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ== + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +readable-stream@^1.0.33: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + integrity sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.2.2, readable-stream@^2.2.8, readable-stream@^2.2.9, readable-stream@^2.3.6, readable-stream@~2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.0.6, readable-stream@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readable-stream@~1.0.15: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + integrity sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +reduce-flatten@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" + integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w== + +regenerate@^1.2.1: + version "1.4.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== + +regenerator-transform@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" + integrity sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q== + dependencies: + babel-runtime "^6.18.0" + babel-types "^6.19.0" + private "^0.1.6" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" + integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + functions-have-names "^1.2.2" + +regexpu-core@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" + integrity sha512-tJ9+S4oKjxY8IZ9jmjnp/mtytu1u3iyIQAfmI51IKWH6bFf7XR1ybtaO6j7INhZKXOTYADk7V5qxaqLkmNxiZQ== + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + integrity sha512-x+Y3yA24uF68m5GA+tBjbGYo64xXVJpbToBaWCoSNSc1hdk6dfctaRWrNFTVJZIIhL5GxW8zwjoixbnifnK59g== + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + integrity sha512-jlQ9gYLfk2p3V5Ag5fYhA7fv7OHzd1KUH0PRP46xc3TgwjwgROIW572AfYg/X9kaNq/LJnu6oJcFRXlIrGoTRw== + dependencies: + jsesc "~0.5.0" + +repeat-element@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" + integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + integrity sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A== + dependencies: + is-finite "^1.0.0" + +request@^2.79.0, request@^2.85.0: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-from-string@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" + integrity sha512-H7AkJWMobeskkttHyhTVtS0fxpFLjxhbfMa6Bk3wimP7sdPRGL3EyCg3sAQenFfAe+xQ+oAc85Nmtvq0ROM83Q== + +require-from-string@^2.0.0, require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + integrity sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug== + +resolve-alpn@^1.0.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" + integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== + +resolve@1.17.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" + +resolve@^1.10.0, resolve@^1.8.1, resolve@~1.22.1: + version "1.22.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== + dependencies: + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +responselike@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + integrity sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ== + dependencies: + lowercase-keys "^1.0.0" + +responselike@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.1.tgz#9a0bc8fdc252f3fb1cca68b016591059ba1422bc" + integrity sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw== + dependencies: + lowercase-keys "^2.0.0" + +resumer@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" + integrity sha512-Fn9X8rX8yYF4m81rZCK/5VmrmsSbqS/i3rDLl6ZZHAXgC2nTAx3dhwG8q8odP/RmdLa2YrybDJaAMg+X1ajY3w== + dependencies: + through "~2.3.4" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +rimraf@^2.2.8, rimraf@^2.6.2, rimraf@^2.6.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +rlp@^2.0.0, rlp@^2.2.1, rlp@^2.2.2, rlp@^2.2.3, rlp@^2.2.4: + version "2.2.7" + resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" + integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== + dependencies: + bn.js "^5.2.0" + +run-parallel-limit@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz#be80e936f5768623a38a963262d6bef8ff11e7ba" + integrity sha512-jJA7irRNM91jaKc3Hcl1npHsFLOXOoTkPCUL1JEa1R82O2miplXXRaGdjW/KM/98YQWDhJLiSs793CnXfblJUw== + dependencies: + queue-microtask "^1.2.2" + +rustbn.js@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" + integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== + +safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-event-emitter@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz#5b692ef22329ed8f69fdce607e50ca734f6f20af" + integrity sha512-e1wFe99A91XYYxoQbcq2ZJUWurxEyP8vfz7A7vuUe1s95q8r5ebraVaA1BukYJcpM6V16ugWoD9vngi8Ccu5fg== + dependencies: + events "^3.0.0" + +safe-regex-test@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" + integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-regex "^1.1.4" + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg== + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +scrypt-js@3.0.1, scrypt-js@^3.0.0, scrypt-js@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" + integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== + +scryptsy@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" + integrity sha512-aldIRgMozSJ/Gl6K6qmJZysRP82lz83Wb42vl4PWN8SaLFHIaOzLPc9nUUW2jQN88CuGm5q5HefJ9jZ3nWSmTw== + dependencies: + pbkdf2 "^3.0.3" + +secp256k1@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" + integrity sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA== + dependencies: + elliptic "^6.5.4" + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + +seedrandom@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.1.tgz#eb3dde015bcf55df05a233514e5df44ef9dce083" + integrity sha512-1/02Y/rUeU1CJBAGLebiC5Lbo5FnB22gQbIFFYTLkwvp1xdABZJH1sn4ZT1MzXmPpzv+Rf/Lu2NcsLJiK4rcDg== + +semaphore@>=1.0.1, semaphore@^1.0.3, semaphore@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" + integrity sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA== + +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@^7.3.8: + version "7.3.8" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" + integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== + dependencies: + lru-cache "^6.0.0" + +semver@~5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" + integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== + +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + +serialize-javascript@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + +serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.18.0" + +servify@^0.1.12: + version "0.1.12" + resolved "https://registry.yarnpkg.com/servify/-/servify-0.1.12.tgz#142ab7bee1f1d033b66d0707086085b17c06db95" + integrity sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw== + dependencies: + body-parser "^1.16.0" + cors "^2.8.1" + express "^4.14.0" + request "^2.79.0" + xhr "^2.3.3" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + +set-immediate-shim@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" + integrity sha512-Li5AOqrZWCVA2n5kryzEmqai6bKSIvpz5oUJHPVj6+dsbD3X1ixtsY5tEnsaNpH3pFAHmG8eIHUrtEtohrg+UQ== + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== + +simple-get@^2.7.0: + version "2.8.2" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.2.tgz#5708fb0919d440657326cd5fe7d2599d07705019" + integrity sha512-Ijd/rV5o+mSBBs4F/x9oDPtTx9Zb6X9brmnXvMW4J7IR15ngi9q5xxqWBKU744jTZiaXtxaPL7uHG6vtN8kUkw== + dependencies: + decompress-response "^3.3.0" + once "^1.3.1" + simple-concat "^1.0.0" + +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + integrity sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg== + +slash@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" + integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +solc@0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a" + integrity sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA== + dependencies: + command-exists "^1.2.8" + commander "3.0.2" + follow-redirects "^1.12.1" + fs-extra "^0.30.0" + js-sha3 "0.8.0" + memorystream "^0.3.1" + require-from-string "^2.0.0" + semver "^5.5.0" + tmp "0.0.33" + +solc@^0.4.20: + version "0.4.26" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.26.tgz#5390a62a99f40806b86258c737c1cf653cc35cb5" + integrity sha512-o+c6FpkiHd+HPjmjEVpQgH7fqZ14tJpXhho+/bQXlXbliLIS/xjXb42Vxh+qQY1WCSTMQ0+a5vR9vi0MfhU6mA== + dependencies: + fs-extra "^0.30.0" + memorystream "^0.3.1" + require-from-string "^1.1.0" + semver "^5.3.0" + yargs "^4.7.1" + +solc@^0.6.3: + version "0.6.12" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.6.12.tgz#48ac854e0c729361b22a7483645077f58cba080e" + integrity sha512-Lm0Ql2G9Qc7yPP2Ba+WNmzw2jwsrd3u4PobHYlSOxaut3TtUbj9+5ZrT6f4DUpNPEoBaFUOEg9Op9C0mk7ge9g== + dependencies: + command-exists "^1.2.8" + commander "3.0.2" + fs-extra "^0.30.0" + js-sha3 "0.8.0" + memorystream "^0.3.1" + require-from-string "^2.0.0" + semver "^5.5.0" + tmp "0.0.33" + +solidity-comments-extractor@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz#99d8f1361438f84019795d928b931f4e5c39ca19" + integrity sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw== + +source-map-resolve@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@0.5.12: + version "0.5.12" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" + integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-support@^0.4.15: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== + dependencies: + source-map "^0.5.6" + +source-map-support@^0.5.13: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" + integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== + +source-map@^0.5.6, source-map@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +spdx-correct@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.12" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz#69077835abe2710b65f03969898b6637b505a779" + integrity sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA== + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +sshpk@^1.7.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" + integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +stacktrace-parser@^0.1.10: + version "0.1.10" + resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" + integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== + dependencies: + type-fest "^0.7.1" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g== + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +stream-to-pull-stream@^1.7.1: + version "1.7.3" + resolved "https://registry.yarnpkg.com/stream-to-pull-stream/-/stream-to-pull-stream-1.7.3.tgz#4161aa2d2eb9964de60bfa1af7feaf917e874ece" + integrity sha512-6sNyqJpr5dIOQdgNy/xcDWwDuzAsAwVzhzrWlAPAQ7Lkjx/rv0wgvxEyKwTq6FmNd5rjTrELt/CLmaSw7crMGg== + dependencies: + looper "^3.0.0" + pull-stream "^3.2.3" + +streamsearch@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" + integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== + +strict-uri-encode@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + integrity sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ== + +string-format@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" + integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw== + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string.prototype.trim@~1.2.6: + version "1.2.7" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" + integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +string.prototype.trimend@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" + integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +string.prototype.trimstart@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" + integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + integrity sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g== + dependencies: + is-utf8 "^0.2.0" + +strip-hex-prefix@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" + integrity sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A== + dependencies: + is-hex-prefixed "1.0.0" + +strip-json-comments@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +swarm-js@^0.1.40: + version "0.1.42" + resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.42.tgz#497995c62df6696f6e22372f457120e43e727979" + integrity sha512-BV7c/dVlA3R6ya1lMlSSNPLYrntt0LUq4YMgy3iwpCIc6rZnS5W2wUoctarZ5pXlpKtxDDf9hNziEkcfrxdhqQ== + dependencies: + bluebird "^3.5.0" + buffer "^5.0.5" + eth-lib "^0.1.26" + fs-extra "^4.0.2" + got "^11.8.5" + mime-types "^2.1.16" + mkdirp-promise "^5.0.1" + mock-fs "^4.1.0" + setimmediate "^1.0.5" + tar "^4.0.2" + xhr-request "^1.0.1" + +table-layout@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.2.tgz#c4038a1853b0136d63365a734b6931cf4fad4a04" + integrity sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A== + dependencies: + array-back "^4.0.1" + deep-extend "~0.6.0" + typical "^5.2.0" + wordwrapjs "^4.0.0" + +table@^6.8.0: + version "6.8.1" + resolved "https://registry.yarnpkg.com/table/-/table-6.8.1.tgz#ea2b71359fe03b017a5fbc296204471158080bdf" + integrity sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA== + dependencies: + ajv "^8.0.1" + lodash.truncate "^4.4.2" + slice-ansi "^4.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + +tape@^4.6.3: + version "4.16.1" + resolved "https://registry.yarnpkg.com/tape/-/tape-4.16.1.tgz#8d511b3a0be1a30441885972047c1dac822fd9be" + integrity sha512-U4DWOikL5gBYUrlzx+J0oaRedm2vKLFbtA/+BRAXboGWpXO7bMP8ddxlq3Cse2bvXFQ0jZMOj6kk3546mvCdFg== + dependencies: + call-bind "~1.0.2" + deep-equal "~1.1.1" + defined "~1.0.0" + dotignore "~0.1.2" + for-each "~0.3.3" + glob "~7.2.3" + has "~1.0.3" + inherits "~2.0.4" + is-regex "~1.1.4" + minimist "~1.2.6" + object-inspect "~1.12.2" + resolve "~1.22.1" + resumer "~0.0.0" + string.prototype.trim "~1.2.6" + through "~2.3.8" + +tar@^4.0.2: + version "4.4.19" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" + integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA== + dependencies: + chownr "^1.1.4" + fs-minipass "^1.2.7" + minipass "^2.9.0" + minizlib "^1.3.3" + mkdirp "^0.5.5" + safe-buffer "^5.2.1" + yallist "^3.1.1" + +test-value@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/test-value/-/test-value-2.1.0.tgz#11da6ff670f3471a73b625ca4f3fdcf7bb748291" + integrity sha512-+1epbAxtKeXttkGFMTX9H42oqzOTufR1ceCF+GYA5aOmvaPq9wd4PUS8329fn2RRLGNeUkgRLnVpycjx8DsO2w== + dependencies: + array-back "^1.0.3" + typical "^2.6.0" + +testrpc@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/testrpc/-/testrpc-0.0.1.tgz#83e2195b1f5873aec7be1af8cbe6dcf39edb7aed" + integrity sha512-afH1hO+SQ/VPlmaLUFj2636QMeDvPCeQMc/9RBMW0IfjNe9gFD9Ra3ShqYkB7py0do1ZcCna/9acHyzTJ+GcNA== + +through2@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +through@~2.3.4, through@~2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== + +timed-out@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" + integrity sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA== + +tmp@0.0.33, tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +tmp@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877" + integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw== + dependencies: + rimraf "^2.6.3" + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + integrity sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og== + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg== + dependencies: + kind-of "^3.0.2" + +to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg== + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + integrity sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw== + +ts-command-line-args@^2.2.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.3.1.tgz#b6188e42efc6cf7a8898e438a873fbb15505ddd6" + integrity sha512-FR3y7pLl/fuUNSmnPhfLArGqRrpojQgIEEOVzYx9DhTmfIN7C9RWSfpkJEF4J+Gk7aVx5pak8I7vWZsaN4N84g== + dependencies: + chalk "^4.1.0" + command-line-args "^5.1.1" + command-line-usage "^6.1.0" + string-format "^2.0.0" + +ts-essentials@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-1.0.4.tgz#ce3b5dade5f5d97cf69889c11bf7d2da8555b15a" + integrity sha512-q3N1xS4vZpRouhYHDPwO0bDW3EZ6SK9CrrDHxi/D6BPReSjpVgWIOpLS2o0gSBZm+7q/wyKp6RVM1AeeW7uyfQ== + +ts-essentials@^6.0.3: + version "6.0.7" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-6.0.7.tgz#5f4880911b7581a873783740ce8b94da163d18a6" + integrity sha512-2E4HIIj4tQJlIHuATRHayv0EfMGK3ris/GRk1E3CFnsZzeNV+hUmelbaTZHLtXaZppM5oLhHRtO04gINC4Jusw== + +ts-essentials@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-7.0.3.tgz#686fd155a02133eedcc5362dc8b5056cde3e5a38" + integrity sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ== + +ts-generator@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ts-generator/-/ts-generator-0.1.1.tgz#af46f2fb88a6db1f9785977e9590e7bcd79220ab" + integrity sha512-N+ahhZxTLYu1HNTQetwWcx3so8hcYbkKBHTr4b4/YgObFTIKkOSSsaa+nal12w8mfrJAyzJfETXawbNjSfP2gQ== + dependencies: + "@types/mkdirp" "^0.5.2" + "@types/prettier" "^2.1.1" + "@types/resolve" "^0.0.8" + chalk "^2.4.1" + glob "^7.1.2" + mkdirp "^0.5.1" + prettier "^2.1.2" + resolve "^1.8.1" + ts-essentials "^1.0.0" + +ts-node@^10.7.0: + version "10.9.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" + integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + +tslib@^1.9.3: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tsort@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" + integrity sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw== + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== + dependencies: + safe-buffer "^5.0.1" + +tweetnacl-util@^0.15.0, tweetnacl-util@^0.15.1: + version "0.15.1" + resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" + integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== + +tweetnacl@^1.0.0, tweetnacl@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" + integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== + +type-detect@^4.0.0, type-detect@^4.0.5: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type-fest@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" + integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== + +type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +type@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +type@^2.7.2: + version "2.7.2" + resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" + integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== + +typechain@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-3.0.0.tgz#d5a47700831f238e43f7429b987b4bb54849b92e" + integrity sha512-ft4KVmiN3zH4JUFu2WJBrwfHeDf772Tt2d8bssDTo/YcckKW2D+OwFrHXRC6hJvO3mHjFQTihoMV6fJOi0Hngg== + dependencies: + command-line-args "^4.0.7" + debug "^4.1.1" + fs-extra "^7.0.0" + js-sha3 "^0.8.0" + lodash "^4.17.15" + ts-essentials "^6.0.3" + ts-generator "^0.1.1" + +typechain@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-8.1.1.tgz#9c2e8012c2c4c586536fc18402dcd7034c4ff0bd" + integrity sha512-uF/sUvnXTOVF2FHKhQYnxHk4su4JjZR8vr4mA2mBaRwHTbwh0jIlqARz9XJr1tA0l7afJGvEa1dTSi4zt039LQ== + dependencies: + "@types/prettier" "^2.1.1" + debug "^4.3.1" + fs-extra "^7.0.0" + glob "7.1.7" + js-sha3 "^0.8.0" + lodash "^4.17.15" + mkdirp "^1.0.4" + prettier "^2.3.1" + ts-command-line-args "^2.2.0" + ts-essentials "^7.0.1" + +typed-array-length@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" + integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + is-typed-array "^1.1.9" + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== + +typescript@^4.6.4: + version "4.9.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.4.tgz#a2a3d2756c079abda241d75f149df9d561091e78" + integrity sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg== + +typewise-core@^1.2, typewise-core@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/typewise-core/-/typewise-core-1.2.0.tgz#97eb91805c7f55d2f941748fa50d315d991ef195" + integrity sha512-2SCC/WLzj2SbUwzFOzqMCkz5amXLlxtJqDKTICqg30x+2DZxcfZN2MvQZmGfXWKNWaKK9pBPsvkcwv8bF/gxKg== + +typewise@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typewise/-/typewise-1.0.3.tgz#1067936540af97937cc5dcf9922486e9fa284651" + integrity sha512-aXofE06xGhaQSPzt8hlTY+/YWQhm9P0jYUp1f2XtmW/3Bk0qzXcyFWAtPoo2uTGQj1ZwbDuSyuxicq+aDo8lCQ== + dependencies: + typewise-core "^1.2.0" + +typewiselite@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typewiselite/-/typewiselite-1.0.0.tgz#c8882fa1bb1092c06005a97f34ef5c8508e3664e" + integrity sha512-J9alhjVHupW3Wfz6qFRGgQw0N3gr8hOkw6zm7FZ6UR1Cse/oD9/JVok7DNE9TT9IbciDHX2Ex9+ksE6cRmtymw== + +typical@^2.6.0, typical@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/typical/-/typical-2.6.1.tgz#5c080e5d661cbbe38259d2e70a3c7253e873881d" + integrity sha512-ofhi8kjIje6npGozTip9Fr8iecmYfEbS06i0JnIg+rh51KakryWF4+jX8lLKZVhy6N+ID45WYSFCxPOdTWCzNg== + +typical@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" + integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== + +typical@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066" + integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== + +ultron@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" + integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== + +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== + dependencies: + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" + which-boxed-primitive "^1.0.2" + +underscore@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" + integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== + +undici@^5.4.0: + version "5.14.0" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.14.0.tgz#1169d0cdee06a4ffdd30810f6228d57998884d00" + integrity sha512-yJlHYw6yXPPsuOH0x2Ib1Km61vu4hLiRRQoafs+WUgX1vO64vgnxiCEN9dpIrhZyHFsai3F0AEj4P9zy19enEQ== + dependencies: + busboy "^1.6.0" + +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + +unorm@^1.3.3: + version "1.6.0" + resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.6.0.tgz#029b289661fba714f1a9af439eb51d9b16c205af" + integrity sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA== + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ== + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg== + +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + integrity sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ== + dependencies: + prepend-http "^2.0.0" + +url-set-query@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" + integrity sha512-3AChu4NiXquPfeckE5R5cGdiHCMWJx1dwCWOmWIL4KHAziJNOFIYJlpGFeKDvwLPHovZRCxK3cYlwzqI9Vp+Gg== + +url@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + integrity sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ== + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +utf-8-validate@^5.0.2: + version "5.0.10" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" + integrity sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ== + dependencies: + node-gyp-build "^4.3.0" + +utf8@3.0.0, utf8@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" + integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +util.promisify@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.1.1.tgz#77832f57ced2c9478174149cae9b96e9918cd54b" + integrity sha512-/s3UsZUrIfa6xDhr7zZhnE9SLQ5RIXyYfiVnMMyMDzOc8WhWN4Nbh36H842OyurKbCDAesZOJaVyvmSl6fhGQw== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + for-each "^0.3.3" + has-symbols "^1.0.1" + object.getownpropertydescriptors "^2.1.1" + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + +uuid@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== + +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +varint@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" + integrity sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow== + +vary@^1, vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +web3-bzz@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.11.tgz#41bc19a77444bd5365744596d778b811880f707f" + integrity sha512-XGpWUEElGypBjeFyUhTkiPXFbDVD6Nr/S5jznE3t8cWUA0FxRf1n3n/NuIZeb0H9RkN2Ctd/jNma/k8XGa3YKg== + dependencies: + "@types/node" "^12.12.6" + got "9.6.0" + swarm-js "^0.1.40" + underscore "1.9.1" + +web3-core-helpers@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.2.11.tgz#84c681ed0b942c0203f3b324a245a127e8c67a99" + integrity sha512-PEPoAoZd5ME7UfbnCZBdzIerpe74GEvlwT4AjOmHeCVZoIFk7EqvOZDejJHt+feJA6kMVTdd0xzRNN295UhC1A== + dependencies: + underscore "1.9.1" + web3-eth-iban "1.2.11" + web3-utils "1.2.11" + +web3-core-method@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.11.tgz#f880137d1507a0124912bf052534f168b8d8fbb6" + integrity sha512-ff0q76Cde94HAxLDZ6DbdmKniYCQVtvuaYh+rtOUMB6kssa5FX0q3vPmixi7NPooFnbKmmZCM6NvXg4IreTPIw== + dependencies: + "@ethersproject/transactions" "^5.0.0-beta.135" + underscore "1.9.1" + web3-core-helpers "1.2.11" + web3-core-promievent "1.2.11" + web3-core-subscriptions "1.2.11" + web3-utils "1.2.11" + +web3-core-promievent@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.11.tgz#51fe97ca0ddec2f99bf8c3306a7a8e4b094ea3cf" + integrity sha512-il4McoDa/Ox9Agh4kyfQ8Ak/9ABYpnF8poBLL33R/EnxLsJOGQG2nZhkJa3I067hocrPSjEdlPt/0bHXsln4qA== + dependencies: + eventemitter3 "4.0.4" + +web3-core-requestmanager@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.11.tgz#fe6eb603fbaee18530293a91f8cf26d8ae28c45a" + integrity sha512-oFhBtLfOiIbmfl6T6gYjjj9igOvtyxJ+fjS+byRxiwFJyJ5BQOz4/9/17gWR1Cq74paTlI7vDGxYfuvfE/mKvA== + dependencies: + underscore "1.9.1" + web3-core-helpers "1.2.11" + web3-providers-http "1.2.11" + web3-providers-ipc "1.2.11" + web3-providers-ws "1.2.11" + +web3-core-subscriptions@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.11.tgz#beca908fbfcb050c16f45f3f0f4c205e8505accd" + integrity sha512-qEF/OVqkCvQ7MPs1JylIZCZkin0aKK9lDxpAtQ1F8niEDGFqn7DT8E/vzbIa0GsOjL2fZjDhWJsaW+BSoAW1gg== + dependencies: + eventemitter3 "4.0.4" + underscore "1.9.1" + web3-core-helpers "1.2.11" + +web3-core@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.11.tgz#1043cacc1becb80638453cc5b2a14be9050288a7" + integrity sha512-CN7MEYOY5ryo5iVleIWRE3a3cZqVaLlIbIzDPsvQRUfzYnvzZQRZBm9Mq+ttDi2STOOzc1MKylspz/o3yq/LjQ== + dependencies: + "@types/bn.js" "^4.11.5" + "@types/node" "^12.12.6" + bignumber.js "^9.0.0" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-core-requestmanager "1.2.11" + web3-utils "1.2.11" + +web3-eth-abi@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.11.tgz#a887494e5d447c2926d557a3834edd66e17af9b0" + integrity sha512-PkRYc0+MjuLSgg03QVWqWlQivJqRwKItKtEpRUaxUAeLE7i/uU39gmzm2keHGcQXo3POXAbOnMqkDvOep89Crg== + dependencies: + "@ethersproject/abi" "5.0.0-beta.153" + underscore "1.9.1" + web3-utils "1.2.11" + +web3-eth-accounts@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.11.tgz#a9e3044da442d31903a7ce035a86d8fa33f90520" + integrity sha512-6FwPqEpCfKIh3nSSGeo3uBm2iFSnFJDfwL3oS9pyegRBXNsGRVpgiW63yhNzL0796StsvjHWwQnQHsZNxWAkGw== + dependencies: + crypto-browserify "3.12.0" + eth-lib "0.2.8" + ethereumjs-common "^1.3.2" + ethereumjs-tx "^2.1.1" + scrypt-js "^3.0.1" + underscore "1.9.1" + uuid "3.3.2" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-utils "1.2.11" + +web3-eth-contract@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.2.11.tgz#917065902bc27ce89da9a1da26e62ef663663b90" + integrity sha512-MzYuI/Rq2o6gn7vCGcnQgco63isPNK5lMAan2E51AJLknjSLnOxwNY3gM8BcKoy4Z+v5Dv00a03Xuk78JowFow== + dependencies: + "@types/bn.js" "^4.11.5" + underscore "1.9.1" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-core-promievent "1.2.11" + web3-core-subscriptions "1.2.11" + web3-eth-abi "1.2.11" + web3-utils "1.2.11" + +web3-eth-ens@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.2.11.tgz#26d4d7f16d6cbcfff918e39832b939edc3162532" + integrity sha512-dbW7dXP6HqT1EAPvnniZVnmw6TmQEKF6/1KgAxbo8iBBYrVTMDGFQUUnZ+C4VETGrwwaqtX4L9d/FrQhZ6SUiA== + dependencies: + content-hash "^2.5.2" + eth-ens-namehash "2.0.8" + underscore "1.9.1" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-promievent "1.2.11" + web3-eth-abi "1.2.11" + web3-eth-contract "1.2.11" + web3-utils "1.2.11" + +web3-eth-iban@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.2.11.tgz#f5f73298305bc7392e2f188bf38a7362b42144ef" + integrity sha512-ozuVlZ5jwFC2hJY4+fH9pIcuH1xP0HEFhtWsR69u9uDIANHLPQQtWYmdj7xQ3p2YT4bQLq/axKhZi7EZVetmxQ== + dependencies: + bn.js "^4.11.9" + web3-utils "1.2.11" + +web3-eth-personal@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.11.tgz#a38b3942a1d87a62070ce0622a941553c3d5aa70" + integrity sha512-42IzUtKq9iHZ8K9VN0vAI50iSU9tOA1V7XU2BhF/tb7We2iKBVdkley2fg26TxlOcKNEHm7o6HRtiiFsVK4Ifw== + dependencies: + "@types/node" "^12.12.6" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-net "1.2.11" + web3-utils "1.2.11" + +web3-eth@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.2.11.tgz#4c81fcb6285b8caf544058fba3ae802968fdc793" + integrity sha512-REvxW1wJ58AgHPcXPJOL49d1K/dPmuw4LjPLBPStOVkQjzDTVmJEIsiLwn2YeuNDd4pfakBwT8L3bz1G1/wVsQ== + dependencies: + underscore "1.9.1" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-core-subscriptions "1.2.11" + web3-eth-abi "1.2.11" + web3-eth-accounts "1.2.11" + web3-eth-contract "1.2.11" + web3-eth-ens "1.2.11" + web3-eth-iban "1.2.11" + web3-eth-personal "1.2.11" + web3-net "1.2.11" + web3-utils "1.2.11" + +web3-net@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.2.11.tgz#eda68ef25e5cdb64c96c39085cdb74669aabbe1b" + integrity sha512-sjrSDj0pTfZouR5BSTItCuZ5K/oZPVdVciPQ6981PPPIwJJkCMeVjD7I4zO3qDPCnBjBSbWvVnLdwqUBPtHxyg== + dependencies: + web3-core "1.2.11" + web3-core-method "1.2.11" + web3-utils "1.2.11" + +web3-provider-engine@14.2.1: + version "14.2.1" + resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-14.2.1.tgz#ef351578797bf170e08d529cb5b02f8751329b95" + integrity sha512-iSv31h2qXkr9vrL6UZDm4leZMc32SjWJFGOp/D92JXfcEboCqraZyuExDkpxKw8ziTufXieNM7LSXNHzszYdJw== + dependencies: + async "^2.5.0" + backoff "^2.5.0" + clone "^2.0.0" + cross-fetch "^2.1.0" + eth-block-tracker "^3.0.0" + eth-json-rpc-infura "^3.1.0" + eth-sig-util "^1.4.2" + ethereumjs-block "^1.2.2" + ethereumjs-tx "^1.2.0" + ethereumjs-util "^5.1.5" + ethereumjs-vm "^2.3.4" + json-rpc-error "^2.0.0" + json-stable-stringify "^1.0.1" + promise-to-callback "^1.0.0" + readable-stream "^2.2.9" + request "^2.85.0" + semaphore "^1.0.3" + ws "^5.1.1" + xhr "^2.2.0" + xtend "^4.0.1" + +web3-providers-http@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.2.11.tgz#1cd03442c61670572d40e4dcdf1faff8bd91e7c6" + integrity sha512-psh4hYGb1+ijWywfwpB2cvvOIMISlR44F/rJtYkRmQ5jMvG4FOCPlQJPiHQZo+2cc3HbktvvSJzIhkWQJdmvrA== + dependencies: + web3-core-helpers "1.2.11" + xhr2-cookies "1.1.0" + +web3-providers-ipc@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.11.tgz#d16d6c9be1be6e0b4f4536c4acc16b0f4f27ef21" + integrity sha512-yhc7Y/k8hBV/KlELxynWjJDzmgDEDjIjBzXK+e0rHBsYEhdCNdIH5Psa456c+l0qTEU2YzycF8VAjYpWfPnBpQ== + dependencies: + oboe "2.1.4" + underscore "1.9.1" + web3-core-helpers "1.2.11" + +web3-providers-ws@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.11.tgz#a1dfd6d9778d840561d9ec13dd453046451a96bb" + integrity sha512-ZxnjIY1Er8Ty+cE4migzr43zA/+72AF1myzsLaU5eVgdsfV7Jqx7Dix1hbevNZDKFlSoEyq/3j/jYalh3So1Zg== + dependencies: + eventemitter3 "4.0.4" + underscore "1.9.1" + web3-core-helpers "1.2.11" + websocket "^1.0.31" + +web3-shh@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.11.tgz#f5d086f9621c9a47e98d438010385b5f059fd88f" + integrity sha512-B3OrO3oG1L+bv3E1sTwCx66injW1A8hhwpknDUbV+sw3fehFazA06z9SGXUefuFI1kVs4q2vRi0n4oCcI4dZDg== + dependencies: + web3-core "1.2.11" + web3-core-method "1.2.11" + web3-core-subscriptions "1.2.11" + web3-net "1.2.11" + +web3-utils@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.11.tgz#af1942aead3fb166ae851a985bed8ef2c2d95a82" + integrity sha512-3Tq09izhD+ThqHEaWYX4VOT7dNPdZiO+c/1QMA0s5X2lDFKK/xHJb7cyTRRVzN2LvlHbR7baS1tmQhSua51TcQ== + dependencies: + bn.js "^4.11.9" + eth-lib "0.2.8" + ethereum-bloom-filters "^1.0.6" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + underscore "1.9.1" + utf8 "3.0.0" + +web3-utils@^1.0.0-beta.31: + version "1.8.1" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.8.1.tgz#f2f7ca7eb65e6feb9f3d61056d0de6bbd57125ff" + integrity sha512-LgnM9p6V7rHHUGfpMZod+NST8cRfGzJ1BTXAyNo7A9cJX9LczBfSRxJp+U/GInYe9mby40t3v22AJdlELibnsQ== + dependencies: + bn.js "^5.2.1" + ethereum-bloom-filters "^1.0.6" + ethereumjs-util "^7.1.0" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + utf8 "3.0.0" + +web3@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3/-/web3-1.2.11.tgz#50f458b2e8b11aa37302071c170ed61cff332975" + integrity sha512-mjQ8HeU41G6hgOYm1pmeH0mRAeNKJGnJEUzDMoerkpw7QUQT4exVREgF1MYPvL/z6vAshOXei25LE/t/Bxl8yQ== + dependencies: + web3-bzz "1.2.11" + web3-core "1.2.11" + web3-eth "1.2.11" + web3-eth-personal "1.2.11" + web3-net "1.2.11" + web3-shh "1.2.11" + web3-utils "1.2.11" + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +websocket@1.0.32: + version "1.0.32" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.32.tgz#1f16ddab3a21a2d929dec1687ab21cfdc6d3dbb1" + integrity sha512-i4yhcllSP4wrpoPMU2N0TQ/q0O94LRG/eUQjEAamRltjQ1oT1PFFKOG4i877OlJgCG8rw6LrrowJp+TYCEWF7Q== + dependencies: + bufferutil "^4.0.1" + debug "^2.2.0" + es5-ext "^0.10.50" + typedarray-to-buffer "^3.1.5" + utf-8-validate "^5.0.2" + yaeti "^0.0.6" + +websocket@^1.0.31: + version "1.0.34" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" + integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== + dependencies: + bufferutil "^4.0.1" + debug "^2.2.0" + es5-ext "^0.10.50" + typedarray-to-buffer "^3.1.5" + utf-8-validate "^5.0.2" + yaeti "^0.0.6" + +whatwg-fetch@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" + integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + +which-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + integrity sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ== + +which-typed-array@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" + integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + is-typed-array "^1.1.10" + +which@^1.2.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +window-size@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" + integrity sha512-UD7d8HFA2+PZsbKyaOCEy8gMh1oDtHgJh1LfgjQ4zVXmYjAT/kvz3PueITKuqDiIXQe7yzpPnxX3lNc+AhQMyw== + +wordwrapjs@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.1.tgz#d9790bccfb110a0fc7836b5ebce0937b37a8b98f" + integrity sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA== + dependencies: + reduce-flatten "^2.0.0" + typical "^5.2.0" + +workerpool@6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" + integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + integrity sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw== + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== + +ws@^3.0.0: + version "3.3.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" + integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== + dependencies: + async-limiter "~1.0.0" + safe-buffer "~5.1.0" + ultron "~1.1.0" + +ws@^5.1.1: + version "5.2.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.3.tgz#05541053414921bc29c63bee14b8b0dd50b07b3d" + integrity sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA== + dependencies: + async-limiter "~1.0.0" + +ws@^7.4.6: + version "7.5.9" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" + integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== + +xhr-request-promise@^0.1.2: + version "0.1.3" + resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz#2d5f4b16d8c6c893be97f1a62b0ed4cf3ca5f96c" + integrity sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg== + dependencies: + xhr-request "^1.1.0" + +xhr-request@^1.0.1, xhr-request@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/xhr-request/-/xhr-request-1.1.0.tgz#f4a7c1868b9f198723444d82dcae317643f2e2ed" + integrity sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA== + dependencies: + buffer-to-arraybuffer "^0.0.5" + object-assign "^4.1.1" + query-string "^5.0.1" + simple-get "^2.7.0" + timed-out "^4.0.1" + url-set-query "^1.0.0" + xhr "^2.0.4" + +xhr2-cookies@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" + integrity sha512-hjXUA6q+jl/bd8ADHcVfFsSPIf+tyLIjuO9TwJC9WI6JP2zKcS7C+p56I9kCLLsaCiNT035iYvEUUzdEFj/8+g== + dependencies: + cookiejar "^2.1.1" + +xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: + version "2.6.0" + resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.6.0.tgz#b69d4395e792b4173d6b7df077f0fc5e4e2b249d" + integrity sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA== + dependencies: + global "~4.4.0" + is-function "^1.0.1" + parse-headers "^2.0.0" + xtend "^4.0.0" + +xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +xtend@~2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" + integrity sha512-vMNKzr2rHP9Dp/e1NQFnLQlwlhp9L/LfvnsVdHxN1f+uggyVI3i08uD14GPvCToPkdsRfyPqIyYGmIk58V98ZQ== + dependencies: + object-keys "~0.4.0" + +y18n@^3.2.1: + version "3.2.2" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696" + integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yaeti@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" + integrity sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug== + +yallist@^3.0.0, yallist@^3.0.2, yallist@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yaml@^1.10.2: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + +yargs-parser@20.2.4: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + +yargs-parser@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" + integrity sha512-9pIKIJhnI5tonzG6OnCFlz/yln8xHYcGl+pn3xR0Vzff0vzN1PbNRaelgfgRUwZ3s4i3jvxT9WhmUGL4whnasA== + dependencies: + camelcase "^3.0.0" + lodash.assign "^4.0.6" + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yargs@^4.7.1: + version "4.8.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0" + integrity sha512-LqodLrnIDM3IFT+Hf/5sxBnEGECrfdC1uIbgZeJmESCSo4HoCAaKEus8MylXHAkdacGc0ye+Qa+dpkuom8uVYA== + dependencies: + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + lodash.assign "^4.0.3" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.1" + which-module "^1.0.0" + window-size "^0.2.0" + y18n "^3.2.1" + yargs-parser "^2.4.1" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== From 249aa0da8097310d2379b95d0eaa0ffa0a8b1512 Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Sat, 7 Jan 2023 13:37:05 +1100 Subject: [PATCH 02/43] update gitignore for /lib --- .gitignore | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 323a3d12..a5e7f5d1 100644 --- a/.gitignore +++ b/.gitignore @@ -27,4 +27,8 @@ abi build scripts/xbribes # for verify -Flattened.sol \ No newline at end of file +Flattened.sol +lib/openzeppelin-contracts +lib/forge-std +lib/LayerZero +lib/forge-std From 6828388e5f3748dcd7283b8cc6745f140e9de538 Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Sat, 7 Jan 2023 15:25:49 +1100 Subject: [PATCH 03/43] add goerli contracts to readme --- readme.md | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 402b037e..4b3b579c 100644 --- a/readme.md +++ b/readme.md @@ -1,6 +1,36 @@ -# Velodrome +# Velocimeter -This repo contains the contracts for Velodrome Finance, an AMM on Optimism inspired by Solidly. +Goerli + + +Velo deployed to: 0x41754Fd93201B64Cd7633a8e8f861D47594b29A8 +GaugeFactory deployed to: 0x30Ba274c119865312c1417b6E1Be6C98DAceb6B2 +BribeFactory deployed to: 0x4871E36eDEB6750e47f616C57e70a978ac9a9003 +PairFactory deployed to: 0xB4AD2aAC39268687D62b36BD69fC532862CF6590 +Router deployed to: 0x1584d57c849797fb752d3dc5071F49B59D6C7416 +Args: 0xB4AD2aAC39268687D62b36BD69fC532862CF6590 0x4200000000000000000000000000000000000006 + +VelodromeLibrary deployed to: 0x83c08EE991D0010208a117b84F7ea412373AEB90 +Args: 0x1584d57c849797fb752d3dc5071F49B59D6C7416 + +VeArtProxy deployed to: 0x944AF7785d57bcfC00e95388453B93DAD373216e +VotingEscrow deployed to: 0x2B0BB6962e89bD5FE9510Ff09Af8D709be21AAD7 +Args: 0x41754Fd93201B64Cd7633a8e8f861D47594b29A8 0x944AF7785d57bcfC00e95388453B93DAD373216e + +RewardsDistributor deployed to: 0xf4F344Cfa1A82eDD37C96E879f01D9CA03f385b9 +Args: 0x2B0BB6962e89bD5FE9510Ff09Af8D709be21AAD7 + +Voter deployed to: 0x9f7fdaB9317f1442808B90B819Ed0a4eF4f74994 +Args: 0x2B0BB6962e89bD5FE9510Ff09Af8D709be21AAD7 0xB4AD2aAC39268687D62b36BD69fC532862CF6590 0x30Ba274c119865312c1417b6E1Be6C98DAceb6B2 0x4871E36eDEB6750e47f616C57e70a978ac9a9003 + +Minter deployed to: 0x52A18b2386D6221Cf9DbcD4790456a23249e5279 +Args: 0x9f7fdaB9317f1442808B90B819Ed0a4eF4f74994 0x2B0BB6962e89bD5FE9510Ff09Af8D709be21AAD7 0xf4F344Cfa1A82eDD37C96E879f01D9CA03f385b9 + +RedemptionReceiver deployed to: 0xfe873D4923b343F0D6BD98045a9C82D8dDEC511E +Args: 0x3e22e37Cb472c872B5dE121134cFD1B57Ef06560 0x41754Fd93201B64Cd7633a8e8f861D47594b29A8 10012 0x72aB53a133b27Fa428ca7Dc263080807AfEc91b5 + +VeloGovernor deployed to: 0x0bd9d21b40428a650DbFC0F7bd3F7B6FA321F915 +Args: 0x2B0BB6962e89bD5FE9510Ff09Af8D709be21AAD7 ## Testing From 14727c52cf41b7cc0a94264028b7098efc86fd23 Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Sun, 8 Jan 2023 19:06:46 +1100 Subject: [PATCH 04/43] add etherscan verify and start switching to hardhat-deploy --- contracts/deployments/veloAddress.json | 1 + hardhat.config.ts | 4 +- package.json | 4 +- tasks/deploy/arbTest.ts | 355 +++++++++++++++---------- veloAddress.json | 1 + yarn.lock | 78 +++++- 6 files changed, 291 insertions(+), 152 deletions(-) create mode 100644 contracts/deployments/veloAddress.json create mode 100644 veloAddress.json diff --git a/contracts/deployments/veloAddress.json b/contracts/deployments/veloAddress.json new file mode 100644 index 00000000..9f35ad70 --- /dev/null +++ b/contracts/deployments/veloAddress.json @@ -0,0 +1 @@ +{"Velodrome":"0x7B7F4fb44F57DbfD4a111a686946E8091Afe6D59"} \ No newline at end of file diff --git a/hardhat.config.ts b/hardhat.config.ts index b42388ba..e6f3cbba 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -4,6 +4,7 @@ import '@nomiclabs/hardhat-waffle' import '@typechain/hardhat' import 'hardhat-preprocessor' import 'hardhat-abi-exporter' +import '@cartesi/hardhat-verify-deployments' import './tasks/accounts' import './tasks/deploy' @@ -92,7 +93,8 @@ const config: HardhatUserConfig = { ftmTestnet: process.env.FTM_SCAN_API_KEY!, optimisticEthereum: process.env.OP_SCAN_API_KEY!, optimisticKovan: process.env.OP_SCAN_API_KEY!, - arbitrum: process.env.ARB_SCAN_API_KEY! + arbitrum: process.env.ARB_SCAN_API_KEY!, + arbitrumGoerli: process.env.ARB_SCAN_API_KEY! } } } diff --git a/package.json b/package.json index dd8e722d..35d9f6ac 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,9 @@ "lib": "lib" }, "devDependencies": { + "@cartesi/hardhat-verify-deployments": "^0.2.0", "@nomiclabs/hardhat-ethers": "^2.0.6", - "@nomiclabs/hardhat-etherscan": "^3.0.4", + "@nomiclabs/hardhat-etherscan": "^3.1.4", "@nomiclabs/hardhat-waffle": "^2.0.3", "@typechain/ethers-v5": "^10.0.0", "@typechain/hardhat": "^6.0.0", @@ -20,6 +21,7 @@ "ethers": "^5.0.0", "hardhat": "^2.9.5", "hardhat-abi-exporter": "^2.9.0", + "hardhat-deploy": "^0.11.22", "hardhat-preprocessor": "^0.1.4", "prettier": "^2.6.2", "prettier-plugin-solidity": "^1.0.0-beta.19", diff --git a/tasks/deploy/arbTest.ts b/tasks/deploy/arbTest.ts index 2c30b177..3b6aba43 100644 --- a/tasks/deploy/arbTest.ts +++ b/tasks/deploy/arbTest.ts @@ -1,4 +1,5 @@ import { task } from 'hardhat/config' +var fs = require('fs') import optimismConfig from './constants/optimismConfig' import testOptimismConfig from './constants/testOptimismConfig' @@ -19,129 +20,191 @@ task('deploy:arbTest', 'Deploys Optimism contracts').setAction(async function ( // Load const [ Velo, - GaugeFactory, - BribeFactory, - PairFactory, - Router, - Library, - VeArtProxy, - VotingEscrow, - RewardsDistributor, - Voter, - Minter, - VeloGovernor, - RedemptionReceiver, - MerkleClaim + GaugeFactory + // BribeFactory, + // PairFactory, + // Router, + // Library, + // VeArtProxy, + // VotingEscrow, + // RewardsDistributor, + // Voter, + // Minter, + // VeloGovernor, + // RedemptionReceiver, + // MerkleClaim ] = await Promise.all([ ethers.getContractFactory('Velo'), - ethers.getContractFactory('GaugeFactory'), - ethers.getContractFactory('BribeFactory'), - ethers.getContractFactory('PairFactory'), - ethers.getContractFactory('Router'), - ethers.getContractFactory('VelodromeLibrary'), - ethers.getContractFactory('VeArtProxy'), - ethers.getContractFactory('VotingEscrow'), - ethers.getContractFactory('RewardsDistributor'), - ethers.getContractFactory('Voter'), - ethers.getContractFactory('Minter'), - ethers.getContractFactory('VeloGovernor'), - ethers.getContractFactory('RedemptionReceiver'), - ethers.getContractFactory('MerkleClaim') + ethers.getContractFactory('GaugeFactory') + // ethers.getContractFactory('BribeFactory'), + // ethers.getContractFactory('PairFactory'), + // ethers.getContractFactory('Router'), + // ethers.getContractFactory('VelodromeLibrary'), + // ethers.getContractFactory('VeArtProxy'), + // ethers.getContractFactory('VotingEscrow'), + // ethers.getContractFactory('RewardsDistributor'), + // ethers.getContractFactory('Voter'), + // ethers.getContractFactory('Minter'), + // ethers.getContractFactory('VeloGovernor'), + // ethers.getContractFactory('RedemptionReceiver'), + // ethers.getContractFactory('MerkleClaim') ]) + //WIP wait for 5 block transactions to ensure deployment before verifying + // https://stackoverflow.com/questions/72916701/hardhat-compile-deploy-and-verify-in-a-single-script + // https://github.com/profullstackdeveloper/contract-deploy-verify-hardhat + // shows how to save deployments and verify but for a single contract only... Need to find a better example to loop through them all save to /deployments and then verify... + // await Promise.all.deployTransaction.wait(5) + + // //verify + + // await hre.run('verify:verify', { + // address: velo.address, + // contract: 'contracts/Velo.sol:MyContract', //Filename.sol:ClassName + // constructorArguments: [arg1, arg2, arg3] + // }) + + // WIP ^^ + const velo = await Velo.deploy() await velo.deployed() console.log('Velo deployed to: ', velo.address) + await hre.run('verify:verify', { + address: velo.address, + contract: 'contracts/Velo.sol:Velo', //Filename.sol:ClassName + constructorArguments: [] + }) + + await velo.deployed() + const name = await velo.name() + console.log('dunksname: ', name) + + const temp1 = { + [name]: velo.address + } + const json1 = JSON.stringify(temp1) + console.log('result of json is ', json1) + fs.writeFileSync('contracts/deployments/veloAddress.json', json1, err => { + if (err) { + console.log('ERROR! while creating file: ', err) + } else { + console.log('result is ', json1) + } + }) + const gaugeFactory = await GaugeFactory.deploy() await gaugeFactory.deployed() console.log('GaugeFactory deployed to: ', gaugeFactory.address) - const bribeFactory = await BribeFactory.deploy() - await bribeFactory.deployed() - console.log('BribeFactory deployed to: ', bribeFactory.address) - - const pairFactory = await PairFactory.deploy() - await pairFactory.deployed() - console.log('PairFactory deployed to: ', pairFactory.address) - - const router = await Router.deploy(pairFactory.address, OP_CONFIG.WETH) - await router.deployed() - console.log('Router deployed to: ', router.address) - console.log('Args: ', pairFactory.address, OP_CONFIG.WETH, '\n') - - const library = await Library.deploy(router.address) - await library.deployed() - console.log('VelodromeLibrary deployed to: ', library.address) - console.log('Args: ', router.address, '\n') - - const artProxy = await VeArtProxy.deploy() - await artProxy.deployed() - console.log('VeArtProxy deployed to: ', artProxy.address) - - const escrow = await VotingEscrow.deploy(velo.address, artProxy.address) - await escrow.deployed() - console.log('VotingEscrow deployed to: ', escrow.address) - console.log('Args: ', velo.address, artProxy.address, '\n') - - const distributor = await RewardsDistributor.deploy(escrow.address) - await distributor.deployed() - console.log('RewardsDistributor deployed to: ', distributor.address) - console.log('Args: ', escrow.address, '\n') - - const voter = await Voter.deploy( - escrow.address, - pairFactory.address, - gaugeFactory.address, - bribeFactory.address - ) - await voter.deployed() - console.log('Voter deployed to: ', voter.address) - console.log( - 'Args: ', - escrow.address, - pairFactory.address, - gaugeFactory.address, - bribeFactory.address, - '\n' - ) - - const minter = await Minter.deploy( - voter.address, - escrow.address, - distributor.address - ) - await minter.deployed() - console.log('Minter deployed to: ', minter.address) - console.log( - 'Args: ', - voter.address, - escrow.address, - distributor.address, - '\n' - ) - - const receiver = await RedemptionReceiver.deploy( - OP_CONFIG.USDC, - velo.address, - FTM_CONFIG.lzChainId, - OP_CONFIG.lzEndpoint - ) - await receiver.deployed() - console.log('RedemptionReceiver deployed to: ', receiver.address) - console.log( - 'Args: ', - OP_CONFIG.USDC, - velo.address, - FTM_CONFIG.lzChainId, - OP_CONFIG.lzEndpoint, - '\n' - ) - - const governor = await VeloGovernor.deploy(escrow.address) - await governor.deployed() - console.log('VeloGovernor deployed to: ', governor.address) - console.log('Args: ', escrow.address, '\n') + await hre.run('verify:verify', { + address: gaugeFactory.address, + contract: 'contracts/factories/GaugeFactory.sol:GaugeFactory', //Filename.sol:ClassName + constructorArguments: [] + }) + + await gaugeFactory.deployed() + const name1 = await gaugeFactory.name() + console.log('dunksname: ', name) + + const temp = { + [name1]: gaugeFactory.address + } + const json = JSON.stringify(temp) + console.log('result of json is ', json) + fs.writeFileSync('contracts/deployments/veloAddress.json', json, err => { + if (err) { + console.log('ERROR! while creating file: ', err) + } else { + console.log('result is ', json) + } + }) + + // const bribeFactory = await BribeFactory.deploy() + // await bribeFactory.deployed() + // console.log('BribeFactory deployed to: ', bribeFactory.address) + + // const pairFactory = await PairFactory.deploy() + // await pairFactory.deployed() + // console.log('PairFactory deployed to: ', pairFactory.address) + + // const router = await Router.deploy(pairFactory.address, OP_CONFIG.WETH) + // await router.deployed() + // console.log('Router deployed to: ', router.address) + // console.log('Args: ', pairFactory.address, OP_CONFIG.WETH, '\n') + + // const library = await Library.deploy(router.address) + // await library.deployed() + // console.log('VelodromeLibrary deployed to: ', library.address) + // console.log('Args: ', router.address, '\n') + + // const artProxy = await VeArtProxy.deploy() + // await artProxy.deployed() + // console.log('VeArtProxy deployed to: ', artProxy.address) + + // const escrow = await VotingEscrow.deploy(velo.address, artProxy.address) + // await escrow.deployed() + // console.log('VotingEscrow deployed to: ', escrow.address) + // console.log('Args: ', velo.address, artProxy.address, '\n') + + // const distributor = await RewardsDistributor.deploy(escrow.address) + // await distributor.deployed() + // console.log('RewardsDistributor deployed to: ', distributor.address) + // console.log('Args: ', escrow.address, '\n') + + // const voter = await Voter.deploy( + // escrow.address, + // pairFactory.address, + // gaugeFactory.address, + // bribeFactory.address + // ) + // await voter.deployed() + // console.log('Voter deployed to: ', voter.address) + // console.log( + // 'Args: ', + // escrow.address, + // pairFactory.address, + // gaugeFactory.address, + // bribeFactory.address, + // '\n' + // ) + + // const minter = await Minter.deploy( + // voter.address, + // escrow.address, + // distributor.address + // ) + // await minter.deployed() + // console.log('Minter deployed to: ', minter.address) + // console.log( + // 'Args: ', + // voter.address, + // escrow.address, + // distributor.address, + // '\n' + // ) + + // const receiver = await RedemptionReceiver.deploy( + // OP_CONFIG.USDC, + // velo.address, + // FTM_CONFIG.lzChainId, + // OP_CONFIG.lzEndpoint + // ) + // await receiver.deployed() + // console.log('RedemptionReceiver deployed to: ', receiver.address) + // console.log( + // 'Args: ', + // OP_CONFIG.USDC, + // velo.address, + // FTM_CONFIG.lzChainId, + // OP_CONFIG.lzEndpoint, + // '\n' + // ) + + // const governor = await VeloGovernor.deploy(escrow.address) + // await governor.deployed() + // console.log('VeloGovernor deployed to: ', governor.address) + // console.log('Args: ', escrow.address, '\n') // Airdrop // const claim = await MerkleClaim.deploy(velo.address, OP_CONFIG.merkleRoot) @@ -159,49 +222,55 @@ task('deploy:arbTest', 'Deploys Optimism contracts').setAction(async function ( // await velo.setMerkleClaim(claim.address) // console.log('MerkleClaim set') - await velo.setMinter(minter.address) - console.log('Minter set') + // await velo.setMinter(minter.address) + // console.log('Minter set') - await pairFactory.setPauser(OP_CONFIG.teamMultisig) - console.log('Pauser set') + // await pairFactory.setPauser(OP_CONFIG.teamMultisig) + // console.log('Pauser set') - await escrow.setVoter(voter.address) - console.log('Voter set') + // await escrow.setVoter(voter.address) + // console.log( + // 'Voter set', + // 'voter address: ', + // voter.address, + // 'escrow address: ', + // escrow.address + // ) - await escrow.setTeam(OP_CONFIG.teamMultisig) - console.log('Team set for escrow') + // await escrow.setTeam(OP_CONFIG.teamMultisig) + // console.log('Team set for escrow') - await voter.setGovernor(OP_CONFIG.teamMultisig) - console.log('Governor set') + // await voter.setGovernor(OP_CONFIG.teamMultisig) + // console.log('Governor set') - await voter.setEmergencyCouncil(OP_CONFIG.teamMultisig) - console.log('Emergency Council set') + // await voter.setEmergencyCouncil(OP_CONFIG.teamMultisig) + // console.log('Emergency Council set') - await distributor.setDepositor(minter.address) - console.log('Depositor set') + // await distributor.setDepositor(minter.address) + // console.log('Depositor set') - await receiver.setTeam(OP_CONFIG.teamMultisig) - console.log('Team set for receiver') + // await receiver.setTeam(OP_CONFIG.teamMultisig) + // console.log('Team set for receiver') - await governor.setTeam(OP_CONFIG.teamMultisig) - console.log('Team set for governor') + // await governor.setTeam(OP_CONFIG.teamMultisig) + // console.log('Team set for governor') - // Whitelist - const nativeToken = [velo.address] - const tokenWhitelist = nativeToken.concat(OP_CONFIG.tokenWhitelist) - await voter.initialize(tokenWhitelist, minter.address) - console.log('Whitelist set') + // // Whitelist + // const nativeToken = [velo.address] + // const tokenWhitelist = nativeToken.concat(OP_CONFIG.tokenWhitelist) + // await voter.initialize(tokenWhitelist, minter.address) + // console.log('Whitelist set') - // Initial veVELO distro - await minter.initialize( - OP_CONFIG.partnerAddrs, - OP_CONFIG.partnerAmts, - OP_CONFIG.partnerMax - ) - console.log('veVELO distributed') + // // Initial veVELO distro + // await minter.initialize( + // OP_CONFIG.partnerAddrs, + // OP_CONFIG.partnerAmts, + // OP_CONFIG.partnerMax + // ) + // console.log('veVELO distributed') - await minter.setTeam(OP_CONFIG.teamMultisig) - console.log('Team set for minter') + // await minter.setTeam(OP_CONFIG.teamMultisig) + // console.log('Team set for minter') console.log('Arbitrum Goerli Velocimeter Instruments deployed') }) diff --git a/veloAddress.json b/veloAddress.json new file mode 100644 index 00000000..2e212238 --- /dev/null +++ b/veloAddress.json @@ -0,0 +1 @@ +{"address":"0xB9aaBA85A60C48d42d1c6BD1dD1b2a549623D52F"} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index e5270bfd..9a3dc46e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"@cartesi/hardhat-verify-deployments@^0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@cartesi/hardhat-verify-deployments/-/hardhat-verify-deployments-0.2.0.tgz#e0569c5a1d94e432c8567e2c468f1d634ee70b18" + integrity sha512-N8TPnB/nMjIRMgfVetVMUrCNzStf99jL3KHQCFZZHUzXbL/d0ataNkxudA1QZI0jio1OECWncoqSEsqDZvyChA== + "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" @@ -682,7 +687,7 @@ resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.2.1.tgz#8057b43566a0e41abeb8142064a3c0d3f23dca86" integrity sha512-RHWYwnxryWR8hzRmU4Jm/q4gzvXpetUOJ4OPlwH2YARcDB+j79+yAYCwO0lN1SUOb4++oOTJEe6AWLEc42LIvg== -"@nomiclabs/hardhat-etherscan@^3.0.4": +"@nomiclabs/hardhat-etherscan@^3.1.4": version "3.1.4" resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.1.4.tgz#970e57fabc6060489c93b3f646ca790db36ffee0" integrity sha512-fw8JCfukf6MdIGoySRmSftlM2wBgoaSbWQZgiYfD/KTeaSFEWCdMpuPZcLSBXtwtnQyyWDs07Lo7fL8HSqtD2Q== @@ -1004,6 +1009,11 @@ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.2.tgz#6c2324641cc4ba050a8c710b2b251b377581fbf0" integrity sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg== +"@types/qs@^6.9.7": + version "6.9.7" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" + integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + "@types/resolve@^0.0.8": version "0.0.8" resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194" @@ -1406,6 +1416,13 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== +axios@^0.21.1: + version "0.21.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" + integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== + dependencies: + follow-redirects "^1.14.0" + babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" @@ -2405,7 +2422,7 @@ checkpoint-store@^1.1.0: dependencies: functional-red-black-tree "^1.0.1" -chokidar@3.5.3, chokidar@^3.4.0: +chokidar@3.5.3, chokidar@^3.4.0, chokidar@^3.5.2: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== @@ -2798,7 +2815,7 @@ debug@3.2.6: dependencies: ms "^2.1.1" -debug@4, debug@4.3.4, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3: +debug@4, debug@4.3.4, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -3077,7 +3094,7 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enquirer@^2.3.0: +enquirer@^2.3.0, enquirer@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== @@ -3610,7 +3627,7 @@ ethereumjs-wallet@0.6.5: utf8 "^3.0.0" uuid "^3.3.2" -ethers@^5.0.0, ethers@^5.0.1, ethers@^5.0.2, ethers@^5.5.2: +ethers@^5.0.0, ethers@^5.0.1, ethers@^5.0.2, ethers@^5.5.2, ethers@^5.5.3: version "5.7.2" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== @@ -3910,7 +3927,7 @@ fmix@^0.1.0: dependencies: imul "^1.0.0" -follow-redirects@^1.12.1: +follow-redirects@^1.12.1, follow-redirects@^1.14.0: version "1.15.2" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== @@ -3941,6 +3958,15 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + form-data@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" @@ -3988,6 +4014,15 @@ fs-extra@^0.30.0: path-is-absolute "^1.0.0" rimraf "^2.2.8" +fs-extra@^10.0.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-extra@^4.0.2, fs-extra@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" @@ -4283,6 +4318,25 @@ hardhat-abi-exporter@^2.9.0: "@ethersproject/abi" "^5.5.0" delete-empty "^3.0.0" +hardhat-deploy@^0.11.22: + version "0.11.22" + resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.11.22.tgz#9799c0266a0fc40c84690de54760f1b4dae5e487" + integrity sha512-ZhHVNB7Jo2l8Is+KIAk9F8Q3d7pptyiX+nsNbIFXztCz81kaP+6kxNODRBqRCy7SOD3It4+iKCL6tWsPAA/jVQ== + dependencies: + "@types/qs" "^6.9.7" + axios "^0.21.1" + chalk "^4.1.2" + chokidar "^3.5.2" + debug "^4.3.2" + enquirer "^2.3.6" + ethers "^5.5.3" + form-data "^4.0.0" + fs-extra "^10.0.0" + match-all "^1.2.6" + murmur-128 "^0.2.1" + qs "^6.9.4" + zksync-web3 "^0.8.1" + hardhat-preprocessor@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/hardhat-preprocessor/-/hardhat-preprocessor-0.1.5.tgz#75b22641fd6a680739c995d03bd5f7868eb72144" @@ -5490,6 +5544,11 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" +match-all@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/match-all/-/match-all-1.2.6.tgz#66d276ad6b49655551e63d3a6ee53e8be0566f8d" + integrity sha512-0EESkXiTkWzrQQntBu2uzKvLu6vVkUGz40nGPbSZuegcfE5UuSzNjLaIu76zJWuaT/2I3Z/8M06OlUOZLGwLlQ== + mcl-wasm@^0.7.1: version "0.7.9" resolved "https://registry.yarnpkg.com/mcl-wasm/-/mcl-wasm-0.7.9.tgz#c1588ce90042a8700c3b60e40efb339fc07ab87f" @@ -6457,7 +6516,7 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== -qs@6.11.0, qs@^6.7.0: +qs@6.11.0, qs@^6.7.0, qs@^6.9.4: version "6.11.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== @@ -8518,3 +8577,8 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zksync-web3@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.8.1.tgz#db289d8f6caf61f4d5ddc471fa3448d93208dc14" + integrity sha512-1A4aHPQ3MyuGjpv5X/8pVEN+MdZqMjfVmiweQSRjOlklXYu65wT9BGEOtCmMs5d3gIvLp4ssfTeuR5OCKOD2kw== From 484a8247844d32efed3b73a25d4d3da742ebf962 Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Sun, 8 Jan 2023 21:36:49 +1100 Subject: [PATCH 05/43] uncomment some things --- contracts/deployments/veloAddress.json | 2 +- tasks/deploy/arbTest.ts | 347 +++++++++++++------------ 2 files changed, 176 insertions(+), 173 deletions(-) diff --git a/contracts/deployments/veloAddress.json b/contracts/deployments/veloAddress.json index 9f35ad70..d4740145 100644 --- a/contracts/deployments/veloAddress.json +++ b/contracts/deployments/veloAddress.json @@ -1 +1 @@ -{"Velodrome":"0x7B7F4fb44F57DbfD4a111a686946E8091Afe6D59"} \ No newline at end of file +{"Velodrome":"0x3290aE1e3A028bc060b2AC541A91acf8F3927d2d"} \ No newline at end of file diff --git a/tasks/deploy/arbTest.ts b/tasks/deploy/arbTest.ts index 3b6aba43..e007848c 100644 --- a/tasks/deploy/arbTest.ts +++ b/tasks/deploy/arbTest.ts @@ -20,34 +20,34 @@ task('deploy:arbTest', 'Deploys Optimism contracts').setAction(async function ( // Load const [ Velo, - GaugeFactory - // BribeFactory, - // PairFactory, - // Router, - // Library, - // VeArtProxy, - // VotingEscrow, - // RewardsDistributor, - // Voter, - // Minter, - // VeloGovernor, - // RedemptionReceiver, - // MerkleClaim + GaugeFactory, + BribeFactory, + PairFactory, + Router, + Library, + VeArtProxy, + VotingEscrow, + RewardsDistributor, + Voter, + Minter, + VeloGovernor, + RedemptionReceiver, + MerkleClaim ] = await Promise.all([ ethers.getContractFactory('Velo'), - ethers.getContractFactory('GaugeFactory') - // ethers.getContractFactory('BribeFactory'), - // ethers.getContractFactory('PairFactory'), - // ethers.getContractFactory('Router'), - // ethers.getContractFactory('VelodromeLibrary'), - // ethers.getContractFactory('VeArtProxy'), - // ethers.getContractFactory('VotingEscrow'), - // ethers.getContractFactory('RewardsDistributor'), - // ethers.getContractFactory('Voter'), - // ethers.getContractFactory('Minter'), - // ethers.getContractFactory('VeloGovernor'), - // ethers.getContractFactory('RedemptionReceiver'), - // ethers.getContractFactory('MerkleClaim') + ethers.getContractFactory('GaugeFactory'), + ethers.getContractFactory('BribeFactory'), + ethers.getContractFactory('PairFactory'), + ethers.getContractFactory('Router'), + ethers.getContractFactory('VelodromeLibrary'), + ethers.getContractFactory('VeArtProxy'), + ethers.getContractFactory('VotingEscrow'), + ethers.getContractFactory('RewardsDistributor'), + ethers.getContractFactory('Voter'), + ethers.getContractFactory('Minter'), + ethers.getContractFactory('VeloGovernor'), + ethers.getContractFactory('RedemptionReceiver'), + ethers.getContractFactory('MerkleClaim') ]) //WIP wait for 5 block transactions to ensure deployment before verifying @@ -93,118 +93,121 @@ task('deploy:arbTest', 'Deploys Optimism contracts').setAction(async function ( } }) + // repeat for gauge factory + // update all the things... + const gaugeFactory = await GaugeFactory.deploy() await gaugeFactory.deployed() console.log('GaugeFactory deployed to: ', gaugeFactory.address) - await hre.run('verify:verify', { - address: gaugeFactory.address, - contract: 'contracts/factories/GaugeFactory.sol:GaugeFactory', //Filename.sol:ClassName - constructorArguments: [] - }) - - await gaugeFactory.deployed() - const name1 = await gaugeFactory.name() - console.log('dunksname: ', name) + // await hre.run('verify:verify', { + // address: gaugeFactory.address, + // contract: 'contracts/factories/GaugeFactory.sol:GaugeFactory', //Filename.sol:ClassName + // constructorArguments: [] + // }) - const temp = { - [name1]: gaugeFactory.address - } - const json = JSON.stringify(temp) - console.log('result of json is ', json) - fs.writeFileSync('contracts/deployments/veloAddress.json', json, err => { - if (err) { - console.log('ERROR! while creating file: ', err) - } else { - console.log('result is ', json) - } - }) + // await gaugeFactory.deployed() + // const name1 = await gaugeFactory.name() + // console.log('dunksname: ', name) + + // const temp = { + // [name1]: gaugeFactory.address + // } + // const json = JSON.stringify(temp) + // console.log('result of json is ', json) + // fs.writeFileSync('contracts/deployments/veloAddress.json', json, err => { + // if (err) { + // console.log('ERROR! while creating file: ', err) + // } else { + // console.log('result is ', json) + // } + // }) - // const bribeFactory = await BribeFactory.deploy() - // await bribeFactory.deployed() - // console.log('BribeFactory deployed to: ', bribeFactory.address) - - // const pairFactory = await PairFactory.deploy() - // await pairFactory.deployed() - // console.log('PairFactory deployed to: ', pairFactory.address) - - // const router = await Router.deploy(pairFactory.address, OP_CONFIG.WETH) - // await router.deployed() - // console.log('Router deployed to: ', router.address) - // console.log('Args: ', pairFactory.address, OP_CONFIG.WETH, '\n') - - // const library = await Library.deploy(router.address) - // await library.deployed() - // console.log('VelodromeLibrary deployed to: ', library.address) - // console.log('Args: ', router.address, '\n') - - // const artProxy = await VeArtProxy.deploy() - // await artProxy.deployed() - // console.log('VeArtProxy deployed to: ', artProxy.address) - - // const escrow = await VotingEscrow.deploy(velo.address, artProxy.address) - // await escrow.deployed() - // console.log('VotingEscrow deployed to: ', escrow.address) - // console.log('Args: ', velo.address, artProxy.address, '\n') - - // const distributor = await RewardsDistributor.deploy(escrow.address) - // await distributor.deployed() - // console.log('RewardsDistributor deployed to: ', distributor.address) - // console.log('Args: ', escrow.address, '\n') - - // const voter = await Voter.deploy( - // escrow.address, - // pairFactory.address, - // gaugeFactory.address, - // bribeFactory.address - // ) - // await voter.deployed() - // console.log('Voter deployed to: ', voter.address) - // console.log( - // 'Args: ', - // escrow.address, - // pairFactory.address, - // gaugeFactory.address, - // bribeFactory.address, - // '\n' - // ) - - // const minter = await Minter.deploy( - // voter.address, - // escrow.address, - // distributor.address - // ) - // await minter.deployed() - // console.log('Minter deployed to: ', minter.address) - // console.log( - // 'Args: ', - // voter.address, - // escrow.address, - // distributor.address, - // '\n' - // ) - - // const receiver = await RedemptionReceiver.deploy( - // OP_CONFIG.USDC, - // velo.address, - // FTM_CONFIG.lzChainId, - // OP_CONFIG.lzEndpoint - // ) - // await receiver.deployed() - // console.log('RedemptionReceiver deployed to: ', receiver.address) - // console.log( - // 'Args: ', - // OP_CONFIG.USDC, - // velo.address, - // FTM_CONFIG.lzChainId, - // OP_CONFIG.lzEndpoint, - // '\n' - // ) - - // const governor = await VeloGovernor.deploy(escrow.address) - // await governor.deployed() - // console.log('VeloGovernor deployed to: ', governor.address) - // console.log('Args: ', escrow.address, '\n') + const bribeFactory = await BribeFactory.deploy() + await bribeFactory.deployed() + console.log('BribeFactory deployed to: ', bribeFactory.address) + + const pairFactory = await PairFactory.deploy() + await pairFactory.deployed() + console.log('PairFactory deployed to: ', pairFactory.address) + + const router = await Router.deploy(pairFactory.address, OP_CONFIG.WETH) + await router.deployed() + console.log('Router deployed to: ', router.address) + console.log('Args: ', pairFactory.address, OP_CONFIG.WETH, '\n') + + const library = await Library.deploy(router.address) + await library.deployed() + console.log('VelodromeLibrary deployed to: ', library.address) + console.log('Args: ', router.address, '\n') + + const artProxy = await VeArtProxy.deploy() + await artProxy.deployed() + console.log('VeArtProxy deployed to: ', artProxy.address) + + const escrow = await VotingEscrow.deploy(velo.address, artProxy.address) + await escrow.deployed() + console.log('VotingEscrow deployed to: ', escrow.address) + console.log('Args: ', velo.address, artProxy.address, '\n') + + const distributor = await RewardsDistributor.deploy(escrow.address) + await distributor.deployed() + console.log('RewardsDistributor deployed to: ', distributor.address) + console.log('Args: ', escrow.address, '\n') + + const voter = await Voter.deploy( + escrow.address, + pairFactory.address, + gaugeFactory.address, + bribeFactory.address + ) + await voter.deployed() + console.log('Voter deployed to: ', voter.address) + console.log( + 'Args: ', + escrow.address, + pairFactory.address, + gaugeFactory.address, + bribeFactory.address, + '\n' + ) + + const minter = await Minter.deploy( + voter.address, + escrow.address, + distributor.address + ) + await minter.deployed() + console.log('Minter deployed to: ', minter.address) + console.log( + 'Args: ', + voter.address, + escrow.address, + distributor.address, + '\n' + ) + + const receiver = await RedemptionReceiver.deploy( + OP_CONFIG.USDC, + velo.address, + FTM_CONFIG.lzChainId, + OP_CONFIG.lzEndpoint + ) + await receiver.deployed() + console.log('RedemptionReceiver deployed to: ', receiver.address) + console.log( + 'Args: ', + OP_CONFIG.USDC, + velo.address, + FTM_CONFIG.lzChainId, + OP_CONFIG.lzEndpoint, + '\n' + ) + + const governor = await VeloGovernor.deploy(escrow.address) + await governor.deployed() + console.log('VeloGovernor deployed to: ', governor.address) + console.log('Args: ', escrow.address, '\n') // Airdrop // const claim = await MerkleClaim.deploy(velo.address, OP_CONFIG.merkleRoot) @@ -216,61 +219,61 @@ task('deploy:arbTest', 'Deploys Optimism contracts').setAction(async function ( await velo.initialMint(OP_CONFIG.teamEOA) console.log('Initial minted') - // await velo.setRedemptionReceiver(receiver.address) - // console.log('RedemptionReceiver set') + await velo.setRedemptionReceiver(receiver.address) + console.log('RedemptionReceiver set') // await velo.setMerkleClaim(claim.address) // console.log('MerkleClaim set') - // await velo.setMinter(minter.address) - // console.log('Minter set') + await velo.setMinter(minter.address) + console.log('Minter set') - // await pairFactory.setPauser(OP_CONFIG.teamMultisig) - // console.log('Pauser set') + await pairFactory.setPauser(OP_CONFIG.teamMultisig) + console.log('Pauser set') - // await escrow.setVoter(voter.address) - // console.log( - // 'Voter set', - // 'voter address: ', - // voter.address, - // 'escrow address: ', - // escrow.address - // ) + await escrow.setVoter(voter.address) + console.log( + 'Voter set', + 'voter address: ', + voter.address, + 'escrow address: ', + escrow.address + ) - // await escrow.setTeam(OP_CONFIG.teamMultisig) - // console.log('Team set for escrow') + await escrow.setTeam(OP_CONFIG.teamMultisig) + console.log('Team set for escrow') - // await voter.setGovernor(OP_CONFIG.teamMultisig) - // console.log('Governor set') + await voter.setGovernor(OP_CONFIG.teamMultisig) + console.log('Governor set') - // await voter.setEmergencyCouncil(OP_CONFIG.teamMultisig) - // console.log('Emergency Council set') + await voter.setEmergencyCouncil(OP_CONFIG.teamMultisig) + console.log('Emergency Council set') - // await distributor.setDepositor(minter.address) - // console.log('Depositor set') + await distributor.setDepositor(minter.address) + console.log('Depositor set') - // await receiver.setTeam(OP_CONFIG.teamMultisig) - // console.log('Team set for receiver') + await receiver.setTeam(OP_CONFIG.teamMultisig) + console.log('Team set for receiver') - // await governor.setTeam(OP_CONFIG.teamMultisig) - // console.log('Team set for governor') + await governor.setTeam(OP_CONFIG.teamMultisig) + console.log('Team set for governor') - // // Whitelist - // const nativeToken = [velo.address] - // const tokenWhitelist = nativeToken.concat(OP_CONFIG.tokenWhitelist) - // await voter.initialize(tokenWhitelist, minter.address) - // console.log('Whitelist set') + // Whitelist + const nativeToken = [velo.address] + const tokenWhitelist = nativeToken.concat(OP_CONFIG.tokenWhitelist) + await voter.initialize(tokenWhitelist, minter.address) + console.log('Whitelist set') - // // Initial veVELO distro - // await minter.initialize( - // OP_CONFIG.partnerAddrs, - // OP_CONFIG.partnerAmts, - // OP_CONFIG.partnerMax - // ) - // console.log('veVELO distributed') + // Initial veVELO distro + await minter.initialize( + OP_CONFIG.partnerAddrs, + OP_CONFIG.partnerAmts, + OP_CONFIG.partnerMax + ) + console.log('veVELO distributed') - // await minter.setTeam(OP_CONFIG.teamMultisig) - // console.log('Team set for minter') + await minter.setTeam(OP_CONFIG.teamMultisig) + console.log('Team set for minter') console.log('Arbitrum Goerli Velocimeter Instruments deployed') }) From 487dc34c69eb32cad8cc15dcb505ed6cd089b4c7 Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Sun, 8 Jan 2023 21:44:02 +1100 Subject: [PATCH 06/43] update readme --- readme.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/readme.md b/readme.md index 4b3b579c..3f7c5146 100644 --- a/readme.md +++ b/readme.md @@ -1,5 +1,11 @@ # Velocimeter +run this script after cloning the repo to get the openzeppelin contracts and foundry setup etc. + +https://github.com/Velocimeter/instruments/blob/master/gitsubmodules.sh + + + Goerli From 9f34253415c50bf5eb561e31cb75a8e1351a27ce Mon Sep 17 00:00:00 2001 From: torbik Date: Mon, 9 Jan 2023 20:31:36 +0700 Subject: [PATCH 07/43] Switch to hardhat-deploy plugin, change some settings in hh config and add env checker --- checkEnv.ts | 36 + contracts/deployments/veloAddress.json | 1 - deploy/00_velo.ts | 17 + deploy/01_gaugeFactory.ts | 17 + deploy/02_bribeFactory.ts | 17 + deploy/04_pairFactory.ts | 17 + deploy/05_router.ts | 22 + deploy/06_library.ts | 19 + deploy/07_veArtProxy.ts | 17 + deploy/08_votingEscrow.ts | 20 + deploy/09_rewardsDist.ts | 19 + deploy/10_voter.ts | 27 + deploy/11_minter.ts | 21 + deploy/12_veloGovernor.ts | 19 + deploy/13_redemptionReceiver.ts | 30 + deploy/14_merkleClaim.ts | 23 + deployments/arbitrumGoerli/.chainId | 1 + deployments/arbitrumGoerli/BribeFactory.json | 128 + deployments/arbitrumGoerli/GaugeFactory.json | 113 + deployments/arbitrumGoerli/MerkleClaim.json | 220 + deployments/arbitrumGoerli/Minter.json | 427 + deployments/arbitrumGoerli/PairFactory.json | 577 ++ .../arbitrumGoerli/RedemptionReceiver.json | 428 + .../arbitrumGoerli/RewardsDistributor.json | 520 ++ deployments/arbitrumGoerli/Router.json | 1021 +++ deployments/arbitrumGoerli/VeArtProxy.json | 75 + deployments/arbitrumGoerli/Velo.json | 522 ++ deployments/arbitrumGoerli/VeloGovernor.json | 1459 ++++ .../arbitrumGoerli/VelodromeLibrary.json | 229 + deployments/arbitrumGoerli/Voter.json | 1418 ++++ deployments/arbitrumGoerli/VotingEscrow.json | 2339 ++++++ .../0faaa79d8b79020b765ba7705413c447.json | 238 + .../1bc83d498cf3ed68f4ca9abac087a4fd.json | 238 + .../6045e31091c7162ece1e348fdb6fb21d.json | 238 + .../bb56ebd0528f2e0f691b8bc31f08a7c1.json | 238 + .../e6fbf9feea298b0eb6ed1dc19df1c5ab.json | 238 + exported.json | 6960 +++++++++++++++++ hardhat.config.ts | 113 +- package.json | 8 +- tasks/accounts.ts | 10 - tsconfig.json | 4 +- veloAddress.json | 1 - yarn.lock | 10 +- 43 files changed, 18023 insertions(+), 72 deletions(-) create mode 100644 checkEnv.ts delete mode 100644 contracts/deployments/veloAddress.json create mode 100644 deploy/00_velo.ts create mode 100644 deploy/01_gaugeFactory.ts create mode 100644 deploy/02_bribeFactory.ts create mode 100644 deploy/04_pairFactory.ts create mode 100644 deploy/05_router.ts create mode 100644 deploy/06_library.ts create mode 100644 deploy/07_veArtProxy.ts create mode 100644 deploy/08_votingEscrow.ts create mode 100644 deploy/09_rewardsDist.ts create mode 100644 deploy/10_voter.ts create mode 100644 deploy/11_minter.ts create mode 100644 deploy/12_veloGovernor.ts create mode 100644 deploy/13_redemptionReceiver.ts create mode 100644 deploy/14_merkleClaim.ts create mode 100644 deployments/arbitrumGoerli/.chainId create mode 100644 deployments/arbitrumGoerli/BribeFactory.json create mode 100644 deployments/arbitrumGoerli/GaugeFactory.json create mode 100644 deployments/arbitrumGoerli/MerkleClaim.json create mode 100644 deployments/arbitrumGoerli/Minter.json create mode 100644 deployments/arbitrumGoerli/PairFactory.json create mode 100644 deployments/arbitrumGoerli/RedemptionReceiver.json create mode 100644 deployments/arbitrumGoerli/RewardsDistributor.json create mode 100644 deployments/arbitrumGoerli/Router.json create mode 100644 deployments/arbitrumGoerli/VeArtProxy.json create mode 100644 deployments/arbitrumGoerli/Velo.json create mode 100644 deployments/arbitrumGoerli/VeloGovernor.json create mode 100644 deployments/arbitrumGoerli/VelodromeLibrary.json create mode 100644 deployments/arbitrumGoerli/Voter.json create mode 100644 deployments/arbitrumGoerli/VotingEscrow.json create mode 100644 deployments/arbitrumGoerli/solcInputs/0faaa79d8b79020b765ba7705413c447.json create mode 100644 deployments/arbitrumGoerli/solcInputs/1bc83d498cf3ed68f4ca9abac087a4fd.json create mode 100644 deployments/arbitrumGoerli/solcInputs/6045e31091c7162ece1e348fdb6fb21d.json create mode 100644 deployments/arbitrumGoerli/solcInputs/bb56ebd0528f2e0f691b8bc31f08a7c1.json create mode 100644 deployments/arbitrumGoerli/solcInputs/e6fbf9feea298b0eb6ed1dc19df1c5ab.json create mode 100644 exported.json delete mode 100644 tasks/accounts.ts delete mode 100644 veloAddress.json diff --git a/checkEnv.ts b/checkEnv.ts new file mode 100644 index 00000000..5381cfc1 --- /dev/null +++ b/checkEnv.ts @@ -0,0 +1,36 @@ +import { z, type ZodFormattedError } from "zod"; + +const schema = z.object({ + ALCHEMY_GOERLI_ARBITRUM_API_KEY: z.string().min(1), + ARB_SCAN_API_KEY: z.string().min(1), +}); + +type DestructedEnv = { + [k in keyof z.infer]: z.infer[k] | undefined; +}; + +const destructedEnv: DestructedEnv = { + ALCHEMY_GOERLI_ARBITRUM_API_KEY: process.env.ALCHEMY_GOERLI_ARBITRUM_API_KEY, + ARB_SCAN_API_KEY: process.env.ARB_SCAN_API_KEY, +}; + +const _env = schema.safeParse(destructedEnv); + +const formatErrors = ( + errors: ZodFormattedError, string> +) => { + return Object.entries(errors) + .map(([name, value]) => { + if (value && "_errors" in value) + return `${name}: ${value._errors.join(", ")}\n`; + }) + .filter(Boolean); +}; + +if (!_env.success) { + console.error( + "❌ Invalid environment variables:\n", + ...formatErrors(_env.error.format()) + ); + throw new Error("Invalid environment variables"); +} diff --git a/contracts/deployments/veloAddress.json b/contracts/deployments/veloAddress.json deleted file mode 100644 index d4740145..00000000 --- a/contracts/deployments/veloAddress.json +++ /dev/null @@ -1 +0,0 @@ -{"Velodrome":"0x3290aE1e3A028bc060b2AC541A91acf8F3927d2d"} \ No newline at end of file diff --git a/deploy/00_velo.ts b/deploy/00_velo.ts new file mode 100644 index 00000000..731a3b8e --- /dev/null +++ b/deploy/00_velo.ts @@ -0,0 +1,17 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + + const { deployer } = await getNamedAccounts(); + + await deploy("Velo", { + from: deployer, + args: [], + log: true, + }); +}; +export default func; +func.tags = ["Velo"]; diff --git a/deploy/01_gaugeFactory.ts b/deploy/01_gaugeFactory.ts new file mode 100644 index 00000000..d389be8c --- /dev/null +++ b/deploy/01_gaugeFactory.ts @@ -0,0 +1,17 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + + const { deployer } = await getNamedAccounts(); + + await deploy("GaugeFactory", { + from: deployer, + args: [], + log: true, + }); +}; +export default func; +func.tags = ["GaugeFactory"]; diff --git a/deploy/02_bribeFactory.ts b/deploy/02_bribeFactory.ts new file mode 100644 index 00000000..49ec7654 --- /dev/null +++ b/deploy/02_bribeFactory.ts @@ -0,0 +1,17 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + + const { deployer } = await getNamedAccounts(); + + await deploy("BribeFactory", { + from: deployer, + args: [], + log: true, + }); +}; +export default func; +func.tags = ["BribeFactory"]; diff --git a/deploy/04_pairFactory.ts b/deploy/04_pairFactory.ts new file mode 100644 index 00000000..745dfe9b --- /dev/null +++ b/deploy/04_pairFactory.ts @@ -0,0 +1,17 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + + const { deployer } = await getNamedAccounts(); + + await deploy("PairFactory", { + from: deployer, + args: [], + log: true, + }); +}; +export default func; +func.tags = ["PairFactory"]; diff --git a/deploy/05_router.ts b/deploy/05_router.ts new file mode 100644 index 00000000..e0231330 --- /dev/null +++ b/deploy/05_router.ts @@ -0,0 +1,22 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; + +import arbTestnetConfig from "../tasks/deploy/constants/arbTestnetConfig"; +const ARB_TEST_CONFIG = arbTestnetConfig; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + + const { deployer } = await getNamedAccounts(); + + const pairFactory = await deployments.get("PairFactory"); + + await deploy("Router", { + from: deployer, + args: [pairFactory.address, ARB_TEST_CONFIG.WETH], + log: true, + }); +}; +export default func; +func.tags = ["Router"]; diff --git a/deploy/06_library.ts b/deploy/06_library.ts new file mode 100644 index 00000000..859c5c3a --- /dev/null +++ b/deploy/06_library.ts @@ -0,0 +1,19 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + + const { deployer } = await getNamedAccounts(); + + const router = await deployments.get("Router"); + + await deploy("VelodromeLibrary", { + from: deployer, + args: [router.address], + log: true, + }); +}; +export default func; +func.tags = ["VelodromeLibrary"]; diff --git a/deploy/07_veArtProxy.ts b/deploy/07_veArtProxy.ts new file mode 100644 index 00000000..4fc7f14a --- /dev/null +++ b/deploy/07_veArtProxy.ts @@ -0,0 +1,17 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + + const { deployer } = await getNamedAccounts(); + + await deploy("VeArtProxy", { + from: deployer, + args: [], + log: true, + }); +}; +export default func; +func.tags = ["VeArtProxy"]; diff --git a/deploy/08_votingEscrow.ts b/deploy/08_votingEscrow.ts new file mode 100644 index 00000000..a0d8ed9f --- /dev/null +++ b/deploy/08_votingEscrow.ts @@ -0,0 +1,20 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + + const { deployer } = await getNamedAccounts(); + + const velo = await deployments.get("Velo"); + const veArtProxy = await deployments.get("VeArtProxy"); + + await deploy("VotingEscrow", { + from: deployer, + args: [velo.address, veArtProxy.address], + log: true, + }); +}; +export default func; +func.tags = ["VotingEscrow"]; diff --git a/deploy/09_rewardsDist.ts b/deploy/09_rewardsDist.ts new file mode 100644 index 00000000..99d5018f --- /dev/null +++ b/deploy/09_rewardsDist.ts @@ -0,0 +1,19 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + + const { deployer } = await getNamedAccounts(); + + const escrow = await deployments.get("VotingEscrow"); + + await deploy("RewardsDistributor", { + from: deployer, + args: [escrow.address], + log: true, + }); +}; +export default func; +func.tags = ["RewardsDistributor"]; diff --git a/deploy/10_voter.ts b/deploy/10_voter.ts new file mode 100644 index 00000000..189b023c --- /dev/null +++ b/deploy/10_voter.ts @@ -0,0 +1,27 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + + const { deployer } = await getNamedAccounts(); + + const escrow = await deployments.get("VotingEscrow"); + const pairFactory = await deployments.get("PairFactory"); + const gaugeFactory = await deployments.get("GaugeFactory"); + const bribeFactory = await deployments.get("BribeFactory"); + + await deploy("Voter", { + from: deployer, + args: [ + escrow.address, + pairFactory.address, + gaugeFactory.address, + bribeFactory.address, + ], + log: true, + }); +}; +export default func; +func.tags = ["Voter"]; diff --git a/deploy/11_minter.ts b/deploy/11_minter.ts new file mode 100644 index 00000000..fa472418 --- /dev/null +++ b/deploy/11_minter.ts @@ -0,0 +1,21 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + + const { deployer } = await getNamedAccounts(); + + const escrow = await deployments.get("VotingEscrow"); + const voter = await deployments.get("Voter"); + const dist = await deployments.get("RewardsDistributor"); + + await deploy("Minter", { + from: deployer, + args: [voter.address, escrow.address, dist.address], + log: true, + }); +}; +export default func; +func.tags = ["Minter"]; diff --git a/deploy/12_veloGovernor.ts b/deploy/12_veloGovernor.ts new file mode 100644 index 00000000..024f6b25 --- /dev/null +++ b/deploy/12_veloGovernor.ts @@ -0,0 +1,19 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + + const { deployer } = await getNamedAccounts(); + + const escrow = await deployments.get("VotingEscrow"); + + await deploy("VeloGovernor", { + from: deployer, + args: [escrow.address], + log: true, + }); +}; +export default func; +func.tags = ["VeloGovernor"]; diff --git a/deploy/13_redemptionReceiver.ts b/deploy/13_redemptionReceiver.ts new file mode 100644 index 00000000..d12d41b4 --- /dev/null +++ b/deploy/13_redemptionReceiver.ts @@ -0,0 +1,30 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; + +import arbTestnetConfig from "../tasks/deploy/constants/arbTestnetConfig"; +import testFantomConfig from "../tasks/deploy/constants/testFantomConfig"; + +const ARB_TEST_CONFIG = arbTestnetConfig; +const FTM_CONFIG = testFantomConfig; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + + const { deployer } = await getNamedAccounts(); + + const velo = await deployments.get("Velo"); + + await deploy("RedemptionReceiver", { + from: deployer, + args: [ + ARB_TEST_CONFIG.USDC, + velo.address, + FTM_CONFIG.lzChainId, + ARB_TEST_CONFIG.lzEndpoint, + ], + log: true, + }); +}; +export default func; +func.tags = ["RedemptionReceiver"]; diff --git a/deploy/14_merkleClaim.ts b/deploy/14_merkleClaim.ts new file mode 100644 index 00000000..8431b345 --- /dev/null +++ b/deploy/14_merkleClaim.ts @@ -0,0 +1,23 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; + +import arbTestnetConfig from "../tasks/deploy/constants/arbTestnetConfig"; + +const ARB_TEST_CONFIG = arbTestnetConfig; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + + const { deployer } = await getNamedAccounts(); + + const velo = await deployments.get("Velo"); + + await deploy("MerkleClaim", { + from: deployer, + args: [velo.address, ARB_TEST_CONFIG.merkleRoot], + log: true, + }); +}; +export default func; +func.tags = ["MerkleClaim"]; diff --git a/deployments/arbitrumGoerli/.chainId b/deployments/arbitrumGoerli/.chainId new file mode 100644 index 00000000..16be23a3 --- /dev/null +++ b/deployments/arbitrumGoerli/.chainId @@ -0,0 +1 @@ +421613 \ No newline at end of file diff --git a/deployments/arbitrumGoerli/BribeFactory.json b/deployments/arbitrumGoerli/BribeFactory.json new file mode 100644 index 00000000..e1168e8d --- /dev/null +++ b/deployments/arbitrumGoerli/BribeFactory.json @@ -0,0 +1,128 @@ +{ + "address": "0x5542edb529F7c963583e9B8e5339121cFCf4B606", + "abi": [ + { + "inputs": [ + { + "internalType": "address[]", + "name": "allowedRewards", + "type": "address[]" + } + ], + "name": "createExternalBribe", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "allowedRewards", + "type": "address[]" + } + ], + "name": "createInternalBribe", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "last_external_bribe", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "last_internal_bribe", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xd2295e39221606283b3b8546159a76c72a42aa57c2b34c891ddb54de0a4f2d18", + "receipt": { + "to": null, + "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", + "contractAddress": "0x5542edb529F7c963583e9B8e5339121cFCf4B606", + "transactionIndex": 1, + "gasUsed": "37915213", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x275b23ee626d6c37edf116a20b66f0859aca71be63e068739cee659b82b5bee8", + "transactionHash": "0xd2295e39221606283b3b8546159a76c72a42aa57c2b34c891ddb54de0a4f2d18", + "logs": [], + "blockNumber": 4195008, + "cumulativeGasUsed": "37915213", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 5, + "solcInputHash": "0faaa79d8b79020b765ba7705413c447", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createExternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createInternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_external_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_internal_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/BribeFactory.sol\":\"BribeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/ExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract ExternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve; // \\u5929\\u4f7f\\u306e\\u305f\\u307e\\u3054\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balanceOf;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n _prevSupply = supplyCheckpoints[\\n getPriorSupplyIndex(_nextEpochStart + DURATION)\\n ].supply;\\n prevRewards.balanceOf =\\n (cp0.balanceOf *\\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (block.timestamp > _lastEpochEnd) {\\n reward +=\\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\\n }\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0xfe1e53dea8a63ce448c5856a740ed73038ad29a9dcd0f2a2752049b146bb4eb0\",\"license\":\"MIT\"},\"contracts/InternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract InternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve;\\n\\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 public constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n mapping(address => mapping(uint256 => uint256))\\n public userRewardPerTokenStored;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (totalSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / totalSupply);\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\\n _startTimestamp = endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][tokenId],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][tokenId]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n require(isReward[token]);\\n\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2dc302de5dfd95018d1fba7a3a1916d2c1fcf32859d19d38648767f13422a694\",\"license\":\"MIT\"},\"contracts/factories/BribeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IBribeFactory.sol\\\";\\nimport 'contracts/InternalBribe.sol';\\nimport 'contracts/ExternalBribe.sol';\\n\\ncontract BribeFactory is IBribeFactory {\\n address public last_internal_bribe;\\n address public last_external_bribe;\\n\\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\\n return last_internal_bribe;\\n }\\n\\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\\n return last_external_bribe;\\n }\\n}\\n\",\"keccak256\":\"0x30d69b5733c01d1d27e8af06e6217200709721fb84ee8458ee50269bf2ce7ed8\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50614cca806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea26469706673582212205b93468d06478818879cb427a7ca7c73b721ca254f037422ec97cabf99fbbc3664736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea264697066735822122078729899baedc77b130e2f4072073dad293ec9103c5aa03801a6a9313038b6c864736f6c634300080d0033a26469706673582212208da3b33a270aaa552b25843a6147be3e4e286cd741990f1a2e68b8b14926288464736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea26469706673582212205b93468d06478818879cb427a7ca7c73b721ca254f037422ec97cabf99fbbc3664736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea264697066735822122078729899baedc77b130e2f4072073dad293ec9103c5aa03801a6a9313038b6c864736f6c634300080d0033a26469706673582212208da3b33a270aaa552b25843a6147be3e4e286cd741990f1a2e68b8b14926288464736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 21321, + "contract": "contracts/factories/BribeFactory.sol:BribeFactory", + "label": "last_internal_bribe", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 21323, + "contract": "contracts/factories/BribeFactory.sol:BribeFactory", + "label": "last_external_bribe", + "offset": 0, + "slot": "1", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/GaugeFactory.json b/deployments/arbitrumGoerli/GaugeFactory.json new file mode 100644 index 00000000..efe497bc --- /dev/null +++ b/deployments/arbitrumGoerli/GaugeFactory.json @@ -0,0 +1,113 @@ +{ + "address": "0x1Ac3032Dfd7e206BA6d08F453f38593b9A583052", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_pool", + "type": "address" + }, + { + "internalType": "address", + "name": "_internal_bribe", + "type": "address" + }, + { + "internalType": "address", + "name": "_external_bribe", + "type": "address" + }, + { + "internalType": "address", + "name": "_ve", + "type": "address" + }, + { + "internalType": "bool", + "name": "isPair", + "type": "bool" + }, + { + "internalType": "address[]", + "name": "allowedRewards", + "type": "address[]" + } + ], + "name": "createGauge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "last_gauge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x938a3d14930cbed82e1302af131ea56c350db648e5346d7b165695f5d0a501cd", + "receipt": { + "to": null, + "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", + "contractAddress": "0x1Ac3032Dfd7e206BA6d08F453f38593b9A583052", + "transactionIndex": 1, + "gasUsed": "32701694", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x166db84c6d10fbaefdb2535321626cf25e67658dca1c9ba1bbd47bd77b57dc62", + "transactionHash": "0x938a3d14930cbed82e1302af131ea56c350db648e5346d7b165695f5d0a501cd", + "logs": [], + "blockNumber": 4195007, + "cumulativeGasUsed": "32701694", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 5, + "solcInputHash": "0faaa79d8b79020b765ba7705413c447", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_internal_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_external_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_ve\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isPair\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_gauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/GaugeFactory.sol\":\"GaugeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Gauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\\ncontract Gauge is IGauge {\\n address public immutable stake; // the LP token that needs to be staked for rewards\\n address public immutable _ve; // the ve token used for gauges\\n address public immutable internal_bribe;\\n address public immutable external_bribe;\\n address public immutable voter;\\n\\n uint256 public derivedSupply;\\n mapping(address => uint256) public derivedBalances;\\n\\n bool public isForPair;\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 internal constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(address => uint256)) public lastEarn;\\n mapping(address => mapping(address => uint256))\\n public userRewardPerTokenStored;\\n\\n mapping(address => uint256) public tokenIds;\\n\\n uint256 public totalSupply;\\n mapping(address => uint256) public balanceOf;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n uint256 public fees0;\\n uint256 public fees1;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(\\n address _stake,\\n address _internal_bribe,\\n address _external_bribe,\\n address __ve,\\n address _voter,\\n bool _forPair,\\n address[] memory _allowedRewardTokens\\n ) {\\n stake = _stake;\\n internal_bribe = _internal_bribe;\\n external_bribe = _external_bribe;\\n _ve = __ve;\\n voter = _voter;\\n isForPair = _forPair;\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function claimFees()\\n external\\n lock\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n return _claimFees();\\n }\\n\\n function _claimFees()\\n internal\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n if (!isForPair) {\\n return (0, 0);\\n }\\n (claimed0, claimed1) = IPair(stake).claimFees();\\n if (claimed0 > 0 || claimed1 > 0) {\\n uint256 _fees0 = fees0 + claimed0;\\n uint256 _fees1 = fees1 + claimed1;\\n (address _token0, address _token1) = IPair(stake).tokens();\\n if (\\n _fees0 > IBribe(internal_bribe).left(_token0) &&\\n _fees0 / DURATION > 0\\n ) {\\n fees0 = 0;\\n _safeApprove(_token0, internal_bribe, _fees0);\\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\\n } else {\\n fees0 = _fees0;\\n }\\n if (\\n _fees1 > IBribe(internal_bribe).left(_token1) &&\\n _fees1 / DURATION > 0\\n ) {\\n fees1 = 0;\\n _safeApprove(_token1, internal_bribe, _fees1);\\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\\n } else {\\n fees1 = _fees1;\\n }\\n\\n emit ClaimFees(msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(address account, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(address account, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[account][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[account] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n derivedSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n function getReward(address account, address[] memory tokens) external lock {\\n require(msg.sender == account || msg.sender == voter);\\n _unlocked = 1;\\n IVoter(voter).distribute(address(this));\\n _unlocked = 2;\\n\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], account);\\n lastEarn[tokens[i]][account] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n\\n uint256 _derivedBalance = derivedBalances[account];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(account);\\n derivedBalances[account] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(account, derivedBalances[account]);\\n _writeSupplyCheckpoint();\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (derivedSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / derivedSupply);\\n }\\n\\n function derivedBalance(address account) public view returns (uint256) {\\n return balanceOf[account];\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\\n function earned(address token, address account)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][account],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[account] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[account] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[account][i];\\n Checkpoint memory cp1 = checkpoints[account][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[account][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][account]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n function depositAll(uint256 tokenId) external {\\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\\n }\\n\\n function deposit(uint256 amount, uint256 tokenId) public lock {\\n require(amount > 0);\\n _updateRewardForAllTokens();\\n\\n _safeTransferFrom(stake, msg.sender, address(this), amount);\\n totalSupply += amount;\\n balanceOf[msg.sender] += amount;\\n\\n if (tokenId > 0) {\\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\\n if (tokenIds[msg.sender] == 0) {\\n tokenIds[msg.sender] = tokenId;\\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\\n }\\n require(tokenIds[msg.sender] == tokenId);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, _derivedBalance);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function withdrawAll() external {\\n withdraw(balanceOf[msg.sender]);\\n }\\n\\n function withdraw(uint256 amount) public {\\n uint256 tokenId = 0;\\n if (amount == balanceOf[msg.sender]) {\\n tokenId = tokenIds[msg.sender];\\n }\\n withdrawToken(amount, tokenId);\\n }\\n\\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[msg.sender] -= amount;\\n _safeTransfer(stake, msg.sender, amount);\\n\\n if (tokenId > 0) {\\n require(tokenId == tokenIds[msg.sender]);\\n tokenIds[msg.sender] = 0;\\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(token != stake);\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"rewards tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n _claimFees();\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeApprove(\\n address token,\\n address spender,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x38cc0284dd60d8a1418d9c34e6be84911ca4a1b479dc129f19b9027e4c670e1f\",\"license\":\"MIT\"},\"contracts/factories/GaugeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/Gauge.sol';\\n\\ncontract GaugeFactory is IGaugeFactory {\\n address public last_gauge;\\n\\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\\n return last_gauge;\\n }\\n}\\n\",\"keccak256\":\"0x34f6ac4bdace9ef01d8cffda9b45842efae88b519230c67759b9936aee6acc9b\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50613b19806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea26469706673582212204be9fb7205b1a10b89a5bdb5d1d49b90c1efa5220c1a307bfed2aef8bfdec3be64736f6c634300080d0033a2646970667358221220eccecd0b41985a8acaefecdc0f1ccc41783300d7cc91bf7cc27046dd1d7e179064736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea26469706673582212204be9fb7205b1a10b89a5bdb5d1d49b90c1efa5220c1a307bfed2aef8bfdec3be64736f6c634300080d0033a2646970667358221220eccecd0b41985a8acaefecdc0f1ccc41783300d7cc91bf7cc27046dd1d7e179064736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 21380, + "contract": "contracts/factories/GaugeFactory.sol:GaugeFactory", + "label": "last_gauge", + "offset": 0, + "slot": "0", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/MerkleClaim.json b/deployments/arbitrumGoerli/MerkleClaim.json new file mode 100644 index 00000000..6b9b8052 --- /dev/null +++ b/deployments/arbitrumGoerli/MerkleClaim.json @@ -0,0 +1,220 @@ +{ + "address": "0x0a68F78212D69EfC6346B5F9d72BC5A301779BE9", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_velo", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_merkleRoot", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Claim", + "type": "event" + }, + { + "inputs": [], + "name": "VELO", + "outputs": [ + { + "internalType": "contract IVelo", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "name": "claim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "hasClaimed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "merkleRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x41cbc82b30365881b829a222362d8258bc95e6f177ee28c9bd37d005957b74cb", + "receipt": { + "to": null, + "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", + "contractAddress": "0x0a68F78212D69EfC6346B5F9d72BC5A301779BE9", + "transactionIndex": 1, + "gasUsed": "5184295", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x3f42b181811bab0a156751433e49b95d8dc444fe487d83807bb07fc29ece9865", + "transactionHash": "0x41cbc82b30365881b829a222362d8258bc95e6f177ee28c9bd37d005957b74cb", + "logs": [], + "blockNumber": 4195042, + "cumulativeGasUsed": "5184295", + "status": 1, + "byzantium": true + }, + "args": [ + "0xe69b00A164047e7eB87B73971B0f340eEbFF9c81", + "0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f" + ], + "numDeployments": 3, + "solcInputHash": "0faaa79d8b79020b765ba7705413c447", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_velo\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"_merkleRoot\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Claim\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"VELO\",\"outputs\":[{\"internalType\":\"contract IVelo\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"hasClaimed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\",\"events\":{\"Claim(address,uint256)\":{\"params\":{\"amount\":\"of tokens claimed\",\"to\":\"recipient of claim\"}}},\"kind\":\"dev\",\"methods\":{\"claim(address,uint256,bytes32[])\":{\"params\":{\"amount\":\"of tokens owed to claimee\",\"proof\":\"merkle proof to prove address and amount are in tree\",\"to\":\"address of claimee\"}},\"constructor\":{\"params\":{\"_merkleRoot\":\"of claimees\",\"_velo\":\"address\"}}},\"title\":\"MerkleClaim\",\"version\":1},\"userdoc\":{\"events\":{\"Claim(address,uint256)\":{\"notice\":\"Emitted after a successful token claim\"}},\"kind\":\"user\",\"methods\":{\"VELO()\":{\"notice\":\"VELO token to claim\"},\"claim(address,uint256,bytes32[])\":{\"notice\":\"Allows claiming tokens if address is part of merkle tree\"},\"constructor\":{\"notice\":\"Creates a new MerkleClaim contract\"},\"hasClaimed(address)\":{\"notice\":\"Mapping of addresses who have claimed tokens\"},\"merkleRoot()\":{\"notice\":\"ERC20-claimee inclusion root\"}},\"notice\":\"Claims VELO for members of a merkle tree\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/MerkleClaim.sol\":\"MerkleClaim\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"},\"contracts/redeem/MerkleClaim.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity 0.8.13;\\n\\n/// ============ Imports ============\\n\\nimport {IVelo} from \\\"contracts/interfaces/IVelo.sol\\\";\\nimport {MerkleProof} from \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\\\"; // OZ: MerkleProof\\n\\n/// @title MerkleClaim\\n/// @notice Claims VELO for members of a merkle tree\\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\\ncontract MerkleClaim {\\n /// ============ Immutable storage ============\\n\\n /// @notice VELO token to claim\\n IVelo public immutable VELO;\\n /// @notice ERC20-claimee inclusion root\\n bytes32 public immutable merkleRoot;\\n\\n /// ============ Mutable storage ============\\n\\n /// @notice Mapping of addresses who have claimed tokens\\n mapping(address => bool) public hasClaimed;\\n\\n /// ============ Constructor ============\\n\\n /// @notice Creates a new MerkleClaim contract\\n /// @param _velo address\\n /// @param _merkleRoot of claimees\\n constructor(address _velo, bytes32 _merkleRoot) {\\n VELO = IVelo(_velo);\\n merkleRoot = _merkleRoot;\\n }\\n\\n /// ============ Events ============\\n\\n /// @notice Emitted after a successful token claim\\n /// @param to recipient of claim\\n /// @param amount of tokens claimed\\n event Claim(address indexed to, uint256 amount);\\n\\n /// ============ Functions ============\\n\\n /// @notice Allows claiming tokens if address is part of merkle tree\\n /// @param to address of claimee\\n /// @param amount of tokens owed to claimee\\n /// @param proof merkle proof to prove address and amount are in tree\\n function claim(\\n address to,\\n uint256 amount,\\n bytes32[] calldata proof\\n ) external {\\n // Throw if address has already claimed tokens\\n require(!hasClaimed[to], \\\"ALREADY_CLAIMED\\\");\\n\\n // Verify merkle proof, or revert if not in tree\\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\\n require(isValidLeaf, \\\"NOT_IN_MERKLE\\\");\\n\\n // Set address to claimed\\n hasClaimed[to] = true;\\n\\n // Claim tokens for address\\n require(VELO.claim(to, amount), \\\"CLAIM_FAILED\\\");\\n\\n // Emit claim event\\n emit Claim(to, amount);\\n }\\n}\\n\",\"keccak256\":\"0xb4724b0f4bf1f8a9f5ef9147e834b2d85ae61005ffc1d6b261f911c093f38270\",\"license\":\"AGPL-3.0-only\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev These functions deal with verification of Merkle Tree proofs.\\n *\\n * The tree and the proofs can be generated using our\\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\\n * You will find a quickstart guide in the readme.\\n *\\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\\n * hashing, or use a hash function other than keccak256 for hashing leaves.\\n * This is because the concatenation of a sorted pair of internal nodes in\\n * the merkle tree could be reinterpreted as a leaf value.\\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\\n * against this attack out of the box.\\n */\\nlibrary MerkleProof {\\n /**\\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\\n * defined by `root`. For this, a `proof` must be provided, containing\\n * sibling hashes on the branch from the leaf to the root of the tree. Each\\n * pair of leaves and each pair of pre-images are assumed to be sorted.\\n */\\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProof(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {verify}\\n *\\n * _Available since v4.7._\\n */\\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProofCalldata(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\\n * hash matches the root of the tree. When processing the proof, the pairs\\n * of leafs & pre-images are assumed to be sorted.\\n *\\n * _Available since v4.4._\\n */\\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Calldata version of {processProof}\\n *\\n * _Available since v4.7._\\n */\\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerify(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProof(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {multiProofVerify}\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerifyCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\\n * respectively.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProof(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n /**\\n * @dev Calldata version of {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProofCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\\n }\\n\\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x00, a)\\n mstore(0x20, b)\\n value := keccak256(0x00, 0x40)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcc76dbe53154a5bbd12fdd1613a73f73f3dc7c63d813be36f7ee606f52d6a7b3\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c060405234801561001057600080fd5b5060405161062638038061062683398101604081905261002f91610045565b6001600160a01b0390911660805260a05261007f565b6000806040838503121561005857600080fd5b82516001600160a01b038116811461006f57600080fd5b6020939093015192949293505050565b60805160a0516105766100b060003960008181605601526101ea01526000818160d8015261029601526105766000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633d13f8741461008b57806373b2e80e146100a0578063a0eeb39a146100d3575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61009e61009936600461043c565b610112565b005b6100c36100ae3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6100fa7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea26469706673582212200271092771994fc7918f24a308c1d35a97c9ff921b435a90f1e8e07f6ccee75d64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633d13f8741461008b57806373b2e80e146100a0578063a0eeb39a146100d3575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61009e61009936600461043c565b610112565b005b6100c36100ae3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6100fa7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea26469706673582212200271092771994fc7918f24a308c1d35a97c9ff921b435a90f1e8e07f6ccee75d64736f6c634300080d0033", + "devdoc": { + "author": "Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)", + "events": { + "Claim(address,uint256)": { + "params": { + "amount": "of tokens claimed", + "to": "recipient of claim" + } + } + }, + "kind": "dev", + "methods": { + "claim(address,uint256,bytes32[])": { + "params": { + "amount": "of tokens owed to claimee", + "proof": "merkle proof to prove address and amount are in tree", + "to": "address of claimee" + } + }, + "constructor": { + "params": { + "_merkleRoot": "of claimees", + "_velo": "address" + } + } + }, + "title": "MerkleClaim", + "version": 1 + }, + "userdoc": { + "events": { + "Claim(address,uint256)": { + "notice": "Emitted after a successful token claim" + } + }, + "kind": "user", + "methods": { + "VELO()": { + "notice": "VELO token to claim" + }, + "claim(address,uint256,bytes32[])": { + "notice": "Allows claiming tokens if address is part of merkle tree" + }, + "constructor": { + "notice": "Creates a new MerkleClaim contract" + }, + "hasClaimed(address)": { + "notice": "Mapping of addresses who have claimed tokens" + }, + "merkleRoot()": { + "notice": "ERC20-claimee inclusion root" + } + }, + "notice": "Claims VELO for members of a merkle tree", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 24472, + "contract": "contracts/redeem/MerkleClaim.sol:MerkleClaim", + "label": "hasClaimed", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_bool)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/Minter.json b/deployments/arbitrumGoerli/Minter.json new file mode 100644 index 00000000..df67f8db --- /dev/null +++ b/deployments/arbitrumGoerli/Minter.json @@ -0,0 +1,427 @@ +{ + "address": "0xd2C3ebFB8e7e79CA84080a8551D86Df50B0F559d", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "__voter", + "type": "address" + }, + { + "internalType": "address", + "name": "__ve", + "type": "address" + }, + { + "internalType": "address", + "name": "__rewards_distributor", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weekly", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "circulating_supply", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "circulating_emission", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "inputs": [], + "name": "MAX_TEAM_RATE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_rewards_distributor", + "outputs": [ + { + "internalType": "contract IRewardsDistributor", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_ve", + "outputs": [ + { + "internalType": "contract IVotingEscrow", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_velo", + "outputs": [ + { + "internalType": "contract IVelo", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_voter", + "outputs": [ + { + "internalType": "contract IVoter", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "active_period", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "calculate_emission", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_minted", + "type": "uint256" + } + ], + "name": "calculate_growth", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "circulating_emission", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "circulating_supply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "claimants", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "max", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingTeam", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_team", + "type": "address" + } + ], + "name": "setTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_teamRate", + "type": "uint256" + } + ], + "name": "setTeamRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "team", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "teamRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "update_period", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "weekly", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "weekly_emission", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x168c6cf31abe5f09dda0cfddf11ffbc4b8dc5adc5590029193721e79a137368f", + "receipt": { + "to": null, + "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", + "contractAddress": "0xd2C3ebFB8e7e79CA84080a8551D86Df50B0F559d", + "transactionIndex": 1, + "gasUsed": "12422232", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x4ff31abdadb682b773acc1285d51d5ebf31972ea063150d92009d5ec9a9ddcaa", + "transactionHash": "0x168c6cf31abe5f09dda0cfddf11ffbc4b8dc5adc5590029193721e79a137368f", + "logs": [], + "blockNumber": 4195027, + "cumulativeGasUsed": "12422232", + "status": 1, + "byzantium": true + }, + "args": [ + "0x574607c69f369f0535E77C5F7C35767Aee04879A", + "0x6b938BA22FB5520fFB5D14c9C4Fef82a48761497", + "0xf6CdA702C6Bd15d5C0A325CE8f9f88219fE5F445" + ], + "numDeployments": 3, + "solcInputHash": "0faaa79d8b79020b765ba7705413c447", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__voter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__rewards_distributor\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weekly\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_supply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_emission\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_TEAM_RATE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_rewards_distributor\",\"outputs\":[{\"internalType\":\"contract IRewardsDistributor\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"contract IVotingEscrow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_velo\",\"outputs\":[{\"internalType\":\"contract IVelo\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_voter\",\"outputs\":[{\"internalType\":\"contract IVoter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"active_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"calculate_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minted\",\"type\":\"uint256\"}],\"name\":\"calculate_growth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"claimants\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingTeam\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_teamRate\",\"type\":\"uint256\"}],\"name\":\"setTeamRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"teamRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"update_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Minter.sol\":\"Minter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Minter.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IMinter.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVelo.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\\n\\ncontract Minter is IMinter {\\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\\n uint256 internal constant EMISSION = 990;\\n uint256 internal constant TAIL_EMISSION = 2;\\n uint256 internal constant PRECISION = 1000;\\n IVelo public immutable _velo;\\n IVoter public immutable _voter;\\n IVotingEscrow public immutable _ve;\\n IRewardsDistributor public immutable _rewards_distributor;\\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\\n uint256 public active_period;\\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\\n\\n address internal initializer;\\n address public team;\\n address public pendingTeam;\\n uint256 public teamRate;\\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\\n\\n event Mint(\\n address indexed sender,\\n uint256 weekly,\\n uint256 circulating_supply,\\n uint256 circulating_emission\\n );\\n\\n constructor(\\n address __voter, // the voting & distribution system\\n address __ve, // the ve(3,3) system that will be locked into\\n address __rewards_distributor // the distribution system that ensures users aren't diluted\\n ) {\\n initializer = msg.sender;\\n team = msg.sender;\\n teamRate = 30; // 30 bps = 0.03%\\n _velo = IVelo(IVotingEscrow(__ve).token());\\n _voter = IVoter(__voter);\\n _ve = IVotingEscrow(__ve);\\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\\n }\\n\\n function initialize(\\n address[] memory claimants,\\n uint256[] memory amounts,\\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\\n ) external {\\n require(initializer == msg.sender);\\n _velo.mint(address(this), max);\\n _velo.approve(address(_ve), type(uint256).max);\\n for (uint256 i = 0; i < claimants.length; i++) {\\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\\n }\\n initializer = address(0);\\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\\n }\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team, \\\"not team\\\");\\n pendingTeam = _team;\\n }\\n\\n function acceptTeam() external {\\n require(msg.sender == pendingTeam, \\\"not pending team\\\");\\n team = pendingTeam;\\n }\\n\\n function setTeamRate(uint256 _teamRate) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(_teamRate <= MAX_TEAM_RATE, \\\"rate too high\\\");\\n teamRate = _teamRate;\\n }\\n\\n // calculate circulating supply as total token supply - locked supply\\n function circulating_supply() public view returns (uint256) {\\n return _velo.totalSupply() - _ve.totalSupply();\\n }\\n\\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\\n function calculate_emission() public view returns (uint256) {\\n return (weekly * EMISSION) / PRECISION;\\n }\\n\\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\\n function weekly_emission() public view returns (uint256) {\\n return MathDunks.max(calculate_emission(), circulating_emission());\\n }\\n\\n // calculates tail end (infinity) emissions as 0.2% of total supply\\n function circulating_emission() public view returns (uint256) {\\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\\n }\\n\\n // calculate inflation and adjust ve balances accordingly\\n function calculate_growth(uint256 _minted) public view returns (uint256) {\\n uint256 _veTotal = _ve.totalSupply();\\n uint256 _veloTotal = _velo.totalSupply();\\n return\\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\\n _veTotal) /\\n _veloTotal /\\n 2;\\n }\\n\\n // update period can only be called once per cycle (1 week)\\n function update_period() external returns (uint256) {\\n uint256 _period = active_period;\\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\\n // only trigger if new week\\n _period = (block.timestamp / WEEK) * WEEK;\\n active_period = _period;\\n weekly = weekly_emission();\\n\\n uint256 _growth = calculate_growth(weekly);\\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\\n (PRECISION - teamRate);\\n uint256 _required = _growth + weekly + _teamEmissions;\\n uint256 _balanceOf = _velo.balanceOf(address(this));\\n if (_balanceOf < _required) {\\n _velo.mint(address(this), _required - _balanceOf);\\n }\\n\\n require(_velo.transfer(team, _teamEmissions));\\n require(_velo.transfer(address(_rewards_distributor), _growth));\\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\\n\\n _velo.approve(address(_voter), weekly);\\n _voter.notifyRewardAmount(weekly);\\n\\n emit Mint(\\n msg.sender,\\n weekly,\\n circulating_supply(),\\n circulating_emission()\\n );\\n }\\n return _period;\\n }\\n}\\n\",\"keccak256\":\"0x8dce50c09815e53982006f9ddc46cd52cf7ac86b0c1b7bb15c817f86fb990580\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x6101006040526a0c685fa11e01ec6f0000006000553480156200002157600080fd5b506040516200158938038062001589833981016040819052620000449162000156565b60028054336001600160a01b03199182168117909255600380549091169091179055601e60055560408051637e062a3560e11b815290516001600160a01b0384169163fc0c546a9160048083019260209291908290030181865afa158015620000b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d79190620001a0565b6001600160a01b0390811660805283811660a05282811660c052811660e05262093a808062000108816002620001db565b620001149042620001fd565b62000120919062000218565b6200012c9190620001db565b600155506200023b915050565b80516001600160a01b03811681146200015157600080fd5b919050565b6000806000606084860312156200016c57600080fd5b620001778462000139565b9250620001876020850162000139565b9150620001976040850162000139565b90509250925092565b600060208284031215620001b357600080fd5b620001be8262000139565b9392505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620001f857620001f8620001c5565b500290565b60008219821115620002135762000213620001c5565b500190565b6000826200023657634e487b7160e01b600052601260045260246000fd5b500490565b60805160a05160c05160e051611296620002f3600039600081816101f801528181610c3701528181610cde0152610d51015260008181610261015281816104b30152818161055f0152818161068901526108750152600081816101d101528181610e090152610ea301526000818161015101528181610426015281816104e30152818161070f015281816108f701528181610a5f01528181610ade01528181610ba801528181610c660152610dda01526112966000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c806378ef7f02116100ad578063b5cc143a11610071578063b5cc143a14610296578063cfc6c8ff1461029e578063d1399608146102a6578063e038c75a146102af578063ed29fc11146102b757600080fd5b806378ef7f021461022d578063851708131461023657806385f2aef2146102495780638dd598fb1461025c5780638e01fbfa1461028357600080fd5b80632e8f7b1f116100f45780632e8f7b1f146101b157806336d96faf146101c45780633db9b42a146101cc5780634b1cd5da146101f357806359d46ffc1461021a57600080fd5b806301c8e6fd1461013157806308aa44581461014c578063095cf5c61461018b5780631eebae80146101a057806326cfc17b146101a8575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b61019e610199366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61019e6101bf366004610fb8565b610353565b6101396103de565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b600454610173906001600160a01b031681565b61013960055481565b61019e6102443660046110a7565b6103f3565b600354610173906001600160a01b031681565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b610139610291366004610fb8565b610684565b61019e6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea2646970667358221220b8d7ed6a52e73b73f97d46da03043d96cda8f93d690887652d48bca060b4064c64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c806378ef7f02116100ad578063b5cc143a11610071578063b5cc143a14610296578063cfc6c8ff1461029e578063d1399608146102a6578063e038c75a146102af578063ed29fc11146102b757600080fd5b806378ef7f021461022d578063851708131461023657806385f2aef2146102495780638dd598fb1461025c5780638e01fbfa1461028357600080fd5b80632e8f7b1f116100f45780632e8f7b1f146101b157806336d96faf146101c45780633db9b42a146101cc5780634b1cd5da146101f357806359d46ffc1461021a57600080fd5b806301c8e6fd1461013157806308aa44581461014c578063095cf5c61461018b5780631eebae80146101a057806326cfc17b146101a8575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b61019e610199366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61019e6101bf366004610fb8565b610353565b6101396103de565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b600454610173906001600160a01b031681565b61013960055481565b61019e6102443660046110a7565b6103f3565b600354610173906001600160a01b031681565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b610139610291366004610fb8565b610684565b61019e6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea2646970667358221220b8d7ed6a52e73b73f97d46da03043d96cda8f93d690887652d48bca060b4064c64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 6187, + "contract": "contracts/Minter.sol:Minter", + "label": "weekly", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 6189, + "contract": "contracts/Minter.sol:Minter", + "label": "active_period", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 6200, + "contract": "contracts/Minter.sol:Minter", + "label": "initializer", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 6202, + "contract": "contracts/Minter.sol:Minter", + "label": "team", + "offset": 0, + "slot": "3", + "type": "t_address" + }, + { + "astId": 6204, + "contract": "contracts/Minter.sol:Minter", + "label": "pendingTeam", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 6206, + "contract": "contracts/Minter.sol:Minter", + "label": "teamRate", + "offset": 0, + "slot": "5", + "type": "t_uint256" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/PairFactory.json b/deployments/arbitrumGoerli/PairFactory.json new file mode 100644 index 00000000..5c3520ca --- /dev/null +++ b/deployments/arbitrumGoerli/PairFactory.json @@ -0,0 +1,577 @@ +{ + "address": "0x7488AC81DC3908ff7141db4949e70D60A3Fd4DCc", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token0", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token1", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "indexed": false, + "internalType": "address", + "name": "pair", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "PairCreated", + "type": "event" + }, + { + "inputs": [], + "name": "MAX_FEE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptFeeManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "acceptPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allPairs", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPairsLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "createPair", + "outputs": [ + { + "internalType": "address", + "name": "pair", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "feeManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_stable", + "type": "bool" + } + ], + "name": "getFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getInitializable", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "name": "getPair", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isPair", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pairCodeHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "pauser", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingFeeManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingPauser", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "_fee", + "type": "uint256" + } + ], + "name": "setFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_feeManager", + "type": "address" + } + ], + "name": "setFeeManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_state", + "type": "bool" + } + ], + "name": "setPause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_pauser", + "type": "address" + } + ], + "name": "setPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "stableFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "volatileFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x98cd8764878aad721b508178f237c66ef70ffc56d18d009975ad54885dc71634", + "receipt": { + "to": null, + "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", + "contractAddress": "0x7488AC81DC3908ff7141db4949e70D60A3Fd4DCc", + "transactionIndex": 1, + "gasUsed": "43959185", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc5644de2951e89db8815c7bf22743e0529f1da7d9a31cd2ccaabe00e1e883c55", + "transactionHash": "0x98cd8764878aad721b508178f237c66ef70ffc56d18d009975ad54885dc71634", + "logs": [], + "blockNumber": 4195009, + "cumulativeGasUsed": "43959185", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 5, + "solcInputHash": "0faaa79d8b79020b765ba7705413c447", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"PairCreated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_FEE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allPairs\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"allPairsLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"createPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getInitializable\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"name\":\"getPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pairCodeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingFeeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingPauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_feeManager\",\"type\":\"address\"}],\"name\":\"setFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_state\",\"type\":\"bool\"}],\"name\":\"setPause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pauser\",\"type\":\"address\"}],\"name\":\"setPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stableFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"volatileFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/PairFactory.sol\":\"PairFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Pair.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairCallee.sol\\\";\\nimport \\\"contracts/factories/PairFactory.sol\\\";\\nimport \\\"contracts/PairFees.sol\\\";\\n\\n// The base pair of pools, either stable or volatile\\ncontract Pair is IPair {\\n string public name;\\n string public symbol;\\n uint8 public constant decimals = 18;\\n\\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\\n bool public immutable stable;\\n\\n uint256 public totalSupply = 0;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n mapping(address => uint256) public balanceOf;\\n\\n bytes32 internal DOMAIN_SEPARATOR;\\n // keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 internal constant PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n mapping(address => uint256) public nonces;\\n\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n\\n address public immutable token0;\\n address public immutable token1;\\n address public immutable fees;\\n address immutable factory;\\n\\n // Structure to capture time period obervations every 30 minutes, used for local oracles\\n struct Observation {\\n uint256 timestamp;\\n uint256 reserve0Cumulative;\\n uint256 reserve1Cumulative;\\n }\\n\\n // Capture oracle reading every 30 minutes\\n uint256 constant periodSize = 1800;\\n\\n Observation[] public observations;\\n\\n uint256 internal immutable decimals0;\\n uint256 internal immutable decimals1;\\n\\n uint256 public reserve0;\\n uint256 public reserve1;\\n uint256 public blockTimestampLast;\\n\\n uint256 public reserve0CumulativeLast;\\n uint256 public reserve1CumulativeLast;\\n\\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \\\"clean\\\"\\n // this further allows LP holders to easily claim fees for tokens they have/staked\\n uint256 public index0 = 0;\\n uint256 public index1 = 0;\\n\\n // position assigned to each LP to track their current index0 & index1 vs the global position\\n mapping(address => uint256) public supplyIndex0;\\n mapping(address => uint256) public supplyIndex1;\\n\\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\\n mapping(address => uint256) public claimable0;\\n mapping(address => uint256) public claimable1;\\n\\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\\n event Burn(\\n address indexed sender,\\n uint256 amount0,\\n uint256 amount1,\\n address indexed to\\n );\\n event Swap(\\n address indexed sender,\\n uint256 amount0In,\\n uint256 amount1In,\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address indexed to\\n );\\n event Sync(uint256 reserve0, uint256 reserve1);\\n event Claim(\\n address indexed sender,\\n address indexed recipient,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 amount\\n );\\n\\n constructor() {\\n factory = msg.sender;\\n (address _token0, address _token1, bool _stable) = PairFactory(\\n msg.sender\\n ).getInitializable();\\n (token0, token1, stable) = (_token0, _token1, _stable);\\n fees = address(new PairFees(_token0, _token1));\\n if (_stable) {\\n name = string(\\n abi.encodePacked(\\n \\\"StableV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"sAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n } else {\\n name = string(\\n abi.encodePacked(\\n \\\"VolatileV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"vAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n }\\n\\n decimals0 = 10**IERC20(_token0).decimals();\\n decimals1 = 10**IERC20(_token1).decimals();\\n\\n observations.push(Observation(block.timestamp, 0, 0));\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function observationLength() external view returns (uint256) {\\n return observations.length;\\n }\\n\\n function lastObservation() public view returns (Observation memory) {\\n return observations[observations.length - 1];\\n }\\n\\n function metadata()\\n external\\n view\\n returns (\\n uint256 dec0,\\n uint256 dec1,\\n uint256 r0,\\n uint256 r1,\\n bool st,\\n address t0,\\n address t1\\n )\\n {\\n return (\\n decimals0,\\n decimals1,\\n reserve0,\\n reserve1,\\n stable,\\n token0,\\n token1\\n );\\n }\\n\\n function tokens() external view returns (address, address) {\\n return (token0, token1);\\n }\\n\\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\\n _updateFor(msg.sender);\\n\\n claimed0 = claimable0[msg.sender];\\n claimed1 = claimable1[msg.sender];\\n\\n if (claimed0 > 0 || claimed1 > 0) {\\n claimable0[msg.sender] = 0;\\n claimable1[msg.sender] = 0;\\n\\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\\n\\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n // Accrue fees on token0\\n function _update0(uint256 amount) internal {\\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index0 += _ratio;\\n }\\n emit Fees(msg.sender, amount, 0);\\n }\\n\\n // Accrue fees on token1\\n function _update1(uint256 amount) internal {\\n _safeTransfer(token1, fees, amount);\\n uint256 _ratio = (amount * 1e18) / totalSupply;\\n if (_ratio > 0) {\\n index1 += _ratio;\\n }\\n emit Fees(msg.sender, 0, amount);\\n }\\n\\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\\n // Fees are segregated from core funds, so fees can never put liquidity at risk\\n function _updateFor(address recipient) internal {\\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\\n if (_supplied > 0) {\\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\\n uint256 _supplyIndex1 = supplyIndex1[recipient];\\n uint256 _index0 = index0; // get global index0 for accumulated fees\\n uint256 _index1 = index1;\\n supplyIndex0[recipient] = _index0; // update user current position to global position\\n supplyIndex1[recipient] = _index1;\\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\\n uint256 _delta1 = _index1 - _supplyIndex1;\\n if (_delta0 > 0) {\\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\\n claimable0[recipient] += _share;\\n }\\n if (_delta1 > 0) {\\n uint256 _share = (_supplied * _delta1) / 1e18;\\n claimable1[recipient] += _share;\\n }\\n } else {\\n supplyIndex0[recipient] = index0; // new users are set to the default global state\\n supplyIndex1[recipient] = index1;\\n }\\n }\\n\\n function getReserves()\\n public\\n view\\n returns (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n )\\n {\\n _reserve0 = reserve0;\\n _reserve1 = reserve1;\\n _blockTimestampLast = blockTimestampLast;\\n }\\n\\n // update reserves and, on the first call per block, price accumulators\\n function _update(\\n uint256 balance0,\\n uint256 balance1,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal {\\n uint256 blockTimestamp = block.timestamp;\\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\\n reserve0CumulativeLast += _reserve0 * timeElapsed;\\n reserve1CumulativeLast += _reserve1 * timeElapsed;\\n }\\n\\n Observation memory _point = lastObservation();\\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\\n if (timeElapsed > periodSize) {\\n observations.push(\\n Observation(\\n blockTimestamp,\\n reserve0CumulativeLast,\\n reserve1CumulativeLast\\n )\\n );\\n }\\n reserve0 = balance0;\\n reserve1 = balance1;\\n blockTimestampLast = blockTimestamp;\\n emit Sync(reserve0, reserve1);\\n }\\n\\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\\n function currentCumulativePrices()\\n public\\n view\\n returns (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n uint256 blockTimestamp\\n )\\n {\\n blockTimestamp = block.timestamp;\\n reserve0Cumulative = reserve0CumulativeLast;\\n reserve1Cumulative = reserve1CumulativeLast;\\n\\n // if time has elapsed since the last update on the pair, mock the accumulated price values\\n (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n ) = getReserves();\\n if (_blockTimestampLast != blockTimestamp) {\\n // subtraction overflow is desired\\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\\n reserve0Cumulative += _reserve0 * timeElapsed;\\n reserve1Cumulative += _reserve1 * timeElapsed;\\n }\\n }\\n\\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\\n function current(address tokenIn, uint256 amountIn)\\n external\\n view\\n returns (uint256 amountOut)\\n {\\n Observation memory _observation = lastObservation();\\n (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n\\n ) = currentCumulativePrices();\\n if (block.timestamp == _observation.timestamp) {\\n _observation = observations[observations.length - 2];\\n }\\n\\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\\n uint256 _reserve0 = (reserve0Cumulative -\\n _observation.reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (reserve1Cumulative -\\n _observation.reserve1Cumulative) / timeElapsed;\\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n // as per `current`, however allows user configured granularity, up to the full window size\\n function quote(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 granularity\\n ) external view returns (uint256 amountOut) {\\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\\n uint256 priceAverageCumulative;\\n for (uint256 i = 0; i < _prices.length; i++) {\\n priceAverageCumulative += _prices[i];\\n }\\n return priceAverageCumulative / granularity;\\n }\\n\\n // returns a memory set of twap prices\\n function prices(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points\\n ) external view returns (uint256[] memory) {\\n return sample(tokenIn, amountIn, points, 1);\\n }\\n\\n function sample(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points,\\n uint256 window\\n ) public view returns (uint256[] memory) {\\n uint256[] memory _prices = new uint256[](points);\\n\\n uint256 length = observations.length - 1;\\n uint256 i = length - (points * window);\\n uint256 nextIndex = 0;\\n uint256 index = 0;\\n\\n for (; i < length; i += window) {\\n nextIndex = i + window;\\n uint256 timeElapsed = observations[nextIndex].timestamp -\\n observations[i].timestamp;\\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\\n observations[i].reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\\n observations[i].reserve1Cumulative) / timeElapsed;\\n _prices[index] = _getAmountOut(\\n amountIn,\\n tokenIn,\\n _reserve0,\\n _reserve1\\n );\\n // index < length; length cannot overflow\\n unchecked {\\n index = index + 1;\\n }\\n }\\n return _prices;\\n }\\n\\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\\n // standard uniswap v2 implementation\\n function mint(address to) external lock returns (uint256 liquidity) {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\\n uint256 _amount0 = _balance0 - _reserve0;\\n uint256 _amount1 = _balance1 - _reserve1;\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n if (_totalSupply == 0) {\\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\\n } else {\\n liquidity = MathDunks.min(\\n (_amount0 * _totalSupply) / _reserve0,\\n (_amount1 * _totalSupply) / _reserve1\\n );\\n }\\n require(liquidity > 0, \\\"ILM\\\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\\n _mint(to, liquidity);\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Mint(msg.sender, _amount0, _amount1);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n // standard uniswap v2 implementation\\n function burn(address to)\\n external\\n lock\\n returns (uint256 amount0, uint256 amount1)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n (address _token0, address _token1) = (token0, token1);\\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\\n uint256 _liquidity = balanceOf[address(this)];\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\\n require(amount0 > 0 && amount1 > 0, \\\"ILB\\\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\\n _burn(address(this), _liquidity);\\n _safeTransfer(_token0, to, amount0);\\n _safeTransfer(_token1, to, amount1);\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Burn(msg.sender, amount0, amount1, to);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n function swap(\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address to,\\n bytes calldata data\\n ) external lock {\\n require(!PairFactory(factory).isPaused());\\n require(amount0Out > 0 || amount1Out > 0, \\\"IOA\\\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \\\"IL\\\"); // Pair: INSUFFICIENT_LIQUIDITY\\n\\n uint256 _balance0;\\n uint256 _balance1;\\n {\\n // scope for _token{0,1}, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n require(to != _token0 && to != _token1, \\\"IT\\\"); // Pair: INVALID_TO\\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\\n if (data.length > 0)\\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n }\\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\\n ? _balance0 - (_reserve0 - amount0Out)\\n : 0;\\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\\n ? _balance1 - (_reserve1 - amount1Out)\\n : 0;\\n require(amount0In > 0 || amount1In > 0, \\\"IIA\\\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\\n {\\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n if (amount0In > 0)\\n _update0(\\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token0 and move them out of pool\\n if (amount1In > 0)\\n _update1(\\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token1 and move them out of pool\\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \\\"K\\\"); // Pair: K\\n }\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\\n }\\n\\n // force balances to match reserves\\n function skim(address to) external lock {\\n (address _token0, address _token1) = (token0, token1);\\n _safeTransfer(\\n _token0,\\n to,\\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\\n );\\n _safeTransfer(\\n _token1,\\n to,\\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\\n );\\n }\\n\\n // force reserves to match balances\\n function sync() external lock {\\n _update(\\n IERC20(token0).balanceOf(address(this)),\\n IERC20(token1).balanceOf(address(this)),\\n reserve0,\\n reserve1\\n );\\n }\\n\\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\\n 1e18 +\\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\\n 1e18;\\n }\\n\\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (3 * x0 * ((y * y) / 1e18)) /\\n 1e18 +\\n ((((x0 * x0) / 1e18) * x0) / 1e18);\\n }\\n\\n function _get_y(\\n uint256 x0,\\n uint256 xy,\\n uint256 y\\n ) internal pure returns (uint256) {\\n for (uint256 i = 0; i < 255; i++) {\\n uint256 y_prev = y;\\n uint256 k = _f(x0, y);\\n if (k < xy) {\\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\\n y = y + dy;\\n } else {\\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getAmountOut(uint256 amountIn, address tokenIn)\\n external\\n view\\n returns (uint256)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n function _getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal view returns (uint256) {\\n if (stable) {\\n uint256 xy = _k(_reserve0, _reserve1);\\n _reserve0 = (_reserve0 * 1e18) / decimals0;\\n _reserve1 = (_reserve1 * 1e18) / decimals1;\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0\\n ? (amountIn * 1e18) / decimals0\\n : (amountIn * 1e18) / decimals1;\\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\\n } else {\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n return (amountIn * reserveB) / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\\n if (stable) {\\n uint256 _x = (x * 1e18) / decimals0;\\n uint256 _y = (y * 1e18) / decimals1;\\n uint256 _a = (_x * _y) / 1e18;\\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return (_a * _b) / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n\\n function _mint(address dst, uint256 amount) internal {\\n _updateFor(dst); // balances must be updated on mint/burn/transfer\\n totalSupply += amount;\\n balanceOf[dst] += amount;\\n emit Transfer(address(0), dst, amount);\\n }\\n\\n function _burn(address dst, uint256 amount) internal {\\n _updateFor(dst);\\n totalSupply -= amount;\\n balanceOf[dst] -= amount;\\n emit Transfer(dst, address(0), amount);\\n }\\n\\n function approve(address spender, uint256 amount) external returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external {\\n require(deadline >= block.timestamp, \\\"Pair: EXPIRED\\\");\\n DOMAIN_SEPARATOR = keccak256(\\n abi.encode(\\n keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n ),\\n keccak256(bytes(name)),\\n keccak256(bytes(\\\"1\\\")),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR,\\n keccak256(\\n abi.encode(\\n PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n );\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n require(\\n recoveredAddress != address(0) && recoveredAddress == owner,\\n \\\"Pair: INVALID_SIGNATURE\\\"\\n );\\n allowance[owner][spender] = value;\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function transfer(address dst, uint256 amount) external returns (bool) {\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 amount\\n ) external returns (bool) {\\n address spender = msg.sender;\\n uint256 spenderAllowance = allowance[src][spender];\\n\\n if (spender != src && spenderAllowance != type(uint256).max) {\\n uint256 newAllowance = spenderAllowance - amount;\\n allowance[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n function _transferTokens(\\n address src,\\n address dst,\\n uint256 amount\\n ) internal {\\n _updateFor(src); // update fee position for src\\n _updateFor(dst); // update fee position for dst\\n\\n balanceOf[src] -= amount;\\n balanceOf[dst] += amount;\\n\\n emit Transfer(src, dst, amount);\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x4f508747645f4480e0b0f23d952fa9b82af1d9bc60b15b8cd1f542ee136043d1\",\"license\":\"MIT\"},\"contracts/PairFees.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IERC20.sol';\\n\\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\\ncontract PairFees {\\n\\n address internal immutable pair; // The pair it is bonded to\\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\\n\\n constructor(address _token0, address _token1) {\\n pair = msg.sender;\\n token0 = _token0;\\n token1 = _token1;\\n }\\n\\n function _safeTransfer(address token,address to,uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n // Allow the pair to transfer fees to users\\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\\n require(msg.sender == pair);\\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\\n }\\n\\n}\\n\",\"keccak256\":\"0xb772e192bab353f8642e89a95ef4ef0255d1caef08444101d7fe34469c1000ca\",\"license\":\"MIT\"},\"contracts/factories/PairFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/Pair.sol';\\n\\ncontract PairFactory is IPairFactory {\\n\\n bool public isPaused;\\n address public pauser;\\n address public pendingPauser;\\n\\n uint256 public stableFee;\\n uint256 public volatileFee;\\n uint256 public constant MAX_FEE = 5; // 0.05%\\n address public feeManager;\\n address public pendingFeeManager;\\n\\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\\n address[] public allPairs;\\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\\n\\n address internal _temp0;\\n address internal _temp1;\\n bool internal _temp;\\n\\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\\n\\n constructor() {\\n pauser = msg.sender;\\n isPaused = false;\\n feeManager = msg.sender;\\n stableFee = 2; // 0.02%\\n volatileFee = 2;\\n }\\n\\n function allPairsLength() external view returns (uint) {\\n return allPairs.length;\\n }\\n\\n function setPauser(address _pauser) external {\\n require(msg.sender == pauser);\\n pendingPauser = _pauser;\\n }\\n\\n function acceptPauser() external {\\n require(msg.sender == pendingPauser);\\n pauser = pendingPauser;\\n }\\n\\n function setPause(bool _state) external {\\n require(msg.sender == pauser);\\n isPaused = _state;\\n }\\n\\n function setFeeManager(address _feeManager) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n pendingFeeManager = _feeManager;\\n }\\n\\n function acceptFeeManager() external {\\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\\n feeManager = pendingFeeManager;\\n }\\n\\n function setFee(bool _stable, uint256 _fee) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n require(_fee <= MAX_FEE, 'fee too high');\\n require(_fee != 0, 'fee must be nonzero');\\n if (_stable) {\\n stableFee = _fee;\\n } else {\\n volatileFee = _fee;\\n }\\n }\\n\\n function getFee(bool _stable) public view returns(uint256) {\\n return _stable ? stableFee : volatileFee;\\n }\\n\\n function pairCodeHash() external pure returns (bytes32) {\\n return keccak256(type(Pair).creationCode);\\n }\\n\\n function getInitializable() external view returns (address, address, bool) {\\n return (_temp0, _temp1, _temp);\\n }\\n\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\\n (_temp0, _temp1, _temp) = (token0, token1, stable);\\n pair = address(new Pair{salt:salt}());\\n getPair[token0][token1][stable] = pair;\\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\\n allPairs.push(pair);\\n isPair[pair] = true;\\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\\n }\\n}\\n\",\"keccak256\":\"0x9b7984117a5a32188aa9ddf42b6cff024240579ab30f3776f7a201285d813e4f\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairCallee.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairCallee {\\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x3ac2de2c7a08bf59fd1006e4d108b247916369de15fbd048b72ca2b7814023ca\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50600080546001600160a81b03191633610100810260ff1916919091178255600480546001600160a01b0319169091179055600280805560035561519190819061005a90396000f3fe60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea26469706673582212208b453bc7549999ab5f900d35221afe3ea71f11a1ef126003a17f9e83cda073b764736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea2646970667358221220a0e5d8be5a804858df78ae47f8fc2a744df9f79fa1277638415ca361262d388d64736f6c634300080d0033a2646970667358221220f746ba6d1ae747d9562e9ee216fb7ac76a7c799b9e95dff2eb578c8d39a9912864736f6c634300080d0033", + "deployedBytecode": "0x60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea26469706673582212208b453bc7549999ab5f900d35221afe3ea71f11a1ef126003a17f9e83cda073b764736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea2646970667358221220a0e5d8be5a804858df78ae47f8fc2a744df9f79fa1277638415ca361262d388d64736f6c634300080d0033a2646970667358221220f746ba6d1ae747d9562e9ee216fb7ac76a7c799b9e95dff2eb578c8d39a9912864736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 21428, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "isPaused", + "offset": 0, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 21430, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "pauser", + "offset": 1, + "slot": "0", + "type": "t_address" + }, + { + "astId": 21432, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "pendingPauser", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 21434, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "stableFee", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 21436, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "volatileFee", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 21441, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "feeManager", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 21443, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "pendingFeeManager", + "offset": 0, + "slot": "5", + "type": "t_address" + }, + { + "astId": 21451, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "getPair", + "offset": 0, + "slot": "6", + "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_bool,t_address)))" + }, + { + "astId": 21454, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "allPairs", + "offset": 0, + "slot": "7", + "type": "t_array(t_address)dyn_storage" + }, + { + "astId": 21458, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "isPair", + "offset": 0, + "slot": "8", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 21460, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "_temp0", + "offset": 0, + "slot": "9", + "type": "t_address" + }, + { + "astId": 21462, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "_temp1", + "offset": 0, + "slot": "10", + "type": "t_address" + }, + { + "astId": 21464, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "_temp", + "offset": 20, + "slot": "10", + "type": "t_bool" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "base": "t_address", + "encoding": "dynamic_array", + "label": "address[]", + "numberOfBytes": "32" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_address,t_mapping(t_address,t_mapping(t_bool,t_address)))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => mapping(bool => address)))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_mapping(t_bool,t_address))" + }, + "t_mapping(t_address,t_mapping(t_bool,t_address))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(bool => address))", + "numberOfBytes": "32", + "value": "t_mapping(t_bool,t_address)" + }, + "t_mapping(t_bool,t_address)": { + "encoding": "mapping", + "key": "t_bool", + "label": "mapping(bool => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/RedemptionReceiver.json b/deployments/arbitrumGoerli/RedemptionReceiver.json new file mode 100644 index 00000000..85b51c2b --- /dev/null +++ b/deployments/arbitrumGoerli/RedemptionReceiver.json @@ -0,0 +1,428 @@ +{ + "address": "0x08e352f2130d4b68d7B1264CD42191205B61b60f", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_usdc", + "type": "address" + }, + { + "internalType": "address", + "name": "_velo", + "type": "address" + }, + { + "internalType": "uint16", + "name": "_fantomChainId", + "type": "uint16" + }, + { + "internalType": "address", + "name": "_endpoint", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "fantomSender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemableUSDC", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemableVELO", + "type": "uint256" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "inputs": [], + "name": "ELIGIBLE_WEVE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "USDC", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VELO", + "outputs": [ + { + "internalType": "contract IVelo", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "toAddressBytes", + "type": "bytes" + } + ], + "name": "addressFromPackedBytes", + "outputs": [ + { + "internalType": "address", + "name": "toAddress", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "claimLeftovers", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "deployed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "endpoint", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "fantomChainId", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "fantomSender", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_fantomSender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_redeemableUSDC", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_redeemableVELO", + "type": "uint256" + } + ], + "name": "initializeReceiverWith", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "leftoverVELO", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "srcChainId", + "type": "uint16" + }, + { + "internalType": "bytes", + "name": "srcAddress", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "lzReceive", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountWEVE", + "type": "uint256" + } + ], + "name": "previewRedeem", + "outputs": [ + { + "internalType": "uint256", + "name": "shareOfUSDC", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "shareOfVELO", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "redeemableUSDC", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "redeemableVELO", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "redeemedWEVE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_team", + "type": "address" + } + ], + "name": "setTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "team", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xf3acdd7467b958f2cfdef54cb5014fe6decea05a26c06c15f2ff9c5b519f2d18", + "receipt": { + "to": null, + "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", + "contractAddress": "0x08e352f2130d4b68d7B1264CD42191205B61b60f", + "transactionIndex": 1, + "gasUsed": "9877695", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xfb4dfca6f15c0239ae6fd9048744b536edfd666421a9c22a7f2a18ec92fa104d", + "transactionHash": "0xf3acdd7467b958f2cfdef54cb5014fe6decea05a26c06c15f2ff9c5b519f2d18", + "logs": [], + "blockNumber": 4195038, + "cumulativeGasUsed": "9877695", + "status": 1, + "byzantium": true + }, + "args": [ + "0x7F5c764cBc14f9669B88837ca1490cCa17c31607", + "0xe69b00A164047e7eB87B73971B0f340eEbFF9c81", + 10012, + "0x3c2269811836af69497E5F486A85D7316753cf62" + ], + "numDeployments": 3, + "solcInputHash": "0faaa79d8b79020b765ba7705413c447", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_usdc\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_velo\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"_fantomChainId\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"_endpoint\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fantomSender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableUSDC\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableVELO\",\"type\":\"uint256\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ELIGIBLE_WEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"USDC\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VELO\",\"outputs\":[{\"internalType\":\"contract IVelo\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"toAddressBytes\",\"type\":\"bytes\"}],\"name\":\"addressFromPackedBytes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimLeftovers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endpoint\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomChainId\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_fantomSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableVELO\",\"type\":\"uint256\"}],\"name\":\"initializeReceiverWith\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"leftoverVELO\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"srcChainId\",\"type\":\"uint16\"},{\"internalType\":\"bytes\",\"name\":\"srcAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"lzReceive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountWEVE\",\"type\":\"uint256\"}],\"name\":\"previewRedeem\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"shareOfUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shareOfVELO\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableUSDC\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableVELO\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemedWEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process This contract is responsible for receiving the LZ message and distributing USDC + VELO\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/RedemptionReceiver.sol\":\"RedemptionReceiver\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"},\"contracts/redeem/RedemptionReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\\\";\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IVelo.sol\\\";\\n\\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\\ncontract RedemptionReceiver is ILayerZeroReceiver {\\n IERC20 public immutable USDC;\\n IVelo public immutable VELO;\\n\\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\\n address public immutable endpoint;\\n\\n address public team;\\n uint256 public immutable deployed;\\n\\n address public fantomSender;\\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\\n uint256 public redeemedWEVE;\\n uint256 public redeemableUSDC;\\n uint256 public redeemableVELO;\\n uint256 public leftoverVELO;\\n\\n constructor(\\n address _usdc,\\n address _velo,\\n uint16 _fantomChainId,\\n address _endpoint\\n ) {\\n require(_fantomChainId == 12 || _fantomChainId == 10012, \\\"CHAIN_ID_NOT_FTM\\\");\\n\\n USDC = IERC20(_usdc);\\n VELO = IVelo(_velo);\\n\\n fantomChainId = _fantomChainId;\\n endpoint = _endpoint;\\n\\n team = msg.sender;\\n deployed = block.timestamp;\\n }\\n\\n modifier onlyTeam() {\\n require(msg.sender == team, \\\"ONLY_TEAM\\\");\\n _;\\n }\\n\\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\\n\\n function initializeReceiverWith(\\n address _fantomSender,\\n uint256 _redeemableUSDC,\\n uint256 _redeemableVELO\\n ) external onlyTeam {\\n require(fantomSender == address(0), \\\"ALREADY_INITIALIZED\\\");\\n require(\\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n fantomSender = _fantomSender;\\n redeemableUSDC = _redeemableUSDC;\\n redeemableVELO = _redeemableVELO;\\n leftoverVELO = _redeemableVELO;\\n\\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\\n }\\n\\n function setTeam(address _team) external onlyTeam {\\n team = _team;\\n }\\n\\n function previewRedeem(uint256 amountWEVE)\\n public\\n view\\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\\n {\\n // pro rata USDC\\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\\n // pro rata VELO\\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\\n }\\n\\n function lzReceive(\\n uint16 srcChainId,\\n bytes memory srcAddress,\\n uint64,\\n bytes memory payload\\n ) external override {\\n require(fantomSender != address(0), \\\"NOT_INITIALIZED\\\");\\n require(\\n msg.sender == endpoint &&\\n srcChainId == fantomChainId &&\\n addressFromPackedBytes(srcAddress) == fantomSender,\\n \\\"UNAUTHORIZED_CALLER\\\"\\n );\\n\\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\\n payload,\\n (address, uint256)\\n );\\n\\n require(\\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\\n \\\"cannot redeem more than eligible\\\"\\n );\\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\\n\\n require(\\n USDC.transfer(redemptionAddress, shareOfUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n leftoverVELO -= shareOfVELO; // this will revert if underflows\\n require(\\n VELO.claim(redemptionAddress, shareOfVELO),\\n \\\"CLAIM_FAILED\\\"\\n );\\n }\\n\\n function addressFromPackedBytes(bytes memory toAddressBytes)\\n public\\n pure\\n returns (address toAddress)\\n {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n toAddress := mload(add(toAddressBytes, 20))\\n }\\n }\\n\\n function claimLeftovers() external onlyTeam {\\n require(block.timestamp >= deployed + 30 days, \\\"LEFTOVERS_NOT_CLAIMABLE\\\");\\n require(\\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n }\\n}\\n\",\"keccak256\":\"0xb5c76f083e5076206e2713b64eed8bfc782715c19f6993ac8e97b1db898ae304\",\"license\":\"MIT\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\nimport \\\"./ILayerZeroUserApplicationConfig.sol\\\";\\n\\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\\n // @param _dstChainId - the destination chain identifier\\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\\n // @param _payload - a custom bytes payload to send to the destination contract\\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\\n\\n // @notice used by the messaging library to publish verified payload\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source contract (as bytes) at the source chain\\n // @param _dstAddress - the address on destination chain\\n // @param _nonce - the unbound message ordering nonce\\n // @param _gasLimit - the gas limit for external contract execution\\n // @param _payload - verified payload to send to the destination contract\\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\\n\\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\\n\\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\\n // @param _srcAddress - the source chain contract address\\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\\n\\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\\n // @param _dstChainId - the destination chain identifier\\n // @param _userApplication - the user app address on this EVM chain\\n // @param _payload - the custom message to send over LayerZero\\n // @param _payInZRO - if false, user app pays the protocol fee in native token\\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\\n\\n // @notice get this Endpoint's immutable source identifier\\n function getChainId() external view returns (uint16);\\n\\n // @notice the interface to retry failed message on this Endpoint destination\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n // @param _payload - the payload to be retried\\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\\n\\n // @notice query if any STORED payload (message blocking) at the endpoint.\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\\n\\n // @notice query if the _libraryAddress is valid for sending msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getSendLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the _libraryAddress is valid for receiving msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the non-reentrancy guard for send() is on\\n // @return true if the guard is on. false otherwise\\n function isSendingPayload() external view returns (bool);\\n\\n // @notice query if the non-reentrancy guard for receive() is on\\n // @return true if the guard is on. false otherwise\\n function isReceivingPayload() external view returns (bool);\\n\\n // @notice get the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _userApplication - the contract address of the user application\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\\n\\n // @notice get the send() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getSendVersion(address _userApplication) external view returns (uint16);\\n\\n // @notice get the lzReceive() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getReceiveVersion(address _userApplication) external view returns (uint16);\\n}\\n\",\"keccak256\":\"0xbc2e0022d4d53d136830aa90037be2ed7a0966f5fd1b409bf5986185984c495f\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroReceiver {\\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\\n // @param _srcChainId - the source endpoint identifier\\n // @param _srcAddress - the source sending contract address from the source chain\\n // @param _nonce - the ordered message nonce\\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\\n}\\n\",\"keccak256\":\"0xd1617e455d90d41556bba636bc440627d301ec481de16ff04fbd520333c3c6f3\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroUserApplicationConfig {\\n // @notice set the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n // @param _config - configuration in the bytes. can encode arbitrary content.\\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\\n\\n // @notice set the send() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setSendVersion(uint16 _version) external;\\n\\n // @notice set the lzReceive() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setReceiveVersion(uint16 _version) external;\\n\\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\\n // @param _srcChainId - the chainId of the source chain\\n // @param _srcAddress - the contract address of the source contract at the source chain\\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\\n}\\n\",\"keccak256\":\"0xdc7e072cf3064081a8edf4a286ca43ddecc24330f2923d96f416f9d3f6538447\",\"license\":\"BUSL-1.1\"}},\"version\":1}", + "bytecode": "0x61012060405234801561001157600080fd5b50604051610f81380380610f81833981016040819052610030916100e2565b8161ffff16600c148061004857508161ffff1661271c145b61008b5760405162461bcd60e51b815260206004820152601060248201526f434841494e5f49445f4e4f545f46544d60801b604482015260640160405180910390fd5b6001600160a01b0393841660805291831660a05261ffff1660c0521660e052600080546001600160a01b03191633179055426101005261013f565b80516001600160a01b03811681146100dd57600080fd5b919050565b600080600080608085870312156100f857600080fd5b610101856100c6565b935061010f602086016100c6565b9250604085015161ffff8116811461012657600080fd5b9150610134606086016100c6565b905092959194509250565b60805160a05160c05160e05161010051610dcd6101b4600039600081816102d601526108c00152600081816101940152610352015260008181610245015261037c01526000818161027f015261059f01526000818161021e015281816104d70152818161078e015261094c0152610dcd6000f3fe608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a0eeb39a11610071578063a0eeb39a1461027a578063a408bb4c146102a1578063aaa8f2ef146102a9578063b8ea6281146102bc578063f905c15a146102d157600080fd5b80636bfd23a7146101fd57806385f2aef21461020657806389a3027114610219578063997a03b71461024057600080fd5b80634cdad506116100e95780634cdad506146101675780635e280f111461018f57806363b4eb8d146101ce57806368ecc6bc146101e15780636ac55083146101f457600080fd5b80621d35671461011a578063095cf5c61461012f578063221798ad1461014257806347db1a6a1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60045481565b6040519081526020015b60405180910390f35b61014b60035481565b61017a610175366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b6001546101b6906001600160a01b031681565b61012d6101ef366004610be5565b6106f3565b61014b60055481565b61014b60025481565b6000546101b6906001600160a01b031681565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6102677f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101b66102ca366004610c1a565b6014015190565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea264697066735822122063436f3755bf60d5767a51cb987ff704bae7ed446b1faa6c1311050a8b5dab6164736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a0eeb39a11610071578063a0eeb39a1461027a578063a408bb4c146102a1578063aaa8f2ef146102a9578063b8ea6281146102bc578063f905c15a146102d157600080fd5b80636bfd23a7146101fd57806385f2aef21461020657806389a3027114610219578063997a03b71461024057600080fd5b80634cdad506116100e95780634cdad506146101675780635e280f111461018f57806363b4eb8d146101ce57806368ecc6bc146101e15780636ac55083146101f457600080fd5b80621d35671461011a578063095cf5c61461012f578063221798ad1461014257806347db1a6a1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60045481565b6040519081526020015b60405180910390f35b61014b60035481565b61017a610175366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b6001546101b6906001600160a01b031681565b61012d6101ef366004610be5565b6106f3565b61014b60055481565b61014b60025481565b6000546101b6906001600160a01b031681565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6102677f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101b66102ca366004610c1a565b6014015190565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea264697066735822122063436f3755bf60d5767a51cb987ff704bae7ed446b1faa6c1311050a8b5dab6164736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "notice": "Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process This contract is responsible for receiving the LZ message and distributing USDC + VELO", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 24584, + "contract": "contracts/redeem/RedemptionReceiver.sol:RedemptionReceiver", + "label": "team", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 24588, + "contract": "contracts/redeem/RedemptionReceiver.sol:RedemptionReceiver", + "label": "fantomSender", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 24595, + "contract": "contracts/redeem/RedemptionReceiver.sol:RedemptionReceiver", + "label": "redeemedWEVE", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 24597, + "contract": "contracts/redeem/RedemptionReceiver.sol:RedemptionReceiver", + "label": "redeemableUSDC", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 24599, + "contract": "contracts/redeem/RedemptionReceiver.sol:RedemptionReceiver", + "label": "redeemableVELO", + "offset": 0, + "slot": "4", + "type": "t_uint256" + }, + { + "astId": 24601, + "contract": "contracts/redeem/RedemptionReceiver.sol:RedemptionReceiver", + "label": "leftoverVELO", + "offset": 0, + "slot": "5", + "type": "t_uint256" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/RewardsDistributor.json b/deployments/arbitrumGoerli/RewardsDistributor.json new file mode 100644 index 00000000..0fd5f67f --- /dev/null +++ b/deployments/arbitrumGoerli/RewardsDistributor.json @@ -0,0 +1,520 @@ +{ + "address": "0xf6CdA702C6Bd15d5C0A325CE8f9f88219fE5F445", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_voting_escrow", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "time", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "CheckpointToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "claim_epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "max_epoch", + "type": "uint256" + } + ], + "name": "Claimed", + "type": "event" + }, + { + "inputs": [], + "name": "checkpoint_token", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "checkpoint_total_supply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "claim", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "_tokenIds", + "type": "uint256[]" + } + ], + "name": "claim_many", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "claimable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "depositor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "last_token_time", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_depositor", + "type": "address" + } + ], + "name": "setDepositor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "start_time", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "time_cursor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "time_cursor_of", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "timestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token_last_balance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "tokens_per_week", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "user_epoch_of", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_timestamp", + "type": "uint256" + } + ], + "name": "ve_for_at", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "ve_supply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "voting_escrow", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x4f6fe37d5a57f4d8d07132c4c0f36f39be601dbc51d30e578cfba82b684a60ce", + "receipt": { + "to": null, + "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", + "contractAddress": "0xf6CdA702C6Bd15d5C0A325CE8f9f88219fE5F445", + "transactionIndex": 1, + "gasUsed": "16135585", + "logsBloom": "0x00000800000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000200000000000000000200000200000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000008000000000000000000000000020000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010008000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x65c28893c6e6b16729b2470a5e51f63b6b568597bb301d8e6896f6f2e3fdf808", + "transactionHash": "0x4f6fe37d5a57f4d8d07132c4c0f36f39be601dbc51d30e578cfba82b684a60ce", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 4195022, + "transactionHash": "0x4f6fe37d5a57f4d8d07132c4c0f36f39be601dbc51d30e578cfba82b684a60ce", + "address": "0xe69b00A164047e7eB87B73971B0f340eEbFF9c81", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000f6cda702c6bd15d5c0a325ce8f9f88219fe5f445", + "0x0000000000000000000000006b938ba22fb5520ffb5d14c9c4fef82a48761497" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 0, + "blockHash": "0x65c28893c6e6b16729b2470a5e51f63b6b568597bb301d8e6896f6f2e3fdf808" + } + ], + "blockNumber": 4195022, + "cumulativeGasUsed": "16135585", + "status": 1, + "byzantium": true + }, + "args": [ + "0x6b938BA22FB5520fFB5D14c9C4Fef82a48761497" + ], + "numDeployments": 4, + "solcInputHash": "0faaa79d8b79020b765ba7705413c447", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voting_escrow\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"time\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"CheckpointToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"claim_epoch\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"max_epoch\",\"type\":\"uint256\"}],\"name\":\"Claimed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"checkpoint_token\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint_total_supply\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"_tokenIds\",\"type\":\"uint256[]\"}],\"name\":\"claim_many\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_token_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"}],\"name\":\"setDepositor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"start_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"time_cursor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"time_cursor_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token_last_balance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"tokens_per_week\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_epoch_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"ve_for_at\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ve_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voting_escrow\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RewardsDistributor.sol\":\"RewardsDistributor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/*\\n\\n@title Curve Fee Distribution modified for ve(3,3) emissions\\n@author Curve Finance, andrecronje\\n@license MIT\\n\\n*/\\n\\ncontract RewardsDistributor is IRewardsDistributor {\\n event CheckpointToken(uint256 time, uint256 tokens);\\n\\n event Claimed(\\n uint256 tokenId,\\n uint256 amount,\\n uint256 claim_epoch,\\n uint256 max_epoch\\n );\\n\\n uint256 constant WEEK = 7 * 86400;\\n\\n uint256 public start_time;\\n uint256 public time_cursor;\\n mapping(uint256 => uint256) public time_cursor_of;\\n mapping(uint256 => uint256) public user_epoch_of;\\n\\n uint256 public last_token_time;\\n uint256[1000000000000000] public tokens_per_week;\\n\\n address public voting_escrow;\\n address public token;\\n uint256 public token_last_balance;\\n\\n uint256[1000000000000000] public ve_supply;\\n\\n address public depositor;\\n\\n constructor(address _voting_escrow) {\\n uint256 _t = (block.timestamp / WEEK) * WEEK;\\n start_time = _t;\\n last_token_time = _t;\\n time_cursor = _t;\\n address _token = IVotingEscrow(_voting_escrow).token();\\n token = _token;\\n voting_escrow = _voting_escrow;\\n depositor = msg.sender;\\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\\n }\\n\\n function timestamp() external view returns (uint256) {\\n return (block.timestamp / WEEK) * WEEK;\\n }\\n\\n function _checkpoint_token() internal {\\n uint256 token_balance = IERC20(token).balanceOf(address(this));\\n uint256 to_distribute = token_balance - token_last_balance;\\n token_last_balance = token_balance;\\n\\n uint256 t = last_token_time;\\n uint256 since_last = block.timestamp - t;\\n last_token_time = block.timestamp;\\n uint256 this_week = (t / WEEK) * WEEK;\\n uint256 next_week = 0;\\n\\n for (uint256 i = 0; i < 20; i++) {\\n next_week = this_week + WEEK;\\n if (block.timestamp < next_week) {\\n if (since_last == 0 && block.timestamp == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (block.timestamp - t)) /\\n since_last;\\n }\\n break;\\n } else {\\n if (since_last == 0 && next_week == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (next_week - t)) /\\n since_last;\\n }\\n }\\n t = next_week;\\n this_week = next_week;\\n }\\n emit CheckpointToken(block.timestamp, to_distribute);\\n }\\n\\n function checkpoint_token() external {\\n assert(msg.sender == depositor);\\n _checkpoint_token();\\n }\\n\\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\\n internal\\n view\\n returns (uint256)\\n {\\n uint256 _min = 0;\\n uint256 _max = IVotingEscrow(ve).epoch();\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n _mid\\n );\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function _find_timestamp_user_epoch(\\n address ve,\\n uint256 tokenId,\\n uint256 _timestamp,\\n uint256 max_user_epoch\\n ) internal view returns (uint256) {\\n uint256 _min = 0;\\n uint256 _max = max_user_epoch;\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\\n .user_point_history(tokenId, _mid);\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\\n external\\n view\\n returns (uint256)\\n {\\n address ve = voting_escrow;\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _timestamp,\\n max_user_epoch\\n );\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n epoch\\n );\\n return\\n MathDunks.max(\\n uint256(\\n int256(\\n pt.bias -\\n pt.slope *\\n (int128(int256(_timestamp - pt.ts)))\\n )\\n ),\\n 0\\n );\\n }\\n\\n function _checkpoint_total_supply() internal {\\n address ve = voting_escrow;\\n uint256 t = time_cursor;\\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\\n IVotingEscrow(ve).checkpoint();\\n\\n for (uint256 i = 0; i < 20; i++) {\\n if (t > rounded_timestamp) {\\n break;\\n } else {\\n uint256 epoch = _find_timestamp_epoch(ve, t);\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n epoch\\n );\\n int128 dt = 0;\\n if (t > pt.ts) {\\n dt = int128(int256(t - pt.ts));\\n }\\n ve_supply[t] = MathDunks.max(\\n uint256(int256(pt.bias - pt.slope * dt)),\\n 0\\n );\\n }\\n t += WEEK;\\n }\\n time_cursor = t;\\n }\\n\\n function checkpoint_total_supply() external {\\n _checkpoint_total_supply();\\n }\\n\\n function _claim(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\\n user_epoch_of[_tokenId] = user_epoch;\\n time_cursor_of[_tokenId] = week_cursor;\\n\\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\\n\\n return to_distribute;\\n }\\n\\n function _claimable(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal view returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n return to_distribute;\\n }\\n\\n function claimable(uint256 _tokenId) external view returns (uint256) {\\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\\n return _claimable(_tokenId, voting_escrow, _last_token_time);\\n }\\n\\n function claim(uint256 _tokenId) external returns (uint256) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\\n token_last_balance -= amount;\\n }\\n return amount;\\n }\\n\\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n address _voting_escrow = voting_escrow;\\n uint256 total = 0;\\n\\n for (uint256 i = 0; i < _tokenIds.length; i++) {\\n uint256 _tokenId = _tokenIds[i];\\n if (_tokenId == 0) break;\\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\\n total += amount;\\n }\\n }\\n if (total != 0) {\\n token_last_balance -= total;\\n }\\n\\n return true;\\n }\\n\\n // Once off event on contract initialize\\n function setDepositor(address _depositor) external {\\n require(msg.sender == depositor);\\n depositor = _depositor;\\n }\\n}\\n\",\"keccak256\":\"0xdbcfb11d65c6ca7d63baba42fb2f1222478c6ca78d8e81970032eff5e034e09b\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b5060405162001b9f38038062001b9f83398101604081905262000034916200019f565b600062093a80620000468142620001d1565b620000529190620001f4565b90508060008190555080600481905550806001819055506000826001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000aa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d091906200019f565b66038d7ea4c6800680546001600160a01b038381166001600160a01b0319928316811790935566038d7ea4c6800580549188169183168217905566071afd498d00088054909216331790915560405163095ea7b360e01b8152600481019190915260001960248201529192509063095ea7b3906044016020604051808303816000875af115801562000166573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200018c919062000222565b6200019657600080fd5b50505062000246565b600060208284031215620001b257600080fd5b81516001600160a01b0381168114620001ca57600080fd5b9392505050565b600082620001ef57634e487b7160e01b600052601260045260246000fd5b500490565b60008160001904831182151516156200021d57634e487b7160e01b600052601160045260246000fd5b500290565b6000602082840312156200023557600080fd5b81518015158114620001ca57600080fd5b61194980620002566000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea2646970667358221220faa2ede3260adc0a11d81d56de5912df92f5289c5ac4e9b5ce7525019a4e773e64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea2646970667358221220faa2ede3260adc0a11d81d56de5912df92f5289c5ac4e9b5ce7525019a4e773e64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 9410, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "start_time", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 9412, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "time_cursor", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 9416, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "time_cursor_of", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 9420, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "user_epoch_of", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 9422, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "last_token_time", + "offset": 0, + "slot": "4", + "type": "t_uint256" + }, + { + "astId": 9426, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "tokens_per_week", + "offset": 0, + "slot": "5", + "type": "t_array(t_uint256)1000000000000000_storage" + }, + { + "astId": 9428, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "voting_escrow", + "offset": 0, + "slot": "1000000000000005", + "type": "t_address" + }, + { + "astId": 9430, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "token", + "offset": 0, + "slot": "1000000000000006", + "type": "t_address" + }, + { + "astId": 9432, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "token_last_balance", + "offset": 0, + "slot": "1000000000000007", + "type": "t_uint256" + }, + { + "astId": 9436, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "ve_supply", + "offset": 0, + "slot": "1000000000000008", + "type": "t_array(t_uint256)1000000000000000_storage" + }, + { + "astId": 9438, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "depositor", + "offset": 0, + "slot": "2000000000000008", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)1000000000000000_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[1000000000000000]", + "numberOfBytes": "32000000000000000" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/Router.json b/deployments/arbitrumGoerli/Router.json new file mode 100644 index 00000000..fd18d25e --- /dev/null +++ b/deployments/arbitrumGoerli/Router.json @@ -0,0 +1,1021 @@ +{ + "address": "0xCeaEA7A5cB3e7521DdE6717BCc99a4c8c60E07b6", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_factory", + "type": "address" + }, + { + "internalType": "address", + "name": "_weth", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "internalType": "struct Router.route[]", + "name": "routes", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "UNSAFE_swapExactTokensForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "amountADesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBDesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountAMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "addLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "amountTokenDesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountTokenMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETHMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "addLiquidityETH", + "outputs": [ + { + "internalType": "uint256", + "name": "amountToken", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETH", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + } + ], + "name": "getAmountOut", + "outputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "internalType": "struct Router.route[]", + "name": "routes", + "type": "tuple[]" + } + ], + "name": "getAmountsOut", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "reserveA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveB", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pair", + "type": "address" + } + ], + "name": "isPair", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "pairFor", + "outputs": [ + { + "internalType": "address", + "name": "pair", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "amountADesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBDesired", + "type": "uint256" + } + ], + "name": "quoteAddLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "name": "quoteRemoveLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountAMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "removeLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountTokenMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETHMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "removeLiquidityETH", + "outputs": [ + { + "internalType": "uint256", + "name": "amountToken", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETH", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountTokenMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETHMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "approveMax", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "removeLiquidityETHWithPermit", + "outputs": [ + { + "internalType": "uint256", + "name": "amountToken", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETH", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountAMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "approveMax", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "removeLiquidityWithPermit", + "outputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + } + ], + "name": "sortTokens", + "outputs": [ + { + "internalType": "address", + "name": "token0", + "type": "address" + }, + { + "internalType": "address", + "name": "token1", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "internalType": "struct Router.route[]", + "name": "routes", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactETHForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "internalType": "struct Router.route[]", + "name": "routes", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForETH", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "internalType": "struct Router.route[]", + "name": "routes", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenFrom", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenTo", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensSimple", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "weth", + "outputs": [ + { + "internalType": "contract IWETH", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x941d082fc841e56456d6b4db26c1a309aa00922f4d13c3d7088172b13da20fab", + "receipt": { + "to": null, + "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", + "contractAddress": "0xCeaEA7A5cB3e7521DdE6717BCc99a4c8c60E07b6", + "transactionIndex": 1, + "gasUsed": "30613012", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7d9555496abbbd6cfec0e3f28a49f8101af207880f7e92cf05f18531291de64d", + "transactionHash": "0x941d082fc841e56456d6b4db26c1a309aa00922f4d13c3d7088172b13da20fab", + "logs": [], + "blockNumber": 4195013, + "cumulativeGasUsed": "30613012", + "status": 1, + "byzantium": true + }, + "args": [ + "0x7488AC81DC3908ff7141db4949e70D60A3Fd4DCc", + "0x4200000000000000000000000000000000000006" + ], + "numDeployments": 5, + "solcInputHash": "0faaa79d8b79020b765ba7705413c447", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_weth\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"UNSAFE_swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"}],\"name\":\"getAmountsOut\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reserveA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"pairFor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"}],\"name\":\"quoteAddLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"name\":\"quoteRemoveLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityETHWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"}],\"name\":\"sortTokens\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactETHForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForETH\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenFrom\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenTo\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokensSimple\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weth\",\"outputs\":[{\"internalType\":\"contract IWETH\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Router.sol\":\"Router\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Router.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairFactory.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\nimport \\\"contracts/interfaces/IWETH.sol\\\";\\n\\ncontract Router is IRouter {\\n struct route {\\n address from;\\n address to;\\n bool stable;\\n }\\n\\n address public immutable factory;\\n IWETH public immutable weth;\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n bytes32 immutable pairCodeHash;\\n\\n modifier ensure(uint256 deadline) {\\n require(deadline >= block.timestamp, \\\"Router: EXPIRED\\\");\\n _;\\n }\\n\\n constructor(address _factory, address _weth) {\\n factory = _factory;\\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\\n weth = IWETH(_weth);\\n }\\n\\n receive() external payable {\\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\\n }\\n\\n function sortTokens(address tokenA, address tokenB)\\n public\\n pure\\n returns (address token0, address token1)\\n {\\n require(tokenA != tokenB, \\\"Router: IDENTICAL_ADDRESSES\\\");\\n (token0, token1) = tokenA < tokenB\\n ? (tokenA, tokenB)\\n : (tokenB, tokenA);\\n require(token0 != address(0), \\\"Router: ZERO_ADDRESS\\\");\\n }\\n\\n // calculates the CREATE2 address for a pair without making any external calls\\n function pairFor(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (address pair) {\\n (address token0, address token1) = sortTokens(tokenA, tokenB);\\n pair = address(\\n uint160(\\n uint256(\\n keccak256(\\n abi.encodePacked(\\n hex\\\"ff\\\",\\n factory,\\n keccak256(abi.encodePacked(token0, token1, stable)),\\n pairCodeHash // init code hash\\n )\\n )\\n )\\n )\\n );\\n }\\n\\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\\n function quoteLiquidity(\\n uint256 amountA,\\n uint256 reserveA,\\n uint256 reserveB\\n ) internal pure returns (uint256 amountB) {\\n require(amountA > 0, \\\"Router: INSUFFICIENT_AMOUNT\\\");\\n require(reserveA > 0 && reserveB > 0, \\\"Router: INSUFFICIENT_LIQUIDITY\\\");\\n amountB = (amountA * reserveB) / reserveA;\\n }\\n\\n // fetches and sorts the reserves for a pair\\n function getReserves(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (uint256 reserveA, uint256 reserveB) {\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (uint256 reserve0, uint256 reserve1, ) = IPair(\\n pairFor(tokenA, tokenB, stable)\\n ).getReserves();\\n (reserveA, reserveB) = tokenA == token0\\n ? (reserve0, reserve1)\\n : (reserve1, reserve0);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n address tokenOut\\n ) external view returns (uint256 amount, bool stable) {\\n address pair = pairFor(tokenIn, tokenOut, true);\\n uint256 amountStable;\\n uint256 amountVolatile;\\n if (IPairFactory(factory).isPair(pair)) {\\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n pair = pairFor(tokenIn, tokenOut, false);\\n if (IPairFactory(factory).isPair(pair)) {\\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n return\\n amountStable > amountVolatile\\n ? (amountStable, true)\\n : (amountVolatile, false);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountsOut(uint256 amountIn, route[] memory routes)\\n public\\n view\\n returns (uint256[] memory amounts)\\n {\\n require(routes.length >= 1, \\\"Router: INVALID_PATH\\\");\\n amounts = new uint256[](routes.length + 1);\\n amounts[0] = amountIn;\\n for (uint256 i = 0; i < routes.length; i++) {\\n address pair = pairFor(\\n routes[i].from,\\n routes[i].to,\\n routes[i].stable\\n );\\n if (IPairFactory(factory).isPair(pair)) {\\n amounts[i + 1] = IPair(pair).getAmountOut(\\n amounts[i],\\n routes[i].from\\n );\\n }\\n }\\n }\\n\\n function isPair(address pair) external view returns (bool) {\\n return IPairFactory(factory).isPair(pair);\\n }\\n\\n function quoteAddLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired\\n )\\n external\\n view\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n (uint256 reserveA, uint256 reserveB) = (0, 0);\\n uint256 _totalSupply = 0;\\n if (_pair != address(0)) {\\n _totalSupply = IERC20(_pair).totalSupply();\\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\\n }\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n }\\n }\\n }\\n\\n function quoteRemoveLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity\\n ) external view returns (uint256 amountA, uint256 amountB) {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n\\n if (_pair == address(0)) {\\n return (0, 0);\\n }\\n\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n uint256 _totalSupply = IERC20(_pair).totalSupply();\\n\\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\\n }\\n\\n function _addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin\\n ) internal returns (uint256 amountA, uint256 amountB) {\\n require(amountADesired >= amountAMin);\\n require(amountBDesired >= amountBMin);\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n if (_pair == address(0)) {\\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\\n }\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n require(\\n amountBOptimal >= amountBMin,\\n \\\"Router: INSUFFICIENT_B_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n assert(amountAOptimal <= amountADesired);\\n require(\\n amountAOptimal >= amountAMin,\\n \\\"Router: INSUFFICIENT_A_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n }\\n }\\n }\\n\\n function addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n ensure(deadline)\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n (amountA, amountB) = _addLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n amountADesired,\\n amountBDesired,\\n amountAMin,\\n amountBMin\\n );\\n address pair = pairFor(tokenA, tokenB, stable);\\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\\n liquidity = IPair(pair).mint(to);\\n }\\n\\n function addLiquidityETH(\\n address token,\\n bool stable,\\n uint256 amountTokenDesired,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n payable\\n ensure(deadline)\\n returns (\\n uint256 amountToken,\\n uint256 amountETH,\\n uint256 liquidity\\n )\\n {\\n (amountToken, amountETH) = _addLiquidity(\\n token,\\n address(weth),\\n stable,\\n amountTokenDesired,\\n msg.value,\\n amountTokenMin,\\n amountETHMin\\n );\\n address pair = pairFor(token, address(weth), stable);\\n _safeTransferFrom(token, msg.sender, pair, amountToken);\\n weth.deposit{value: amountETH}();\\n assert(weth.transfer(pair, amountETH));\\n liquidity = IPair(pair).mint(to);\\n // refund dust eth, if any\\n if (msg.value > amountETH)\\n _safeTransferETH(msg.sender, msg.value - amountETH);\\n }\\n\\n // **** REMOVE LIQUIDITY ****\\n function removeLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (amountA, amountB) = tokenA == token0\\n ? (amount0, amount1)\\n : (amount1, amount0);\\n require(amountA >= amountAMin, \\\"Router: INSUFFICIENT_A_AMOUNT\\\");\\n require(amountB >= amountBMin, \\\"Router: INSUFFICIENT_B_AMOUNT\\\");\\n }\\n\\n function removeLiquidityETH(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\\n (amountToken, amountETH) = removeLiquidity(\\n token,\\n address(weth),\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n address(this),\\n deadline\\n );\\n _safeTransfer(token, to, amountToken);\\n weth.withdraw(amountETH);\\n _safeTransferETH(to, amountETH);\\n }\\n\\n function removeLiquidityWithPermit(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n {\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(\\n msg.sender,\\n address(this),\\n value,\\n deadline,\\n v,\\n r,\\n s\\n );\\n }\\n\\n (amountA, amountB) = removeLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n liquidity,\\n amountAMin,\\n amountBMin,\\n to,\\n deadline\\n );\\n }\\n\\n function removeLiquidityETHWithPermit(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountToken, uint256 amountETH) {\\n address pair = pairFor(token, address(weth), stable);\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\\n (amountToken, amountETH) = removeLiquidityETH(\\n token,\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n to,\\n deadline\\n );\\n }\\n\\n // **** SWAP ****\\n // requires the initial amount to have already been sent to the first pair\\n function _swap(\\n uint256[] memory amounts,\\n route[] memory routes,\\n address _to\\n ) internal virtual {\\n for (uint256 i = 0; i < routes.length; i++) {\\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\\n uint256 amountOut = amounts[i + 1];\\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\\n ? (uint256(0), amountOut)\\n : (amountOut, uint256(0));\\n address to = i < routes.length - 1\\n ? pairFor(\\n routes[i + 1].from,\\n routes[i + 1].to,\\n routes[i + 1].stable\\n )\\n : _to;\\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\\n amount0Out,\\n amount1Out,\\n to,\\n new bytes(0)\\n );\\n }\\n }\\n\\n function swapExactTokensForTokensSimple(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n address tokenFrom,\\n address tokenTo,\\n bool stable,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n route[] memory routes = new route[](1);\\n routes[0].from = tokenFrom;\\n routes[0].to = tokenTo;\\n routes[0].stable = stable;\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForTokens(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactETHForTokens(\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\\n require(routes[0].from == address(weth), \\\"Router: INVALID_PATH\\\");\\n amounts = getAmountsOut(msg.value, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n weth.deposit{value: amounts[0]}();\\n assert(\\n weth.transfer(\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n )\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForETH(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n require(\\n routes[routes.length - 1].to == address(weth),\\n \\\"Router: INVALID_PATH\\\"\\n );\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, address(this));\\n weth.withdraw(amounts[amounts.length - 1]);\\n _safeTransferETH(to, amounts[amounts.length - 1]);\\n }\\n\\n function UNSAFE_swapExactTokensForTokens(\\n uint256[] memory amounts,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory) {\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n return amounts;\\n }\\n\\n function _safeTransferETH(address to, uint256 value) internal {\\n (bool success, ) = to.call{value: value}(new bytes(0));\\n require(success, \\\"TransferHelper: ETH_TRANSFER_FAILED\\\");\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x3d84c846129d645eec66c37a493bb7fb401a2524497f450eaced155088305ead\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"},\"contracts/interfaces/IWETH.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n function transfer(address to, uint256 value) external returns (bool);\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0x20ad0b3a319a36e3430f0d8512ee3755de8f85a80effe78d06f333f5326ee3d7\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x60e06040523480156200001157600080fd5b50604051620039bc380380620039bc8339810160408190526200003491620000d8565b6001600160a01b038216608081905260408051631355724960e31b81529051639aab9248916004808201926020929091908290030181865afa1580156200007f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000a5919062000110565b60c0526001600160a01b031660a052506200012a565b80516001600160a01b0381168114620000d357600080fd5b919050565b60008060408385031215620000ec57600080fd5b620000f783620000bb565b91506200010760208401620000bb565b90509250929050565b6000602082840312156200012357600080fd5b5051919050565b60805160a05160c0516137c8620001f46000396000610ef901526000818161013e0152818161020b0152818161091901528181610b5801528181610da901528181611470015281816115830152818161161101528181611de901528181611e1f01528181611e5401528181611ee901528181612028015261207801526000818161042d01528181610c3e01528181610ebe015281816111770152818161128b0152818161199601528181611b0a01528181612115015281816126ff01526127a001526137c86000f3fe60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea264697066735822122061c9ed8dec3ddb93963ec08aa04769e1e1c77f8f8cb927af407b5c9994f2ad8d64736f6c634300080d0033", + "deployedBytecode": "0x60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea264697066735822122061c9ed8dec3ddb93963ec08aa04769e1e1c77f8f8cb927af407b5c9994f2ad8d64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/VeArtProxy.json b/deployments/arbitrumGoerli/VeArtProxy.json new file mode 100644 index 00000000..fba3ebf5 --- /dev/null +++ b/deployments/arbitrumGoerli/VeArtProxy.json @@ -0,0 +1,75 @@ +{ + "address": "0x5e7569D02214289490d16bCE4F96B38071db1aD8", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_balanceOf", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_locked_end", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "_tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "output", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "transactionHash": "0x64c172576980de0bc037dc48f1a0336c76d244b0f6615e48b1473165127ad5af", + "receipt": { + "to": null, + "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", + "contractAddress": "0x5e7569D02214289490d16bCE4F96B38071db1aD8", + "transactionIndex": 1, + "gasUsed": "8226871", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x365257e039acdb508014dcef6f26eea346febbf1dc77fb83da1df099ec229869", + "transactionHash": "0x64c172576980de0bc037dc48f1a0336c76d244b0f6615e48b1473165127ad5af", + "logs": [], + "blockNumber": 4195017, + "cumulativeGasUsed": "8226871", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 4, + "solcInputHash": "0faaa79d8b79020b765ba7705413c447", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_locked_end\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"_tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"output\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VeArtProxy.sol\":\"VeArtProxy\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\nimport {Base64} from \\\"contracts/libraries/Base64.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\n\\ncontract VeArtProxy is IVeArtProxy {\\n function toString(uint value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT license\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint temp = value;\\n uint digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\\n output = '';\\n output = string(abi.encodePacked(output, \\\"token \\\", toString(_tokenId), ''));\\n output = string(abi.encodePacked(output, \\\"balanceOf \\\", toString(_balanceOf), ''));\\n output = string(abi.encodePacked(output, \\\"locked_end \\\", toString(_locked_end), ''));\\n output = string(abi.encodePacked(output, \\\"value \\\", toString(_value), ''));\\n\\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\\\"name\\\": \\\"lock #', toString(_tokenId), '\\\", \\\"description\\\": \\\"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\\\", \\\"image\\\": \\\"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\\\"}'))));\\n output = string(abi.encodePacked('data:application/json;base64,', json));\\n }\\n}\\n\",\"keccak256\":\"0x8757d8095922dcad7af8c6820415049fd7d5af61a5580719210e5e91a31d80b1\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/libraries/Base64.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n/// [MIT License]\\n/// @title Base64\\n/// @notice Provides a function for encoding some bytes in base64\\n/// @author Brecht Devos \\nlibrary Base64 {\\n bytes internal constant TABLE = \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\";\\n\\n /// @notice Encodes some bytes to the base64 representation\\n function encode(bytes memory data) internal pure returns (string memory) {\\n uint len = data.length;\\n if (len == 0) return \\\"\\\";\\n\\n // multiply by 4/3 rounded up\\n uint encodedLen = 4 * ((len + 2) / 3);\\n\\n // Add some extra buffer at the end\\n bytes memory result = new bytes(encodedLen + 32);\\n\\n bytes memory table = TABLE;\\n\\n assembly {\\n let tablePtr := add(table, 1)\\n let resultPtr := add(result, 32)\\n\\n for {\\n let i := 0\\n } lt(i, len) {\\n\\n } {\\n i := add(i, 3)\\n let input := and(mload(add(data, i)), 0xffffff)\\n\\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\\n out := shl(224, out)\\n\\n mstore(resultPtr, out)\\n\\n resultPtr := add(resultPtr, 4)\\n }\\n\\n switch mod(len, 3)\\n case 1 {\\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\\n }\\n case 2 {\\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\\n }\\n\\n mstore(result, encodedLen)\\n }\\n\\n return string(result);\\n }\\n}\\n\",\"keccak256\":\"0x55535e1e0a14bbac370fe5f25df23aa88c678b915af53517672130f9a54f7e3e\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610a2b806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f64726f6d65206c6f636010918401918201527f6b732c2063616e206265207573656420746f20626f6f7374206761756765207960308201527f69656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c206160508201527f6e64207265636569766520627269626573222c2022696d616765223a2022646160708201527f74613a696d6167652f7376672b786d6c3b6261736536342c0000000000000000609082015283516107718160a8840160208801610435565b61227d60f01b60a8929091019182015260aa01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220abfc8dcf4be5f263f1c7db4795f195a980c77a740eaa4ece8d9746af53e2be4364736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f64726f6d65206c6f636010918401918201527f6b732c2063616e206265207573656420746f20626f6f7374206761756765207960308201527f69656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c206160508201527f6e64207265636569766520627269626573222c2022696d616765223a2022646160708201527f74613a696d6167652f7376672b786d6c3b6261736536342c0000000000000000609082015283516107718160a8840160208801610435565b61227d60f01b60a8929091019182015260aa01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220abfc8dcf4be5f263f1c7db4795f195a980c77a740eaa4ece8d9746af53e2be4364736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/Velo.json b/deployments/arbitrumGoerli/Velo.json new file mode 100644 index 00000000..5c3cb706 --- /dev/null +++ b/deployments/arbitrumGoerli/Velo.json @@ -0,0 +1,522 @@ +{ + "address": "0xe69b00A164047e7eB87B73971B0f340eEbFF9c81", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "claim", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_recipient", + "type": "address" + } + ], + "name": "initialMint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initialMinted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "merkleClaim", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "minter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "redemptionReceiver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_merkleClaim", + "type": "address" + } + ], + "name": "setMerkleClaim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_minter", + "type": "address" + } + ], + "name": "setMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_receiver", + "type": "address" + } + ], + "name": "setRedemptionReceiver", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x8c100b2c979d9c2518478168d49380e5049bc8ec1f04f58b7217ff7b85ea8447", + "receipt": { + "to": null, + "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", + "contractAddress": "0xe69b00A164047e7eB87B73971B0f340eEbFF9c81", + "transactionIndex": 1, + "gasUsed": "6812425", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000200000000000000000000000000000000000000000000008000000000000000000000000000040000000000000000000020000000000000000000800000000000000000000000010000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000400000000000000000000000000020000000008000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x060d1f20218f44cc143168d1501b1f1bb70b22e8076c71027ca17b9f26c30420", + "transactionHash": "0x8c100b2c979d9c2518478168d49380e5049bc8ec1f04f58b7217ff7b85ea8447", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 4195003, + "transactionHash": "0x8c100b2c979d9c2518478168d49380e5049bc8ec1f04f58b7217ff7b85ea8447", + "address": "0xe69b00A164047e7eB87B73971B0f340eEbFF9c81", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000003406eda8850592ea85886d854edbd55042cb7805" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000", + "logIndex": 0, + "blockHash": "0x060d1f20218f44cc143168d1501b1f1bb70b22e8076c71027ca17b9f26c30420" + } + ], + "blockNumber": 4195003, + "cumulativeGasUsed": "6812425", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 5, + "solcInputHash": "0faaa79d8b79020b765ba7705413c447", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"initialMint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialMinted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleClaim\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redemptionReceiver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_merkleClaim\",\"type\":\"address\"}],\"name\":\"setMerkleClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"setMinter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_receiver\",\"type\":\"address\"}],\"name\":\"setRedemptionReceiver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Velo.sol\":\"Velo\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Velo.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IVelo.sol\\\";\\n\\ncontract Velo is IVelo {\\n\\n string public constant name = \\\"Velodrome\\\";\\n string public constant symbol = \\\"VELO\\\";\\n uint8 public constant decimals = 18;\\n uint public totalSupply = 0;\\n\\n mapping(address => uint) public balanceOf;\\n mapping(address => mapping(address => uint)) public allowance;\\n\\n bool public initialMinted;\\n address public minter;\\n address public redemptionReceiver;\\n address public merkleClaim;\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n\\n constructor() {\\n minter = msg.sender;\\n _mint(msg.sender, 0);\\n }\\n\\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\\n function setMinter(address _minter) external {\\n require(msg.sender == minter);\\n minter = _minter;\\n }\\n\\n function setRedemptionReceiver(address _receiver) external {\\n require(msg.sender == minter);\\n redemptionReceiver = _receiver;\\n }\\n\\n function setMerkleClaim(address _merkleClaim) external {\\n require(msg.sender == minter);\\n merkleClaim = _merkleClaim;\\n }\\n\\n // Initial mint: total 82M\\n // 4M for \\\"Genesis\\\" pools\\n // 30M for liquid team allocation (40M excl init veNFT)\\n // 48M for future partners\\n function initialMint(address _recipient) external {\\n require(msg.sender == minter && !initialMinted);\\n initialMinted = true;\\n _mint(_recipient, 82 * 1e6 * 1e18);\\n }\\n\\n function approve(address _spender, uint _value) external returns (bool) {\\n allowance[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n function _mint(address _to, uint _amount) internal returns (bool) {\\n totalSupply += _amount;\\n unchecked {\\n balanceOf[_to] += _amount;\\n }\\n emit Transfer(address(0x0), _to, _amount);\\n return true;\\n }\\n\\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\\n balanceOf[_from] -= _value;\\n unchecked {\\n balanceOf[_to] += _value;\\n }\\n emit Transfer(_from, _to, _value);\\n return true;\\n }\\n\\n function transfer(address _to, uint _value) external returns (bool) {\\n return _transfer(msg.sender, _to, _value);\\n }\\n\\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\\n uint allowed_from = allowance[_from][msg.sender];\\n if (allowed_from != type(uint).max) {\\n allowance[_from][msg.sender] -= _value;\\n }\\n return _transfer(_from, _to, _value);\\n }\\n\\n function mint(address account, uint amount) external returns (bool) {\\n require(msg.sender == minter);\\n _mint(account, amount);\\n return true;\\n }\\n\\n function claim(address account, uint amount) external returns (bool) {\\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\\n _mint(account, amount);\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xb5231de79b43d576febc9d6a0ebee8c4f251ec109869ce7a3e0afc2a185d0246\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"}},\"version\":1}", + "bytecode": "0x60806040526000805534801561001457600080fd5b5060038054610100600160a81b0319163361010081029190911790915561003c906000610042565b506100d9565b60008160008082825461005591906100b3565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a350600192915050565b600082198211156100d457634e487b7160e01b600052601160045260246000fd5b500190565b61082c806100e86000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ac578063dd62ed3e146102bf578063e752c44a146102ea578063ec676a25146102fd578063fca3b5aa1461031057600080fd5b806395d89b4114610241578063a9059cbb14610264578063aad3ec9614610277578063c268f9ba1461028a578063ca1c4de91461029f57600080fd5b806323b872dd116100f457806323b872dd146101ce578063313ce567146101e157806340c10f19146101fb5780635e05fe501461020e57806370a082311461022157600080fd5b806306fdde03146101265780630754617214610164578063095ea7b31461019457806318160ddd146101b7575b600080fd5b61014e6040518060400160405280600981526020016856656c6f64726f6d6560b81b81525081565b60405161015b919061068c565b60405180910390f35b60035461017c9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015b565b6101a76101a23660046106fd565b610323565b604051901515815260200161015b565b6101c060005481565b60405190815260200161015b565b6101a76101dc366004610727565b61038f565b6101e9601281565b60405160ff909116815260200161015b565b6101a76102093660046106fd565b610409565b60045461017c906001600160a01b031681565b6101c061022f366004610763565b60016020526000908152604090205481565b61014e6040518060400160405280600481526020016356454c4f60e01b81525081565b6101a76102723660046106fd565b61043c565b6101a76102853660046106fd565b610450565b61029d610298366004610763565b61047f565b005b6003546101a79060ff1681565b61029d6102ba366004610763565b6104d0565b6101c06102cd36600461077e565b600260209081526000928352604080842090915290825290205481565b60055461017c906001600160a01b031681565b61029d61030b366004610763565b61050e565b61029d61031e366004610763565b61054c565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259061037e9086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f5576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103ef9084906107c7565b90915550505b610400858585610590565b95945050505050565b60035460009061010090046001600160a01b0316331461042857600080fd5b6104328383610627565b5060019392505050565b6000610449338484610590565b9392505050565b6004546000906001600160a01b031633148061047657506005546001600160a01b031633145b61042857600080fd5b60035461010090046001600160a01b0316331480156104a1575060035460ff16155b6104aa57600080fd5b6003805460ff191660011790556104cc816a43d42ce83da41d92000000610627565b5050565b60035461010090046001600160a01b031633146104ec57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052a57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056857600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105ba9084906107c7565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106159086815260200190565b60405180910390a35060019392505050565b60008160008082825461063a91906107de565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910161037e565b600060208083528351808285015260005b818110156106b95785810183015185820160400152820161069d565b818111156106cb576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106f857600080fd5b919050565b6000806040838503121561071057600080fd5b610719836106e1565b946020939093013593505050565b60008060006060848603121561073c57600080fd5b610745846106e1565b9250610753602085016106e1565b9150604084013590509250925092565b60006020828403121561077557600080fd5b610449826106e1565b6000806040838503121561079157600080fd5b61079a836106e1565b91506107a8602084016106e1565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107d9576107d96107b1565b500390565b600082198211156107f1576107f16107b1565b50019056fea2646970667358221220bebc3a2234b72bd2fd84b02793c989f9dfae6f8feb95470b1dc74a79df11e23a64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ac578063dd62ed3e146102bf578063e752c44a146102ea578063ec676a25146102fd578063fca3b5aa1461031057600080fd5b806395d89b4114610241578063a9059cbb14610264578063aad3ec9614610277578063c268f9ba1461028a578063ca1c4de91461029f57600080fd5b806323b872dd116100f457806323b872dd146101ce578063313ce567146101e157806340c10f19146101fb5780635e05fe501461020e57806370a082311461022157600080fd5b806306fdde03146101265780630754617214610164578063095ea7b31461019457806318160ddd146101b7575b600080fd5b61014e6040518060400160405280600981526020016856656c6f64726f6d6560b81b81525081565b60405161015b919061068c565b60405180910390f35b60035461017c9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015b565b6101a76101a23660046106fd565b610323565b604051901515815260200161015b565b6101c060005481565b60405190815260200161015b565b6101a76101dc366004610727565b61038f565b6101e9601281565b60405160ff909116815260200161015b565b6101a76102093660046106fd565b610409565b60045461017c906001600160a01b031681565b6101c061022f366004610763565b60016020526000908152604090205481565b61014e6040518060400160405280600481526020016356454c4f60e01b81525081565b6101a76102723660046106fd565b61043c565b6101a76102853660046106fd565b610450565b61029d610298366004610763565b61047f565b005b6003546101a79060ff1681565b61029d6102ba366004610763565b6104d0565b6101c06102cd36600461077e565b600260209081526000928352604080842090915290825290205481565b60055461017c906001600160a01b031681565b61029d61030b366004610763565b61050e565b61029d61031e366004610763565b61054c565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259061037e9086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f5576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103ef9084906107c7565b90915550505b610400858585610590565b95945050505050565b60035460009061010090046001600160a01b0316331461042857600080fd5b6104328383610627565b5060019392505050565b6000610449338484610590565b9392505050565b6004546000906001600160a01b031633148061047657506005546001600160a01b031633145b61042857600080fd5b60035461010090046001600160a01b0316331480156104a1575060035460ff16155b6104aa57600080fd5b6003805460ff191660011790556104cc816a43d42ce83da41d92000000610627565b5050565b60035461010090046001600160a01b031633146104ec57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052a57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056857600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105ba9084906107c7565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106159086815260200190565b60405180910390a35060019392505050565b60008160008082825461063a91906107de565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910161037e565b600060208083528351808285015260005b818110156106b95785810183015185820160400152820161069d565b818111156106cb576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106f857600080fd5b919050565b6000806040838503121561071057600080fd5b610719836106e1565b946020939093013593505050565b60008060006060848603121561073c57600080fd5b610745846106e1565b9250610753602085016106e1565b9150604084013590509250925092565b60006020828403121561077557600080fd5b610449826106e1565b6000806040838503121561079157600080fd5b61079a836106e1565b91506107a8602084016106e1565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107d9576107d96107b1565b500390565b600082198211156107f1576107f16107b1565b50019056fea2646970667358221220bebc3a2234b72bd2fd84b02793c989f9dfae6f8feb95470b1dc74a79df11e23a64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 13061, + "contract": "contracts/Velo.sol:Velo", + "label": "totalSupply", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 13065, + "contract": "contracts/Velo.sol:Velo", + "label": "balanceOf", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 13071, + "contract": "contracts/Velo.sol:Velo", + "label": "allowance", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 13073, + "contract": "contracts/Velo.sol:Velo", + "label": "initialMinted", + "offset": 0, + "slot": "3", + "type": "t_bool" + }, + { + "astId": 13075, + "contract": "contracts/Velo.sol:Velo", + "label": "minter", + "offset": 1, + "slot": "3", + "type": "t_address" + }, + { + "astId": 13077, + "contract": "contracts/Velo.sol:Velo", + "label": "redemptionReceiver", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 13079, + "contract": "contracts/Velo.sol:Velo", + "label": "merkleClaim", + "offset": 0, + "slot": "5", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/VeloGovernor.json b/deployments/arbitrumGoerli/VeloGovernor.json new file mode 100644 index 00000000..8cacd3f8 --- /dev/null +++ b/deployments/arbitrumGoerli/VeloGovernor.json @@ -0,0 +1,1459 @@ +{ + "address": "0x588ADD83f24690BceEbaa4266cd8DC65709DDa4d", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IVotes", + "name": "_ve", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "Empty", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "ProposalCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldQuorumNumerator", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newQuorumNumerator", + "type": "uint256" + } + ], + "name": "QuorumNumeratorUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "VoteCast", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "VoteCastWithParams", + "type": "event" + }, + { + "inputs": [], + "name": "BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COUNTING_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "EXTENDED_BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_PROPOSAL_NUMERATOR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PROPOSAL_DENOMINATOR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + } + ], + "name": "castVote", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "castVoteBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "castVoteWithReason", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "castVoteWithReasonAndParamsBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "execute", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockTimestamp", + "type": "uint256" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockTimestamp", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "getVotesWithParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasVoted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "hashProposal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalDeadline", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalNumerator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "againstVotes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "forVotes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "abstainVotes", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "propose", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "blockTimestamp", + "type": "uint256" + } + ], + "name": "quorum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "quorumDenominator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "quorumNumerator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "relay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "numerator", + "type": "uint256" + } + ], + "name": "setProposalNumerator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newTeam", + "type": "address" + } + ], + "name": "setTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "state", + "outputs": [ + { + "internalType": "enum IGovernor.ProposalState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "team", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IVotes", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newQuorumNumerator", + "type": "uint256" + } + ], + "name": "updateQuorumNumerator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "votingPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xc18cb1e92e23ab919bfab4ca664330e7c363affcd02e6ae98747baf66adecbac", + "receipt": { + "to": null, + "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", + "contractAddress": "0x588ADD83f24690BceEbaa4266cd8DC65709DDa4d", + "transactionIndex": 1, + "gasUsed": "30055138", + "logsBloom": "0x00000000000000000100000000001000000800000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7526fdc29a3710d3feed1075b4a5fb9e8833a49264dc170bde90e11923fe7b8f", + "transactionHash": "0xc18cb1e92e23ab919bfab4ca664330e7c363affcd02e6ae98747baf66adecbac", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 4195032, + "transactionHash": "0xc18cb1e92e23ab919bfab4ca664330e7c363affcd02e6ae98747baf66adecbac", + "address": "0x588ADD83f24690BceEbaa4266cd8DC65709DDa4d", + "topics": [ + "0x0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004", + "logIndex": 0, + "blockHash": "0x7526fdc29a3710d3feed1075b4a5fb9e8833a49264dc170bde90e11923fe7b8f" + } + ], + "blockNumber": 4195032, + "cumulativeGasUsed": "30055138", + "status": 1, + "byzantium": true + }, + "args": [ + "0x6b938BA22FB5520fFB5D14c9C4Fef82a48761497" + ], + "numDeployments": 3, + "solcInputHash": "0faaa79d8b79020b765ba7705413c447", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"_ve\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"Empty\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"proposer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"string[]\",\"name\":\"signatures\",\"type\":\"string[]\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"ProposalCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldQuorumNumerator\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"QuorumNumeratorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"VoteCast\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"VoteCastWithParams\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"COUNTING_MODE\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EXTENDED_BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_PROPOSAL_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROPOSAL_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"}],\"name\":\"castVote\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"castVoteWithReason\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"castVoteWithReasonAndParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteWithReasonAndParamsBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"execute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"getVotesWithParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasVoted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"hashProposal\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalDeadline\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalSnapshot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"againstVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"forVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"abstainVotes\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"propose\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"quorum\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumDenominator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"}],\"name\":\"setProposalNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTeam\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"state\",\"outputs\":[{\"internalType\":\"enum IGovernor.ProposalState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"updateQuorumNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"Empty()\":[{\"details\":\"An operation (e.g. {front}) couldn't be completed due to the queue being empty.\"}]},\"kind\":\"dev\",\"methods\":{\"COUNTING_MODE()\":{\"details\":\"See {IGovernor-COUNTING_MODE}.\"},\"castVote(uint256,uint8)\":{\"details\":\"See {IGovernor-castVote}.\"},\"castVoteBySig(uint256,uint8,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteBySig}.\"},\"castVoteWithReason(uint256,uint8,string)\":{\"details\":\"See {IGovernor-castVoteWithReason}.\"},\"castVoteWithReasonAndParams(uint256,uint8,string,bytes)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParams}.\"},\"castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParamsBySig}.\"},\"execute(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-execute}.\"},\"getVotes(address,uint256)\":{\"details\":\"See {IGovernor-getVotes}.\"},\"getVotesWithParams(address,uint256,bytes)\":{\"details\":\"See {IGovernor-getVotesWithParams}.\"},\"hasVoted(uint256,address)\":{\"details\":\"See {IGovernor-hasVoted}.\"},\"hashProposal(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-hashProposal}. The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in advance, before the proposal is submitted. Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the same proposal (with same operation and same description) will have the same id if submitted on multiple governors across multiple networks. This also means that in order to execute the same operation twice (on the same governor) the proposer will have to change the description in order to avoid proposal id conflicts.\"},\"name()\":{\"details\":\"See {IGovernor-name}.\"},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155BatchReceived}.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155Received}.\"},\"onERC721Received(address,address,uint256,bytes)\":{\"details\":\"See {IERC721Receiver-onERC721Received}.\"},\"proposalDeadline(uint256)\":{\"details\":\"See {IGovernor-proposalDeadline}.\"},\"proposalSnapshot(uint256)\":{\"details\":\"See {IGovernor-proposalSnapshot}.\"},\"proposalThreshold()\":{\"details\":\"Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\"},\"proposalVotes(uint256)\":{\"details\":\"Accessor to the internal vote counts.\"},\"propose(address[],uint256[],bytes[],string)\":{\"details\":\"See {IGovernor-propose}.\"},\"quorum(uint256)\":{\"details\":\"Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\"},\"quorumDenominator()\":{\"details\":\"Returns the quorum denominator. Defaults to 100, but may be overridden.\"},\"quorumNumerator()\":{\"details\":\"Returns the current quorum numerator. See {quorumDenominator}.\"},\"relay(address,uint256,bytes)\":{\"details\":\"Relays a transaction or function call to an arbitrary target. In cases where the governance executor is some contract other than the governor itself, like when using a timelock, this function can be invoked in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake. Note that if the executor is simply the governor itself, use of `relay` is redundant.\"},\"state(uint256)\":{\"details\":\"See {IGovernor-state}.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"updateQuorumNumerator(uint256)\":{\"details\":\"Changes the quorum numerator. Emits a {QuorumNumeratorUpdated} event. Requirements: - Must be called through a governance proposal. - New numerator must be smaller or equal to the denominator.\"},\"version()\":{\"details\":\"See {IGovernor-version}.\"},\"votingDelay()\":{\"details\":\"Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\"},\"votingPeriod()\":{\"details\":\"Delay, in number of blocks, between the vote start and vote ends. NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting duration compared to the voting delay.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"votingDelay()\":{\"notice\":\"module:user-config\"},\"votingPeriod()\":{\"notice\":\"module:user-config\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VeloGovernor.sol\":\"VeloGovernor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VeloGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IGovernor} from \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\nimport {L2GovernorCountingSimple} from \\\"contracts/governance/L2GovernorCountingSimple.sol\\\";\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\nimport {L2GovernorVotesQuorumFraction} from \\\"contracts/governance/L2GovernorVotesQuorumFraction.sol\\\";\\n\\ncontract VeloGovernor is\\n L2Governor,\\n L2GovernorCountingSimple,\\n L2GovernorVotes,\\n L2GovernorVotesQuorumFraction\\n{\\n address public team;\\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\\n uint256 public proposalNumerator = 2; // start at 0.02%\\n\\n constructor(IVotes _ve)\\n L2Governor(\\\"Velodrome Governor\\\")\\n L2GovernorVotes(_ve)\\n L2GovernorVotesQuorumFraction(4) // 4%\\n {\\n team = msg.sender;\\n }\\n\\n function votingDelay() public pure override(IGovernor) returns (uint256) {\\n return 15 minutes; // 1 block\\n }\\n\\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\\n return 1 weeks;\\n }\\n\\n function setTeam(address newTeam) external {\\n require(msg.sender == team, \\\"not team\\\");\\n team = newTeam;\\n }\\n\\n function setProposalNumerator(uint256 numerator) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \\\"numerator too high\\\");\\n proposalNumerator = numerator;\\n }\\n\\n function proposalThreshold()\\n public\\n view\\n override(L2Governor)\\n returns (uint256)\\n {\\n return\\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\\n PROPOSAL_DENOMINATOR;\\n }\\n}\\n\",\"keccak256\":\"0xbdbc34fd1c78fdffb528f7a2f450e75457cb089369204f4671ec241aa0eb3a7e\",\"license\":\"MIT\"},\"contracts/governance/L2Governor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Address.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Context.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\\n *\\n * @dev Core of the governance system, designed to be extended though various modules.\\n *\\n * This contract is abstract and requires several function to be implemented in various modules:\\n *\\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\\n * - A voting module must implement {_getVotes}\\n * - Additionanly, the {votingPeriod} must also be implemented\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\\n using SafeCast for uint256;\\n using Timers for Timers.Timestamp;\\n\\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\\\"Ballot(uint256 proposalId,uint8 support)\\\");\\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\\n keccak256(\\\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\\\");\\n\\n struct ProposalCore {\\n Timers.Timestamp voteStart;\\n Timers.Timestamp voteEnd;\\n bool executed;\\n bool canceled;\\n }\\n\\n string private _name;\\n\\n mapping(uint256 => ProposalCore) private _proposals;\\n\\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\\n\\n /**\\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\\n * parameter setters in {GovernorSettings} are protected using this modifier.\\n *\\n * The governance executing address may be different from the Governor's own address, for example it could be a\\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\\n * for example, additional timelock proposers are not able to change governance parameters without going through the\\n * governance protocol (since v4.6).\\n */\\n modifier onlyGovernance() {\\n require(_msgSender() == _executor(), \\\"Governor: onlyGovernance\\\");\\n if (_executor() != address(this)) {\\n bytes32 msgDataHash = keccak256(_msgData());\\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\\n while (_governanceCall.popFront() != msgDataHash) {}\\n }\\n _;\\n }\\n\\n /**\\n * @dev Sets the value for {name} and {version}\\n */\\n constructor(string memory name_) EIP712(name_, version()) {\\n _name = name_;\\n }\\n\\n /**\\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\\n */\\n receive() external payable virtual {\\n require(_executor() == address(this));\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\\n // include the castVoteWithReasonAndParams() function as standard\\n return\\n interfaceId ==\\n (type(IGovernor).interfaceId ^\\n this.castVoteWithReasonAndParams.selector ^\\n this.castVoteWithReasonAndParamsBySig.selector ^\\n this.getVotesWithParams.selector) ||\\n interfaceId == type(IGovernor).interfaceId ||\\n interfaceId == type(IERC1155Receiver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IGovernor-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IGovernor-version}.\\n */\\n function version() public view virtual override returns (string memory) {\\n return \\\"1\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hashProposal}.\\n *\\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\\n * advance, before the proposal is submitted.\\n *\\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual override returns (uint256) {\\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\\n }\\n\\n /**\\n * @dev See {IGovernor-state}.\\n */\\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n\\n if (proposal.executed) {\\n return ProposalState.Executed;\\n }\\n\\n if (proposal.canceled) {\\n return ProposalState.Canceled;\\n }\\n\\n uint256 start = proposalSnapshot(proposalId);\\n\\n if (start == 0) {\\n revert(\\\"Governor: unknown proposal id\\\");\\n }\\n\\n if (start >= block.timestamp) {\\n return ProposalState.Pending;\\n }\\n\\n uint256 deadline = proposalDeadline(proposalId);\\n\\n if (deadline >= block.timestamp) {\\n return ProposalState.Active;\\n }\\n\\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\\n return ProposalState.Succeeded;\\n } else {\\n return ProposalState.Defeated;\\n }\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalSnapshot}.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteStart.getDeadline();\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalDeadline}.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteEnd.getDeadline();\\n }\\n\\n /**\\n * @dev Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\\n */\\n function proposalThreshold() public view virtual returns (uint256) {\\n return 0;\\n }\\n\\n /**\\n * @dev Amount of votes already cast passes the threshold limit.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Is the proposal successful or not.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) internal view virtual returns (uint256);\\n\\n /**\\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\\n *\\n * Note: Support is generic and can represent various things depending on the voting system used.\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory params\\n ) internal virtual;\\n\\n /**\\n * @dev Default additional encoded parameters used by castVote methods that don't include them\\n *\\n * Note: Should be overridden by specific implementations to use an appropriate value, the\\n * meaning of the additional params, in the context of that implementation\\n */\\n function _defaultParams() internal view virtual returns (bytes memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-propose}.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual override returns (uint256) {\\n require(\\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\\n \\\"Governor: proposer votes below proposal threshold\\\"\\n );\\n\\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\\n\\n require(targets.length == values.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length == calldatas.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length > 0, \\\"Governor: empty proposal\\\");\\n\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(proposal.voteStart.isUnset(), \\\"Governor: proposal already exists\\\");\\n\\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\\n uint64 deadline = start + votingPeriod().toUint64();\\n\\n proposal.voteStart.setDeadline(start);\\n proposal.voteEnd.setDeadline(deadline);\\n\\n emit ProposalCreated(\\n proposalId,\\n _msgSender(),\\n targets,\\n values,\\n new string[](targets.length),\\n calldatas,\\n start,\\n deadline,\\n description\\n );\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-execute}.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual override returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n\\n ProposalState status = state(proposalId);\\n require(\\n status == ProposalState.Succeeded || status == ProposalState.Queued,\\n \\\"Governor: proposal not successful\\\"\\n );\\n _proposals[proposalId].executed = true;\\n\\n emit ProposalExecuted(proposalId);\\n\\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\\n _execute(proposalId, targets, values, calldatas, descriptionHash);\\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\\n */\\n function _execute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n string memory errorMessage = \\\"Governor: call reverted without message\\\";\\n for (uint256 i = 0; i < targets.length; ++i) {\\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\\n Address.verifyCallResult(success, returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Hook before execution is triggered.\\n */\\n function _beforeExecute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory, /* values */\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n for (uint256 i = 0; i < targets.length; ++i) {\\n if (targets[i] == address(this)) {\\n _governanceCall.pushBack(keccak256(calldatas[i]));\\n }\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook after execution is triggered.\\n */\\n function _afterExecute(\\n uint256, /* proposalId */\\n address[] memory, /* targets */\\n uint256[] memory, /* values */\\n bytes[] memory, /* calldatas */\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n if (!_governanceCall.empty()) {\\n _governanceCall.clear();\\n }\\n }\\n }\\n\\n /**\\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\\n * canceled to allow distinguishing it from executed proposals.\\n *\\n * Emits a {IGovernor-ProposalCanceled} event.\\n */\\n function _cancel(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) internal virtual returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n ProposalState status = state(proposalId);\\n\\n require(\\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\\n \\\"Governor: proposal not active\\\"\\n );\\n _proposals[proposalId].canceled = true;\\n\\n emit ProposalCanceled(proposalId);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotes}.\\n */\\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, _defaultParams());\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotesWithParams}.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVote}.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReason}.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteBySig}.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\\n v,\\n r,\\n s\\n );\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(\\n keccak256(\\n abi.encode(\\n EXTENDED_BALLOT_TYPEHASH,\\n proposalId,\\n support,\\n keccak256(bytes(reason)),\\n keccak256(params)\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason\\n ) internal virtual returns (uint256) {\\n return _castVote(proposalId, account, support, reason, _defaultParams());\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason,\\n bytes memory params\\n ) internal virtual returns (uint256) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(state(proposalId) == ProposalState.Active, \\\"Governor: vote not currently active\\\");\\n\\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\\n _countVote(proposalId, account, support, weight, params);\\n\\n if (params.length == 0) {\\n emit VoteCast(account, proposalId, support, weight, reason);\\n } else {\\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\\n }\\n\\n return weight;\\n }\\n\\n /**\\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\\n */\\n function relay(\\n address target,\\n uint256 value,\\n bytes calldata data\\n ) external virtual onlyGovernance {\\n Address.functionCallWithValue(target, data, value);\\n }\\n\\n /**\\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\\n * through another contract such as a timelock.\\n */\\n function _executor() internal view virtual returns (address) {\\n return address(this);\\n }\\n\\n /**\\n * @dev See {IERC721Receiver-onERC721Received}.\\n */\\n function onERC721Received(\\n address,\\n address,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155Received}.\\n */\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\\n */\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] memory,\\n uint256[] memory,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155BatchReceived.selector;\\n }\\n}\\n\",\"keccak256\":\"0xa2846313b89a871807cdebd0225b0bf8f23b17505ab8b3288549ec54a5a4a71b\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorCountingSimple.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\\n *\\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorCountingSimple is L2Governor {\\n /**\\n * @dev Supported vote types. Matches Governor Bravo ordering.\\n */\\n enum VoteType {\\n Against,\\n For,\\n Abstain\\n }\\n\\n struct ProposalVote {\\n uint256 againstVotes;\\n uint256 forVotes;\\n uint256 abstainVotes;\\n mapping(address => bool) hasVoted;\\n }\\n\\n mapping(uint256 => ProposalVote) private _proposalVotes;\\n\\n /**\\n * @dev See {IGovernor-COUNTING_MODE}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual override returns (string memory) {\\n return \\\"support=bravo&quorum=for,abstain\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hasVoted}.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\\n return _proposalVotes[proposalId].hasVoted[account];\\n }\\n\\n /**\\n * @dev Accessor to the internal vote counts.\\n */\\n function proposalVotes(uint256 proposalId)\\n public\\n view\\n virtual\\n returns (\\n uint256 againstVotes,\\n uint256 forVotes,\\n uint256 abstainVotes\\n )\\n {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\\n }\\n\\n /**\\n * @dev See {Governor-_quorumReached}.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return proposalvote.forVotes > proposalvote.againstVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory // params\\n ) internal virtual override {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n require(!proposalvote.hasVoted[account], \\\"GovernorVotingSimple: vote already cast\\\");\\n proposalvote.hasVoted[account] = true;\\n\\n if (support == uint8(VoteType.Against)) {\\n proposalvote.againstVotes += weight;\\n } else if (support == uint8(VoteType.For)) {\\n proposalvote.forVotes += weight;\\n } else if (support == uint8(VoteType.Abstain)) {\\n proposalvote.abstainVotes += weight;\\n } else {\\n revert(\\\"GovernorVotingSimple: invalid value for enum VoteType\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xdc37daa24118a6e6ba5208b4abefa1632af2ff340135ca6c6d7237f70102d5db\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotes is L2Governor {\\n IVotes public immutable token;\\n\\n constructor(IVotes tokenAddress) {\\n token = tokenAddress;\\n }\\n\\n /**\\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory /*params*/\\n ) internal view virtual override returns (uint256) {\\n return token.getPastVotes(account, blockTimestamp);\\n }\\n}\\n\",\"keccak256\":\"0x605a7de71228dda3cb8fd878cac313a86bc5841fd34d7344214346ba46e63af1\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotesQuorumFraction.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\\n * fraction of the total supply.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\\n uint256 private _quorumNumerator;\\n\\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\\n\\n /**\\n * @dev Initialize quorum as a fraction of the token's total supply.\\n *\\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\\n * customized by overriding {quorumDenominator}.\\n */\\n constructor(uint256 quorumNumeratorValue) {\\n _updateQuorumNumerator(quorumNumeratorValue);\\n }\\n\\n /**\\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\\n */\\n function quorumNumerator() public view virtual returns (uint256) {\\n return _quorumNumerator;\\n }\\n\\n /**\\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\\n */\\n function quorumDenominator() public view virtual returns (uint256) {\\n return 100;\\n }\\n\\n /**\\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\\n */\\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - Must be called through a governance proposal.\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\\n _updateQuorumNumerator(newQuorumNumerator);\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\\n require(\\n newQuorumNumerator <= quorumDenominator(),\\n \\\"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\\\"\\n );\\n\\n uint256 oldQuorumNumerator = _quorumNumerator;\\n _quorumNumerator = newQuorumNumerator;\\n\\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\\n }\\n}\\n\",\"keccak256\":\"0xe66d29c0ffd2274de933d80e11d68891f3acc3f078be4560a2b493b7d88dcb7f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Interface of the {Governor} core.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract IGovernor is IERC165 {\\n enum ProposalState {\\n Pending,\\n Active,\\n Canceled,\\n Defeated,\\n Succeeded,\\n Queued,\\n Expired,\\n Executed\\n }\\n\\n /**\\n * @dev Emitted when a proposal is created.\\n */\\n event ProposalCreated(\\n uint256 proposalId,\\n address proposer,\\n address[] targets,\\n uint256[] values,\\n string[] signatures,\\n bytes[] calldatas,\\n uint256 startBlock,\\n uint256 endBlock,\\n string description\\n );\\n\\n /**\\n * @dev Emitted when a proposal is canceled.\\n */\\n event ProposalCanceled(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a proposal is executed.\\n */\\n event ProposalExecuted(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a vote is cast without params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n */\\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\\n\\n /**\\n * @dev Emitted when a vote is cast with params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\\n */\\n event VoteCastWithParams(\\n address indexed voter,\\n uint256 proposalId,\\n uint8 support,\\n uint256 weight,\\n string reason,\\n bytes params\\n );\\n\\n /**\\n * @notice module:core\\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\\n */\\n function name() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \\\"1\\\"\\n */\\n function version() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:voting\\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\\n *\\n * There are 2 standard keys: `support` and `quorum`.\\n *\\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\\n * - `quorum=bravo` means that only For votes are counted towards quorum.\\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\\n *\\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\\n * name that describes the behavior. For example:\\n *\\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\\n *\\n * NOTE: The string can be decoded by the standard\\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\\n * JavaScript class.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Current state of a proposal, following Compound's convention\\n */\\n function state(uint256 proposalId) public view virtual returns (ProposalState);\\n\\n /**\\n * @notice module:core\\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\\n * beginning of the following block.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\\n * during this block.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\\n */\\n function votingDelay() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of blocks, between the vote start and vote ends.\\n *\\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\\n * duration compared to the voting delay.\\n */\\n function votingPeriod() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Minimum number of cast voted required for a proposal to be successful.\\n *\\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\\n */\\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber`.\\n *\\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\\n * multiple), {ERC20Votes} tokens.\\n */\\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockNumber,\\n bytes memory params\\n ) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:voting\\n * @dev Returns whether `account` has cast a vote on `proposalId`.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\\n\\n /**\\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\\n * {IGovernor-votingPeriod} blocks after the voting starts.\\n *\\n * Emits a {ProposalCreated} event.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\\n * deadline to be reached.\\n *\\n * Emits a {ProposalExecuted} event.\\n *\\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Cast a vote\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xa52d593ff06a2353f78fa149da31f2ca94f03d1eff99bde41977fa2fe985a92f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2e53602b96c1bf97c731ed3e2a981b4f85e23a9410a5ebd36e549a4cc93340dc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x2626d8ab3dfdad0fad630c212ad146d59473d0f48b771784c61a7c1dbbea1f3f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Tooling for timepoints, timers and delays\\n */\\nlibrary Timers {\\n struct Timestamp {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(Timestamp storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(Timestamp memory timer) internal view returns (bool) {\\n return timer._deadline > block.timestamp;\\n }\\n\\n function isExpired(Timestamp memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.timestamp;\\n }\\n\\n struct BlockNumber {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(BlockNumber storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(BlockNumber memory timer) internal view returns (bool) {\\n return timer._deadline > block.number;\\n }\\n\\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.number;\\n }\\n}\\n\",\"keccak256\":\"0x29791a62950a7983e02a673639c1a781d1e448691800456c2ce4b99715391b14\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS,\\n InvalidSignatureV // Deprecated in v4.8\\n }\\n\\n function _throwError(RecoverError error) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert(\\\"ECDSA: invalid signature\\\");\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert(\\\"ECDSA: invalid signature 's' value\\\");\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature` or error string. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\\n if (signature.length == 65) {\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n /// @solidity memory-safe-assembly\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n return tryRecover(hash, v, r, s);\\n } else {\\n return (address(0), RecoverError.InvalidSignatureLength);\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, signature);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n *\\n * _Available since v4.2._\\n */\\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature);\\n }\\n\\n return (signer, RecoverError.NoError);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from `s`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", Strings.toString(s.length), s));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Typed Data, created from a\\n * `domainSeparator` and a `structHash`. This produces hash corresponding\\n * to the one signed with the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\\n * JSON-RPC method as part of EIP-712.\\n *\\n * See {recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n }\\n}\\n\",\"keccak256\":\"0x54ee424bfc83ce63b2a918b9a1efb5090a0fb68dbd1de3b10bc667776885dd4f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ECDSA.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n /* solhint-disable var-name-mixedcase */\\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n // invalidate the cached domain separator if the chain id changes.\\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n uint256 private immutable _CACHED_CHAIN_ID;\\n address private immutable _CACHED_THIS;\\n\\n bytes32 private immutable _HASHED_NAME;\\n bytes32 private immutable _HASHED_VERSION;\\n bytes32 private immutable _TYPE_HASH;\\n\\n /* solhint-enable var-name-mixedcase */\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n constructor(string memory name, string memory version) {\\n bytes32 hashedName = keccak256(bytes(name));\\n bytes32 hashedVersion = keccak256(bytes(version));\\n bytes32 typeHash = keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n );\\n _HASHED_NAME = hashedName;\\n _HASHED_VERSION = hashedVersion;\\n _CACHED_CHAIN_ID = block.chainid;\\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n _CACHED_THIS = address(this);\\n _TYPE_HASH = typeHash;\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\\n return _CACHED_DOMAIN_SEPARATOR;\\n } else {\\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n }\\n }\\n\\n function _buildDomainSeparator(\\n bytes32 typeHash,\\n bytes32 nameHash,\\n bytes32 versionHash\\n ) private view returns (bytes32) {\\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\\n }\\n}\\n\",\"keccak256\":\"0x948d8b2d18f38141ec78c5229d770d950ebc781ed3f44cc9e3ccbb9fded5846a\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\\n\\nimport \\\"./EIP712.sol\\\";\\n\",\"keccak256\":\"0xea30c402170bc240354b74e6c6f6a8e5bdb1935d90d168cc58c0654461c6a72b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3546b156d97633f7f8cad536d5454c81d1d604687c02b2eb105fdc33cb962b41\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\\npragma solidity ^0.8.4;\\n\\nimport \\\"../math/SafeCast.sol\\\";\\n\\n/**\\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\\n * the existing queue contents are left in storage.\\n *\\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\\n * used in storage, and not in memory.\\n * ```\\n * DoubleEndedQueue.Bytes32Deque queue;\\n * ```\\n *\\n * _Available since v4.6._\\n */\\nlibrary DoubleEndedQueue {\\n /**\\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\\n */\\n error Empty();\\n\\n /**\\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\\n */\\n error OutOfBounds();\\n\\n /**\\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\\n *\\n * Struct members have an underscore prefix indicating that they are \\\"private\\\" and should not be read or written to\\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\\n * lead to unexpected behavior.\\n *\\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\\n * data[end - 1].\\n */\\n struct Bytes32Deque {\\n int128 _begin;\\n int128 _end;\\n mapping(int128 => bytes32) _data;\\n }\\n\\n /**\\n * @dev Inserts an item at the end of the queue.\\n */\\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 backIndex = deque._end;\\n deque._data[backIndex] = value;\\n unchecked {\\n deque._end = backIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Removes the item at the end of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n value = deque._data[backIndex];\\n delete deque._data[backIndex];\\n deque._end = backIndex;\\n }\\n\\n /**\\n * @dev Inserts an item at the beginning of the queue.\\n */\\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 frontIndex;\\n unchecked {\\n frontIndex = deque._begin - 1;\\n }\\n deque._data[frontIndex] = value;\\n deque._begin = frontIndex;\\n }\\n\\n /**\\n * @dev Removes the item at the beginning of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n value = deque._data[frontIndex];\\n delete deque._data[frontIndex];\\n unchecked {\\n deque._begin = frontIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Returns the item at the beginning of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n return deque._data[frontIndex];\\n }\\n\\n /**\\n * @dev Returns the item at the end of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n return deque._data[backIndex];\\n }\\n\\n /**\\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\\n * `length(deque) - 1`.\\n *\\n * Reverts with `OutOfBounds` if the index is out of bounds.\\n */\\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\\n // int256(deque._begin) is a safe upcast\\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\\n if (idx >= deque._end) revert OutOfBounds();\\n return deque._data[idx];\\n }\\n\\n /**\\n * @dev Resets the queue back to being empty.\\n *\\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\\n * out on potential gas refunds.\\n */\\n function clear(Bytes32Deque storage deque) internal {\\n deque._begin = 0;\\n deque._end = 0;\\n }\\n\\n /**\\n * @dev Returns the number of items in the queue.\\n */\\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\\n // We also assume there are at most int256.max items in the queue.\\n unchecked {\\n return uint256(int256(deque._end) - int256(deque._begin));\\n }\\n }\\n\\n /**\\n * @dev Returns true if the queue is empty.\\n */\\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\\n return deque._end <= deque._begin;\\n }\\n}\\n\",\"keccak256\":\"0x4859ffd6dd69382a1462930c00b6e394007da80e78e510f56930271034737bf2\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x61016060405260026007553480156200001757600080fd5b506040516200328f3803806200328f8339810160408190526200003a91620002e1565b600481604051806040016040528060128152602001712b32b637b23937b6b29023b7bb32b93737b960711b81525080620000796200015360201b60201c565b815160208084019190912082518383012060e08290526101008190524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81880181905281830187905260608201869052608082019490945230818401528151808203909301835260c00190528051940193909320919290916080523060c05261012052505082516200011f92506000915060208401906200023b565b50506001600160a01b03166101405262000139816200016e565b5050600680546001600160a01b031916331790556200034f565b6040805180820190915260018152603160f81b602082015290565b6064811115620001f65760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a40160405180910390fd5b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b828054620002499062000313565b90600052602060002090601f0160209004810192826200026d5760008555620002b8565b82601f106200028857805160ff1916838001178555620002b8565b82800160010185558215620002b8579182015b82811115620002b85782518255916020019190600101906200029b565b50620002c6929150620002ca565b5090565b5b80821115620002c65760008155600101620002cb565b600060208284031215620002f457600080fd5b81516001600160a01b03811681146200030c57600080fd5b9392505050565b600181811c908216806200032857607f821691505b6020821081036200034957634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e051610100516101205161014051612ed0620003bf600039600081816107df0152818161120f015281816113e40152611a0601526000611b2301526000611b7201526000611b4d01526000611aa601526000611ad001526000611afa0152612ed06000f3fe6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220fff679e9a49aa645f41ec6b78c9165ce8e728c549ab43d25df657d05e22c9d7664736f6c634300080d0033", + "deployedBytecode": "0x6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220fff679e9a49aa645f41ec6b78c9165ce8e728c549ab43d25df657d05e22c9d7664736f6c634300080d0033", + "devdoc": { + "errors": { + "Empty()": [ + { + "details": "An operation (e.g. {front}) couldn't be completed due to the queue being empty." + } + ] + }, + "kind": "dev", + "methods": { + "COUNTING_MODE()": { + "details": "See {IGovernor-COUNTING_MODE}." + }, + "castVote(uint256,uint8)": { + "details": "See {IGovernor-castVote}." + }, + "castVoteBySig(uint256,uint8,uint8,bytes32,bytes32)": { + "details": "See {IGovernor-castVoteBySig}." + }, + "castVoteWithReason(uint256,uint8,string)": { + "details": "See {IGovernor-castVoteWithReason}." + }, + "castVoteWithReasonAndParams(uint256,uint8,string,bytes)": { + "details": "See {IGovernor-castVoteWithReasonAndParams}." + }, + "castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32)": { + "details": "See {IGovernor-castVoteWithReasonAndParamsBySig}." + }, + "execute(address[],uint256[],bytes[],bytes32)": { + "details": "See {IGovernor-execute}." + }, + "getVotes(address,uint256)": { + "details": "See {IGovernor-getVotes}." + }, + "getVotesWithParams(address,uint256,bytes)": { + "details": "See {IGovernor-getVotesWithParams}." + }, + "hasVoted(uint256,address)": { + "details": "See {IGovernor-hasVoted}." + }, + "hashProposal(address[],uint256[],bytes[],bytes32)": { + "details": "See {IGovernor-hashProposal}. The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in advance, before the proposal is submitted. Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the same proposal (with same operation and same description) will have the same id if submitted on multiple governors across multiple networks. This also means that in order to execute the same operation twice (on the same governor) the proposer will have to change the description in order to avoid proposal id conflicts." + }, + "name()": { + "details": "See {IGovernor-name}." + }, + "onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)": { + "details": "See {IERC1155Receiver-onERC1155BatchReceived}." + }, + "onERC1155Received(address,address,uint256,uint256,bytes)": { + "details": "See {IERC1155Receiver-onERC1155Received}." + }, + "onERC721Received(address,address,uint256,bytes)": { + "details": "See {IERC721Receiver-onERC721Received}." + }, + "proposalDeadline(uint256)": { + "details": "See {IGovernor-proposalDeadline}." + }, + "proposalSnapshot(uint256)": { + "details": "See {IGovernor-proposalSnapshot}." + }, + "proposalThreshold()": { + "details": "Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_." + }, + "proposalVotes(uint256)": { + "details": "Accessor to the internal vote counts." + }, + "propose(address[],uint256[],bytes[],string)": { + "details": "See {IGovernor-propose}." + }, + "quorum(uint256)": { + "details": "Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`." + }, + "quorumDenominator()": { + "details": "Returns the quorum denominator. Defaults to 100, but may be overridden." + }, + "quorumNumerator()": { + "details": "Returns the current quorum numerator. See {quorumDenominator}." + }, + "relay(address,uint256,bytes)": { + "details": "Relays a transaction or function call to an arbitrary target. In cases where the governance executor is some contract other than the governor itself, like when using a timelock, this function can be invoked in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake. Note that if the executor is simply the governor itself, use of `relay` is redundant." + }, + "state(uint256)": { + "details": "See {IGovernor-state}." + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + }, + "updateQuorumNumerator(uint256)": { + "details": "Changes the quorum numerator. Emits a {QuorumNumeratorUpdated} event. Requirements: - Must be called through a governance proposal. - New numerator must be smaller or equal to the denominator." + }, + "version()": { + "details": "See {IGovernor-version}." + }, + "votingDelay()": { + "details": "Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to leave time for users to buy voting power, or delegate it, before the voting of a proposal starts." + }, + "votingPeriod()": { + "details": "Delay, in number of blocks, between the vote start and vote ends. NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting duration compared to the voting delay." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "votingDelay()": { + "notice": "module:user-config" + }, + "votingPeriod()": { + "notice": "module:user-config" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 21935, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "_name", + "offset": 0, + "slot": "0", + "type": "t_string_storage" + }, + { + "astId": 21940, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "_proposals", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_uint256,t_struct(ProposalCore)21933_storage)" + }, + { + "astId": 21943, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "_governanceCall", + "offset": 0, + "slot": "2", + "type": "t_struct(Bytes32Deque)30247_storage" + }, + { + "astId": 23199, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "_proposalVotes", + "offset": 0, + "slot": "4", + "type": "t_mapping(t_uint256,t_struct(ProposalVote)23194_storage)" + }, + { + "astId": 23452, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "_quorumNumerator", + "offset": 0, + "slot": "5", + "type": "t_uint256" + }, + { + "astId": 13423, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "team", + "offset": 0, + "slot": "6", + "type": "t_address" + }, + { + "astId": 13432, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "proposalNumerator", + "offset": 0, + "slot": "7", + "type": "t_uint256" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_int128": { + "encoding": "inplace", + "label": "int128", + "numberOfBytes": "16" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_int128,t_bytes32)": { + "encoding": "mapping", + "key": "t_int128", + "label": "mapping(int128 => bytes32)", + "numberOfBytes": "32", + "value": "t_bytes32" + }, + "t_mapping(t_uint256,t_struct(ProposalCore)21933_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct L2Governor.ProposalCore)", + "numberOfBytes": "32", + "value": "t_struct(ProposalCore)21933_storage" + }, + "t_mapping(t_uint256,t_struct(ProposalVote)23194_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct L2GovernorCountingSimple.ProposalVote)", + "numberOfBytes": "32", + "value": "t_struct(ProposalVote)23194_storage" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Bytes32Deque)30247_storage": { + "encoding": "inplace", + "label": "struct DoubleEndedQueue.Bytes32Deque", + "members": [ + { + "astId": 30240, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "_begin", + "offset": 0, + "slot": "0", + "type": "t_int128" + }, + { + "astId": 30242, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "_end", + "offset": 16, + "slot": "0", + "type": "t_int128" + }, + { + "astId": 30246, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "_data", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_int128,t_bytes32)" + } + ], + "numberOfBytes": "64" + }, + "t_struct(ProposalCore)21933_storage": { + "encoding": "inplace", + "label": "struct L2Governor.ProposalCore", + "members": [ + { + "astId": 21925, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "voteStart", + "offset": 0, + "slot": "0", + "type": "t_struct(Timestamp)26448_storage" + }, + { + "astId": 21928, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "voteEnd", + "offset": 0, + "slot": "1", + "type": "t_struct(Timestamp)26448_storage" + }, + { + "astId": 21930, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "executed", + "offset": 0, + "slot": "2", + "type": "t_bool" + }, + { + "astId": 21932, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "canceled", + "offset": 1, + "slot": "2", + "type": "t_bool" + } + ], + "numberOfBytes": "96" + }, + "t_struct(ProposalVote)23194_storage": { + "encoding": "inplace", + "label": "struct L2GovernorCountingSimple.ProposalVote", + "members": [ + { + "astId": 23185, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "againstVotes", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 23187, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "forVotes", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 23189, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "abstainVotes", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 23193, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "hasVoted", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_address,t_bool)" + } + ], + "numberOfBytes": "128" + }, + "t_struct(Timestamp)26448_storage": { + "encoding": "inplace", + "label": "struct Timers.Timestamp", + "members": [ + { + "astId": 26447, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "_deadline", + "offset": 0, + "slot": "0", + "type": "t_uint64" + } + ], + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint64": { + "encoding": "inplace", + "label": "uint64", + "numberOfBytes": "8" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/VelodromeLibrary.json b/deployments/arbitrumGoerli/VelodromeLibrary.json new file mode 100644 index 00000000..7ed248e2 --- /dev/null +++ b/deployments/arbitrumGoerli/VelodromeLibrary.json @@ -0,0 +1,229 @@ +{ + "address": "0x233ed5d7FAed19F7b8A28844E2845FBF0F145Be2", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_router", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getAmountOut", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getMinimumValue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getSample", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getTradeDiff", + "outputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "pair", + "type": "address" + } + ], + "name": "getTradeDiff", + "outputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xf0eab16bc0468726fdb1b4a50c842a9b8f0cbb15ab4412a36413aca09091f354", + "receipt": { + "to": null, + "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", + "contractAddress": "0x233ed5d7FAed19F7b8A28844E2845FBF0F145Be2", + "transactionIndex": 1, + "gasUsed": "9031975", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xe561c641dd7efbe9c84d2d477b154d7c9b6ad54bba72181943437038772a4b4d", + "transactionHash": "0xf0eab16bc0468726fdb1b4a50c842a9b8f0cbb15ab4412a36413aca09091f354", + "logs": [], + "blockNumber": 4195016, + "cumulativeGasUsed": "9031975", + "status": 1, + "byzantium": true + }, + "args": [ + "0xCeaEA7A5cB3e7521DdE6717BCc99a4c8c60E07b6" + ], + "numDeployments": 4, + "solcInputHash": "0faaa79d8b79020b765ba7705413c447", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getMinimumValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getSample\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VelodromeLibrary.sol\":\"VelodromeLibrary\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VelodromeLibrary.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\n\\ncontract VelodromeLibrary {\\n IRouter internal immutable router;\\n\\n constructor(address _router) {\\n router = IRouter(_router);\\n }\\n\\n function _f(uint x0, uint y) internal pure returns (uint) {\\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\\n }\\n\\n function _d(uint x0, uint y) internal pure returns (uint) {\\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\\n }\\n\\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\\n for (uint i = 0; i < 255; i++) {\\n uint y_prev = y;\\n uint k = _f(x0, y);\\n if (k < xy) {\\n uint dy = (xy - k)*1e18/_d(x0, y);\\n y = y + dy;\\n } else {\\n uint dy = (k - xy)*1e18/_d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n }\\n\\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return (sample, r0, r1);\\n }\\n\\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\\n if (stable) {\\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\\n _reserve0 = _reserve0 * 1e18 / decimals0;\\n _reserve1 = _reserve1 * 1e18 / decimals1;\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\\n } else {\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n return amountIn * reserveB / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\\n if (stable) {\\n uint _x = x * 1e18 / decimals0;\\n uint _y = y * 1e18 / decimals1;\\n uint _a = (_x * _y) / 1e18;\\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return _a * _b / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n \\n}\\n\",\"keccak256\":\"0x01df9d4f97d905560776a0b2d29e6dc1337dc952fdc3d8bfbfde99a510a62c1c\",\"license\":\"MIT\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"}},\"version\":1}", + "bytecode": "0x60a060405234801561001057600080fd5b5060405161100238038061100283398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051610f626100a06000396000818161010c015281816102730152818161043701526105cb0152610f626000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea264697066735822122015bc5301a8c944c3cc07f793e4c65b7813134e5409dcbb6cdc0a4a1f3cf42a2e64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea264697066735822122015bc5301a8c944c3cc07f793e4c65b7813134e5409dcbb6cdc0a4a1f3cf42a2e64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/Voter.json b/deployments/arbitrumGoerli/Voter.json new file mode 100644 index 00000000..6b991390 --- /dev/null +++ b/deployments/arbitrumGoerli/Voter.json @@ -0,0 +1,1418 @@ +{ + "address": "0x574607c69f369f0535E77C5F7C35767Aee04879A", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "__ve", + "type": "address" + }, + { + "internalType": "address", + "name": "_factory", + "type": "address" + }, + { + "internalType": "address", + "name": "_gauges", + "type": "address" + }, + { + "internalType": "address", + "name": "_bribes", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + } + ], + "name": "Abstained", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Attach", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "lp", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Detach", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DistributeReward", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "internal_bribe", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "external_bribe", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "GaugeCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + } + ], + "name": "GaugeKilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + } + ], + "name": "GaugeRevived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "reward", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "NotifyReward", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + } + ], + "name": "Voted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "whitelister", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "Whitelisted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "lp", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [], + "name": "_ve", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "attachTokenToGauge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bribefactory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_bribes", + "type": "address[]" + }, + { + "internalType": "address[][]", + "name": "_tokens", + "type": "address[][]" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "claimBribes", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_fees", + "type": "address[]" + }, + { + "internalType": "address[][]", + "name": "_tokens", + "type": "address[][]" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "claimFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_gauges", + "type": "address[]" + }, + { + "internalType": "address[][]", + "name": "_tokens", + "type": "address[][]" + } + ], + "name": "claimRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "claimable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_pool", + "type": "address" + } + ], + "name": "createGauge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "detachTokenFromGauge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_gauges", + "type": "address[]" + } + ], + "name": "distribute", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gauge", + "type": "address" + } + ], + "name": "distribute", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "start", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "finish", + "type": "uint256" + } + ], + "name": "distribute", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "distribute", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_gauges", + "type": "address[]" + } + ], + "name": "distributeFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "distro", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "emergencyCouncil", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "emitDeposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "emitWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "external_bribes", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gaugefactory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "gauges", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_tokens", + "type": "address[]" + }, + { + "internalType": "address", + "name": "_minter", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "internal_bribes", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isAlive", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isGauge", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isWhitelisted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gauge", + "type": "address" + } + ], + "name": "killGauge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "lastVoted", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "length", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "notifyRewardAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "poke", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "poolForGauge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "poolVote", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "pools", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "reset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gauge", + "type": "address" + } + ], + "name": "reviveGauge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_council", + "type": "address" + } + ], + "name": "setEmergencyCouncil", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_governor", + "type": "address" + } + ], + "name": "setGovernor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalWeight", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "updateAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_gauges", + "type": "address[]" + } + ], + "name": "updateFor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "start", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "end", + "type": "uint256" + } + ], + "name": "updateForRange", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gauge", + "type": "address" + } + ], + "name": "updateGauge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "usedWeights", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "_poolVote", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "_weights", + "type": "uint256[]" + } + ], + "name": "vote", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "votes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "weights", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + } + ], + "name": "whitelist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x863a7c9537e8bb10b2707a78c987cdbd068dc5e29785757d2ab4c0345f3da75f", + "receipt": { + "to": null, + "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", + "contractAddress": "0x574607c69f369f0535E77C5F7C35767Aee04879A", + "transactionIndex": 1, + "gasUsed": "30733498", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xfc9c943e85b7244024dc971ca02ed5f6ddf6a55352731bd5806c62f354ec813f", + "transactionHash": "0x863a7c9537e8bb10b2707a78c987cdbd068dc5e29785757d2ab4c0345f3da75f", + "logs": [], + "blockNumber": 4195024, + "cumulativeGasUsed": "30733498", + "status": 1, + "byzantium": true + }, + "args": [ + "0x6b938BA22FB5520fFB5D14c9C4Fef82a48761497", + "0x7488AC81DC3908ff7141db4949e70D60A3Fd4DCc", + "0x1Ac3032Dfd7e206BA6d08F453f38593b9A583052", + "0x5542edb529F7c963583e9B8e5339121cFCf4B606" + ], + "numDeployments": 3, + "solcInputHash": "0faaa79d8b79020b765ba7705413c447", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_gauges\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_bribes\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Abstained\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Attach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Detach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributeReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"internal_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"external_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"name\":\"GaugeCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeKilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeRevived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"reward\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NotifyReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Voted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"whitelister\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"Whitelisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"attachTokenToGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bribefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_bribes\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimBribes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_fees\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"}],\"name\":\"claimRewards\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"detachTokenFromGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"finish\",\"type\":\"uint256\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distributeFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distro\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"emergencyCouncil\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"external_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gaugefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"gauges\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_tokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"internal_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isAlive\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isGauge\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isWhitelisted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"killGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"lastVoted\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"length\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"notifyRewardAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"poke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolForGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"poolVote\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"reset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"reviveGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_council\",\"type\":\"address\"}],\"name\":\"setEmergencyCouncil\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"setGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalWeight\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"updateFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"name\":\"updateForRange\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"updateGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedWeights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"_poolVote\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_weights\",\"type\":\"uint256[]\"}],\"name\":\"vote\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"votes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"weights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"whitelist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Voter.sol\":\"Voter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Voter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/libraries/Math.sol';\\nimport 'contracts/interfaces/IBribe.sol';\\nimport 'contracts/interfaces/IBribeFactory.sol';\\nimport 'contracts/interfaces/IGauge.sol';\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/interfaces/IERC20.sol';\\nimport 'contracts/interfaces/IMinter.sol';\\nimport 'contracts/interfaces/IPair.sol';\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/interfaces/IVoter.sol';\\nimport 'contracts/interfaces/IVotingEscrow.sol';\\n\\ncontract Voter is IVoter {\\n\\n address public immutable _ve; // the ve token that governs these contracts\\n address public immutable factory; // the PairFactory\\n address internal immutable base;\\n address public immutable gaugefactory;\\n address public immutable bribefactory;\\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\\n address public minter;\\n address public governor; // should be set to an IGovernor\\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\\n\\n uint public totalWeight; // total voting weight\\n\\n address[] public pools; // all pools viable for incentives\\n mapping(address => address) public gauges; // pool => gauge\\n mapping(address => address) public poolForGauge; // gauge => pool\\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\\n mapping(address => uint256) public weights; // pool => weight\\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\\n mapping(uint => address[]) public poolVote; // nft => pools\\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\\n mapping(address => bool) public isGauge;\\n mapping(address => bool) public isWhitelisted;\\n mapping(address => bool) public isAlive;\\n\\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\\n event GaugeKilled(address indexed gauge);\\n event GaugeRevived(address indexed gauge);\\n event Voted(address indexed voter, uint tokenId, uint256 weight);\\n event Abstained(uint tokenId, uint256 weight);\\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\\n event Whitelisted(address indexed whitelister, address indexed token);\\n\\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\\n _ve = __ve;\\n factory = _factory;\\n base = IVotingEscrow(__ve).token();\\n gaugefactory = _gauges;\\n bribefactory = _bribes;\\n minter = msg.sender;\\n governor = msg.sender;\\n emergencyCouncil = msg.sender;\\n }\\n\\n // simple re-entrancy check\\n uint internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n modifier onlyNewEpoch(uint _tokenId) {\\n // ensure new epoch since last vote \\n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \\\"TOKEN_ALREADY_VOTED_THIS_EPOCH\\\");\\n _;\\n }\\n\\n function initialize(address[] memory _tokens, address _minter) external {\\n require(msg.sender == minter);\\n for (uint i = 0; i < _tokens.length; i++) {\\n _whitelist(_tokens[i]);\\n }\\n minter = _minter;\\n }\\n\\n function setGovernor(address _governor) public {\\n require(msg.sender == governor);\\n governor = _governor;\\n }\\n\\n function setEmergencyCouncil(address _council) public {\\n require(msg.sender == emergencyCouncil);\\n emergencyCouncil = _council;\\n }\\n\\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n lastVoted[_tokenId] = block.timestamp;\\n _reset(_tokenId);\\n IVotingEscrow(_ve).abstain(_tokenId);\\n }\\n\\n function _reset(uint _tokenId) internal {\\n address[] storage _poolVote = poolVote[_tokenId];\\n uint _poolVoteCnt = _poolVote.length;\\n uint256 _totalWeight = 0;\\n\\n for (uint i = 0; i < _poolVoteCnt; i ++) {\\n address _pool = _poolVote[i];\\n uint256 _votes = votes[_tokenId][_pool];\\n\\n if (_votes != 0) {\\n _updateFor(gauges[_pool]);\\n weights[_pool] -= _votes;\\n votes[_tokenId][_pool] -= _votes;\\n if (_votes > 0) {\\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n _totalWeight += _votes;\\n } else {\\n _totalWeight -= _votes;\\n }\\n emit Abstained(_tokenId, _votes);\\n }\\n }\\n totalWeight -= uint256(_totalWeight);\\n usedWeights[_tokenId] = 0;\\n delete poolVote[_tokenId];\\n }\\n\\n function poke(uint _tokenId) external {\\n address[] memory _poolVote = poolVote[_tokenId];\\n uint _poolCnt = _poolVote.length;\\n uint256[] memory _weights = new uint256[](_poolCnt);\\n\\n for (uint i = 0; i < _poolCnt; i ++) {\\n _weights[i] = votes[_tokenId][_poolVote[i]];\\n }\\n\\n _vote(_tokenId, _poolVote, _weights);\\n }\\n\\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\\n _reset(_tokenId);\\n uint _poolCnt = _poolVote.length;\\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\\n uint256 _totalVoteWeight = 0;\\n uint256 _totalWeight = 0;\\n uint256 _usedWeight = 0;\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n _totalVoteWeight += _weights[i];\\n }\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n address _pool = _poolVote[i];\\n address _gauge = gauges[_pool];\\n\\n if (isGauge[_gauge]) {\\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\\n require(votes[_tokenId][_pool] == 0);\\n require(_poolWeight != 0);\\n _updateFor(_gauge);\\n\\n poolVote[_tokenId].push(_pool);\\n\\n weights[_pool] += _poolWeight;\\n votes[_tokenId][_pool] += _poolWeight;\\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n _usedWeight += _poolWeight;\\n _totalWeight += _poolWeight;\\n emit Voted(msg.sender, _tokenId, _poolWeight);\\n }\\n }\\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\\n totalWeight += uint256(_totalWeight);\\n usedWeights[_tokenId] = uint256(_usedWeight);\\n }\\n\\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n require(_poolVote.length == _weights.length);\\n lastVoted[tokenId] = block.timestamp;\\n _vote(tokenId, _poolVote, _weights);\\n }\\n\\n function whitelist(address _token) public {\\n require(msg.sender == governor);\\n _whitelist(_token);\\n }\\n\\n function _whitelist(address _token) internal {\\n require(!isWhitelisted[_token]);\\n isWhitelisted[_token] = true;\\n emit Whitelisted(msg.sender, _token);\\n }\\n\\n function createGauge(address _pool) external returns (address) {\\n require(gauges[_pool] == address(0x0), \\\"exists\\\");\\n address[] memory allowedRewards = new address[](3);\\n address[] memory internalRewards = new address[](2);\\n bool isPair = IPairFactory(factory).isPair(_pool);\\n address tokenA;\\n address tokenB;\\n\\n if (isPair) {\\n (tokenA, tokenB) = IPair(_pool).tokens();\\n allowedRewards[0] = tokenA;\\n allowedRewards[1] = tokenB;\\n internalRewards[0] = tokenA;\\n internalRewards[1] = tokenB;\\n\\n if (base != tokenA && base != tokenB) {\\n allowedRewards[2] = base;\\n }\\n }\\n\\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\\n require(isPair, \\\"!_pool\\\");\\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \\\"!whitelisted\\\");\\n }\\n\\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\\n\\n IERC20(base).approve(_gauge, type(uint).max);\\n internal_bribes[_gauge] = _internal_bribe;\\n external_bribes[_gauge] = _external_bribe;\\n gauges[_pool] = _gauge;\\n poolForGauge[_gauge] = _pool;\\n isGauge[_gauge] = true;\\n isAlive[_gauge] = true;\\n _updateFor(_gauge);\\n pools.push(_pool);\\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\\n return _gauge;\\n }\\n\\n function killGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(isAlive[_gauge], \\\"gauge already dead\\\");\\n isAlive[_gauge] = false;\\n claimable[_gauge] = 0;\\n emit GaugeKilled(_gauge);\\n }\\n\\n function reviveGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(!isAlive[_gauge], \\\"gauge already alive\\\");\\n isAlive[_gauge] = true;\\n emit GaugeRevived(_gauge);\\n }\\n\\n function attachTokenToGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\\n emit Attach(account, msg.sender, tokenId);\\n }\\n\\n function emitDeposit(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]);\\n emit Deposit(account, msg.sender, tokenId, amount);\\n }\\n\\n function detachTokenFromGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\\n emit Detach(account, msg.sender, tokenId);\\n }\\n\\n function emitWithdraw(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n emit Withdraw(account, msg.sender, tokenId, amount);\\n }\\n\\n function length() external view returns (uint) {\\n return pools.length;\\n }\\n\\n uint internal index;\\n mapping(address => uint) internal supplyIndex;\\n mapping(address => uint) public claimable;\\n\\n function notifyRewardAmount(uint amount) external {\\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index += _ratio;\\n }\\n emit NotifyReward(msg.sender, base, amount);\\n }\\n\\n function updateFor(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n _updateFor(_gauges[i]);\\n }\\n }\\n\\n function updateForRange(uint start, uint end) public {\\n for (uint i = start; i < end; i++) {\\n _updateFor(gauges[pools[i]]);\\n }\\n }\\n\\n function updateAll() external {\\n updateForRange(0, pools.length);\\n }\\n\\n function updateGauge(address _gauge) external {\\n _updateFor(_gauge);\\n }\\n\\n function _updateFor(address _gauge) internal {\\n address _pool = poolForGauge[_gauge];\\n uint256 _supplied = weights[_pool];\\n if (_supplied > 0) {\\n uint _supplyIndex = supplyIndex[_gauge];\\n uint _index = index; // get global index0 for accumulated distro\\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\\n if (_delta > 0) {\\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\\n if (isAlive[_gauge]) {\\n claimable[_gauge] += _share;\\n }\\n }\\n } else {\\n supplyIndex[_gauge] = index; // new users are set to the default global state\\n }\\n }\\n\\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\\n }\\n }\\n\\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _bribes.length; i++) {\\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _fees.length; i++) {\\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function distributeFees(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n if (IGauge(_gauges[i]).isForPair()){\\n IGauge(_gauges[i]).claimFees();\\n }\\n }\\n }\\n\\n function distribute(address _gauge) public lock {\\n IMinter(minter).update_period();\\n _updateFor(_gauge); // should set claimable to 0 if killed\\n uint _claimable = claimable[_gauge];\\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\\n claimable[_gauge] = 0;\\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\\n emit DistributeReward(msg.sender, _gauge, _claimable);\\n }\\n }\\n\\n function distro() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute(uint start, uint finish) public {\\n for (uint x = start; x < finish; x++) {\\n distribute(gauges[pools[x]]);\\n }\\n }\\n\\n function distribute(address[] memory _gauges) external {\\n for (uint x = 0; x < _gauges.length; x++) {\\n distribute(_gauges[x]);\\n }\\n }\\n\\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2ff3fc2765dfa0c54870e428d3a2c625f413fb6e10ed7742e786ab4404aae6dc\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x61012060405260016011553480156200001757600080fd5b5060405162003656380380620036568339810160408190526200003a916200011c565b6001600160a01b03808516608081905290841660a05260408051637e062a3560e11b8152905163fc0c546a916004808201926020929091908290030181865afa1580156200008c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b2919062000179565b6001600160a01b0390811660c05291821660e0521661010052505060008054336001600160a01b03199182168117909255600180548216831790556002805490911690911790556200019e565b80516001600160a01b03811681146200011757600080fd5b919050565b600080600080608085870312156200013357600080fd5b6200013e85620000ff565b93506200014e60208601620000ff565b92506200015e60408601620000ff565b91506200016e60608601620000ff565b905092959194509250565b6000602082840312156200018c57600080fd5b6200019782620000ff565b9392505050565b60805160a05160c05160e051610100516133e062000276600039600081816103e701528181611c680152611ce60152600081816104d30152611d79015260008181610b9401528181610c0d01528181610edd01528181610f9901528181611acd01528181611b0601528181611b380152611e5a0152600081816106fc015261192401526000818161058c0152818161092b015281816109d701528181610c9a01528181611069015281816111ea0152818161131a015281816114d901528181611dab015281816125e501526129a801526133e06000f3fe608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea26469706673582212204288741f0c7e0bf9fdc3fcd46932b025210387817a5bfe199a16d22292942a6064736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea26469706673582212204288741f0c7e0bf9fdc3fcd46932b025210387817a5bfe199a16d22292942a6064736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 14322, + "contract": "contracts/Voter.sol:Voter", + "label": "minter", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 14324, + "contract": "contracts/Voter.sol:Voter", + "label": "governor", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 14326, + "contract": "contracts/Voter.sol:Voter", + "label": "emergencyCouncil", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 14328, + "contract": "contracts/Voter.sol:Voter", + "label": "totalWeight", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 14331, + "contract": "contracts/Voter.sol:Voter", + "label": "pools", + "offset": 0, + "slot": "4", + "type": "t_array(t_address)dyn_storage" + }, + { + "astId": 14335, + "contract": "contracts/Voter.sol:Voter", + "label": "gauges", + "offset": 0, + "slot": "5", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 14339, + "contract": "contracts/Voter.sol:Voter", + "label": "poolForGauge", + "offset": 0, + "slot": "6", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 14343, + "contract": "contracts/Voter.sol:Voter", + "label": "internal_bribes", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 14347, + "contract": "contracts/Voter.sol:Voter", + "label": "external_bribes", + "offset": 0, + "slot": "8", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 14351, + "contract": "contracts/Voter.sol:Voter", + "label": "weights", + "offset": 0, + "slot": "9", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 14357, + "contract": "contracts/Voter.sol:Voter", + "label": "votes", + "offset": 0, + "slot": "10", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))" + }, + { + "astId": 14362, + "contract": "contracts/Voter.sol:Voter", + "label": "poolVote", + "offset": 0, + "slot": "11", + "type": "t_mapping(t_uint256,t_array(t_address)dyn_storage)" + }, + { + "astId": 14366, + "contract": "contracts/Voter.sol:Voter", + "label": "usedWeights", + "offset": 0, + "slot": "12", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 14370, + "contract": "contracts/Voter.sol:Voter", + "label": "lastVoted", + "offset": 0, + "slot": "13", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 14374, + "contract": "contracts/Voter.sol:Voter", + "label": "isGauge", + "offset": 0, + "slot": "14", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 14378, + "contract": "contracts/Voter.sol:Voter", + "label": "isWhitelisted", + "offset": 0, + "slot": "15", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 14382, + "contract": "contracts/Voter.sol:Voter", + "label": "isAlive", + "offset": 0, + "slot": "16", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 14528, + "contract": "contracts/Voter.sol:Voter", + "label": "_unlocked", + "offset": 0, + "slot": "17", + "type": "t_uint256" + }, + { + "astId": 15620, + "contract": "contracts/Voter.sol:Voter", + "label": "index", + "offset": 0, + "slot": "18", + "type": "t_uint256" + }, + { + "astId": 15624, + "contract": "contracts/Voter.sol:Voter", + "label": "supplyIndex", + "offset": 0, + "slot": "19", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 15628, + "contract": "contracts/Voter.sol:Voter", + "label": "claimable", + "offset": 0, + "slot": "20", + "type": "t_mapping(t_address,t_uint256)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "base": "t_address", + "encoding": "dynamic_array", + "label": "address[]", + "numberOfBytes": "32" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_address)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_uint256,t_array(t_address)dyn_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => address[])", + "numberOfBytes": "32", + "value": "t_array(t_address)dyn_storage" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/VotingEscrow.json b/deployments/arbitrumGoerli/VotingEscrow.json new file mode 100644 index 00000000..842958fb --- /dev/null +++ b/deployments/arbitrumGoerli/VotingEscrow.json @@ -0,0 +1,2339 @@ +{ + "address": "0x6b938BA22FB5520fFB5D14c9C4Fef82a48761497", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "token_addr", + "type": "address" + }, + { + "internalType": "address", + "name": "art_proxy", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "fromDelegate", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "toDelegate", + "type": "address" + } + ], + "name": "DelegateChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "DelegateVotesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "locktime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum VotingEscrow.DepositType", + "name": "deposit_type", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "ts", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "prevSupply", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "supply", + "type": "uint256" + } + ], + "name": "Supply", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "ts", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [], + "name": "DELEGATION_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DOMAIN_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_DELEGATES", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "abstain", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_approved", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "artProxy", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "attach", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "attachments", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_block", + "type": "uint256" + } + ], + "name": "balanceOfAtNFT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "balanceOfNFT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_t", + "type": "uint256" + } + ], + "name": "balanceOfNFTAt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "block_number", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkpoint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "name": "checkpoints", + "outputs": [ + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_lock_duration", + "type": "uint256" + } + ], + "name": "create_lock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_lock_duration", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + } + ], + "name": "create_lock_for", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + } + ], + "name": "delegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "delegateBySig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "delegates", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "deposit_for", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "detach", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "epoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "getPastTotalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "getPastVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "getPastVotesIndex", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "get_last_user_slope", + "outputs": [ + { + "internalType": "int128", + "name": "", + "type": "int128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "increase_amount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_lock_duration", + "type": "uint256" + } + ], + "name": "increase_unlock_time", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "isApprovedOrOwner", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "locked", + "outputs": [ + { + "internalType": "int128", + "name": "amount", + "type": "int128" + }, + { + "internalType": "uint256", + "name": "end", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "locked__end", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_from", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_to", + "type": "uint256" + } + ], + "name": "merge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "numCheckpoints", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "ownership_change", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "point_history", + "outputs": [ + { + "internalType": "int128", + "name": "bias", + "type": "int128" + }, + { + "internalType": "int128", + "name": "slope", + "type": "int128" + }, + { + "internalType": "uint256", + "name": "ts", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "blk", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "_approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_proxy", + "type": "address" + } + ], + "name": "setArtProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_team", + "type": "address" + } + ], + "name": "setTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_voter", + "type": "address" + } + ], + "name": "setVoter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "slope_changes", + "outputs": [ + { + "internalType": "int128", + "name": "", + "type": "int128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "supply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_interfaceID", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "team", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenIndex", + "type": "uint256" + } + ], + "name": "tokenOfOwnerByIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_block", + "type": "uint256" + } + ], + "name": "totalSupplyAt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "t", + "type": "uint256" + } + ], + "name": "totalSupplyAtT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "user_point_epoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "user_point_history", + "outputs": [ + { + "internalType": "int128", + "name": "bias", + "type": "int128" + }, + { + "internalType": "int128", + "name": "slope", + "type": "int128" + }, + { + "internalType": "uint256", + "name": "ts", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "blk", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_idx", + "type": "uint256" + } + ], + "name": "user_point_history__ts", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "voted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "voter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "voting", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xe05d10a4cc87b56cdd16015b6af08bcda78ccecebe822f74b7ca5aaf6a83b5b6", + "receipt": { + "to": null, + "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", + "contractAddress": "0x6b938BA22FB5520fFB5D14c9C4Fef82a48761497", + "transactionIndex": 1, + "gasUsed": "44732908", + "logsBloom": "0x00000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000400000000000008000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000010000000000000000000000000000020000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000020000000000000000000000002000000000000000000000000000000000000000000", + "blockHash": "0x375ed9ee32d98b6b4e0d006b9633efa2410d424c5b2a9d6cfe4faab534eca831", + "transactionHash": "0xe05d10a4cc87b56cdd16015b6af08bcda78ccecebe822f74b7ca5aaf6a83b5b6", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 4195018, + "transactionHash": "0xe05d10a4cc87b56cdd16015b6af08bcda78ccecebe822f74b7ca5aaf6a83b5b6", + "address": "0x6b938BA22FB5520fFB5D14c9C4Fef82a48761497", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000006b938ba22fb5520ffb5d14c9c4fef82a48761497", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x375ed9ee32d98b6b4e0d006b9633efa2410d424c5b2a9d6cfe4faab534eca831" + }, + { + "transactionIndex": 1, + "blockNumber": 4195018, + "transactionHash": "0xe05d10a4cc87b56cdd16015b6af08bcda78ccecebe822f74b7ca5aaf6a83b5b6", + "address": "0x6b938BA22FB5520fFB5D14c9C4Fef82a48761497", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000006b938ba22fb5520ffb5d14c9c4fef82a48761497", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0x375ed9ee32d98b6b4e0d006b9633efa2410d424c5b2a9d6cfe4faab534eca831" + } + ], + "blockNumber": 4195018, + "cumulativeGasUsed": "44732908", + "status": 1, + "byzantium": true + }, + "args": [ + "0xe69b00A164047e7eB87B73971B0f340eEbFF9c81", + "0x5e7569D02214289490d16bCE4F96B38071db1aD8" + ], + "numDeployments": 4, + "solcInputHash": "0faaa79d8b79020b765ba7705413c447", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token_addr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"art_proxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromDelegate\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toDelegate\",\"type\":\"address\"}],\"name\":\"DelegateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"DelegateVotesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"locktime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum VotingEscrow.DepositType\",\"name\":\"deposit_type\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"prevSupply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"supply\",\"type\":\"uint256\"}],\"name\":\"Supply\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DELEGATION_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_DELEGATES\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"abstain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_approved\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"artProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"attach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"attachments\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"balanceOfAtNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_t\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFTAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"block_number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"checkpoints\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"create_lock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"create_lock_for\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"}],\"name\":\"delegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"delegateBySig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"}],\"name\":\"delegates\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"deposit_for\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"detach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastTotalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotesIndex\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"get_last_user_slope\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"increase_amount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"increase_unlock_time\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"isApprovedOrOwner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"locked\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"amount\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"locked__end\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_from\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_to\",\"type\":\"uint256\"}],\"name\":\"merge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"numCheckpoints\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ownership_change\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_proxy\",\"type\":\"address\"}],\"name\":\"setArtProxy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voter\",\"type\":\"address\"}],\"name\":\"setVoter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"slope_changes\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenIndex\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"t\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAtT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_idx\",\"type\":\"uint256\"}],\"name\":\"user_point_history__ts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"voted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"voting\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\",\"details\":\"Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\",\"kind\":\"dev\",\"methods\":{\"approve(address,uint256)\":{\"details\":\"Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address. Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner. Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP) Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"Address to be approved for the given NFT ID.\",\"_tokenId\":\"ID of the token to be approved.\"}},\"balanceOf(address)\":{\"details\":\"Returns the number of NFTs owned by `_owner`. Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\",\"params\":{\"_owner\":\"Address for whom to query the balance.\"}},\"constructor\":{\"params\":{\"token_addr\":\"`VELO` token address\"}},\"create_lock(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_value\":\"Amount to deposit\"}},\"create_lock_for(uint256,uint256,address)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_to\":\"Address to deposit\",\"_value\":\"Amount to deposit\"}},\"delegate(address)\":{\"params\":{\"delegatee\":\"The address to delegate votes to\"}},\"delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Delegates votes from signer to `delegatee`.\"},\"deposit_for(uint256,uint256)\":{\"details\":\"Anyone (even a smart contract) can deposit for someone else, but cannot extend their locktime and deposit for a brand new user\",\"params\":{\"_tokenId\":\"lock NFT\",\"_value\":\"Amount to add to user's lock\"}},\"getApproved(uint256)\":{\"details\":\"Get the approved address for a single NFT.\",\"params\":{\"_tokenId\":\"ID of the NFT to query the approval of.\"}},\"getVotes(address)\":{\"params\":{\"account\":\"The address to get votes balance\"},\"returns\":{\"_0\":\"The number of current votes for `account`\"}},\"get_last_user_slope(uint256)\":{\"params\":{\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Value of the slope\"}},\"increase_amount(uint256,uint256)\":{\"params\":{\"_value\":\"Amount of tokens to deposit and add to the lock\"}},\"increase_unlock_time(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"New number of seconds until tokens unlock\"}},\"isApprovedForAll(address,address)\":{\"details\":\"Checks if `_operator` is an approved operator for `_owner`.\",\"params\":{\"_operator\":\"The address that acts on behalf of the owner.\",\"_owner\":\"The address that owns the NFTs.\"}},\"locked__end(uint256)\":{\"params\":{\"_tokenId\":\"User NFT\"},\"returns\":{\"_0\":\"Epoch time of the lock end\"}},\"ownerOf(uint256)\":{\"details\":\"Returns the address of the owner of the NFT.\",\"params\":{\"_tokenId\":\"The identifier for an NFT.\"}},\"safeTransferFrom(address,address,uint256)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"safeTransferFrom(address,address,uint256,bytes)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_data\":\"Additional data with no specified format, sent in call to `_to`.\",\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"details\":\"Enables or disables approval for a third party (\\\"operator\\\") to manage all of `msg.sender`'s assets. It also emits the ApprovalForAll event. Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"True if the operators is approved, false to revoke approval.\",\"_operator\":\"Address to add to the set of authorized operators.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Interface identification is specified in ERC-165.\",\"params\":{\"_interfaceID\":\"Id of the interface\"}},\"tokenOfOwnerByIndex(address,uint256)\":{\"details\":\"Get token by index\"},\"tokenURI(uint256)\":{\"details\":\"Returns current token URI metadata\",\"params\":{\"_tokenId\":\"Token ID to fetch URI for.\"}},\"totalSupplyAt(uint256)\":{\"params\":{\"_block\":\"Block to calculate the total voting power at\"},\"returns\":{\"_0\":\"Total voting power at `_block`\"}},\"totalSupplyAtT(uint256)\":{\"details\":\"Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\",\"returns\":{\"_0\":\"Total voting power\"}},\"transferFrom(address,address,uint256)\":{\"details\":\"Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"user_point_history__ts(uint256,uint256)\":{\"params\":{\"_idx\":\"User epoch number\",\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Epoch time of the checkpoint\"}},\"withdraw(uint256)\":{\"details\":\"Only possible if the lock has expired\"}},\"stateVariables\":{\"ERC165_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC165\"},\"ERC721_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721\"},\"ERC721_METADATA_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721Metadata\"},\"_not_entered\":{\"details\":\"reentrancy guard\"},\"idToApprovals\":{\"details\":\"Mapping from NFT ID to approved address.\"},\"idToOwner\":{\"details\":\"Mapping from NFT ID to the address that owns it.\"},\"name\":{\"details\":\"Returns the token collection name.\"},\"ownerToNFTokenCount\":{\"details\":\"Mapping from owner address to count of his tokens.\"},\"ownerToNFTokenIdList\":{\"details\":\"Mapping from owner address to mapping of index to tokenIds\"},\"ownerToOperators\":{\"details\":\"Mapping from owner address to mapping of operator addresses.\"},\"supportedInterfaces\":{\"details\":\"Mapping of interface id to bool about whether or not it's supported\"},\"symbol\":{\"details\":\"Returns the token collection symbol.\"},\"tokenId\":{\"details\":\"Current count of token\"},\"tokenToOwnerIndex\":{\"details\":\"Mapping from NFT ID to index of owner\"}},\"title\":\"Voting Escrow\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DELEGATION_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the delegation struct used by the contract\"},\"DOMAIN_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the contract's domain\"},\"checkpoint()\":{\"notice\":\"Record global data to checkpoint\"},\"checkpoints(address,uint32)\":{\"notice\":\"A record of delegated token checkpoints for each account, by index\"},\"constructor\":{\"notice\":\"Contract constructor\"},\"create_lock(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\"},\"create_lock_for(uint256,uint256,address)\":{\"notice\":\"Deposit `_value` tokens for `_to` and lock for `_lock_duration`\"},\"delegate(address)\":{\"notice\":\"Delegate votes from `msg.sender` to `delegatee`\"},\"delegates(address)\":{\"notice\":\"Overrides the standard `Comp.sol` delegates mapping to return the delegator's own address if they haven't delegated. This avoids having to delegate to oneself.\"},\"deposit_for(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `_tokenId` and add to the lock\"},\"getVotes(address)\":{\"notice\":\"Gets the current votes balance for `account`\"},\"get_last_user_slope(uint256)\":{\"notice\":\"Get the most recently recorded rate of voting power decrease for `_tokenId`\"},\"increase_amount(uint256,uint256)\":{\"notice\":\"Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\"},\"increase_unlock_time(uint256,uint256)\":{\"notice\":\"Extend the unlock time for `_tokenId`\"},\"locked__end(uint256)\":{\"notice\":\"Get timestamp when `_tokenId`'s lock finishes\"},\"nonces(address)\":{\"notice\":\"A record of states for signing / validating signatures\"},\"numCheckpoints(address)\":{\"notice\":\"The number of checkpoints for each account\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"This works even if sender doesn't own any tokens at the time.\"},\"totalSupplyAt(uint256)\":{\"notice\":\"Calculate total voting power at some point in the past\"},\"totalSupplyAtT(uint256)\":{\"notice\":\"Calculate total voting power\"},\"transferFrom(address,address,uint256)\":{\"notice\":\"The caller is responsible to confirm that `_to` is capable of receiving NFTs or else they maybe be permanently lost.\"},\"user_point_history__ts(uint256,uint256)\":{\"notice\":\"Get the timestamp for checkpoint `_idx` for `_tokenId`\"},\"withdraw(uint256)\":{\"notice\":\"Withdraw all tokens for `_tokenId`\"}},\"notice\":\"veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFTVotes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VotingEscrow.sol\":\"VotingEscrow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VotingEscrow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IERC721, IERC721Metadata} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {IERC721Receiver} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {IERC20} from \\\"contracts/interfaces/IERC20.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\nimport {IVotingEscrow} from \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/// @title Voting Escrow\\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\\n enum DepositType {\\n DEPOSIT_FOR_TYPE,\\n CREATE_LOCK_TYPE,\\n INCREASE_LOCK_AMOUNT,\\n INCREASE_UNLOCK_TIME,\\n MERGE_TYPE\\n }\\n\\n struct LockedBalance {\\n int128 amount;\\n uint end;\\n }\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint ts;\\n uint blk; // block\\n }\\n /* We cannot really do block numbers per se b/c slope is per time, not per block\\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\\n * What we can do is to extrapolate ***At functions */\\n\\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\\n struct Checkpoint {\\n uint timestamp;\\n uint[] tokenIds;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Deposit(\\n address indexed provider,\\n uint tokenId,\\n uint value,\\n uint indexed locktime,\\n DepositType deposit_type,\\n uint ts\\n );\\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\\n event Supply(uint prevSupply, uint supply);\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n address public immutable token;\\n address public voter;\\n address public team;\\n address public artProxy;\\n\\n mapping(uint => Point) public point_history; // epoch -> unsigned point\\n\\n /// @dev Mapping of interface id to bool about whether or not it's supported\\n mapping(bytes4 => bool) internal supportedInterfaces;\\n\\n /// @dev ERC165 interface ID of ERC165\\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\\n\\n /// @dev ERC165 interface ID of ERC721\\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\\n\\n /// @dev ERC165 interface ID of ERC721Metadata\\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\\n\\n /// @dev Current count of token\\n uint internal tokenId;\\n\\n /// @notice Contract constructor\\n /// @param token_addr `VELO` token address\\n constructor(address token_addr, address art_proxy) {\\n token = token_addr;\\n voter = msg.sender;\\n team = msg.sender;\\n artProxy = art_proxy;\\n\\n point_history[0].blk = block.number;\\n point_history[0].ts = block.timestamp;\\n\\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\\n\\n // mint-ish\\n emit Transfer(address(0), address(this), tokenId);\\n // burn-ish\\n emit Transfer(address(this), address(0), tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n MODIFIERS\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev reentrancy guard\\n uint8 internal constant _not_entered = 1;\\n uint8 internal constant _entered = 2;\\n uint8 internal _entered_state = 1;\\n modifier nonreentrant() {\\n require(_entered_state == _not_entered);\\n _entered_state = _entered;\\n _;\\n _entered_state = _not_entered;\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string constant public name = \\\"veNFT\\\";\\n string constant public symbol = \\\"veNFT\\\";\\n string constant public version = \\\"1.0.0\\\";\\n uint8 constant public decimals = 18;\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team);\\n team = _team;\\n }\\n\\n function setArtProxy(address _proxy) external {\\n require(msg.sender == team);\\n artProxy = _proxy;\\n }\\n\\n /// @dev Returns current token URI metadata\\n /// @param _tokenId Token ID to fetch URI for.\\n function tokenURI(uint _tokenId) external view returns (string memory) {\\n require(idToOwner[_tokenId] != address(0), \\\"Query for nonexistent token\\\");\\n LockedBalance memory _locked = locked[_tokenId];\\n return IVeArtProxy(artProxy)._tokenURI(\\n _tokenId,\\n _balanceOfNFT(_tokenId, block.timestamp),\\n _locked.end,\\n uint(int256(_locked.amount))\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 BALANCE/OWNER STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to the address that owns it.\\n mapping(uint => address) internal idToOwner;\\n\\n /// @dev Mapping from owner address to count of his tokens.\\n mapping(address => uint) internal ownerToNFTokenCount;\\n\\n /// @dev Returns the address of the owner of the NFT.\\n /// @param _tokenId The identifier for an NFT.\\n function ownerOf(uint _tokenId) public view returns (address) {\\n return idToOwner[_tokenId];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function _balance(address _owner) internal view returns (uint) {\\n return ownerToNFTokenCount[_owner];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function balanceOf(address _owner) external view returns (uint) {\\n return _balance(_owner);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 APPROVAL STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to approved address.\\n mapping(uint => address) internal idToApprovals;\\n\\n /// @dev Mapping from owner address to mapping of operator addresses.\\n mapping(address => mapping(address => bool)) internal ownerToOperators;\\n\\n mapping(uint => uint) public ownership_change;\\n\\n /// @dev Get the approved address for a single NFT.\\n /// @param _tokenId ID of the NFT to query the approval of.\\n function getApproved(uint _tokenId) external view returns (address) {\\n return idToApprovals[_tokenId];\\n }\\n\\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\\n /// @param _owner The address that owns the NFTs.\\n /// @param _operator The address that acts on behalf of the owner.\\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\\n return (ownerToOperators[_owner])[_operator];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\\n /// @param _approved Address to be approved for the given NFT ID.\\n /// @param _tokenId ID of the token to be approved.\\n function approve(address _approved, uint _tokenId) public {\\n address owner = idToOwner[_tokenId];\\n // Throws if `_tokenId` is not a valid NFT\\n require(owner != address(0));\\n // Throws if `_approved` is the current owner\\n require(_approved != owner);\\n // Check requirements\\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\\n require(senderIsOwner || senderIsApprovedForAll);\\n // Set the approval\\n idToApprovals[_tokenId] = _approved;\\n emit Approval(owner, _approved, _tokenId);\\n }\\n\\n /// @dev Enables or disables approval for a third party (\\\"operator\\\") to manage all of\\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\\n /// @notice This works even if sender doesn't own any tokens at the time.\\n /// @param _operator Address to add to the set of authorized operators.\\n /// @param _approved True if the operators is approved, false to revoke approval.\\n function setApprovalForAll(address _operator, bool _approved) external {\\n // Throws if `_operator` is the `msg.sender`\\n assert(_operator != msg.sender);\\n ownerToOperators[msg.sender][_operator] = _approved;\\n emit ApprovalForAll(msg.sender, _operator, _approved);\\n }\\n\\n /* TRANSFER FUNCTIONS */\\n /// @dev Clear an approval of a given address\\n /// Throws if `_owner` is not the current owner.\\n function _clearApproval(address _owner, uint _tokenId) internal {\\n // Throws if `_owner` is not the current owner\\n assert(idToOwner[_tokenId] == _owner);\\n if (idToApprovals[_tokenId] != address(0)) {\\n // Reset approvals\\n idToApprovals[_tokenId] = address(0);\\n }\\n }\\n\\n /// @dev Returns whether the given spender can transfer a given token ID\\n /// @param _spender address of the spender to query\\n /// @param _tokenId uint ID of the token to be transferred\\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\\n address owner = idToOwner[_tokenId];\\n bool spenderIsOwner = owner == _spender;\\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\\n }\\n\\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\\n return _isApprovedOrOwner(_spender, _tokenId);\\n }\\n\\n /// @dev Exeute transfer of a NFT.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_tokenId` is not a valid NFT.\\n function _transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n address _sender\\n ) internal {\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n // Check requirements\\n require(_isApprovedOrOwner(_sender, _tokenId));\\n // Clear approval. Throws if `_from` is not the current owner\\n _clearApproval(_from, _tokenId);\\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\\n _removeTokenFrom(_from, _tokenId);\\n // auto re-delegate\\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\\n // Add NFT\\n _addTokenTo(_to, _tokenId);\\n // Set the block of ownership transfer (for Flash NFT protection)\\n ownership_change[_tokenId] = block.number;\\n // Log the transfer\\n emit Transfer(_from, _to, _tokenId);\\n }\\n\\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\\n /// they maybe be permanently lost.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n safeTransferFrom(_from, _to, _tokenId, \\\"\\\");\\n }\\n\\n function _isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n uint size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n /// @param _data Additional data with no specified format, sent in call to `_to`.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n bytes memory _data\\n ) public {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n\\n if (_isContract(_to)) {\\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\\n revert(\\\"ERC721: ERC721Receiver rejected tokens\\\");\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert('ERC721: transfer to non ERC721Receiver implementer');\\n } else {\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC165 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Interface identification is specified in ERC-165.\\n /// @param _interfaceID Id of the interface\\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\\n return supportedInterfaces[_interfaceID];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from owner address to mapping of index to tokenIds\\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\\n\\n /// @dev Mapping from NFT ID to index of owner\\n mapping(uint => uint) internal tokenToOwnerIndex;\\n\\n /// @dev Get token by index\\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\\n return ownerToNFTokenIdList[_owner][_tokenIndex];\\n }\\n\\n /// @dev Add a NFT to an index mapping to a given address\\n /// @param _to address of the receiver\\n /// @param _tokenId uint ID Of the token to be added\\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\\n uint current_count = _balance(_to);\\n\\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\\n tokenToOwnerIndex[_tokenId] = current_count;\\n }\\n\\n /// @dev Add a NFT to a given address\\n /// Throws if `_tokenId` is owned by someone.\\n function _addTokenTo(address _to, uint _tokenId) internal {\\n // Throws if `_tokenId` is owned by someone\\n assert(idToOwner[_tokenId] == address(0));\\n // Change the owner\\n idToOwner[_tokenId] = _to;\\n // Update owner token index tracking\\n _addTokenToOwnerList(_to, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_to] += 1;\\n }\\n\\n /// @dev Function to mint tokens\\n /// Throws if `_to` is zero address.\\n /// Throws if `_tokenId` is owned by someone.\\n /// @param _to The address that will receive the minted tokens.\\n /// @param _tokenId The token id to mint.\\n /// @return A boolean that indicates if the operation was successful.\\n function _mint(address _to, uint _tokenId) internal returns (bool) {\\n // Throws if `_to` is zero address\\n assert(_to != address(0));\\n // checkpoint for gov\\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\\n // Add NFT. Throws if `_tokenId` is owned by someone\\n _addTokenTo(_to, _tokenId);\\n emit Transfer(address(0), _to, _tokenId);\\n return true;\\n }\\n\\n /// @dev Remove a NFT from an index mapping to a given address\\n /// @param _from address of the sender\\n /// @param _tokenId uint ID Of the token to be removed\\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\\n // Delete\\n uint current_count = _balance(_from) - 1;\\n uint current_index = tokenToOwnerIndex[_tokenId];\\n\\n if (current_count == current_index) {\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n } else {\\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\\n\\n // Add\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[lastTokenId] = current_index;\\n\\n // Delete\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n }\\n }\\n\\n /// @dev Remove a NFT from a given address\\n /// Throws if `_from` is not the current owner.\\n function _removeTokenFrom(address _from, uint _tokenId) internal {\\n // Throws if `_from` is not the current owner\\n assert(idToOwner[_tokenId] == _from);\\n // Change the owner\\n idToOwner[_tokenId] = address(0);\\n // Update owner token index tracking\\n _removeTokenFromOwnerList(_from, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_from] -= 1;\\n }\\n\\n function _burn(uint _tokenId) internal {\\n require(_isApprovedOrOwner(msg.sender, _tokenId), \\\"caller is not owner nor approved\\\");\\n\\n address owner = ownerOf(_tokenId);\\n\\n // Clear approval\\n approve(address(0), _tokenId);\\n // checkpoint for gov\\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\\n // Remove token\\n _removeTokenFrom(msg.sender, _tokenId);\\n emit Transfer(owner, address(0), _tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public user_point_epoch;\\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\\n mapping(uint => LockedBalance) public locked;\\n uint public epoch;\\n mapping(uint => int128) public slope_changes; // time -> signed slope change\\n uint public supply;\\n\\n uint internal constant WEEK = 1 weeks;\\n uint internal constant MAXTIME = 4 * 365 * 86400;\\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\\n uint internal constant MULTIPLIER = 1 ether;\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @return Value of the slope\\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\\n uint uepoch = user_point_epoch[_tokenId];\\n return user_point_history[_tokenId][uepoch].slope;\\n }\\n\\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @param _idx User epoch number\\n /// @return Epoch time of the checkpoint\\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\\n return user_point_history[_tokenId][_idx].ts;\\n }\\n\\n /// @notice Get timestamp when `_tokenId`'s lock finishes\\n /// @param _tokenId User NFT\\n /// @return Epoch time of the lock end\\n function locked__end(uint _tokenId) external view returns (uint) {\\n return locked[_tokenId].end;\\n }\\n\\n /// @notice Record global and per-user data to checkpoint\\n /// @param _tokenId NFT token ID. No user checkpoint if 0\\n /// @param old_locked Pevious locked amount / end lock time for the user\\n /// @param new_locked New locked amount / end lock time for the user\\n function _checkpoint(\\n uint _tokenId,\\n LockedBalance memory old_locked,\\n LockedBalance memory new_locked\\n ) internal {\\n Point memory u_old;\\n Point memory u_new;\\n int128 old_dslope = 0;\\n int128 new_dslope = 0;\\n uint _epoch = epoch;\\n\\n if (_tokenId != 0) {\\n // Calculate slopes and biases\\n // Kept at zero when they have to\\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\\n u_old.slope = old_locked.amount / iMAXTIME;\\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\\n }\\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\\n u_new.slope = new_locked.amount / iMAXTIME;\\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\\n }\\n\\n // Read values of scheduled changes in the slope\\n // old_locked.end can be in the past and in the future\\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\\n old_dslope = slope_changes[old_locked.end];\\n if (new_locked.end != 0) {\\n if (new_locked.end == old_locked.end) {\\n new_dslope = old_dslope;\\n } else {\\n new_dslope = slope_changes[new_locked.end];\\n }\\n }\\n }\\n\\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\\n if (_epoch > 0) {\\n last_point = point_history[_epoch];\\n }\\n uint last_checkpoint = last_point.ts;\\n // initial_last_point is used for extrapolation to calculate block number\\n // (approximately, for *At methods) and save them\\n // as we cannot figure that out exactly from inside the contract\\n Point memory initial_last_point = last_point;\\n uint block_slope = 0; // dblock/dt\\n if (block.timestamp > last_point.ts) {\\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\\n }\\n // If last point is already recorded in this block, slope=0\\n // But that's ok b/c we know the block in such case\\n\\n // Go over weeks to fill history and calculate what the current point is\\n {\\n uint t_i = (last_checkpoint / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n // Hopefully it won't happen that this won't get used in 5 years!\\n // If it does, users will be able to withdraw but vote weight will be broken\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > block.timestamp) {\\n t_i = block.timestamp;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\\n last_point.slope += d_slope;\\n if (last_point.bias < 0) {\\n // This can happen\\n last_point.bias = 0;\\n }\\n if (last_point.slope < 0) {\\n // This cannot happen - just in case\\n last_point.slope = 0;\\n }\\n last_checkpoint = t_i;\\n last_point.ts = t_i;\\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\\n _epoch += 1;\\n if (t_i == block.timestamp) {\\n last_point.blk = block.number;\\n break;\\n } else {\\n point_history[_epoch] = last_point;\\n }\\n }\\n }\\n\\n epoch = _epoch;\\n // Now point_history is filled until t=now\\n\\n if (_tokenId != 0) {\\n // If last point was in this block, the slope change has been applied already\\n // But in such case we have 0 slope(s)\\n last_point.slope += (u_new.slope - u_old.slope);\\n last_point.bias += (u_new.bias - u_old.bias);\\n if (last_point.slope < 0) {\\n last_point.slope = 0;\\n }\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n }\\n\\n // Record the changed point into history\\n point_history[_epoch] = last_point;\\n\\n if (_tokenId != 0) {\\n // Schedule the slope changes (slope is going down)\\n // We subtract new_user_slope from [new_locked.end]\\n // and add old_user_slope to [old_locked.end]\\n if (old_locked.end > block.timestamp) {\\n // old_dslope was - u_old.slope, so we cancel that\\n old_dslope += u_old.slope;\\n if (new_locked.end == old_locked.end) {\\n old_dslope -= u_new.slope; // It was a new deposit, not extension\\n }\\n slope_changes[old_locked.end] = old_dslope;\\n }\\n\\n if (new_locked.end > block.timestamp) {\\n if (new_locked.end > old_locked.end) {\\n new_dslope -= u_new.slope; // old slope disappeared at this point\\n slope_changes[new_locked.end] = new_dslope;\\n }\\n // else: we recorded it already in old_dslope\\n }\\n // Now handle user history\\n uint user_epoch = user_point_epoch[_tokenId] + 1;\\n\\n user_point_epoch[_tokenId] = user_epoch;\\n u_new.ts = block.timestamp;\\n u_new.blk = block.number;\\n user_point_history[_tokenId][user_epoch] = u_new;\\n }\\n }\\n\\n /// @notice Deposit and lock tokens for a user\\n /// @param _tokenId NFT that holds lock\\n /// @param _value Amount to deposit\\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\\n /// @param locked_balance Previous locked amount / timestamp\\n /// @param deposit_type The type of deposit\\n function _deposit_for(\\n uint _tokenId,\\n uint _value,\\n uint unlock_time,\\n LockedBalance memory locked_balance,\\n DepositType deposit_type\\n ) internal {\\n LockedBalance memory _locked = locked_balance;\\n uint supply_before = supply;\\n\\n supply = supply_before + _value;\\n LockedBalance memory old_locked;\\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\\n // Adding to existing lock, or if a lock is expired - creating a new one\\n _locked.amount += int128(int256(_value));\\n if (unlock_time != 0) {\\n _locked.end = unlock_time;\\n }\\n locked[_tokenId] = _locked;\\n\\n // Possibilities:\\n // Both old_locked.end could be current or expired (>/< block.timestamp)\\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\\n // _locked.end > block.timestamp (always)\\n _checkpoint(_tokenId, old_locked, _locked);\\n\\n address from = msg.sender;\\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\\n assert(IERC20(token).transferFrom(from, address(this), _value));\\n }\\n\\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\\n emit Supply(supply_before, supply_before + _value);\\n }\\n\\n function block_number() external view returns (uint) {\\n return block.number;\\n }\\n\\n /// @notice Record global data to checkpoint\\n function checkpoint() external {\\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\\n }\\n\\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\\n /// cannot extend their locktime and deposit for a brand new user\\n /// @param _tokenId lock NFT\\n /// @param _value Amount to add to user's lock\\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n require(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_value > 0); // dev: need non-zero value\\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n ++tokenId;\\n uint _tokenId = tokenId;\\n _mint(_to, _tokenId);\\n\\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\\n return _tokenId;\\n }\\n\\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, msg.sender);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, _to);\\n }\\n\\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\\n /// @param _value Amount of tokens to deposit and add to the lock\\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n assert(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\\n }\\n\\n /// @notice Extend the unlock time for `_tokenId`\\n /// @param _lock_duration New number of seconds until tokens unlock\\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_locked.end > block.timestamp, 'Lock expired');\\n require(_locked.amount > 0, 'Nothing is locked');\\n require(unlock_time > _locked.end, 'Can only increase lock duration');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\\n }\\n\\n /// @notice Withdraw all tokens for `_tokenId`\\n /// @dev Only possible if the lock has expired\\n function withdraw(uint _tokenId) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n require(block.timestamp >= _locked.end, \\\"The lock didn't expire\\\");\\n uint value = uint(int256(_locked.amount));\\n\\n locked[_tokenId] = LockedBalance(0,0);\\n uint supply_before = supply;\\n supply = supply_before - value;\\n\\n // old_locked can have either expired <= timestamp or zero end\\n // _locked has only 0 end\\n // Both can have >= 0 amount\\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\\n\\n assert(IERC20(token).transfer(msg.sender, value));\\n\\n // Burn the NFT\\n _burn(_tokenId);\\n\\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\\n emit Supply(supply_before, supply_before - value);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\\n // They measure the weights for the purpose of voting, so they don't represent\\n // real coins.\\n\\n /// @notice Binary search to estimate timestamp for block number\\n /// @param _block Block to find\\n /// @param max_epoch Don't go beyond this epoch\\n /// @return Approximate timestamp for block\\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\\n // Binary search\\n uint _min = 0;\\n uint _max = max_epoch;\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (point_history[_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n /// @notice Get the current voting power for `_tokenId`\\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\\n /// @param _tokenId NFT for lock\\n /// @param _t Epoch time to return voting power at\\n /// @return User voting power\\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\\n uint _epoch = user_point_epoch[_tokenId];\\n if (_epoch == 0) {\\n return 0;\\n } else {\\n Point memory last_point = user_point_history[_tokenId][_epoch];\\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(int256(last_point.bias));\\n }\\n }\\n\\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\\n if (ownership_change[_tokenId] == block.number) return 0;\\n return _balanceOfNFT(_tokenId, block.timestamp);\\n }\\n\\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\\n return _balanceOfNFT(_tokenId, _t);\\n }\\n\\n /// @notice Measure voting power of `_tokenId` at block height `_block`\\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\\n /// @param _tokenId User's wallet NFT\\n /// @param _block Block to calculate the voting power at\\n /// @return Voting power\\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\\n // Copying and pasting totalSupply code because Vyper cannot pass by\\n // reference yet\\n assert(_block <= block.number);\\n\\n // Binary search\\n uint _min = 0;\\n uint _max = user_point_epoch[_tokenId];\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (user_point_history[_tokenId][_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n\\n Point memory upoint = user_point_history[_tokenId][_min];\\n\\n uint max_epoch = epoch;\\n uint _epoch = _find_block_epoch(_block, max_epoch);\\n Point memory point_0 = point_history[_epoch];\\n uint d_block = 0;\\n uint d_t = 0;\\n if (_epoch < max_epoch) {\\n Point memory point_1 = point_history[_epoch + 1];\\n d_block = point_1.blk - point_0.blk;\\n d_t = point_1.ts - point_0.ts;\\n } else {\\n d_block = block.number - point_0.blk;\\n d_t = block.timestamp - point_0.ts;\\n }\\n uint block_time = point_0.ts;\\n if (d_block != 0) {\\n block_time += (d_t * (_block - point_0.blk)) / d_block;\\n }\\n\\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\\n if (upoint.bias >= 0) {\\n return uint(uint128(upoint.bias));\\n } else {\\n return 0;\\n }\\n }\\n\\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\\n return _balanceOfAtNFT(_tokenId, _block);\\n }\\n\\n /// @notice Calculate total voting power at some point in the past\\n /// @param _block Block to calculate the total voting power at\\n /// @return Total voting power at `_block`\\n function totalSupplyAt(uint _block) external view returns (uint) {\\n assert(_block <= block.number);\\n uint _epoch = epoch;\\n uint target_epoch = _find_block_epoch(_block, _epoch);\\n\\n Point memory point = point_history[target_epoch];\\n uint dt = 0;\\n if (target_epoch < _epoch) {\\n Point memory point_next = point_history[target_epoch + 1];\\n if (point.blk != point_next.blk) {\\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\\n }\\n } else {\\n if (point.blk != block.number) {\\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\\n }\\n }\\n // Now dt contains info on how far are we beyond point\\n return _supply_at(point, point.ts + dt);\\n }\\n /// @notice Calculate total voting power at some point in the past\\n /// @param point The point (bias/slope) to start search from\\n /// @param t Time to calculate the total voting power at\\n /// @return Total voting power at that time\\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\\n Point memory last_point = point;\\n uint t_i = (last_point.ts / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > t) {\\n t_i = t;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\\n if (t_i == t) {\\n break;\\n }\\n last_point.slope += d_slope;\\n last_point.ts = t_i;\\n }\\n\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(uint128(last_point.bias));\\n }\\n\\n function totalSupply() external view returns (uint) {\\n return totalSupplyAtT(block.timestamp);\\n }\\n\\n /// @notice Calculate total voting power\\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\\n /// @return Total voting power\\n function totalSupplyAtT(uint t) public view returns (uint) {\\n uint _epoch = epoch;\\n Point memory last_point = point_history[_epoch];\\n return _supply_at(last_point, t);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public attachments;\\n mapping(uint => bool) public voted;\\n\\n function setVoter(address _voter) external {\\n require(msg.sender == voter);\\n voter = _voter;\\n }\\n\\n function voting(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = true;\\n }\\n\\n function abstain(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = false;\\n }\\n\\n function attach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] + 1;\\n }\\n\\n function detach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] - 1;\\n }\\n\\n function merge(uint _from, uint _to) external {\\n require(attachments[_from] == 0 && !voted[_from], \\\"attached\\\");\\n require(_from != _to);\\n require(_isApprovedOrOwner(msg.sender, _from));\\n require(_isApprovedOrOwner(msg.sender, _to));\\n\\n LockedBalance memory _locked0 = locked[_from];\\n LockedBalance memory _locked1 = locked[_to];\\n uint value0 = uint(int256(_locked0.amount));\\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\\n\\n locked[_from] = LockedBalance(0, 0);\\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\\n _burn(_from);\\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of each accounts delegate\\n mapping(address => address) private _delegates;\\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\\n\\n /// @notice A record of delegated token checkpoints for each account, by index\\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint32) public numCheckpoints;\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping(address => uint) public nonces;\\n\\n /**\\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\\n * the delegator's own address if they haven't delegated.\\n * This avoids having to delegate to oneself.\\n */\\n function delegates(address delegator) public view returns (address) {\\n address current = _delegates[delegator];\\n return current == address(0) ? delegator : current;\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getVotes(address account) external view returns (uint) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n votes = votes + _balanceOfNFT(tId, block.timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint storage cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPastVotes(address account, uint timestamp)\\n public\\n view\\n returns (uint)\\n {\\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\\n // Sum votes\\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n // Use the provided input timestamp here to get the right decay\\n votes = votes + _balanceOfNFT(tId, timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\\n return totalSupplyAtT(timestamp);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _moveTokenDelegates(\\n address srcRep,\\n address dstRep,\\n uint _tokenId\\n ) internal {\\n if (srcRep != dstRep && _tokenId > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except _tokenId\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (tId != _tokenId) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n // All the same plus _tokenId\\n require(\\n dstRepOld.length + 1 <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n dstRepNew.push(_tokenId);\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _findWhatCheckpointToWrite(address account)\\n internal\\n view\\n returns (uint32)\\n {\\n uint _timestamp = block.timestamp;\\n uint32 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n return _nCheckPoints - 1;\\n } else {\\n return _nCheckPoints;\\n }\\n }\\n\\n function _moveAllDelegates(\\n address owner,\\n address srcRep,\\n address dstRep\\n ) internal {\\n // You can only redelegate what you own\\n if (srcRep != dstRep) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except what owner owns\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (idToOwner[tId] != owner) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n uint ownerTokenCount = ownerToNFTokenCount[owner];\\n require(\\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n // All the same\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n // Plus all that's owned\\n for (uint i = 0; i < ownerTokenCount; i++) {\\n uint tId = ownerToNFTokenIdList[owner][i];\\n dstRepNew.push(tId);\\n }\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\\n address currentDelegate = delegates(delegator);\\n\\n _delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n _moveAllDelegates(delegator, currentDelegate, delegatee);\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n if (delegatee == address(0)) delegatee = msg.sender;\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n function delegateBySig(\\n address delegatee,\\n uint nonce,\\n uint expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public {\\n bytes32 domainSeparator = keccak256(\\n abi.encode(\\n DOMAIN_TYPEHASH,\\n keccak256(bytes(name)),\\n keccak256(bytes(version)),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 structHash = keccak256(\\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash)\\n );\\n address signatory = ecrecover(digest, v, r, s);\\n require(\\n signatory != address(0),\\n \\\"VotingEscrow::delegateBySig: invalid signature\\\"\\n );\\n require(\\n nonce == nonces[signatory]++,\\n \\\"VotingEscrow::delegateBySig: invalid nonce\\\"\\n );\\n require(\\n block.timestamp <= expiry,\\n \\\"VotingEscrow::delegateBySig: signature expired\\\"\\n );\\n return _delegate(signatory, delegatee);\\n }\\n}\\n\",\"keccak256\":\"0x37e5ee306472a946a665be22bc1d370d566a575a1fac84f72f97b0575571d40d\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x41bbb2c41036ca64b2f6c9e973e8cfaa113ebc42af86702cd0d267f915a7e886\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a06040526006805460ff191660011790553480156200001e57600080fd5b5060405162004a1c38038062004a1c8339810160408190526200004191620001b8565b6001600160a01b0382811660805260008054336001600160a01b031991821681178355600180548316909117815560028054909216938516939093179055437f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f0155427f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f005560046020527f9fe05126d2d9ecf60592e254dead906a4b2e492f36cca727682c38e9008c6ac1805460ff1990811684179091557f4267c0a6fd96b7a87f183ee8744f24d011423cd0e0142b3f563f183d8d9a456b8054821684179055635b5e139f60e01b82527e24030bcf4927897dffe721c2d8dda4bfd8910861687c42b03a463b43b04147805490911690921790915560055460405190913091600080516020620049fc833981519152908290a46005546040516000903090600080516020620049fc833981519152908390a45050620001f0565b80516001600160a01b0381168114620001b357600080fd5b919050565b60008060408385031215620001cc57600080fd5b620001d7836200019b565b9150620001e7602084016200019b565b90509250929050565b6080516147e26200021a60003960008181610b220152818161101801526133b501526147e26000f3fe608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea2646970667358221220c2ef8dcbebf2610bd708916a1bc05e287f34d3bec992b138a8433fc96f6e1d1164736f6c634300080d0033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea2646970667358221220c2ef8dcbebf2610bd708916a1bc05e287f34d3bec992b138a8433fc96f6e1d1164736f6c634300080d0033", + "devdoc": { + "author": "Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)", + "details": "Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).", + "kind": "dev", + "methods": { + "approve(address,uint256)": { + "details": "Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address. Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner. Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP) Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)", + "params": { + "_approved": "Address to be approved for the given NFT ID.", + "_tokenId": "ID of the token to be approved." + } + }, + "balanceOf(address)": { + "details": "Returns the number of NFTs owned by `_owner`. Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.", + "params": { + "_owner": "Address for whom to query the balance." + } + }, + "constructor": { + "params": { + "token_addr": "`VELO` token address" + } + }, + "create_lock(uint256,uint256)": { + "params": { + "_lock_duration": "Number of seconds to lock tokens for (rounded down to nearest week)", + "_value": "Amount to deposit" + } + }, + "create_lock_for(uint256,uint256,address)": { + "params": { + "_lock_duration": "Number of seconds to lock tokens for (rounded down to nearest week)", + "_to": "Address to deposit", + "_value": "Amount to deposit" + } + }, + "delegate(address)": { + "params": { + "delegatee": "The address to delegate votes to" + } + }, + "delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)": { + "details": "Delegates votes from signer to `delegatee`." + }, + "deposit_for(uint256,uint256)": { + "details": "Anyone (even a smart contract) can deposit for someone else, but cannot extend their locktime and deposit for a brand new user", + "params": { + "_tokenId": "lock NFT", + "_value": "Amount to add to user's lock" + } + }, + "getApproved(uint256)": { + "details": "Get the approved address for a single NFT.", + "params": { + "_tokenId": "ID of the NFT to query the approval of." + } + }, + "getVotes(address)": { + "params": { + "account": "The address to get votes balance" + }, + "returns": { + "_0": "The number of current votes for `account`" + } + }, + "get_last_user_slope(uint256)": { + "params": { + "_tokenId": "token of the NFT" + }, + "returns": { + "_0": "Value of the slope" + } + }, + "increase_amount(uint256,uint256)": { + "params": { + "_value": "Amount of tokens to deposit and add to the lock" + } + }, + "increase_unlock_time(uint256,uint256)": { + "params": { + "_lock_duration": "New number of seconds until tokens unlock" + } + }, + "isApprovedForAll(address,address)": { + "details": "Checks if `_operator` is an approved operator for `_owner`.", + "params": { + "_operator": "The address that acts on behalf of the owner.", + "_owner": "The address that owns the NFTs." + } + }, + "locked__end(uint256)": { + "params": { + "_tokenId": "User NFT" + }, + "returns": { + "_0": "Epoch time of the lock end" + } + }, + "ownerOf(uint256)": { + "details": "Returns the address of the owner of the NFT.", + "params": { + "_tokenId": "The identifier for an NFT." + } + }, + "safeTransferFrom(address,address,uint256)": { + "details": "Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.", + "params": { + "_from": "The current owner of the NFT.", + "_to": "The new owner.", + "_tokenId": "The NFT to transfer." + } + }, + "safeTransferFrom(address,address,uint256,bytes)": { + "details": "Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.", + "params": { + "_data": "Additional data with no specified format, sent in call to `_to`.", + "_from": "The current owner of the NFT.", + "_to": "The new owner.", + "_tokenId": "The NFT to transfer." + } + }, + "setApprovalForAll(address,bool)": { + "details": "Enables or disables approval for a third party (\"operator\") to manage all of `msg.sender`'s assets. It also emits the ApprovalForAll event. Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)", + "params": { + "_approved": "True if the operators is approved, false to revoke approval.", + "_operator": "Address to add to the set of authorized operators." + } + }, + "supportsInterface(bytes4)": { + "details": "Interface identification is specified in ERC-165.", + "params": { + "_interfaceID": "Id of the interface" + } + }, + "tokenOfOwnerByIndex(address,uint256)": { + "details": "Get token by index" + }, + "tokenURI(uint256)": { + "details": "Returns current token URI metadata", + "params": { + "_tokenId": "Token ID to fetch URI for." + } + }, + "totalSupplyAt(uint256)": { + "params": { + "_block": "Block to calculate the total voting power at" + }, + "returns": { + "_0": "Total voting power at `_block`" + } + }, + "totalSupplyAtT(uint256)": { + "details": "Adheres to the ERC20 `totalSupply` interface for Aragon compatibility", + "returns": { + "_0": "Total voting power" + } + }, + "transferFrom(address,address,uint256)": { + "details": "Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT.", + "params": { + "_from": "The current owner of the NFT.", + "_to": "The new owner.", + "_tokenId": "The NFT to transfer." + } + }, + "user_point_history__ts(uint256,uint256)": { + "params": { + "_idx": "User epoch number", + "_tokenId": "token of the NFT" + }, + "returns": { + "_0": "Epoch time of the checkpoint" + } + }, + "withdraw(uint256)": { + "details": "Only possible if the lock has expired" + } + }, + "stateVariables": { + "ERC165_INTERFACE_ID": { + "details": "ERC165 interface ID of ERC165" + }, + "ERC721_INTERFACE_ID": { + "details": "ERC165 interface ID of ERC721" + }, + "ERC721_METADATA_INTERFACE_ID": { + "details": "ERC165 interface ID of ERC721Metadata" + }, + "_not_entered": { + "details": "reentrancy guard" + }, + "idToApprovals": { + "details": "Mapping from NFT ID to approved address." + }, + "idToOwner": { + "details": "Mapping from NFT ID to the address that owns it." + }, + "name": { + "details": "Returns the token collection name." + }, + "ownerToNFTokenCount": { + "details": "Mapping from owner address to count of his tokens." + }, + "ownerToNFTokenIdList": { + "details": "Mapping from owner address to mapping of index to tokenIds" + }, + "ownerToOperators": { + "details": "Mapping from owner address to mapping of operator addresses." + }, + "supportedInterfaces": { + "details": "Mapping of interface id to bool about whether or not it's supported" + }, + "symbol": { + "details": "Returns the token collection symbol." + }, + "tokenId": { + "details": "Current count of token" + }, + "tokenToOwnerIndex": { + "details": "Mapping from NFT ID to index of owner" + } + }, + "title": "Voting Escrow", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "DELEGATION_TYPEHASH()": { + "notice": "The EIP-712 typehash for the delegation struct used by the contract" + }, + "DOMAIN_TYPEHASH()": { + "notice": "The EIP-712 typehash for the contract's domain" + }, + "checkpoint()": { + "notice": "Record global data to checkpoint" + }, + "checkpoints(address,uint32)": { + "notice": "A record of delegated token checkpoints for each account, by index" + }, + "constructor": { + "notice": "Contract constructor" + }, + "create_lock(uint256,uint256)": { + "notice": "Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`" + }, + "create_lock_for(uint256,uint256,address)": { + "notice": "Deposit `_value` tokens for `_to` and lock for `_lock_duration`" + }, + "delegate(address)": { + "notice": "Delegate votes from `msg.sender` to `delegatee`" + }, + "delegates(address)": { + "notice": "Overrides the standard `Comp.sol` delegates mapping to return the delegator's own address if they haven't delegated. This avoids having to delegate to oneself." + }, + "deposit_for(uint256,uint256)": { + "notice": "Deposit `_value` tokens for `_tokenId` and add to the lock" + }, + "getVotes(address)": { + "notice": "Gets the current votes balance for `account`" + }, + "get_last_user_slope(uint256)": { + "notice": "Get the most recently recorded rate of voting power decrease for `_tokenId`" + }, + "increase_amount(uint256,uint256)": { + "notice": "Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time" + }, + "increase_unlock_time(uint256,uint256)": { + "notice": "Extend the unlock time for `_tokenId`" + }, + "locked__end(uint256)": { + "notice": "Get timestamp when `_tokenId`'s lock finishes" + }, + "nonces(address)": { + "notice": "A record of states for signing / validating signatures" + }, + "numCheckpoints(address)": { + "notice": "The number of checkpoints for each account" + }, + "setApprovalForAll(address,bool)": { + "notice": "This works even if sender doesn't own any tokens at the time." + }, + "totalSupplyAt(uint256)": { + "notice": "Calculate total voting power at some point in the past" + }, + "totalSupplyAtT(uint256)": { + "notice": "Calculate total voting power" + }, + "transferFrom(address,address,uint256)": { + "notice": "The caller is responsible to confirm that `_to` is capable of receiving NFTs or else they maybe be permanently lost." + }, + "user_point_history__ts(uint256,uint256)": { + "notice": "Get the timestamp for checkpoint `_idx` for `_tokenId`" + }, + "withdraw(uint256)": { + "notice": "Withdraw all tokens for `_tokenId`" + } + }, + "notice": "veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFTVotes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 16268, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "voter", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 16270, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "team", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 16272, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "artProxy", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 16277, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "point_history", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint256,t_struct(Point)16227_storage)" + }, + { + "astId": 16282, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "supportedInterfaces", + "offset": 0, + "slot": "4", + "type": "t_mapping(t_bytes4,t_bool)" + }, + { + "astId": 16297, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "tokenId", + "offset": 0, + "slot": "5", + "type": "t_uint256" + }, + { + "astId": 16392, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "_entered_state", + "offset": 0, + "slot": "6", + "type": "t_uint8" + }, + { + "astId": 16511, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "idToOwner", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_uint256,t_address)" + }, + { + "astId": 16516, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "ownerToNFTokenCount", + "offset": 0, + "slot": "8", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 16560, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "idToApprovals", + "offset": 0, + "slot": "9", + "type": "t_mapping(t_uint256,t_address)" + }, + { + "astId": 16567, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "ownerToOperators", + "offset": 0, + "slot": "10", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" + }, + { + "astId": 16571, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "ownership_change", + "offset": 0, + "slot": "11", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 17016, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "ownerToNFTokenIdList", + "offset": 0, + "slot": "12", + "type": "t_mapping(t_address,t_mapping(t_uint256,t_uint256))" + }, + { + "astId": 17021, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "tokenToOwnerIndex", + "offset": 0, + "slot": "13", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 17326, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "user_point_epoch", + "offset": 0, + "slot": "14", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 17333, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "user_point_history", + "offset": 0, + "slot": "15", + "type": "t_mapping(t_uint256,t_array(t_struct(Point)16227_storage)1000000000_storage)" + }, + { + "astId": 17338, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "locked", + "offset": 0, + "slot": "16", + "type": "t_mapping(t_uint256,t_struct(LockedBalance)16218_storage)" + }, + { + "astId": 17340, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "epoch", + "offset": 0, + "slot": "17", + "type": "t_uint256" + }, + { + "astId": 17344, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "slope_changes", + "offset": 0, + "slot": "18", + "type": "t_mapping(t_uint256,t_int128)" + }, + { + "astId": 17346, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "supply", + "offset": 0, + "slot": "19", + "type": "t_uint256" + }, + { + "astId": 19217, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "attachments", + "offset": 0, + "slot": "20", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 19221, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "voted", + "offset": 0, + "slot": "21", + "type": "t_mapping(t_uint256,t_bool)" + }, + { + "astId": 19452, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "_delegates", + "offset": 0, + "slot": "22", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 19463, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "checkpoints", + "offset": 0, + "slot": "23", + "type": "t_mapping(t_address,t_mapping(t_uint32,t_struct(Checkpoint)16233_storage))" + }, + { + "astId": 19468, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "numCheckpoints", + "offset": 0, + "slot": "24", + "type": "t_mapping(t_address,t_uint32)" + }, + { + "astId": 19473, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "nonces", + "offset": 0, + "slot": "25", + "type": "t_mapping(t_address,t_uint256)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(Point)16227_storage)1000000000_storage": { + "base": "t_struct(Point)16227_storage", + "encoding": "inplace", + "label": "struct VotingEscrow.Point[1000000000]", + "numberOfBytes": "96000000000" + }, + "t_array(t_uint256)dyn_storage": { + "base": "t_uint256", + "encoding": "dynamic_array", + "label": "uint256[]", + "numberOfBytes": "32" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes4": { + "encoding": "inplace", + "label": "bytes4", + "numberOfBytes": "4" + }, + "t_int128": { + "encoding": "inplace", + "label": "int128", + "numberOfBytes": "16" + }, + "t_mapping(t_address,t_address)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_bool)" + }, + "t_mapping(t_address,t_mapping(t_uint256,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(uint256 => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_uint256,t_uint256)" + }, + "t_mapping(t_address,t_mapping(t_uint32,t_struct(Checkpoint)16233_storage))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(uint32 => struct VotingEscrow.Checkpoint))", + "numberOfBytes": "32", + "value": "t_mapping(t_uint32,t_struct(Checkpoint)16233_storage)" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_address,t_uint32)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint32)", + "numberOfBytes": "32", + "value": "t_uint32" + }, + "t_mapping(t_bytes4,t_bool)": { + "encoding": "mapping", + "key": "t_bytes4", + "label": "mapping(bytes4 => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_uint256,t_address)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_uint256,t_array(t_struct(Point)16227_storage)1000000000_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct VotingEscrow.Point[1000000000])", + "numberOfBytes": "32", + "value": "t_array(t_struct(Point)16227_storage)1000000000_storage" + }, + "t_mapping(t_uint256,t_bool)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_uint256,t_int128)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => int128)", + "numberOfBytes": "32", + "value": "t_int128" + }, + "t_mapping(t_uint256,t_struct(LockedBalance)16218_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct VotingEscrow.LockedBalance)", + "numberOfBytes": "32", + "value": "t_struct(LockedBalance)16218_storage" + }, + "t_mapping(t_uint256,t_struct(Point)16227_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct VotingEscrow.Point)", + "numberOfBytes": "32", + "value": "t_struct(Point)16227_storage" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_uint32,t_struct(Checkpoint)16233_storage)": { + "encoding": "mapping", + "key": "t_uint32", + "label": "mapping(uint32 => struct VotingEscrow.Checkpoint)", + "numberOfBytes": "32", + "value": "t_struct(Checkpoint)16233_storage" + }, + "t_struct(Checkpoint)16233_storage": { + "encoding": "inplace", + "label": "struct VotingEscrow.Checkpoint", + "members": [ + { + "astId": 16229, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "timestamp", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 16232, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "tokenIds", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)dyn_storage" + } + ], + "numberOfBytes": "64" + }, + "t_struct(LockedBalance)16218_storage": { + "encoding": "inplace", + "label": "struct VotingEscrow.LockedBalance", + "members": [ + { + "astId": 16215, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "amount", + "offset": 0, + "slot": "0", + "type": "t_int128" + }, + { + "astId": 16217, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "end", + "offset": 0, + "slot": "1", + "type": "t_uint256" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Point)16227_storage": { + "encoding": "inplace", + "label": "struct VotingEscrow.Point", + "members": [ + { + "astId": 16220, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "bias", + "offset": 0, + "slot": "0", + "type": "t_int128" + }, + { + "astId": 16222, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "slope", + "offset": 16, + "slot": "0", + "type": "t_int128" + }, + { + "astId": 16224, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "ts", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 16226, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "blk", + "offset": 0, + "slot": "2", + "type": "t_uint256" + } + ], + "numberOfBytes": "96" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "encoding": "inplace", + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/0faaa79d8b79020b765ba7705413c447.json b/deployments/arbitrumGoerli/solcInputs/0faaa79d8b79020b765ba7705413c447.json new file mode 100644 index 00000000..8e0ee1a1 --- /dev/null +++ b/deployments/arbitrumGoerli/solcInputs/0faaa79d8b79020b765ba7705413c447.json @@ -0,0 +1,238 @@ +{ + "language": "Solidity", + "sources": { + "contracts/ExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/factories/BribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" + }, + "contracts/factories/GaugeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" + }, + "contracts/factories/PairFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" + }, + "contracts/factories/WrappedExternalBribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" + }, + "contracts/Gauge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/governance/L2Governor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" + }, + "contracts/governance/L2GovernorCountingSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" + }, + "contracts/governance/L2GovernorVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" + }, + "contracts/governance/L2GovernorVotesQuorumFraction.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" + }, + "contracts/interfaces/IBribe.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IBribeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IERC20.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" + }, + "contracts/interfaces/IGauge.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" + }, + "contracts/interfaces/IGaugeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IMinter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" + }, + "contracts/interfaces/IPair.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IPairCallee.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" + }, + "contracts/interfaces/IPairFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" + }, + "contracts/interfaces/IRewardsDistributor.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" + }, + "contracts/interfaces/IRouter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" + }, + "contracts/interfaces/IVeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" + }, + "contracts/interfaces/IVelo.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" + }, + "contracts/interfaces/IVoter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" + }, + "contracts/interfaces/IVotingEscrow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" + }, + "contracts/interfaces/IWETH.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" + }, + "contracts/InternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/libraries/Base64.sol": { + "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" + }, + "contracts/libraries/Math.sol": { + "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" + }, + "contracts/Minter.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" + }, + "contracts/Pair.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/PairFees.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" + }, + "contracts/redeem/MerkleClaim.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" + }, + "contracts/redeem/RedemptionReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" + }, + "contracts/redeem/RedemptionSender.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" + }, + "contracts/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" + }, + "contracts/Router.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" + }, + "contracts/Velo.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" + }, + "contracts/VelodromeLibrary.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" + }, + "contracts/VeloGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" + }, + "contracts/Voter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VotingEscrow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" + }, + "contracts/WrappedExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + }, + "libraries": { + "": { + "__CACHE_BREAKER__": "0x0000000000000031363733323636393538333833" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/1bc83d498cf3ed68f4ca9abac087a4fd.json b/deployments/arbitrumGoerli/solcInputs/1bc83d498cf3ed68f4ca9abac087a4fd.json new file mode 100644 index 00000000..58ad9c07 --- /dev/null +++ b/deployments/arbitrumGoerli/solcInputs/1bc83d498cf3ed68f4ca9abac087a4fd.json @@ -0,0 +1,238 @@ +{ + "language": "Solidity", + "sources": { + "contracts/ExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/factories/BribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" + }, + "contracts/factories/GaugeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" + }, + "contracts/factories/PairFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" + }, + "contracts/factories/WrappedExternalBribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" + }, + "contracts/Gauge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/governance/L2Governor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" + }, + "contracts/governance/L2GovernorCountingSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" + }, + "contracts/governance/L2GovernorVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" + }, + "contracts/governance/L2GovernorVotesQuorumFraction.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" + }, + "contracts/interfaces/IBribe.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IBribeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IERC20.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" + }, + "contracts/interfaces/IGauge.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" + }, + "contracts/interfaces/IGaugeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IMinter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" + }, + "contracts/interfaces/IPair.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IPairCallee.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" + }, + "contracts/interfaces/IPairFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" + }, + "contracts/interfaces/IRewardsDistributor.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" + }, + "contracts/interfaces/IRouter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" + }, + "contracts/interfaces/IVeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" + }, + "contracts/interfaces/IVelo.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" + }, + "contracts/interfaces/IVoter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" + }, + "contracts/interfaces/IVotingEscrow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" + }, + "contracts/interfaces/IWETH.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" + }, + "contracts/InternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/libraries/Base64.sol": { + "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" + }, + "contracts/libraries/Math.sol": { + "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" + }, + "contracts/Minter.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" + }, + "contracts/Pair.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/PairFees.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" + }, + "contracts/redeem/MerkleClaim.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" + }, + "contracts/redeem/RedemptionReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" + }, + "contracts/redeem/RedemptionSender.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" + }, + "contracts/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" + }, + "contracts/Router.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" + }, + "contracts/Velo.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" + }, + "contracts/VelodromeLibrary.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" + }, + "contracts/VeloGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" + }, + "contracts/Voter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VotingEscrow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" + }, + "contracts/WrappedExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + }, + "libraries": { + "": { + "__CACHE_BREAKER__": "0x0000000000000031363733323631313736343534" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/6045e31091c7162ece1e348fdb6fb21d.json b/deployments/arbitrumGoerli/solcInputs/6045e31091c7162ece1e348fdb6fb21d.json new file mode 100644 index 00000000..8533a328 --- /dev/null +++ b/deployments/arbitrumGoerli/solcInputs/6045e31091c7162ece1e348fdb6fb21d.json @@ -0,0 +1,238 @@ +{ + "language": "Solidity", + "sources": { + "contracts/ExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/factories/BribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" + }, + "contracts/factories/GaugeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" + }, + "contracts/factories/PairFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" + }, + "contracts/factories/WrappedExternalBribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" + }, + "contracts/Gauge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/governance/L2Governor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" + }, + "contracts/governance/L2GovernorCountingSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" + }, + "contracts/governance/L2GovernorVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" + }, + "contracts/governance/L2GovernorVotesQuorumFraction.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" + }, + "contracts/interfaces/IBribe.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IBribeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IERC20.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" + }, + "contracts/interfaces/IGauge.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" + }, + "contracts/interfaces/IGaugeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IMinter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" + }, + "contracts/interfaces/IPair.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IPairCallee.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" + }, + "contracts/interfaces/IPairFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" + }, + "contracts/interfaces/IRewardsDistributor.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" + }, + "contracts/interfaces/IRouter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" + }, + "contracts/interfaces/IVeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" + }, + "contracts/interfaces/IVelo.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" + }, + "contracts/interfaces/IVoter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" + }, + "contracts/interfaces/IVotingEscrow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" + }, + "contracts/interfaces/IWETH.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" + }, + "contracts/InternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/libraries/Base64.sol": { + "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" + }, + "contracts/libraries/Math.sol": { + "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" + }, + "contracts/Minter.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" + }, + "contracts/Pair.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/PairFees.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" + }, + "contracts/redeem/MerkleClaim.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" + }, + "contracts/redeem/RedemptionReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" + }, + "contracts/redeem/RedemptionSender.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" + }, + "contracts/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" + }, + "contracts/Router.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" + }, + "contracts/Velo.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" + }, + "contracts/VelodromeLibrary.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" + }, + "contracts/VeloGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" + }, + "contracts/Voter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VotingEscrow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" + }, + "contracts/WrappedExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + }, + "libraries": { + "": { + "__CACHE_BREAKER__": "0x0000000000000031363733323539333237323139" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/bb56ebd0528f2e0f691b8bc31f08a7c1.json b/deployments/arbitrumGoerli/solcInputs/bb56ebd0528f2e0f691b8bc31f08a7c1.json new file mode 100644 index 00000000..a1310587 --- /dev/null +++ b/deployments/arbitrumGoerli/solcInputs/bb56ebd0528f2e0f691b8bc31f08a7c1.json @@ -0,0 +1,238 @@ +{ + "language": "Solidity", + "sources": { + "contracts/ExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/factories/BribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" + }, + "contracts/factories/GaugeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" + }, + "contracts/factories/PairFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" + }, + "contracts/factories/WrappedExternalBribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" + }, + "contracts/Gauge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/governance/L2Governor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" + }, + "contracts/governance/L2GovernorCountingSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" + }, + "contracts/governance/L2GovernorVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" + }, + "contracts/governance/L2GovernorVotesQuorumFraction.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" + }, + "contracts/interfaces/IBribe.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IBribeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IERC20.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" + }, + "contracts/interfaces/IGauge.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" + }, + "contracts/interfaces/IGaugeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IMinter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" + }, + "contracts/interfaces/IPair.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IPairCallee.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" + }, + "contracts/interfaces/IPairFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" + }, + "contracts/interfaces/IRewardsDistributor.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" + }, + "contracts/interfaces/IRouter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" + }, + "contracts/interfaces/IVeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" + }, + "contracts/interfaces/IVelo.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" + }, + "contracts/interfaces/IVoter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" + }, + "contracts/interfaces/IVotingEscrow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" + }, + "contracts/interfaces/IWETH.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" + }, + "contracts/InternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/libraries/Base64.sol": { + "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" + }, + "contracts/libraries/Math.sol": { + "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" + }, + "contracts/Minter.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" + }, + "contracts/Pair.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/PairFees.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" + }, + "contracts/redeem/MerkleClaim.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" + }, + "contracts/redeem/RedemptionReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" + }, + "contracts/redeem/RedemptionSender.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" + }, + "contracts/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" + }, + "contracts/Router.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" + }, + "contracts/Velo.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" + }, + "contracts/VelodromeLibrary.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" + }, + "contracts/VeloGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" + }, + "contracts/Voter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VotingEscrow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" + }, + "contracts/WrappedExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + }, + "libraries": { + "": { + "__CACHE_BREAKER__": "0x0000000000000031363733323630303234313031" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/e6fbf9feea298b0eb6ed1dc19df1c5ab.json b/deployments/arbitrumGoerli/solcInputs/e6fbf9feea298b0eb6ed1dc19df1c5ab.json new file mode 100644 index 00000000..bcacefe1 --- /dev/null +++ b/deployments/arbitrumGoerli/solcInputs/e6fbf9feea298b0eb6ed1dc19df1c5ab.json @@ -0,0 +1,238 @@ +{ + "language": "Solidity", + "sources": { + "contracts/ExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/factories/BribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" + }, + "contracts/factories/GaugeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" + }, + "contracts/factories/PairFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" + }, + "contracts/factories/WrappedExternalBribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" + }, + "contracts/Gauge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/governance/L2Governor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" + }, + "contracts/governance/L2GovernorCountingSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" + }, + "contracts/governance/L2GovernorVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" + }, + "contracts/governance/L2GovernorVotesQuorumFraction.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" + }, + "contracts/interfaces/IBribe.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IBribeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IERC20.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" + }, + "contracts/interfaces/IGauge.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" + }, + "contracts/interfaces/IGaugeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IMinter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" + }, + "contracts/interfaces/IPair.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IPairCallee.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" + }, + "contracts/interfaces/IPairFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" + }, + "contracts/interfaces/IRewardsDistributor.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" + }, + "contracts/interfaces/IRouter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" + }, + "contracts/interfaces/IVeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" + }, + "contracts/interfaces/IVelo.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" + }, + "contracts/interfaces/IVoter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" + }, + "contracts/interfaces/IVotingEscrow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" + }, + "contracts/interfaces/IWETH.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" + }, + "contracts/InternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/libraries/Base64.sol": { + "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" + }, + "contracts/libraries/Math.sol": { + "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" + }, + "contracts/Minter.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" + }, + "contracts/Pair.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/PairFees.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" + }, + "contracts/redeem/MerkleClaim.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" + }, + "contracts/redeem/RedemptionReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" + }, + "contracts/redeem/RedemptionSender.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" + }, + "contracts/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" + }, + "contracts/Router.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" + }, + "contracts/Velo.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" + }, + "contracts/VelodromeLibrary.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" + }, + "contracts/VeloGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" + }, + "contracts/Voter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VotingEscrow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" + }, + "contracts/WrappedExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + }, + "libraries": { + "": { + "__CACHE_BREAKER__": "0x0000000000000031363733323539353134343839" + } + } + } +} \ No newline at end of file diff --git a/exported.json b/exported.json new file mode 100644 index 00000000..65005d6b --- /dev/null +++ b/exported.json @@ -0,0 +1,6960 @@ +{ + "name": "arbitrumGoerli", + "chainId": "421613", + "contracts": { + "BribeFactory": { + "address": "0x5542edb529F7c963583e9B8e5339121cFCf4B606", + "abi": [ + { + "inputs": [ + { + "internalType": "address[]", + "name": "allowedRewards", + "type": "address[]" + } + ], + "name": "createExternalBribe", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "allowedRewards", + "type": "address[]" + } + ], + "name": "createInternalBribe", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "last_external_bribe", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "last_internal_bribe", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "GaugeFactory": { + "address": "0x1Ac3032Dfd7e206BA6d08F453f38593b9A583052", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_pool", + "type": "address" + }, + { + "internalType": "address", + "name": "_internal_bribe", + "type": "address" + }, + { + "internalType": "address", + "name": "_external_bribe", + "type": "address" + }, + { + "internalType": "address", + "name": "_ve", + "type": "address" + }, + { + "internalType": "bool", + "name": "isPair", + "type": "bool" + }, + { + "internalType": "address[]", + "name": "allowedRewards", + "type": "address[]" + } + ], + "name": "createGauge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "last_gauge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "MerkleClaim": { + "address": "0x0a68F78212D69EfC6346B5F9d72BC5A301779BE9", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_velo", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_merkleRoot", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Claim", + "type": "event" + }, + { + "inputs": [], + "name": "VELO", + "outputs": [ + { + "internalType": "contract IVelo", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "name": "claim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "hasClaimed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "merkleRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "Minter": { + "address": "0xd2C3ebFB8e7e79CA84080a8551D86Df50B0F559d", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "__voter", + "type": "address" + }, + { + "internalType": "address", + "name": "__ve", + "type": "address" + }, + { + "internalType": "address", + "name": "__rewards_distributor", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weekly", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "circulating_supply", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "circulating_emission", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "inputs": [], + "name": "MAX_TEAM_RATE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_rewards_distributor", + "outputs": [ + { + "internalType": "contract IRewardsDistributor", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_ve", + "outputs": [ + { + "internalType": "contract IVotingEscrow", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_velo", + "outputs": [ + { + "internalType": "contract IVelo", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_voter", + "outputs": [ + { + "internalType": "contract IVoter", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "active_period", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "calculate_emission", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_minted", + "type": "uint256" + } + ], + "name": "calculate_growth", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "circulating_emission", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "circulating_supply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "claimants", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "max", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingTeam", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_team", + "type": "address" + } + ], + "name": "setTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_teamRate", + "type": "uint256" + } + ], + "name": "setTeamRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "team", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "teamRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "update_period", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "weekly", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "weekly_emission", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "PairFactory": { + "address": "0x7488AC81DC3908ff7141db4949e70D60A3Fd4DCc", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token0", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token1", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "indexed": false, + "internalType": "address", + "name": "pair", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "PairCreated", + "type": "event" + }, + { + "inputs": [], + "name": "MAX_FEE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptFeeManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "acceptPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allPairs", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPairsLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "createPair", + "outputs": [ + { + "internalType": "address", + "name": "pair", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "feeManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_stable", + "type": "bool" + } + ], + "name": "getFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getInitializable", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "name": "getPair", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isPair", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pairCodeHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "pauser", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingFeeManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingPauser", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "_fee", + "type": "uint256" + } + ], + "name": "setFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_feeManager", + "type": "address" + } + ], + "name": "setFeeManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_state", + "type": "bool" + } + ], + "name": "setPause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_pauser", + "type": "address" + } + ], + "name": "setPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "stableFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "volatileFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "RedemptionReceiver": { + "address": "0x08e352f2130d4b68d7B1264CD42191205B61b60f", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_usdc", + "type": "address" + }, + { + "internalType": "address", + "name": "_velo", + "type": "address" + }, + { + "internalType": "uint16", + "name": "_fantomChainId", + "type": "uint16" + }, + { + "internalType": "address", + "name": "_endpoint", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "fantomSender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemableUSDC", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemableVELO", + "type": "uint256" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "inputs": [], + "name": "ELIGIBLE_WEVE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "USDC", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VELO", + "outputs": [ + { + "internalType": "contract IVelo", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "toAddressBytes", + "type": "bytes" + } + ], + "name": "addressFromPackedBytes", + "outputs": [ + { + "internalType": "address", + "name": "toAddress", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "claimLeftovers", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "deployed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "endpoint", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "fantomChainId", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "fantomSender", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_fantomSender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_redeemableUSDC", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_redeemableVELO", + "type": "uint256" + } + ], + "name": "initializeReceiverWith", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "leftoverVELO", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "srcChainId", + "type": "uint16" + }, + { + "internalType": "bytes", + "name": "srcAddress", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "lzReceive", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountWEVE", + "type": "uint256" + } + ], + "name": "previewRedeem", + "outputs": [ + { + "internalType": "uint256", + "name": "shareOfUSDC", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "shareOfVELO", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "redeemableUSDC", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "redeemableVELO", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "redeemedWEVE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_team", + "type": "address" + } + ], + "name": "setTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "team", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "RewardsDistributor": { + "address": "0xf6CdA702C6Bd15d5C0A325CE8f9f88219fE5F445", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_voting_escrow", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "time", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "CheckpointToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "claim_epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "max_epoch", + "type": "uint256" + } + ], + "name": "Claimed", + "type": "event" + }, + { + "inputs": [], + "name": "checkpoint_token", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "checkpoint_total_supply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "claim", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "_tokenIds", + "type": "uint256[]" + } + ], + "name": "claim_many", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "claimable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "depositor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "last_token_time", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_depositor", + "type": "address" + } + ], + "name": "setDepositor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "start_time", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "time_cursor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "time_cursor_of", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "timestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token_last_balance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "tokens_per_week", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "user_epoch_of", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_timestamp", + "type": "uint256" + } + ], + "name": "ve_for_at", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "ve_supply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "voting_escrow", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "Router": { + "address": "0xCeaEA7A5cB3e7521DdE6717BCc99a4c8c60E07b6", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_factory", + "type": "address" + }, + { + "internalType": "address", + "name": "_weth", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "internalType": "struct Router.route[]", + "name": "routes", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "UNSAFE_swapExactTokensForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "amountADesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBDesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountAMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "addLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "amountTokenDesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountTokenMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETHMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "addLiquidityETH", + "outputs": [ + { + "internalType": "uint256", + "name": "amountToken", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETH", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + } + ], + "name": "getAmountOut", + "outputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "internalType": "struct Router.route[]", + "name": "routes", + "type": "tuple[]" + } + ], + "name": "getAmountsOut", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "reserveA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveB", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pair", + "type": "address" + } + ], + "name": "isPair", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "pairFor", + "outputs": [ + { + "internalType": "address", + "name": "pair", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "amountADesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBDesired", + "type": "uint256" + } + ], + "name": "quoteAddLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "name": "quoteRemoveLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountAMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "removeLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountTokenMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETHMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "removeLiquidityETH", + "outputs": [ + { + "internalType": "uint256", + "name": "amountToken", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETH", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountTokenMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETHMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "approveMax", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "removeLiquidityETHWithPermit", + "outputs": [ + { + "internalType": "uint256", + "name": "amountToken", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETH", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountAMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "approveMax", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "removeLiquidityWithPermit", + "outputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + } + ], + "name": "sortTokens", + "outputs": [ + { + "internalType": "address", + "name": "token0", + "type": "address" + }, + { + "internalType": "address", + "name": "token1", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "internalType": "struct Router.route[]", + "name": "routes", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactETHForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "internalType": "struct Router.route[]", + "name": "routes", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForETH", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "internalType": "struct Router.route[]", + "name": "routes", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenFrom", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenTo", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensSimple", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "weth", + "outputs": [ + { + "internalType": "contract IWETH", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VeArtProxy": { + "address": "0x5e7569D02214289490d16bCE4F96B38071db1aD8", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_balanceOf", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_locked_end", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "_tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "output", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } + ] + }, + "Velo": { + "address": "0xe69b00A164047e7eB87B73971B0f340eEbFF9c81", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "claim", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_recipient", + "type": "address" + } + ], + "name": "initialMint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initialMinted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "merkleClaim", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "minter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "redemptionReceiver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_merkleClaim", + "type": "address" + } + ], + "name": "setMerkleClaim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_minter", + "type": "address" + } + ], + "name": "setMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_receiver", + "type": "address" + } + ], + "name": "setRedemptionReceiver", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "VeloGovernor": { + "address": "0x588ADD83f24690BceEbaa4266cd8DC65709DDa4d", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IVotes", + "name": "_ve", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "Empty", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "ProposalCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldQuorumNumerator", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newQuorumNumerator", + "type": "uint256" + } + ], + "name": "QuorumNumeratorUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "VoteCast", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "VoteCastWithParams", + "type": "event" + }, + { + "inputs": [], + "name": "BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COUNTING_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "EXTENDED_BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_PROPOSAL_NUMERATOR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PROPOSAL_DENOMINATOR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + } + ], + "name": "castVote", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "castVoteBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "castVoteWithReason", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "castVoteWithReasonAndParamsBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "execute", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockTimestamp", + "type": "uint256" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockTimestamp", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "getVotesWithParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasVoted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "hashProposal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalDeadline", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalNumerator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "againstVotes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "forVotes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "abstainVotes", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "propose", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "blockTimestamp", + "type": "uint256" + } + ], + "name": "quorum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "quorumDenominator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "quorumNumerator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "relay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "numerator", + "type": "uint256" + } + ], + "name": "setProposalNumerator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newTeam", + "type": "address" + } + ], + "name": "setTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "state", + "outputs": [ + { + "internalType": "enum IGovernor.ProposalState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "team", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IVotes", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newQuorumNumerator", + "type": "uint256" + } + ], + "name": "updateQuorumNumerator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "votingPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VelodromeLibrary": { + "address": "0x233ed5d7FAed19F7b8A28844E2845FBF0F145Be2", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_router", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getAmountOut", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getMinimumValue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getSample", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getTradeDiff", + "outputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "pair", + "type": "address" + } + ], + "name": "getTradeDiff", + "outputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "Voter": { + "address": "0x574607c69f369f0535E77C5F7C35767Aee04879A", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "__ve", + "type": "address" + }, + { + "internalType": "address", + "name": "_factory", + "type": "address" + }, + { + "internalType": "address", + "name": "_gauges", + "type": "address" + }, + { + "internalType": "address", + "name": "_bribes", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + } + ], + "name": "Abstained", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Attach", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "lp", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Detach", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DistributeReward", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "internal_bribe", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "external_bribe", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "GaugeCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + } + ], + "name": "GaugeKilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + } + ], + "name": "GaugeRevived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "reward", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "NotifyReward", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + } + ], + "name": "Voted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "whitelister", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "Whitelisted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "lp", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [], + "name": "_ve", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "attachTokenToGauge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bribefactory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_bribes", + "type": "address[]" + }, + { + "internalType": "address[][]", + "name": "_tokens", + "type": "address[][]" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "claimBribes", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_fees", + "type": "address[]" + }, + { + "internalType": "address[][]", + "name": "_tokens", + "type": "address[][]" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "claimFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_gauges", + "type": "address[]" + }, + { + "internalType": "address[][]", + "name": "_tokens", + "type": "address[][]" + } + ], + "name": "claimRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "claimable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_pool", + "type": "address" + } + ], + "name": "createGauge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "detachTokenFromGauge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_gauges", + "type": "address[]" + } + ], + "name": "distribute", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gauge", + "type": "address" + } + ], + "name": "distribute", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "start", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "finish", + "type": "uint256" + } + ], + "name": "distribute", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "distribute", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_gauges", + "type": "address[]" + } + ], + "name": "distributeFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "distro", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "emergencyCouncil", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "emitDeposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "emitWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "external_bribes", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gaugefactory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "gauges", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_tokens", + "type": "address[]" + }, + { + "internalType": "address", + "name": "_minter", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "internal_bribes", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isAlive", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isGauge", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isWhitelisted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gauge", + "type": "address" + } + ], + "name": "killGauge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "lastVoted", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "length", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "notifyRewardAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "poke", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "poolForGauge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "poolVote", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "pools", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "reset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gauge", + "type": "address" + } + ], + "name": "reviveGauge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_council", + "type": "address" + } + ], + "name": "setEmergencyCouncil", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_governor", + "type": "address" + } + ], + "name": "setGovernor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalWeight", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "updateAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_gauges", + "type": "address[]" + } + ], + "name": "updateFor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "start", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "end", + "type": "uint256" + } + ], + "name": "updateForRange", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gauge", + "type": "address" + } + ], + "name": "updateGauge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "usedWeights", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "_poolVote", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "_weights", + "type": "uint256[]" + } + ], + "name": "vote", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "votes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "weights", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + } + ], + "name": "whitelist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "VotingEscrow": { + "address": "0x6b938BA22FB5520fFB5D14c9C4Fef82a48761497", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "token_addr", + "type": "address" + }, + { + "internalType": "address", + "name": "art_proxy", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "fromDelegate", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "toDelegate", + "type": "address" + } + ], + "name": "DelegateChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "DelegateVotesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "locktime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum VotingEscrow.DepositType", + "name": "deposit_type", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "ts", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "prevSupply", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "supply", + "type": "uint256" + } + ], + "name": "Supply", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "ts", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [], + "name": "DELEGATION_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DOMAIN_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_DELEGATES", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "abstain", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_approved", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "artProxy", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "attach", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "attachments", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_block", + "type": "uint256" + } + ], + "name": "balanceOfAtNFT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "balanceOfNFT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_t", + "type": "uint256" + } + ], + "name": "balanceOfNFTAt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "block_number", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkpoint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "name": "checkpoints", + "outputs": [ + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_lock_duration", + "type": "uint256" + } + ], + "name": "create_lock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_lock_duration", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + } + ], + "name": "create_lock_for", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + } + ], + "name": "delegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "delegateBySig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "delegates", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "deposit_for", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "detach", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "epoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "getPastTotalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "getPastVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "getPastVotesIndex", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "get_last_user_slope", + "outputs": [ + { + "internalType": "int128", + "name": "", + "type": "int128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "increase_amount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_lock_duration", + "type": "uint256" + } + ], + "name": "increase_unlock_time", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "isApprovedOrOwner", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "locked", + "outputs": [ + { + "internalType": "int128", + "name": "amount", + "type": "int128" + }, + { + "internalType": "uint256", + "name": "end", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "locked__end", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_from", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_to", + "type": "uint256" + } + ], + "name": "merge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "numCheckpoints", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "ownership_change", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "point_history", + "outputs": [ + { + "internalType": "int128", + "name": "bias", + "type": "int128" + }, + { + "internalType": "int128", + "name": "slope", + "type": "int128" + }, + { + "internalType": "uint256", + "name": "ts", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "blk", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "_approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_proxy", + "type": "address" + } + ], + "name": "setArtProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_team", + "type": "address" + } + ], + "name": "setTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_voter", + "type": "address" + } + ], + "name": "setVoter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "slope_changes", + "outputs": [ + { + "internalType": "int128", + "name": "", + "type": "int128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "supply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_interfaceID", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "team", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenIndex", + "type": "uint256" + } + ], + "name": "tokenOfOwnerByIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_block", + "type": "uint256" + } + ], + "name": "totalSupplyAt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "t", + "type": "uint256" + } + ], + "name": "totalSupplyAtT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "user_point_epoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "user_point_history", + "outputs": [ + { + "internalType": "int128", + "name": "bias", + "type": "int128" + }, + { + "internalType": "int128", + "name": "slope", + "type": "int128" + }, + { + "internalType": "uint256", + "name": "ts", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "blk", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_idx", + "type": "uint256" + } + ], + "name": "user_point_history__ts", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "voted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "voter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "voting", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] + } + } +} \ No newline at end of file diff --git a/hardhat.config.ts b/hardhat.config.ts index e6f3cbba..38f4e9b3 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -1,27 +1,25 @@ -import '@nomiclabs/hardhat-ethers' -import '@nomiclabs/hardhat-etherscan' -import '@nomiclabs/hardhat-waffle' -import '@typechain/hardhat' -import 'hardhat-preprocessor' -import 'hardhat-abi-exporter' -import '@cartesi/hardhat-verify-deployments' +import "@nomiclabs/hardhat-ethers"; +import "@nomiclabs/hardhat-etherscan"; +import "@nomiclabs/hardhat-waffle"; +import "@typechain/hardhat"; +import "hardhat-preprocessor"; +import "hardhat-abi-exporter"; +import "hardhat-deploy"; -import './tasks/accounts' -import './tasks/deploy' +import fs from "fs"; +import { resolve } from "path"; -import fs from 'fs' -import { resolve } from 'path' +import { config as dotenvConfig } from "dotenv"; +import { HardhatUserConfig } from "hardhat/config"; -import { config as dotenvConfig } from 'dotenv' -import { HardhatUserConfig, task } from 'hardhat/config' - -dotenvConfig({ path: resolve(__dirname, './.env') }) +dotenvConfig({ path: resolve(__dirname, "./.env") }); +import "./checkEnv"; const remappings = fs - .readFileSync('remappings.txt', 'utf8') - .split('\n') + .readFileSync("remappings.txt", "utf8") + .split("\n") .filter(Boolean) - .map(line => line.trim().split('=')) + .map((line) => line.trim().split("=")); const config: HardhatUserConfig = { networks: { @@ -29,63 +27,78 @@ const config: HardhatUserConfig = { initialBaseFeePerGas: 0, forking: { url: `https://arb-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY}`, - blockNumber: 16051852 - } + blockNumber: 16051852, + }, }, opera: { - url: 'https://rpc.fantom.network', - accounts: [process.env.PRIVATE_KEY!] + url: "https://rpc.fantom.network", + accounts: [process.env.PRIVATE_KEY!], }, arbitrum: { url: `https://arb-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY}`, accounts: [process.env.PRIVATE_KEY!], - chainId: 42161 + chainId: 42161, + saveDeployments: true, + verify: { + etherscan: { + apiUrl: "https://api.arbiscan.io/api", + }, + }, }, arbitrumGoerli: { - url: 'https://arb-goerli.g.alchemy.com/v2/JW-n2dVWqUeU-bdj_MKeq2qs3LupK8CS', + url: `https://arb-goerli.g.alchemy.com/v2/${process.env.ALCHEMY_GOERLI_ARBITRUM_API_KEY}`, accounts: [process.env.PRIVATE_KEY!], - chainId: 421613 + chainId: 421613, + saveDeployments: true, + verify: { + etherscan: { + apiUrl: "https://api-goerli.arbiscan.io/", + apiKey: process.env.ARB_SCAN_API_KEY!, + }, + }, }, - ftmTestnet: { - url: 'https://rpc.testnet.fantom.network', - accounts: [process.env.PRIVATE_KEY!] + url: "https://rpc.testnet.fantom.network", + accounts: [process.env.PRIVATE_KEY!], }, optimisticEthereum: { - url: 'https://mainnet.optimism.io', - accounts: [process.env.PRIVATE_KEY!] + url: "https://mainnet.optimism.io", + accounts: [process.env.PRIVATE_KEY!], }, optimisticKovan: { - url: 'https://kovan.optimism.io', - accounts: [process.env.PRIVATE_KEY!] - } + url: "https://kovan.optimism.io", + accounts: [process.env.PRIVATE_KEY!], + }, }, solidity: { - version: '0.8.13', + version: "0.8.13", settings: { optimizer: { enabled: true, - runs: 200 - } - } + runs: 200, + }, + }, + }, + namedAccounts: { + deployer: 0, }, // This fully resolves paths for imports in the ./lib directory for Hardhat preprocess: { - eachLine: hre => ({ + eachLine: (hre) => ({ transform: (line: string) => { if (!line.match(/^\s*import /i)) { - return line + return line; } - const remapping = remappings.find(([find]) => line.match('"' + find)) + const remapping = remappings.find(([find]) => line.match('"' + find)); if (!remapping) { - return line + return line; } - const [find, replace] = remapping - return line.replace('"' + find, '"' + replace) - } - }) + const [find, replace] = remapping; + return line.replace('"' + find, '"' + replace); + }, + }), }, etherscan: { apiKey: { @@ -94,9 +107,9 @@ const config: HardhatUserConfig = { optimisticEthereum: process.env.OP_SCAN_API_KEY!, optimisticKovan: process.env.OP_SCAN_API_KEY!, arbitrum: process.env.ARB_SCAN_API_KEY!, - arbitrumGoerli: process.env.ARB_SCAN_API_KEY! - } - } -} + arbitrumGoerli: process.env.ARB_SCAN_API_KEY!, + }, + }, +}; -export default config +export default config; diff --git a/package.json b/package.json index 35d9f6ac..96d228d5 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,11 @@ { - "name": "velodrome", + "name": "velocimeter", "version": "1.0.0", - "description": "Base layer AMM on Optimism", + "description": "Base layer AMM on Arbitrum", "directories": { "lib": "lib" }, "devDependencies": { - "@cartesi/hardhat-verify-deployments": "^0.2.0", "@nomiclabs/hardhat-ethers": "^2.0.6", "@nomiclabs/hardhat-etherscan": "^3.1.4", "@nomiclabs/hardhat-waffle": "^2.0.3", @@ -28,5 +27,8 @@ "ts-node": "^10.7.0", "typechain": "^8.0.0", "typescript": "^4.6.4" + }, + "dependencies": { + "zod": "^3.20.2" } } diff --git a/tasks/accounts.ts b/tasks/accounts.ts deleted file mode 100644 index 86e29167..00000000 --- a/tasks/accounts.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Signer } from "@ethersproject/abstract-signer"; -import { task } from "hardhat/config"; - -task("accounts", "Prints the list of accounts", async (_taskArgs, hre) => { - const accounts: Signer[] = await hre.ethers.getSigners(); - - for (const account of accounts) { - console.log(await account.getAddress()); - } -}); \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index d02355ae..9683fca5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,6 +8,6 @@ "declaration": true, "resolveJsonModule": true }, - "include": ["./tasks", "./test", "./typechain-types"], - "files": ["./hardhat.config.ts"] + "include": ["./tasks", "./test", "./typechain-types", "deploy"], + "files": ["hardhat.config.ts"] } diff --git a/veloAddress.json b/veloAddress.json deleted file mode 100644 index 2e212238..00000000 --- a/veloAddress.json +++ /dev/null @@ -1 +0,0 @@ -{"address":"0xB9aaBA85A60C48d42d1c6BD1dD1b2a549623D52F"} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 9a3dc46e..76e960ee 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,11 +2,6 @@ # yarn lockfile v1 -"@cartesi/hardhat-verify-deployments@^0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@cartesi/hardhat-verify-deployments/-/hardhat-verify-deployments-0.2.0.tgz#e0569c5a1d94e432c8567e2c468f1d634ee70b18" - integrity sha512-N8TPnB/nMjIRMgfVetVMUrCNzStf99jL3KHQCFZZHUzXbL/d0ataNkxudA1QZI0jio1OECWncoqSEsqDZvyChA== - "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" @@ -8582,3 +8577,8 @@ zksync-web3@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.8.1.tgz#db289d8f6caf61f4d5ddc471fa3448d93208dc14" integrity sha512-1A4aHPQ3MyuGjpv5X/8pVEN+MdZqMjfVmiweQSRjOlklXYu65wT9BGEOtCmMs5d3gIvLp4ssfTeuR5OCKOD2kw== + +zod@^3.20.2: + version "3.20.2" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.20.2.tgz#068606642c8f51b3333981f91c0a8ab37dfc2807" + integrity sha512-1MzNQdAvO+54H+EaK5YpyEy0T+Ejo/7YLHS93G3RnYWh5gaotGHwGeN/ZO687qEDU2y4CdStQYXVHIgrUl5UVQ== From 4442671f2c1b75a26f83bb47494609e04cce76b3 Mon Sep 17 00:00:00 2001 From: torbik Date: Wed, 11 Jan 2023 19:10:36 +0700 Subject: [PATCH 08/43] Add reuse of already deployed contracts, init, whitelist and init-dist tasks --- deploy/00_velo.ts | 2 + deploy/01_gaugeFactory.ts | 2 + deploy/02_bribeFactory.ts | 2 + deploy/04_pairFactory.ts | 2 + deploy/05_router.ts | 2 + deploy/06_library.ts | 2 + deploy/07_veArtProxy.ts | 2 + deploy/08_votingEscrow.ts | 2 + deploy/09_rewardsDist.ts | 2 + deploy/10_voter.ts | 2 + deploy/11_minter.ts | 2 + deploy/12_veloGovernor.ts | 2 + deploy/13_redemptionReceiver.ts | 2 + deploy/14_merkleClaim.ts | 2 + deploy/15_init.ts | 72 ++++++ deploy/16_whitelist.ts | 25 ++ deploy/17_dist.ts | 26 ++ deployments/arbitrumGoerli/.migrations.json | 5 + deployments/arbitrumGoerli/BribeFactory.json | 26 +- deployments/arbitrumGoerli/GaugeFactory.json | 26 +- deployments/arbitrumGoerli/MerkleClaim.json | 28 +-- deployments/arbitrumGoerli/Minter.json | 32 +-- deployments/arbitrumGoerli/PairFactory.json | 26 +- .../arbitrumGoerli/RedemptionReceiver.json | 28 +-- .../arbitrumGoerli/RewardsDistributor.json | 42 ++-- deployments/arbitrumGoerli/Router.json | 28 +-- deployments/arbitrumGoerli/VeArtProxy.json | 26 +- deployments/arbitrumGoerli/Velo.json | 36 +-- deployments/arbitrumGoerli/VeloGovernor.json | 38 +-- .../arbitrumGoerli/VelodromeLibrary.json | 28 +-- deployments/arbitrumGoerli/Voter.json | 34 +-- deployments/arbitrumGoerli/VotingEscrow.json | 52 ++-- .../52dedb568751596f5f7bda36f8e139c0.json | 238 ++++++++++++++++++ .../55f774ad815c4347b8fbe726bc77554f.json | 238 ++++++++++++++++++ .../7fabbf584e02c1cd20d7799a434dc4a7.json | 238 ++++++++++++++++++ package.json | 2 +- yarn.lock | 8 +- 37 files changed, 1100 insertions(+), 230 deletions(-) create mode 100644 deploy/15_init.ts create mode 100644 deploy/16_whitelist.ts create mode 100644 deploy/17_dist.ts create mode 100644 deployments/arbitrumGoerli/.migrations.json create mode 100644 deployments/arbitrumGoerli/solcInputs/52dedb568751596f5f7bda36f8e139c0.json create mode 100644 deployments/arbitrumGoerli/solcInputs/55f774ad815c4347b8fbe726bc77554f.json create mode 100644 deployments/arbitrumGoerli/solcInputs/7fabbf584e02c1cd20d7799a434dc4a7.json diff --git a/deploy/00_velo.ts b/deploy/00_velo.ts index 731a3b8e..2901cd93 100644 --- a/deploy/00_velo.ts +++ b/deploy/00_velo.ts @@ -11,7 +11,9 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { from: deployer, args: [], log: true, + skipIfAlreadyDeployed: true, }); }; export default func; func.tags = ["Velo"]; +func.id = "velo"; diff --git a/deploy/01_gaugeFactory.ts b/deploy/01_gaugeFactory.ts index d389be8c..25e01c5a 100644 --- a/deploy/01_gaugeFactory.ts +++ b/deploy/01_gaugeFactory.ts @@ -11,7 +11,9 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { from: deployer, args: [], log: true, + skipIfAlreadyDeployed: true, }); }; export default func; func.tags = ["GaugeFactory"]; +func.id = "gaugeFactory"; diff --git a/deploy/02_bribeFactory.ts b/deploy/02_bribeFactory.ts index 49ec7654..eec353f8 100644 --- a/deploy/02_bribeFactory.ts +++ b/deploy/02_bribeFactory.ts @@ -11,7 +11,9 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { from: deployer, args: [], log: true, + skipIfAlreadyDeployed: true, }); }; export default func; func.tags = ["BribeFactory"]; +func.id = "bribeFactory"; diff --git a/deploy/04_pairFactory.ts b/deploy/04_pairFactory.ts index 745dfe9b..53efd4cb 100644 --- a/deploy/04_pairFactory.ts +++ b/deploy/04_pairFactory.ts @@ -11,7 +11,9 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { from: deployer, args: [], log: true, + skipIfAlreadyDeployed: true, }); }; export default func; func.tags = ["PairFactory"]; +func.id = "pairFactory"; \ No newline at end of file diff --git a/deploy/05_router.ts b/deploy/05_router.ts index e0231330..b04ecaaa 100644 --- a/deploy/05_router.ts +++ b/deploy/05_router.ts @@ -16,7 +16,9 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { from: deployer, args: [pairFactory.address, ARB_TEST_CONFIG.WETH], log: true, + skipIfAlreadyDeployed: true, }); }; export default func; func.tags = ["Router"]; +func.id = "router"; \ No newline at end of file diff --git a/deploy/06_library.ts b/deploy/06_library.ts index 859c5c3a..159707a4 100644 --- a/deploy/06_library.ts +++ b/deploy/06_library.ts @@ -13,7 +13,9 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { from: deployer, args: [router.address], log: true, + skipIfAlreadyDeployed: true, }); }; export default func; func.tags = ["VelodromeLibrary"]; +func.id = "velodromeLibrary"; diff --git a/deploy/07_veArtProxy.ts b/deploy/07_veArtProxy.ts index 4fc7f14a..39c61841 100644 --- a/deploy/07_veArtProxy.ts +++ b/deploy/07_veArtProxy.ts @@ -11,7 +11,9 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { from: deployer, args: [], log: true, + skipIfAlreadyDeployed: true, }); }; export default func; func.tags = ["VeArtProxy"]; +func.id = "veArtProxy"; diff --git a/deploy/08_votingEscrow.ts b/deploy/08_votingEscrow.ts index a0d8ed9f..cdf71098 100644 --- a/deploy/08_votingEscrow.ts +++ b/deploy/08_votingEscrow.ts @@ -14,7 +14,9 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { from: deployer, args: [velo.address, veArtProxy.address], log: true, + skipIfAlreadyDeployed: true, }); }; export default func; func.tags = ["VotingEscrow"]; +func.id = "votingEscrow"; \ No newline at end of file diff --git a/deploy/09_rewardsDist.ts b/deploy/09_rewardsDist.ts index 99d5018f..bdc66b27 100644 --- a/deploy/09_rewardsDist.ts +++ b/deploy/09_rewardsDist.ts @@ -13,7 +13,9 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { from: deployer, args: [escrow.address], log: true, + skipIfAlreadyDeployed: true, }); }; export default func; func.tags = ["RewardsDistributor"]; +func.id = "rewardsDistributor"; diff --git a/deploy/10_voter.ts b/deploy/10_voter.ts index 189b023c..a06fd976 100644 --- a/deploy/10_voter.ts +++ b/deploy/10_voter.ts @@ -21,7 +21,9 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { bribeFactory.address, ], log: true, + skipIfAlreadyDeployed: true, }); }; export default func; func.tags = ["Voter"]; +func.id = "voter"; \ No newline at end of file diff --git a/deploy/11_minter.ts b/deploy/11_minter.ts index fa472418..87c11f5b 100644 --- a/deploy/11_minter.ts +++ b/deploy/11_minter.ts @@ -15,7 +15,9 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { from: deployer, args: [voter.address, escrow.address, dist.address], log: true, + skipIfAlreadyDeployed: true, }); }; export default func; func.tags = ["Minter"]; +func.id = "minter"; \ No newline at end of file diff --git a/deploy/12_veloGovernor.ts b/deploy/12_veloGovernor.ts index 024f6b25..6e7a1d59 100644 --- a/deploy/12_veloGovernor.ts +++ b/deploy/12_veloGovernor.ts @@ -13,7 +13,9 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { from: deployer, args: [escrow.address], log: true, + skipIfAlreadyDeployed: true, }); }; export default func; func.tags = ["VeloGovernor"]; +func.id = "veloGovernor"; \ No newline at end of file diff --git a/deploy/13_redemptionReceiver.ts b/deploy/13_redemptionReceiver.ts index d12d41b4..0ee096ae 100644 --- a/deploy/13_redemptionReceiver.ts +++ b/deploy/13_redemptionReceiver.ts @@ -24,7 +24,9 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { ARB_TEST_CONFIG.lzEndpoint, ], log: true, + skipIfAlreadyDeployed: true, }); }; export default func; func.tags = ["RedemptionReceiver"]; +func.id = "redemptionReceiver"; \ No newline at end of file diff --git a/deploy/14_merkleClaim.ts b/deploy/14_merkleClaim.ts index 8431b345..4b9fb709 100644 --- a/deploy/14_merkleClaim.ts +++ b/deploy/14_merkleClaim.ts @@ -17,7 +17,9 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { from: deployer, args: [velo.address, ARB_TEST_CONFIG.merkleRoot], log: true, + skipIfAlreadyDeployed: true, }); }; export default func; func.tags = ["MerkleClaim"]; +func.id = "merkleClaim"; diff --git a/deploy/15_init.ts b/deploy/15_init.ts new file mode 100644 index 00000000..315532dd --- /dev/null +++ b/deploy/15_init.ts @@ -0,0 +1,72 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; + +import arbTestnetConfig from "../tasks/deploy/constants/arbTestnetConfig"; + +const ARB_TEST_CONFIG = arbTestnetConfig; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, ethers } = hre; + + const velo = await ethers.getContract("Velo"); + const pairFactory = await ethers.getContract("PairFactory"); + const escrow = await ethers.getContract("VotingEscrow"); + const voter = await ethers.getContract("Voter"); + const distributor = await ethers.getContract("RewardsDistributor"); + const governor = await ethers.getContract("VeloGovernor"); + const minter = await ethers.getContract("Minter"); + const receiver = await ethers.getContract("RedemptionReceiver"); + + const claim = await deployments.get("MerkleClaim"); + + // Initialize + await velo.initialMint(ARB_TEST_CONFIG.teamEOA); + console.log("Initial minted"); + + await velo.setRedemptionReceiver(receiver.address); + console.log("RedemptionReceiver set"); + + await velo.setMerkleClaim(claim.address); + console.log("MerkleClaim set"); + + await velo.setMinter(minter.address); + console.log("Minter set"); + + await pairFactory.setPauser(ARB_TEST_CONFIG.teamMultisig); + console.log("Pauser set"); + + await escrow.setVoter(voter.address); + console.log( + "Voter set", + "voter address: ", + voter.address, + "escrow address: ", + escrow.address + ); + + await escrow.setTeam(ARB_TEST_CONFIG.teamMultisig); + console.log("Team set for escrow"); + + await voter.setGovernor(ARB_TEST_CONFIG.teamMultisig); + console.log("Governor set"); + + await voter.setEmergencyCouncil(ARB_TEST_CONFIG.teamMultisig); + console.log("Emergency Council set"); + + await distributor.setDepositor(minter.address); + console.log("Depositor set"); + + await receiver.setTeam(ARB_TEST_CONFIG.teamMultisig); + console.log("Team set for receiver"); + + await governor.setTeam(ARB_TEST_CONFIG.teamMultisig); + console.log("Team set for governor"); + + await minter.setTeam(ARB_TEST_CONFIG.teamMultisig); + console.log("Team set for minter"); + + return true; +}; +export default func; +func.tags = ["init_deploy"]; +func.id = "init_deploy"; diff --git a/deploy/16_whitelist.ts b/deploy/16_whitelist.ts new file mode 100644 index 00000000..8431821a --- /dev/null +++ b/deploy/16_whitelist.ts @@ -0,0 +1,25 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; + +import arbTestnetConfig from "../tasks/deploy/constants/arbTestnetConfig"; + +const ARB_TEST_CONFIG = arbTestnetConfig; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { ethers } = hre; + + const velo = await ethers.getContract("Velo"); + const voter = await ethers.getContract("Voter"); + const minter = await ethers.getContract("Minter"); + + // Whitelist + const nativeToken = [velo.address]; + const tokenWhitelist = nativeToken.concat(ARB_TEST_CONFIG.tokenWhitelist); + await voter.initialize(tokenWhitelist, minter.address); + console.log("Whitelist set"); + + return true; +}; +export default func; +func.tags = ["whitelist"]; +func.id = "whitelist"; diff --git a/deploy/17_dist.ts b/deploy/17_dist.ts new file mode 100644 index 00000000..a4951acc --- /dev/null +++ b/deploy/17_dist.ts @@ -0,0 +1,26 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; + +import arbTestnetConfig from "../tasks/deploy/constants/arbTestnetConfig"; + +const ARB_TEST_CONFIG = arbTestnetConfig; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { ethers } = hre; + const minter = await ethers.getContract("Minter"); + + // Initial veVELO distro + await minter.initialize( + ARB_TEST_CONFIG.partnerAddrs, + ARB_TEST_CONFIG.partnerAmts, + ARB_TEST_CONFIG.partnerMax + ); + console.log("veVELO distributed"); + + console.log("Arbitrum Goerli Velocimeter Instruments deployed"); + + return true; +}; +export default func; +func.tags = ["initial_dist"]; +func.id = "initial_dist"; diff --git a/deployments/arbitrumGoerli/.migrations.json b/deployments/arbitrumGoerli/.migrations.json new file mode 100644 index 00000000..298c850a --- /dev/null +++ b/deployments/arbitrumGoerli/.migrations.json @@ -0,0 +1,5 @@ +{ + "init_deploy": 1673436417, + "whitelist": 1673436420, + "initial_dist": 1673436425 +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/BribeFactory.json b/deployments/arbitrumGoerli/BribeFactory.json index e1168e8d..226f04d5 100644 --- a/deployments/arbitrumGoerli/BribeFactory.json +++ b/deployments/arbitrumGoerli/BribeFactory.json @@ -1,5 +1,5 @@ { - "address": "0x5542edb529F7c963583e9B8e5339121cFCf4B606", + "address": "0x679e8fED0Cd87abAFB0BA481F32b7BDd8b272789", "abi": [ { "inputs": [ @@ -66,28 +66,28 @@ "type": "function" } ], - "transactionHash": "0xd2295e39221606283b3b8546159a76c72a42aa57c2b34c891ddb54de0a4f2d18", + "transactionHash": "0xc2bdc206f40980ba9cd61c742a5305a90998aaad88bf3eb136b4324242635877", "receipt": { "to": null, "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0x5542edb529F7c963583e9B8e5339121cFCf4B606", + "contractAddress": "0x679e8fED0Cd87abAFB0BA481F32b7BDd8b272789", "transactionIndex": 1, - "gasUsed": "37915213", + "gasUsed": "68419398", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x275b23ee626d6c37edf116a20b66f0859aca71be63e068739cee659b82b5bee8", - "transactionHash": "0xd2295e39221606283b3b8546159a76c72a42aa57c2b34c891ddb54de0a4f2d18", + "blockHash": "0x09b064f0ab04c22103e1cfb3be1200f24164a3182432f0953516dd81c27ff50a", + "transactionHash": "0xc2bdc206f40980ba9cd61c742a5305a90998aaad88bf3eb136b4324242635877", "logs": [], - "blockNumber": 4195008, - "cumulativeGasUsed": "37915213", + "blockNumber": 4263671, + "cumulativeGasUsed": "68419398", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 5, - "solcInputHash": "0faaa79d8b79020b765ba7705413c447", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createExternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createInternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_external_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_internal_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/BribeFactory.sol\":\"BribeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/ExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract ExternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve; // \\u5929\\u4f7f\\u306e\\u305f\\u307e\\u3054\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balanceOf;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n _prevSupply = supplyCheckpoints[\\n getPriorSupplyIndex(_nextEpochStart + DURATION)\\n ].supply;\\n prevRewards.balanceOf =\\n (cp0.balanceOf *\\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (block.timestamp > _lastEpochEnd) {\\n reward +=\\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\\n }\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0xfe1e53dea8a63ce448c5856a740ed73038ad29a9dcd0f2a2752049b146bb4eb0\",\"license\":\"MIT\"},\"contracts/InternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract InternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve;\\n\\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 public constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n mapping(address => mapping(uint256 => uint256))\\n public userRewardPerTokenStored;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (totalSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / totalSupply);\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\\n _startTimestamp = endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][tokenId],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][tokenId]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n require(isReward[token]);\\n\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2dc302de5dfd95018d1fba7a3a1916d2c1fcf32859d19d38648767f13422a694\",\"license\":\"MIT\"},\"contracts/factories/BribeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IBribeFactory.sol\\\";\\nimport 'contracts/InternalBribe.sol';\\nimport 'contracts/ExternalBribe.sol';\\n\\ncontract BribeFactory is IBribeFactory {\\n address public last_internal_bribe;\\n address public last_external_bribe;\\n\\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\\n return last_internal_bribe;\\n }\\n\\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\\n return last_external_bribe;\\n }\\n}\\n\",\"keccak256\":\"0x30d69b5733c01d1d27e8af06e6217200709721fb84ee8458ee50269bf2ce7ed8\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50614cca806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea26469706673582212205b93468d06478818879cb427a7ca7c73b721ca254f037422ec97cabf99fbbc3664736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea264697066735822122078729899baedc77b130e2f4072073dad293ec9103c5aa03801a6a9313038b6c864736f6c634300080d0033a26469706673582212208da3b33a270aaa552b25843a6147be3e4e286cd741990f1a2e68b8b14926288464736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea26469706673582212205b93468d06478818879cb427a7ca7c73b721ca254f037422ec97cabf99fbbc3664736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea264697066735822122078729899baedc77b130e2f4072073dad293ec9103c5aa03801a6a9313038b6c864736f6c634300080d0033a26469706673582212208da3b33a270aaa552b25843a6147be3e4e286cd741990f1a2e68b8b14926288464736f6c634300080d0033", + "numDeployments": 8, + "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createExternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createInternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_external_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_internal_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/BribeFactory.sol\":\"BribeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/ExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract ExternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve; // \\u5929\\u4f7f\\u306e\\u305f\\u307e\\u3054\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balanceOf;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n _prevSupply = supplyCheckpoints[\\n getPriorSupplyIndex(_nextEpochStart + DURATION)\\n ].supply;\\n prevRewards.balanceOf =\\n (cp0.balanceOf *\\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (block.timestamp > _lastEpochEnd) {\\n reward +=\\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\\n }\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0xfe1e53dea8a63ce448c5856a740ed73038ad29a9dcd0f2a2752049b146bb4eb0\",\"license\":\"MIT\"},\"contracts/InternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract InternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve;\\n\\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 public constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n mapping(address => mapping(uint256 => uint256))\\n public userRewardPerTokenStored;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (totalSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / totalSupply);\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\\n _startTimestamp = endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][tokenId],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][tokenId]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n require(isReward[token]);\\n\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2dc302de5dfd95018d1fba7a3a1916d2c1fcf32859d19d38648767f13422a694\",\"license\":\"MIT\"},\"contracts/factories/BribeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IBribeFactory.sol\\\";\\nimport 'contracts/InternalBribe.sol';\\nimport 'contracts/ExternalBribe.sol';\\n\\ncontract BribeFactory is IBribeFactory {\\n address public last_internal_bribe;\\n address public last_external_bribe;\\n\\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\\n return last_internal_bribe;\\n }\\n\\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\\n return last_external_bribe;\\n }\\n}\\n\",\"keccak256\":\"0x30d69b5733c01d1d27e8af06e6217200709721fb84ee8458ee50269bf2ce7ed8\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50614cca806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea26469706673582212205001d291b73df7800b68c90f6d4fa28c64f7e39d7715f0603d0486eddb6c899f64736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea2646970667358221220e0d92e5694609f891642dbb48443dd8f64c369879924189c1410511aecb25c1b64736f6c634300080d0033a2646970667358221220fb1c721954beea886e30347669fd9426afc113dc313de278d83530f66e146c4b64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea26469706673582212205001d291b73df7800b68c90f6d4fa28c64f7e39d7715f0603d0486eddb6c899f64736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea2646970667358221220e0d92e5694609f891642dbb48443dd8f64c369879924189c1410511aecb25c1b64736f6c634300080d0033a2646970667358221220fb1c721954beea886e30347669fd9426afc113dc313de278d83530f66e146c4b64736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/GaugeFactory.json b/deployments/arbitrumGoerli/GaugeFactory.json index efe497bc..e7bfdcea 100644 --- a/deployments/arbitrumGoerli/GaugeFactory.json +++ b/deployments/arbitrumGoerli/GaugeFactory.json @@ -1,5 +1,5 @@ { - "address": "0x1Ac3032Dfd7e206BA6d08F453f38593b9A583052", + "address": "0x9974354d3a16C4801cce829349Cf17663b2c58a5", "abi": [ { "inputs": [ @@ -59,28 +59,28 @@ "type": "function" } ], - "transactionHash": "0x938a3d14930cbed82e1302af131ea56c350db648e5346d7b165695f5d0a501cd", + "transactionHash": "0xb24aade33d333dcf09e7eecae811424186221368766fe3fe3cdcb842c0196519", "receipt": { "to": null, "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0x1Ac3032Dfd7e206BA6d08F453f38593b9A583052", + "contractAddress": "0x9974354d3a16C4801cce829349Cf17663b2c58a5", "transactionIndex": 1, - "gasUsed": "32701694", + "gasUsed": "59373355", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x166db84c6d10fbaefdb2535321626cf25e67658dca1c9ba1bbd47bd77b57dc62", - "transactionHash": "0x938a3d14930cbed82e1302af131ea56c350db648e5346d7b165695f5d0a501cd", + "blockHash": "0x71a8a0c6335ff501c4e054413d7def1b5207fd96672cfc17af1b304c9eebdc89", + "transactionHash": "0xb24aade33d333dcf09e7eecae811424186221368766fe3fe3cdcb842c0196519", "logs": [], - "blockNumber": 4195007, - "cumulativeGasUsed": "32701694", + "blockNumber": 4263669, + "cumulativeGasUsed": "59373355", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 5, - "solcInputHash": "0faaa79d8b79020b765ba7705413c447", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_internal_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_external_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_ve\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isPair\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_gauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/GaugeFactory.sol\":\"GaugeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Gauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\\ncontract Gauge is IGauge {\\n address public immutable stake; // the LP token that needs to be staked for rewards\\n address public immutable _ve; // the ve token used for gauges\\n address public immutable internal_bribe;\\n address public immutable external_bribe;\\n address public immutable voter;\\n\\n uint256 public derivedSupply;\\n mapping(address => uint256) public derivedBalances;\\n\\n bool public isForPair;\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 internal constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(address => uint256)) public lastEarn;\\n mapping(address => mapping(address => uint256))\\n public userRewardPerTokenStored;\\n\\n mapping(address => uint256) public tokenIds;\\n\\n uint256 public totalSupply;\\n mapping(address => uint256) public balanceOf;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n uint256 public fees0;\\n uint256 public fees1;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(\\n address _stake,\\n address _internal_bribe,\\n address _external_bribe,\\n address __ve,\\n address _voter,\\n bool _forPair,\\n address[] memory _allowedRewardTokens\\n ) {\\n stake = _stake;\\n internal_bribe = _internal_bribe;\\n external_bribe = _external_bribe;\\n _ve = __ve;\\n voter = _voter;\\n isForPair = _forPair;\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function claimFees()\\n external\\n lock\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n return _claimFees();\\n }\\n\\n function _claimFees()\\n internal\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n if (!isForPair) {\\n return (0, 0);\\n }\\n (claimed0, claimed1) = IPair(stake).claimFees();\\n if (claimed0 > 0 || claimed1 > 0) {\\n uint256 _fees0 = fees0 + claimed0;\\n uint256 _fees1 = fees1 + claimed1;\\n (address _token0, address _token1) = IPair(stake).tokens();\\n if (\\n _fees0 > IBribe(internal_bribe).left(_token0) &&\\n _fees0 / DURATION > 0\\n ) {\\n fees0 = 0;\\n _safeApprove(_token0, internal_bribe, _fees0);\\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\\n } else {\\n fees0 = _fees0;\\n }\\n if (\\n _fees1 > IBribe(internal_bribe).left(_token1) &&\\n _fees1 / DURATION > 0\\n ) {\\n fees1 = 0;\\n _safeApprove(_token1, internal_bribe, _fees1);\\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\\n } else {\\n fees1 = _fees1;\\n }\\n\\n emit ClaimFees(msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(address account, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(address account, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[account][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[account] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n derivedSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n function getReward(address account, address[] memory tokens) external lock {\\n require(msg.sender == account || msg.sender == voter);\\n _unlocked = 1;\\n IVoter(voter).distribute(address(this));\\n _unlocked = 2;\\n\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], account);\\n lastEarn[tokens[i]][account] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n\\n uint256 _derivedBalance = derivedBalances[account];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(account);\\n derivedBalances[account] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(account, derivedBalances[account]);\\n _writeSupplyCheckpoint();\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (derivedSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / derivedSupply);\\n }\\n\\n function derivedBalance(address account) public view returns (uint256) {\\n return balanceOf[account];\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\\n function earned(address token, address account)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][account],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[account] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[account] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[account][i];\\n Checkpoint memory cp1 = checkpoints[account][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[account][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][account]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n function depositAll(uint256 tokenId) external {\\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\\n }\\n\\n function deposit(uint256 amount, uint256 tokenId) public lock {\\n require(amount > 0);\\n _updateRewardForAllTokens();\\n\\n _safeTransferFrom(stake, msg.sender, address(this), amount);\\n totalSupply += amount;\\n balanceOf[msg.sender] += amount;\\n\\n if (tokenId > 0) {\\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\\n if (tokenIds[msg.sender] == 0) {\\n tokenIds[msg.sender] = tokenId;\\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\\n }\\n require(tokenIds[msg.sender] == tokenId);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, _derivedBalance);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function withdrawAll() external {\\n withdraw(balanceOf[msg.sender]);\\n }\\n\\n function withdraw(uint256 amount) public {\\n uint256 tokenId = 0;\\n if (amount == balanceOf[msg.sender]) {\\n tokenId = tokenIds[msg.sender];\\n }\\n withdrawToken(amount, tokenId);\\n }\\n\\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[msg.sender] -= amount;\\n _safeTransfer(stake, msg.sender, amount);\\n\\n if (tokenId > 0) {\\n require(tokenId == tokenIds[msg.sender]);\\n tokenIds[msg.sender] = 0;\\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(token != stake);\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"rewards tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n _claimFees();\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeApprove(\\n address token,\\n address spender,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x38cc0284dd60d8a1418d9c34e6be84911ca4a1b479dc129f19b9027e4c670e1f\",\"license\":\"MIT\"},\"contracts/factories/GaugeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/Gauge.sol';\\n\\ncontract GaugeFactory is IGaugeFactory {\\n address public last_gauge;\\n\\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\\n return last_gauge;\\n }\\n}\\n\",\"keccak256\":\"0x34f6ac4bdace9ef01d8cffda9b45842efae88b519230c67759b9936aee6acc9b\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50613b19806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea26469706673582212204be9fb7205b1a10b89a5bdb5d1d49b90c1efa5220c1a307bfed2aef8bfdec3be64736f6c634300080d0033a2646970667358221220eccecd0b41985a8acaefecdc0f1ccc41783300d7cc91bf7cc27046dd1d7e179064736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea26469706673582212204be9fb7205b1a10b89a5bdb5d1d49b90c1efa5220c1a307bfed2aef8bfdec3be64736f6c634300080d0033a2646970667358221220eccecd0b41985a8acaefecdc0f1ccc41783300d7cc91bf7cc27046dd1d7e179064736f6c634300080d0033", + "numDeployments": 8, + "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_internal_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_external_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_ve\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isPair\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_gauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/GaugeFactory.sol\":\"GaugeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Gauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\\ncontract Gauge is IGauge {\\n address public immutable stake; // the LP token that needs to be staked for rewards\\n address public immutable _ve; // the ve token used for gauges\\n address public immutable internal_bribe;\\n address public immutable external_bribe;\\n address public immutable voter;\\n\\n uint256 public derivedSupply;\\n mapping(address => uint256) public derivedBalances;\\n\\n bool public isForPair;\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 internal constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(address => uint256)) public lastEarn;\\n mapping(address => mapping(address => uint256))\\n public userRewardPerTokenStored;\\n\\n mapping(address => uint256) public tokenIds;\\n\\n uint256 public totalSupply;\\n mapping(address => uint256) public balanceOf;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n uint256 public fees0;\\n uint256 public fees1;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(\\n address _stake,\\n address _internal_bribe,\\n address _external_bribe,\\n address __ve,\\n address _voter,\\n bool _forPair,\\n address[] memory _allowedRewardTokens\\n ) {\\n stake = _stake;\\n internal_bribe = _internal_bribe;\\n external_bribe = _external_bribe;\\n _ve = __ve;\\n voter = _voter;\\n isForPair = _forPair;\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function claimFees()\\n external\\n lock\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n return _claimFees();\\n }\\n\\n function _claimFees()\\n internal\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n if (!isForPair) {\\n return (0, 0);\\n }\\n (claimed0, claimed1) = IPair(stake).claimFees();\\n if (claimed0 > 0 || claimed1 > 0) {\\n uint256 _fees0 = fees0 + claimed0;\\n uint256 _fees1 = fees1 + claimed1;\\n (address _token0, address _token1) = IPair(stake).tokens();\\n if (\\n _fees0 > IBribe(internal_bribe).left(_token0) &&\\n _fees0 / DURATION > 0\\n ) {\\n fees0 = 0;\\n _safeApprove(_token0, internal_bribe, _fees0);\\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\\n } else {\\n fees0 = _fees0;\\n }\\n if (\\n _fees1 > IBribe(internal_bribe).left(_token1) &&\\n _fees1 / DURATION > 0\\n ) {\\n fees1 = 0;\\n _safeApprove(_token1, internal_bribe, _fees1);\\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\\n } else {\\n fees1 = _fees1;\\n }\\n\\n emit ClaimFees(msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(address account, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(address account, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[account][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[account] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n derivedSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n function getReward(address account, address[] memory tokens) external lock {\\n require(msg.sender == account || msg.sender == voter);\\n _unlocked = 1;\\n IVoter(voter).distribute(address(this));\\n _unlocked = 2;\\n\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], account);\\n lastEarn[tokens[i]][account] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n\\n uint256 _derivedBalance = derivedBalances[account];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(account);\\n derivedBalances[account] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(account, derivedBalances[account]);\\n _writeSupplyCheckpoint();\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (derivedSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / derivedSupply);\\n }\\n\\n function derivedBalance(address account) public view returns (uint256) {\\n return balanceOf[account];\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\\n function earned(address token, address account)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][account],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[account] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[account] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[account][i];\\n Checkpoint memory cp1 = checkpoints[account][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[account][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][account]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n function depositAll(uint256 tokenId) external {\\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\\n }\\n\\n function deposit(uint256 amount, uint256 tokenId) public lock {\\n require(amount > 0);\\n _updateRewardForAllTokens();\\n\\n _safeTransferFrom(stake, msg.sender, address(this), amount);\\n totalSupply += amount;\\n balanceOf[msg.sender] += amount;\\n\\n if (tokenId > 0) {\\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\\n if (tokenIds[msg.sender] == 0) {\\n tokenIds[msg.sender] = tokenId;\\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\\n }\\n require(tokenIds[msg.sender] == tokenId);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, _derivedBalance);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function withdrawAll() external {\\n withdraw(balanceOf[msg.sender]);\\n }\\n\\n function withdraw(uint256 amount) public {\\n uint256 tokenId = 0;\\n if (amount == balanceOf[msg.sender]) {\\n tokenId = tokenIds[msg.sender];\\n }\\n withdrawToken(amount, tokenId);\\n }\\n\\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[msg.sender] -= amount;\\n _safeTransfer(stake, msg.sender, amount);\\n\\n if (tokenId > 0) {\\n require(tokenId == tokenIds[msg.sender]);\\n tokenIds[msg.sender] = 0;\\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(token != stake);\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"rewards tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n _claimFees();\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeApprove(\\n address token,\\n address spender,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x38cc0284dd60d8a1418d9c34e6be84911ca4a1b479dc129f19b9027e4c670e1f\",\"license\":\"MIT\"},\"contracts/factories/GaugeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/Gauge.sol';\\n\\ncontract GaugeFactory is IGaugeFactory {\\n address public last_gauge;\\n\\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\\n return last_gauge;\\n }\\n}\\n\",\"keccak256\":\"0x34f6ac4bdace9ef01d8cffda9b45842efae88b519230c67759b9936aee6acc9b\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50613b19806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea2646970667358221220ba05c301c95734156492aaed84b555a4ea9973ba2bdccc78146b6a31bd27572764736f6c634300080d0033a2646970667358221220e87095b83f1200821a412716f12847ba4ce521aa0b052cb3523dc12e213f1e3564736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea2646970667358221220ba05c301c95734156492aaed84b555a4ea9973ba2bdccc78146b6a31bd27572764736f6c634300080d0033a2646970667358221220e87095b83f1200821a412716f12847ba4ce521aa0b052cb3523dc12e213f1e3564736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/MerkleClaim.json b/deployments/arbitrumGoerli/MerkleClaim.json index 6b9b8052..cf87aa5c 100644 --- a/deployments/arbitrumGoerli/MerkleClaim.json +++ b/deployments/arbitrumGoerli/MerkleClaim.json @@ -1,5 +1,5 @@ { - "address": "0x0a68F78212D69EfC6346B5F9d72BC5A301779BE9", + "address": "0x339E9F114af629cefF4f46965c9D58f54F1234AA", "abi": [ { "inputs": [ @@ -105,31 +105,31 @@ "type": "function" } ], - "transactionHash": "0x41cbc82b30365881b829a222362d8258bc95e6f177ee28c9bd37d005957b74cb", + "transactionHash": "0x0c1fc738d08c98a218963f967a9fd62fa4bc9b8cd237f6ee527ba69fefba9cb2", "receipt": { "to": null, "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0x0a68F78212D69EfC6346B5F9d72BC5A301779BE9", + "contractAddress": "0x339E9F114af629cefF4f46965c9D58f54F1234AA", "transactionIndex": 1, - "gasUsed": "5184295", + "gasUsed": "10171864", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x3f42b181811bab0a156751433e49b95d8dc444fe487d83807bb07fc29ece9865", - "transactionHash": "0x41cbc82b30365881b829a222362d8258bc95e6f177ee28c9bd37d005957b74cb", + "blockHash": "0x089722a4f031122e7ddcf39528775a3a16067e1557df0c15b531c734ef62fbc1", + "transactionHash": "0x0c1fc738d08c98a218963f967a9fd62fa4bc9b8cd237f6ee527ba69fefba9cb2", "logs": [], - "blockNumber": 4195042, - "cumulativeGasUsed": "5184295", + "blockNumber": 4263707, + "cumulativeGasUsed": "10171864", "status": 1, "byzantium": true }, "args": [ - "0xe69b00A164047e7eB87B73971B0f340eEbFF9c81", + "0x162404E6Cd4633656925b90EF67237F29D5cc85c", "0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f" ], - "numDeployments": 3, - "solcInputHash": "0faaa79d8b79020b765ba7705413c447", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_velo\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"_merkleRoot\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Claim\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"VELO\",\"outputs\":[{\"internalType\":\"contract IVelo\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"hasClaimed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\",\"events\":{\"Claim(address,uint256)\":{\"params\":{\"amount\":\"of tokens claimed\",\"to\":\"recipient of claim\"}}},\"kind\":\"dev\",\"methods\":{\"claim(address,uint256,bytes32[])\":{\"params\":{\"amount\":\"of tokens owed to claimee\",\"proof\":\"merkle proof to prove address and amount are in tree\",\"to\":\"address of claimee\"}},\"constructor\":{\"params\":{\"_merkleRoot\":\"of claimees\",\"_velo\":\"address\"}}},\"title\":\"MerkleClaim\",\"version\":1},\"userdoc\":{\"events\":{\"Claim(address,uint256)\":{\"notice\":\"Emitted after a successful token claim\"}},\"kind\":\"user\",\"methods\":{\"VELO()\":{\"notice\":\"VELO token to claim\"},\"claim(address,uint256,bytes32[])\":{\"notice\":\"Allows claiming tokens if address is part of merkle tree\"},\"constructor\":{\"notice\":\"Creates a new MerkleClaim contract\"},\"hasClaimed(address)\":{\"notice\":\"Mapping of addresses who have claimed tokens\"},\"merkleRoot()\":{\"notice\":\"ERC20-claimee inclusion root\"}},\"notice\":\"Claims VELO for members of a merkle tree\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/MerkleClaim.sol\":\"MerkleClaim\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"},\"contracts/redeem/MerkleClaim.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity 0.8.13;\\n\\n/// ============ Imports ============\\n\\nimport {IVelo} from \\\"contracts/interfaces/IVelo.sol\\\";\\nimport {MerkleProof} from \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\\\"; // OZ: MerkleProof\\n\\n/// @title MerkleClaim\\n/// @notice Claims VELO for members of a merkle tree\\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\\ncontract MerkleClaim {\\n /// ============ Immutable storage ============\\n\\n /// @notice VELO token to claim\\n IVelo public immutable VELO;\\n /// @notice ERC20-claimee inclusion root\\n bytes32 public immutable merkleRoot;\\n\\n /// ============ Mutable storage ============\\n\\n /// @notice Mapping of addresses who have claimed tokens\\n mapping(address => bool) public hasClaimed;\\n\\n /// ============ Constructor ============\\n\\n /// @notice Creates a new MerkleClaim contract\\n /// @param _velo address\\n /// @param _merkleRoot of claimees\\n constructor(address _velo, bytes32 _merkleRoot) {\\n VELO = IVelo(_velo);\\n merkleRoot = _merkleRoot;\\n }\\n\\n /// ============ Events ============\\n\\n /// @notice Emitted after a successful token claim\\n /// @param to recipient of claim\\n /// @param amount of tokens claimed\\n event Claim(address indexed to, uint256 amount);\\n\\n /// ============ Functions ============\\n\\n /// @notice Allows claiming tokens if address is part of merkle tree\\n /// @param to address of claimee\\n /// @param amount of tokens owed to claimee\\n /// @param proof merkle proof to prove address and amount are in tree\\n function claim(\\n address to,\\n uint256 amount,\\n bytes32[] calldata proof\\n ) external {\\n // Throw if address has already claimed tokens\\n require(!hasClaimed[to], \\\"ALREADY_CLAIMED\\\");\\n\\n // Verify merkle proof, or revert if not in tree\\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\\n require(isValidLeaf, \\\"NOT_IN_MERKLE\\\");\\n\\n // Set address to claimed\\n hasClaimed[to] = true;\\n\\n // Claim tokens for address\\n require(VELO.claim(to, amount), \\\"CLAIM_FAILED\\\");\\n\\n // Emit claim event\\n emit Claim(to, amount);\\n }\\n}\\n\",\"keccak256\":\"0xb4724b0f4bf1f8a9f5ef9147e834b2d85ae61005ffc1d6b261f911c093f38270\",\"license\":\"AGPL-3.0-only\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev These functions deal with verification of Merkle Tree proofs.\\n *\\n * The tree and the proofs can be generated using our\\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\\n * You will find a quickstart guide in the readme.\\n *\\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\\n * hashing, or use a hash function other than keccak256 for hashing leaves.\\n * This is because the concatenation of a sorted pair of internal nodes in\\n * the merkle tree could be reinterpreted as a leaf value.\\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\\n * against this attack out of the box.\\n */\\nlibrary MerkleProof {\\n /**\\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\\n * defined by `root`. For this, a `proof` must be provided, containing\\n * sibling hashes on the branch from the leaf to the root of the tree. Each\\n * pair of leaves and each pair of pre-images are assumed to be sorted.\\n */\\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProof(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {verify}\\n *\\n * _Available since v4.7._\\n */\\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProofCalldata(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\\n * hash matches the root of the tree. When processing the proof, the pairs\\n * of leafs & pre-images are assumed to be sorted.\\n *\\n * _Available since v4.4._\\n */\\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Calldata version of {processProof}\\n *\\n * _Available since v4.7._\\n */\\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerify(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProof(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {multiProofVerify}\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerifyCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\\n * respectively.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProof(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n /**\\n * @dev Calldata version of {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProofCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\\n }\\n\\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x00, a)\\n mstore(0x20, b)\\n value := keccak256(0x00, 0x40)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcc76dbe53154a5bbd12fdd1613a73f73f3dc7c63d813be36f7ee606f52d6a7b3\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60c060405234801561001057600080fd5b5060405161062638038061062683398101604081905261002f91610045565b6001600160a01b0390911660805260a05261007f565b6000806040838503121561005857600080fd5b82516001600160a01b038116811461006f57600080fd5b6020939093015192949293505050565b60805160a0516105766100b060003960008181605601526101ea01526000818160d8015261029601526105766000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633d13f8741461008b57806373b2e80e146100a0578063a0eeb39a146100d3575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61009e61009936600461043c565b610112565b005b6100c36100ae3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6100fa7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea26469706673582212200271092771994fc7918f24a308c1d35a97c9ff921b435a90f1e8e07f6ccee75d64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633d13f8741461008b57806373b2e80e146100a0578063a0eeb39a146100d3575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61009e61009936600461043c565b610112565b005b6100c36100ae3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6100fa7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea26469706673582212200271092771994fc7918f24a308c1d35a97c9ff921b435a90f1e8e07f6ccee75d64736f6c634300080d0033", + "numDeployments": 5, + "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_velo\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"_merkleRoot\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Claim\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"VELO\",\"outputs\":[{\"internalType\":\"contract IVelo\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"hasClaimed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\",\"events\":{\"Claim(address,uint256)\":{\"params\":{\"amount\":\"of tokens claimed\",\"to\":\"recipient of claim\"}}},\"kind\":\"dev\",\"methods\":{\"claim(address,uint256,bytes32[])\":{\"params\":{\"amount\":\"of tokens owed to claimee\",\"proof\":\"merkle proof to prove address and amount are in tree\",\"to\":\"address of claimee\"}},\"constructor\":{\"params\":{\"_merkleRoot\":\"of claimees\",\"_velo\":\"address\"}}},\"title\":\"MerkleClaim\",\"version\":1},\"userdoc\":{\"events\":{\"Claim(address,uint256)\":{\"notice\":\"Emitted after a successful token claim\"}},\"kind\":\"user\",\"methods\":{\"VELO()\":{\"notice\":\"VELO token to claim\"},\"claim(address,uint256,bytes32[])\":{\"notice\":\"Allows claiming tokens if address is part of merkle tree\"},\"constructor\":{\"notice\":\"Creates a new MerkleClaim contract\"},\"hasClaimed(address)\":{\"notice\":\"Mapping of addresses who have claimed tokens\"},\"merkleRoot()\":{\"notice\":\"ERC20-claimee inclusion root\"}},\"notice\":\"Claims VELO for members of a merkle tree\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/MerkleClaim.sol\":\"MerkleClaim\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"},\"contracts/redeem/MerkleClaim.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity 0.8.13;\\n\\n/// ============ Imports ============\\n\\nimport {IVelo} from \\\"contracts/interfaces/IVelo.sol\\\";\\nimport {MerkleProof} from \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\\\"; // OZ: MerkleProof\\n\\n/// @title MerkleClaim\\n/// @notice Claims VELO for members of a merkle tree\\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\\ncontract MerkleClaim {\\n /// ============ Immutable storage ============\\n\\n /// @notice VELO token to claim\\n IVelo public immutable VELO;\\n /// @notice ERC20-claimee inclusion root\\n bytes32 public immutable merkleRoot;\\n\\n /// ============ Mutable storage ============\\n\\n /// @notice Mapping of addresses who have claimed tokens\\n mapping(address => bool) public hasClaimed;\\n\\n /// ============ Constructor ============\\n\\n /// @notice Creates a new MerkleClaim contract\\n /// @param _velo address\\n /// @param _merkleRoot of claimees\\n constructor(address _velo, bytes32 _merkleRoot) {\\n VELO = IVelo(_velo);\\n merkleRoot = _merkleRoot;\\n }\\n\\n /// ============ Events ============\\n\\n /// @notice Emitted after a successful token claim\\n /// @param to recipient of claim\\n /// @param amount of tokens claimed\\n event Claim(address indexed to, uint256 amount);\\n\\n /// ============ Functions ============\\n\\n /// @notice Allows claiming tokens if address is part of merkle tree\\n /// @param to address of claimee\\n /// @param amount of tokens owed to claimee\\n /// @param proof merkle proof to prove address and amount are in tree\\n function claim(\\n address to,\\n uint256 amount,\\n bytes32[] calldata proof\\n ) external {\\n // Throw if address has already claimed tokens\\n require(!hasClaimed[to], \\\"ALREADY_CLAIMED\\\");\\n\\n // Verify merkle proof, or revert if not in tree\\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\\n require(isValidLeaf, \\\"NOT_IN_MERKLE\\\");\\n\\n // Set address to claimed\\n hasClaimed[to] = true;\\n\\n // Claim tokens for address\\n require(VELO.claim(to, amount), \\\"CLAIM_FAILED\\\");\\n\\n // Emit claim event\\n emit Claim(to, amount);\\n }\\n}\\n\",\"keccak256\":\"0xb4724b0f4bf1f8a9f5ef9147e834b2d85ae61005ffc1d6b261f911c093f38270\",\"license\":\"AGPL-3.0-only\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev These functions deal with verification of Merkle Tree proofs.\\n *\\n * The tree and the proofs can be generated using our\\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\\n * You will find a quickstart guide in the readme.\\n *\\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\\n * hashing, or use a hash function other than keccak256 for hashing leaves.\\n * This is because the concatenation of a sorted pair of internal nodes in\\n * the merkle tree could be reinterpreted as a leaf value.\\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\\n * against this attack out of the box.\\n */\\nlibrary MerkleProof {\\n /**\\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\\n * defined by `root`. For this, a `proof` must be provided, containing\\n * sibling hashes on the branch from the leaf to the root of the tree. Each\\n * pair of leaves and each pair of pre-images are assumed to be sorted.\\n */\\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProof(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {verify}\\n *\\n * _Available since v4.7._\\n */\\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProofCalldata(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\\n * hash matches the root of the tree. When processing the proof, the pairs\\n * of leafs & pre-images are assumed to be sorted.\\n *\\n * _Available since v4.4._\\n */\\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Calldata version of {processProof}\\n *\\n * _Available since v4.7._\\n */\\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerify(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProof(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {multiProofVerify}\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerifyCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\\n * respectively.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProof(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n /**\\n * @dev Calldata version of {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProofCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\\n }\\n\\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x00, a)\\n mstore(0x20, b)\\n value := keccak256(0x00, 0x40)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcc76dbe53154a5bbd12fdd1613a73f73f3dc7c63d813be36f7ee606f52d6a7b3\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c060405234801561001057600080fd5b5060405161062638038061062683398101604081905261002f91610045565b6001600160a01b0390911660805260a05261007f565b6000806040838503121561005857600080fd5b82516001600160a01b038116811461006f57600080fd5b6020939093015192949293505050565b60805160a0516105766100b060003960008181605601526101ea01526000818160d8015261029601526105766000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633d13f8741461008b57806373b2e80e146100a0578063a0eeb39a146100d3575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61009e61009936600461043c565b610112565b005b6100c36100ae3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6100fa7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea26469706673582212207394f2666e3f24ba67c7077393298dc048c3e4507cbe99f1f31fc81a3d32dfc164736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633d13f8741461008b57806373b2e80e146100a0578063a0eeb39a146100d3575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61009e61009936600461043c565b610112565b005b6100c36100ae3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6100fa7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea26469706673582212207394f2666e3f24ba67c7077393298dc048c3e4507cbe99f1f31fc81a3d32dfc164736f6c634300080d0033", "devdoc": { "author": "Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)", "events": { diff --git a/deployments/arbitrumGoerli/Minter.json b/deployments/arbitrumGoerli/Minter.json index df67f8db..a4303ac1 100644 --- a/deployments/arbitrumGoerli/Minter.json +++ b/deployments/arbitrumGoerli/Minter.json @@ -1,5 +1,5 @@ { - "address": "0xd2C3ebFB8e7e79CA84080a8551D86Df50B0F559d", + "address": "0x2eE17Ac8031caea5f11F7685715BF375F4BaeF6f", "abi": [ { "inputs": [ @@ -324,32 +324,32 @@ "type": "function" } ], - "transactionHash": "0x168c6cf31abe5f09dda0cfddf11ffbc4b8dc5adc5590029193721e79a137368f", + "transactionHash": "0xa9128e0e846d5ec961d24e5febe22b721bb1e0b185233e402f31fc1935a1b353", "receipt": { "to": null, "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0xd2C3ebFB8e7e79CA84080a8551D86Df50B0F559d", + "contractAddress": "0x2eE17Ac8031caea5f11F7685715BF375F4BaeF6f", "transactionIndex": 1, - "gasUsed": "12422232", + "gasUsed": "22608178", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x4ff31abdadb682b773acc1285d51d5ebf31972ea063150d92009d5ec9a9ddcaa", - "transactionHash": "0x168c6cf31abe5f09dda0cfddf11ffbc4b8dc5adc5590029193721e79a137368f", + "blockHash": "0x744e6f5be02b10f764ccb372ffdde4b4e4911ab5b75034cb84e9baee3598111d", + "transactionHash": "0xa9128e0e846d5ec961d24e5febe22b721bb1e0b185233e402f31fc1935a1b353", "logs": [], - "blockNumber": 4195027, - "cumulativeGasUsed": "12422232", + "blockNumber": 4263696, + "cumulativeGasUsed": "22608178", "status": 1, "byzantium": true }, "args": [ - "0x574607c69f369f0535E77C5F7C35767Aee04879A", - "0x6b938BA22FB5520fFB5D14c9C4Fef82a48761497", - "0xf6CdA702C6Bd15d5C0A325CE8f9f88219fE5F445" + "0x19E081b804AB558cF6f7B629a2902F7c79ADa9cD", + "0xCDAF5f01849Fff0a9E36D768B2ae7354A98360c0", + "0x3B2233FA015D316fdf6e79373470AD59672Ed3BD" ], - "numDeployments": 3, - "solcInputHash": "0faaa79d8b79020b765ba7705413c447", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__voter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__rewards_distributor\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weekly\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_supply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_emission\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_TEAM_RATE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_rewards_distributor\",\"outputs\":[{\"internalType\":\"contract IRewardsDistributor\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"contract IVotingEscrow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_velo\",\"outputs\":[{\"internalType\":\"contract IVelo\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_voter\",\"outputs\":[{\"internalType\":\"contract IVoter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"active_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"calculate_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minted\",\"type\":\"uint256\"}],\"name\":\"calculate_growth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"claimants\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingTeam\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_teamRate\",\"type\":\"uint256\"}],\"name\":\"setTeamRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"teamRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"update_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Minter.sol\":\"Minter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Minter.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IMinter.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVelo.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\\n\\ncontract Minter is IMinter {\\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\\n uint256 internal constant EMISSION = 990;\\n uint256 internal constant TAIL_EMISSION = 2;\\n uint256 internal constant PRECISION = 1000;\\n IVelo public immutable _velo;\\n IVoter public immutable _voter;\\n IVotingEscrow public immutable _ve;\\n IRewardsDistributor public immutable _rewards_distributor;\\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\\n uint256 public active_period;\\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\\n\\n address internal initializer;\\n address public team;\\n address public pendingTeam;\\n uint256 public teamRate;\\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\\n\\n event Mint(\\n address indexed sender,\\n uint256 weekly,\\n uint256 circulating_supply,\\n uint256 circulating_emission\\n );\\n\\n constructor(\\n address __voter, // the voting & distribution system\\n address __ve, // the ve(3,3) system that will be locked into\\n address __rewards_distributor // the distribution system that ensures users aren't diluted\\n ) {\\n initializer = msg.sender;\\n team = msg.sender;\\n teamRate = 30; // 30 bps = 0.03%\\n _velo = IVelo(IVotingEscrow(__ve).token());\\n _voter = IVoter(__voter);\\n _ve = IVotingEscrow(__ve);\\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\\n }\\n\\n function initialize(\\n address[] memory claimants,\\n uint256[] memory amounts,\\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\\n ) external {\\n require(initializer == msg.sender);\\n _velo.mint(address(this), max);\\n _velo.approve(address(_ve), type(uint256).max);\\n for (uint256 i = 0; i < claimants.length; i++) {\\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\\n }\\n initializer = address(0);\\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\\n }\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team, \\\"not team\\\");\\n pendingTeam = _team;\\n }\\n\\n function acceptTeam() external {\\n require(msg.sender == pendingTeam, \\\"not pending team\\\");\\n team = pendingTeam;\\n }\\n\\n function setTeamRate(uint256 _teamRate) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(_teamRate <= MAX_TEAM_RATE, \\\"rate too high\\\");\\n teamRate = _teamRate;\\n }\\n\\n // calculate circulating supply as total token supply - locked supply\\n function circulating_supply() public view returns (uint256) {\\n return _velo.totalSupply() - _ve.totalSupply();\\n }\\n\\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\\n function calculate_emission() public view returns (uint256) {\\n return (weekly * EMISSION) / PRECISION;\\n }\\n\\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\\n function weekly_emission() public view returns (uint256) {\\n return MathDunks.max(calculate_emission(), circulating_emission());\\n }\\n\\n // calculates tail end (infinity) emissions as 0.2% of total supply\\n function circulating_emission() public view returns (uint256) {\\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\\n }\\n\\n // calculate inflation and adjust ve balances accordingly\\n function calculate_growth(uint256 _minted) public view returns (uint256) {\\n uint256 _veTotal = _ve.totalSupply();\\n uint256 _veloTotal = _velo.totalSupply();\\n return\\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\\n _veTotal) /\\n _veloTotal /\\n 2;\\n }\\n\\n // update period can only be called once per cycle (1 week)\\n function update_period() external returns (uint256) {\\n uint256 _period = active_period;\\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\\n // only trigger if new week\\n _period = (block.timestamp / WEEK) * WEEK;\\n active_period = _period;\\n weekly = weekly_emission();\\n\\n uint256 _growth = calculate_growth(weekly);\\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\\n (PRECISION - teamRate);\\n uint256 _required = _growth + weekly + _teamEmissions;\\n uint256 _balanceOf = _velo.balanceOf(address(this));\\n if (_balanceOf < _required) {\\n _velo.mint(address(this), _required - _balanceOf);\\n }\\n\\n require(_velo.transfer(team, _teamEmissions));\\n require(_velo.transfer(address(_rewards_distributor), _growth));\\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\\n\\n _velo.approve(address(_voter), weekly);\\n _voter.notifyRewardAmount(weekly);\\n\\n emit Mint(\\n msg.sender,\\n weekly,\\n circulating_supply(),\\n circulating_emission()\\n );\\n }\\n return _period;\\n }\\n}\\n\",\"keccak256\":\"0x8dce50c09815e53982006f9ddc46cd52cf7ac86b0c1b7bb15c817f86fb990580\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x6101006040526a0c685fa11e01ec6f0000006000553480156200002157600080fd5b506040516200158938038062001589833981016040819052620000449162000156565b60028054336001600160a01b03199182168117909255600380549091169091179055601e60055560408051637e062a3560e11b815290516001600160a01b0384169163fc0c546a9160048083019260209291908290030181865afa158015620000b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d79190620001a0565b6001600160a01b0390811660805283811660a05282811660c052811660e05262093a808062000108816002620001db565b620001149042620001fd565b62000120919062000218565b6200012c9190620001db565b600155506200023b915050565b80516001600160a01b03811681146200015157600080fd5b919050565b6000806000606084860312156200016c57600080fd5b620001778462000139565b9250620001876020850162000139565b9150620001976040850162000139565b90509250925092565b600060208284031215620001b357600080fd5b620001be8262000139565b9392505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620001f857620001f8620001c5565b500290565b60008219821115620002135762000213620001c5565b500190565b6000826200023657634e487b7160e01b600052601260045260246000fd5b500490565b60805160a05160c05160e051611296620002f3600039600081816101f801528181610c3701528181610cde0152610d51015260008181610261015281816104b30152818161055f0152818161068901526108750152600081816101d101528181610e090152610ea301526000818161015101528181610426015281816104e30152818161070f015281816108f701528181610a5f01528181610ade01528181610ba801528181610c660152610dda01526112966000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c806378ef7f02116100ad578063b5cc143a11610071578063b5cc143a14610296578063cfc6c8ff1461029e578063d1399608146102a6578063e038c75a146102af578063ed29fc11146102b757600080fd5b806378ef7f021461022d578063851708131461023657806385f2aef2146102495780638dd598fb1461025c5780638e01fbfa1461028357600080fd5b80632e8f7b1f116100f45780632e8f7b1f146101b157806336d96faf146101c45780633db9b42a146101cc5780634b1cd5da146101f357806359d46ffc1461021a57600080fd5b806301c8e6fd1461013157806308aa44581461014c578063095cf5c61461018b5780631eebae80146101a057806326cfc17b146101a8575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b61019e610199366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61019e6101bf366004610fb8565b610353565b6101396103de565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b600454610173906001600160a01b031681565b61013960055481565b61019e6102443660046110a7565b6103f3565b600354610173906001600160a01b031681565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b610139610291366004610fb8565b610684565b61019e6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea2646970667358221220b8d7ed6a52e73b73f97d46da03043d96cda8f93d690887652d48bca060b4064c64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c806378ef7f02116100ad578063b5cc143a11610071578063b5cc143a14610296578063cfc6c8ff1461029e578063d1399608146102a6578063e038c75a146102af578063ed29fc11146102b757600080fd5b806378ef7f021461022d578063851708131461023657806385f2aef2146102495780638dd598fb1461025c5780638e01fbfa1461028357600080fd5b80632e8f7b1f116100f45780632e8f7b1f146101b157806336d96faf146101c45780633db9b42a146101cc5780634b1cd5da146101f357806359d46ffc1461021a57600080fd5b806301c8e6fd1461013157806308aa44581461014c578063095cf5c61461018b5780631eebae80146101a057806326cfc17b146101a8575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b61019e610199366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61019e6101bf366004610fb8565b610353565b6101396103de565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b600454610173906001600160a01b031681565b61013960055481565b61019e6102443660046110a7565b6103f3565b600354610173906001600160a01b031681565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b610139610291366004610fb8565b610684565b61019e6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea2646970667358221220b8d7ed6a52e73b73f97d46da03043d96cda8f93d690887652d48bca060b4064c64736f6c634300080d0033", + "numDeployments": 5, + "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__voter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__rewards_distributor\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weekly\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_supply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_emission\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_TEAM_RATE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_rewards_distributor\",\"outputs\":[{\"internalType\":\"contract IRewardsDistributor\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"contract IVotingEscrow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_velo\",\"outputs\":[{\"internalType\":\"contract IVelo\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_voter\",\"outputs\":[{\"internalType\":\"contract IVoter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"active_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"calculate_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minted\",\"type\":\"uint256\"}],\"name\":\"calculate_growth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"claimants\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingTeam\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_teamRate\",\"type\":\"uint256\"}],\"name\":\"setTeamRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"teamRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"update_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Minter.sol\":\"Minter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Minter.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IMinter.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVelo.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\\n\\ncontract Minter is IMinter {\\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\\n uint256 internal constant EMISSION = 990;\\n uint256 internal constant TAIL_EMISSION = 2;\\n uint256 internal constant PRECISION = 1000;\\n IVelo public immutable _velo;\\n IVoter public immutable _voter;\\n IVotingEscrow public immutable _ve;\\n IRewardsDistributor public immutable _rewards_distributor;\\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\\n uint256 public active_period;\\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\\n\\n address internal initializer;\\n address public team;\\n address public pendingTeam;\\n uint256 public teamRate;\\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\\n\\n event Mint(\\n address indexed sender,\\n uint256 weekly,\\n uint256 circulating_supply,\\n uint256 circulating_emission\\n );\\n\\n constructor(\\n address __voter, // the voting & distribution system\\n address __ve, // the ve(3,3) system that will be locked into\\n address __rewards_distributor // the distribution system that ensures users aren't diluted\\n ) {\\n initializer = msg.sender;\\n team = msg.sender;\\n teamRate = 30; // 30 bps = 0.03%\\n _velo = IVelo(IVotingEscrow(__ve).token());\\n _voter = IVoter(__voter);\\n _ve = IVotingEscrow(__ve);\\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\\n }\\n\\n function initialize(\\n address[] memory claimants,\\n uint256[] memory amounts,\\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\\n ) external {\\n require(initializer == msg.sender);\\n _velo.mint(address(this), max);\\n _velo.approve(address(_ve), type(uint256).max);\\n for (uint256 i = 0; i < claimants.length; i++) {\\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\\n }\\n initializer = address(0);\\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\\n }\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team, \\\"not team\\\");\\n pendingTeam = _team;\\n }\\n\\n function acceptTeam() external {\\n require(msg.sender == pendingTeam, \\\"not pending team\\\");\\n team = pendingTeam;\\n }\\n\\n function setTeamRate(uint256 _teamRate) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(_teamRate <= MAX_TEAM_RATE, \\\"rate too high\\\");\\n teamRate = _teamRate;\\n }\\n\\n // calculate circulating supply as total token supply - locked supply\\n function circulating_supply() public view returns (uint256) {\\n return _velo.totalSupply() - _ve.totalSupply();\\n }\\n\\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\\n function calculate_emission() public view returns (uint256) {\\n return (weekly * EMISSION) / PRECISION;\\n }\\n\\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\\n function weekly_emission() public view returns (uint256) {\\n return MathDunks.max(calculate_emission(), circulating_emission());\\n }\\n\\n // calculates tail end (infinity) emissions as 0.2% of total supply\\n function circulating_emission() public view returns (uint256) {\\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\\n }\\n\\n // calculate inflation and adjust ve balances accordingly\\n function calculate_growth(uint256 _minted) public view returns (uint256) {\\n uint256 _veTotal = _ve.totalSupply();\\n uint256 _veloTotal = _velo.totalSupply();\\n return\\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\\n _veTotal) /\\n _veloTotal /\\n 2;\\n }\\n\\n // update period can only be called once per cycle (1 week)\\n function update_period() external returns (uint256) {\\n uint256 _period = active_period;\\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\\n // only trigger if new week\\n _period = (block.timestamp / WEEK) * WEEK;\\n active_period = _period;\\n weekly = weekly_emission();\\n\\n uint256 _growth = calculate_growth(weekly);\\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\\n (PRECISION - teamRate);\\n uint256 _required = _growth + weekly + _teamEmissions;\\n uint256 _balanceOf = _velo.balanceOf(address(this));\\n if (_balanceOf < _required) {\\n _velo.mint(address(this), _required - _balanceOf);\\n }\\n\\n require(_velo.transfer(team, _teamEmissions));\\n require(_velo.transfer(address(_rewards_distributor), _growth));\\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\\n\\n _velo.approve(address(_voter), weekly);\\n _voter.notifyRewardAmount(weekly);\\n\\n emit Mint(\\n msg.sender,\\n weekly,\\n circulating_supply(),\\n circulating_emission()\\n );\\n }\\n return _period;\\n }\\n}\\n\",\"keccak256\":\"0x8dce50c09815e53982006f9ddc46cd52cf7ac86b0c1b7bb15c817f86fb990580\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x6101006040526a0c685fa11e01ec6f0000006000553480156200002157600080fd5b506040516200158938038062001589833981016040819052620000449162000156565b60028054336001600160a01b03199182168117909255600380549091169091179055601e60055560408051637e062a3560e11b815290516001600160a01b0384169163fc0c546a9160048083019260209291908290030181865afa158015620000b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d79190620001a0565b6001600160a01b0390811660805283811660a05282811660c052811660e05262093a808062000108816002620001db565b620001149042620001fd565b62000120919062000218565b6200012c9190620001db565b600155506200023b915050565b80516001600160a01b03811681146200015157600080fd5b919050565b6000806000606084860312156200016c57600080fd5b620001778462000139565b9250620001876020850162000139565b9150620001976040850162000139565b90509250925092565b600060208284031215620001b357600080fd5b620001be8262000139565b9392505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620001f857620001f8620001c5565b500290565b60008219821115620002135762000213620001c5565b500190565b6000826200023657634e487b7160e01b600052601260045260246000fd5b500490565b60805160a05160c05160e051611296620002f3600039600081816101f801528181610c3701528181610cde0152610d51015260008181610261015281816104b30152818161055f0152818161068901526108750152600081816101d101528181610e090152610ea301526000818161015101528181610426015281816104e30152818161070f015281816108f701528181610a5f01528181610ade01528181610ba801528181610c660152610dda01526112966000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c806378ef7f02116100ad578063b5cc143a11610071578063b5cc143a14610296578063cfc6c8ff1461029e578063d1399608146102a6578063e038c75a146102af578063ed29fc11146102b757600080fd5b806378ef7f021461022d578063851708131461023657806385f2aef2146102495780638dd598fb1461025c5780638e01fbfa1461028357600080fd5b80632e8f7b1f116100f45780632e8f7b1f146101b157806336d96faf146101c45780633db9b42a146101cc5780634b1cd5da146101f357806359d46ffc1461021a57600080fd5b806301c8e6fd1461013157806308aa44581461014c578063095cf5c61461018b5780631eebae80146101a057806326cfc17b146101a8575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b61019e610199366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61019e6101bf366004610fb8565b610353565b6101396103de565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b600454610173906001600160a01b031681565b61013960055481565b61019e6102443660046110a7565b6103f3565b600354610173906001600160a01b031681565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b610139610291366004610fb8565b610684565b61019e6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea264697066735822122029438f922f44621ac4ad13f191e125db9a2cbc3825de07f3a7f336bcfd98402f64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c806378ef7f02116100ad578063b5cc143a11610071578063b5cc143a14610296578063cfc6c8ff1461029e578063d1399608146102a6578063e038c75a146102af578063ed29fc11146102b757600080fd5b806378ef7f021461022d578063851708131461023657806385f2aef2146102495780638dd598fb1461025c5780638e01fbfa1461028357600080fd5b80632e8f7b1f116100f45780632e8f7b1f146101b157806336d96faf146101c45780633db9b42a146101cc5780634b1cd5da146101f357806359d46ffc1461021a57600080fd5b806301c8e6fd1461013157806308aa44581461014c578063095cf5c61461018b5780631eebae80146101a057806326cfc17b146101a8575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b61019e610199366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61019e6101bf366004610fb8565b610353565b6101396103de565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b600454610173906001600160a01b031681565b61013960055481565b61019e6102443660046110a7565b6103f3565b600354610173906001600160a01b031681565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b610139610291366004610fb8565b610684565b61019e6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea264697066735822122029438f922f44621ac4ad13f191e125db9a2cbc3825de07f3a7f336bcfd98402f64736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/PairFactory.json b/deployments/arbitrumGoerli/PairFactory.json index 5c3520ca..46c85196 100644 --- a/deployments/arbitrumGoerli/PairFactory.json +++ b/deployments/arbitrumGoerli/PairFactory.json @@ -1,5 +1,5 @@ { - "address": "0x7488AC81DC3908ff7141db4949e70D60A3Fd4DCc", + "address": "0xcA698eA7f3A74b7D3D4229765dcF47F7A224859F", "abi": [ { "inputs": [], @@ -383,28 +383,28 @@ "type": "function" } ], - "transactionHash": "0x98cd8764878aad721b508178f237c66ef70ffc56d18d009975ad54885dc71634", + "transactionHash": "0x2af9c03ec273fa0fa064d96e928f6c4837da417a859f27ec469133350ba1160c", "receipt": { "to": null, "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0x7488AC81DC3908ff7141db4949e70D60A3Fd4DCc", + "contractAddress": "0xcA698eA7f3A74b7D3D4229765dcF47F7A224859F", "transactionIndex": 1, - "gasUsed": "43959185", + "gasUsed": "79767077", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc5644de2951e89db8815c7bf22743e0529f1da7d9a31cd2ccaabe00e1e883c55", - "transactionHash": "0x98cd8764878aad721b508178f237c66ef70ffc56d18d009975ad54885dc71634", + "blockHash": "0xab8bc7d3d92f462a3d996a61e22d4a78007f9d4a54c922e675acd0c804ab4185", + "transactionHash": "0x2af9c03ec273fa0fa064d96e928f6c4837da417a859f27ec469133350ba1160c", "logs": [], - "blockNumber": 4195009, - "cumulativeGasUsed": "43959185", + "blockNumber": 4263673, + "cumulativeGasUsed": "79767077", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 5, - "solcInputHash": "0faaa79d8b79020b765ba7705413c447", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"PairCreated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_FEE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allPairs\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"allPairsLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"createPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getInitializable\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"name\":\"getPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pairCodeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingFeeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingPauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_feeManager\",\"type\":\"address\"}],\"name\":\"setFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_state\",\"type\":\"bool\"}],\"name\":\"setPause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pauser\",\"type\":\"address\"}],\"name\":\"setPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stableFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"volatileFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/PairFactory.sol\":\"PairFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Pair.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairCallee.sol\\\";\\nimport \\\"contracts/factories/PairFactory.sol\\\";\\nimport \\\"contracts/PairFees.sol\\\";\\n\\n// The base pair of pools, either stable or volatile\\ncontract Pair is IPair {\\n string public name;\\n string public symbol;\\n uint8 public constant decimals = 18;\\n\\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\\n bool public immutable stable;\\n\\n uint256 public totalSupply = 0;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n mapping(address => uint256) public balanceOf;\\n\\n bytes32 internal DOMAIN_SEPARATOR;\\n // keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 internal constant PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n mapping(address => uint256) public nonces;\\n\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n\\n address public immutable token0;\\n address public immutable token1;\\n address public immutable fees;\\n address immutable factory;\\n\\n // Structure to capture time period obervations every 30 minutes, used for local oracles\\n struct Observation {\\n uint256 timestamp;\\n uint256 reserve0Cumulative;\\n uint256 reserve1Cumulative;\\n }\\n\\n // Capture oracle reading every 30 minutes\\n uint256 constant periodSize = 1800;\\n\\n Observation[] public observations;\\n\\n uint256 internal immutable decimals0;\\n uint256 internal immutable decimals1;\\n\\n uint256 public reserve0;\\n uint256 public reserve1;\\n uint256 public blockTimestampLast;\\n\\n uint256 public reserve0CumulativeLast;\\n uint256 public reserve1CumulativeLast;\\n\\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \\\"clean\\\"\\n // this further allows LP holders to easily claim fees for tokens they have/staked\\n uint256 public index0 = 0;\\n uint256 public index1 = 0;\\n\\n // position assigned to each LP to track their current index0 & index1 vs the global position\\n mapping(address => uint256) public supplyIndex0;\\n mapping(address => uint256) public supplyIndex1;\\n\\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\\n mapping(address => uint256) public claimable0;\\n mapping(address => uint256) public claimable1;\\n\\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\\n event Burn(\\n address indexed sender,\\n uint256 amount0,\\n uint256 amount1,\\n address indexed to\\n );\\n event Swap(\\n address indexed sender,\\n uint256 amount0In,\\n uint256 amount1In,\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address indexed to\\n );\\n event Sync(uint256 reserve0, uint256 reserve1);\\n event Claim(\\n address indexed sender,\\n address indexed recipient,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 amount\\n );\\n\\n constructor() {\\n factory = msg.sender;\\n (address _token0, address _token1, bool _stable) = PairFactory(\\n msg.sender\\n ).getInitializable();\\n (token0, token1, stable) = (_token0, _token1, _stable);\\n fees = address(new PairFees(_token0, _token1));\\n if (_stable) {\\n name = string(\\n abi.encodePacked(\\n \\\"StableV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"sAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n } else {\\n name = string(\\n abi.encodePacked(\\n \\\"VolatileV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"vAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n }\\n\\n decimals0 = 10**IERC20(_token0).decimals();\\n decimals1 = 10**IERC20(_token1).decimals();\\n\\n observations.push(Observation(block.timestamp, 0, 0));\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function observationLength() external view returns (uint256) {\\n return observations.length;\\n }\\n\\n function lastObservation() public view returns (Observation memory) {\\n return observations[observations.length - 1];\\n }\\n\\n function metadata()\\n external\\n view\\n returns (\\n uint256 dec0,\\n uint256 dec1,\\n uint256 r0,\\n uint256 r1,\\n bool st,\\n address t0,\\n address t1\\n )\\n {\\n return (\\n decimals0,\\n decimals1,\\n reserve0,\\n reserve1,\\n stable,\\n token0,\\n token1\\n );\\n }\\n\\n function tokens() external view returns (address, address) {\\n return (token0, token1);\\n }\\n\\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\\n _updateFor(msg.sender);\\n\\n claimed0 = claimable0[msg.sender];\\n claimed1 = claimable1[msg.sender];\\n\\n if (claimed0 > 0 || claimed1 > 0) {\\n claimable0[msg.sender] = 0;\\n claimable1[msg.sender] = 0;\\n\\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\\n\\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n // Accrue fees on token0\\n function _update0(uint256 amount) internal {\\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index0 += _ratio;\\n }\\n emit Fees(msg.sender, amount, 0);\\n }\\n\\n // Accrue fees on token1\\n function _update1(uint256 amount) internal {\\n _safeTransfer(token1, fees, amount);\\n uint256 _ratio = (amount * 1e18) / totalSupply;\\n if (_ratio > 0) {\\n index1 += _ratio;\\n }\\n emit Fees(msg.sender, 0, amount);\\n }\\n\\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\\n // Fees are segregated from core funds, so fees can never put liquidity at risk\\n function _updateFor(address recipient) internal {\\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\\n if (_supplied > 0) {\\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\\n uint256 _supplyIndex1 = supplyIndex1[recipient];\\n uint256 _index0 = index0; // get global index0 for accumulated fees\\n uint256 _index1 = index1;\\n supplyIndex0[recipient] = _index0; // update user current position to global position\\n supplyIndex1[recipient] = _index1;\\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\\n uint256 _delta1 = _index1 - _supplyIndex1;\\n if (_delta0 > 0) {\\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\\n claimable0[recipient] += _share;\\n }\\n if (_delta1 > 0) {\\n uint256 _share = (_supplied * _delta1) / 1e18;\\n claimable1[recipient] += _share;\\n }\\n } else {\\n supplyIndex0[recipient] = index0; // new users are set to the default global state\\n supplyIndex1[recipient] = index1;\\n }\\n }\\n\\n function getReserves()\\n public\\n view\\n returns (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n )\\n {\\n _reserve0 = reserve0;\\n _reserve1 = reserve1;\\n _blockTimestampLast = blockTimestampLast;\\n }\\n\\n // update reserves and, on the first call per block, price accumulators\\n function _update(\\n uint256 balance0,\\n uint256 balance1,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal {\\n uint256 blockTimestamp = block.timestamp;\\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\\n reserve0CumulativeLast += _reserve0 * timeElapsed;\\n reserve1CumulativeLast += _reserve1 * timeElapsed;\\n }\\n\\n Observation memory _point = lastObservation();\\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\\n if (timeElapsed > periodSize) {\\n observations.push(\\n Observation(\\n blockTimestamp,\\n reserve0CumulativeLast,\\n reserve1CumulativeLast\\n )\\n );\\n }\\n reserve0 = balance0;\\n reserve1 = balance1;\\n blockTimestampLast = blockTimestamp;\\n emit Sync(reserve0, reserve1);\\n }\\n\\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\\n function currentCumulativePrices()\\n public\\n view\\n returns (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n uint256 blockTimestamp\\n )\\n {\\n blockTimestamp = block.timestamp;\\n reserve0Cumulative = reserve0CumulativeLast;\\n reserve1Cumulative = reserve1CumulativeLast;\\n\\n // if time has elapsed since the last update on the pair, mock the accumulated price values\\n (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n ) = getReserves();\\n if (_blockTimestampLast != blockTimestamp) {\\n // subtraction overflow is desired\\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\\n reserve0Cumulative += _reserve0 * timeElapsed;\\n reserve1Cumulative += _reserve1 * timeElapsed;\\n }\\n }\\n\\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\\n function current(address tokenIn, uint256 amountIn)\\n external\\n view\\n returns (uint256 amountOut)\\n {\\n Observation memory _observation = lastObservation();\\n (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n\\n ) = currentCumulativePrices();\\n if (block.timestamp == _observation.timestamp) {\\n _observation = observations[observations.length - 2];\\n }\\n\\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\\n uint256 _reserve0 = (reserve0Cumulative -\\n _observation.reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (reserve1Cumulative -\\n _observation.reserve1Cumulative) / timeElapsed;\\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n // as per `current`, however allows user configured granularity, up to the full window size\\n function quote(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 granularity\\n ) external view returns (uint256 amountOut) {\\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\\n uint256 priceAverageCumulative;\\n for (uint256 i = 0; i < _prices.length; i++) {\\n priceAverageCumulative += _prices[i];\\n }\\n return priceAverageCumulative / granularity;\\n }\\n\\n // returns a memory set of twap prices\\n function prices(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points\\n ) external view returns (uint256[] memory) {\\n return sample(tokenIn, amountIn, points, 1);\\n }\\n\\n function sample(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points,\\n uint256 window\\n ) public view returns (uint256[] memory) {\\n uint256[] memory _prices = new uint256[](points);\\n\\n uint256 length = observations.length - 1;\\n uint256 i = length - (points * window);\\n uint256 nextIndex = 0;\\n uint256 index = 0;\\n\\n for (; i < length; i += window) {\\n nextIndex = i + window;\\n uint256 timeElapsed = observations[nextIndex].timestamp -\\n observations[i].timestamp;\\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\\n observations[i].reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\\n observations[i].reserve1Cumulative) / timeElapsed;\\n _prices[index] = _getAmountOut(\\n amountIn,\\n tokenIn,\\n _reserve0,\\n _reserve1\\n );\\n // index < length; length cannot overflow\\n unchecked {\\n index = index + 1;\\n }\\n }\\n return _prices;\\n }\\n\\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\\n // standard uniswap v2 implementation\\n function mint(address to) external lock returns (uint256 liquidity) {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\\n uint256 _amount0 = _balance0 - _reserve0;\\n uint256 _amount1 = _balance1 - _reserve1;\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n if (_totalSupply == 0) {\\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\\n } else {\\n liquidity = MathDunks.min(\\n (_amount0 * _totalSupply) / _reserve0,\\n (_amount1 * _totalSupply) / _reserve1\\n );\\n }\\n require(liquidity > 0, \\\"ILM\\\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\\n _mint(to, liquidity);\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Mint(msg.sender, _amount0, _amount1);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n // standard uniswap v2 implementation\\n function burn(address to)\\n external\\n lock\\n returns (uint256 amount0, uint256 amount1)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n (address _token0, address _token1) = (token0, token1);\\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\\n uint256 _liquidity = balanceOf[address(this)];\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\\n require(amount0 > 0 && amount1 > 0, \\\"ILB\\\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\\n _burn(address(this), _liquidity);\\n _safeTransfer(_token0, to, amount0);\\n _safeTransfer(_token1, to, amount1);\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Burn(msg.sender, amount0, amount1, to);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n function swap(\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address to,\\n bytes calldata data\\n ) external lock {\\n require(!PairFactory(factory).isPaused());\\n require(amount0Out > 0 || amount1Out > 0, \\\"IOA\\\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \\\"IL\\\"); // Pair: INSUFFICIENT_LIQUIDITY\\n\\n uint256 _balance0;\\n uint256 _balance1;\\n {\\n // scope for _token{0,1}, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n require(to != _token0 && to != _token1, \\\"IT\\\"); // Pair: INVALID_TO\\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\\n if (data.length > 0)\\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n }\\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\\n ? _balance0 - (_reserve0 - amount0Out)\\n : 0;\\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\\n ? _balance1 - (_reserve1 - amount1Out)\\n : 0;\\n require(amount0In > 0 || amount1In > 0, \\\"IIA\\\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\\n {\\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n if (amount0In > 0)\\n _update0(\\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token0 and move them out of pool\\n if (amount1In > 0)\\n _update1(\\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token1 and move them out of pool\\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \\\"K\\\"); // Pair: K\\n }\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\\n }\\n\\n // force balances to match reserves\\n function skim(address to) external lock {\\n (address _token0, address _token1) = (token0, token1);\\n _safeTransfer(\\n _token0,\\n to,\\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\\n );\\n _safeTransfer(\\n _token1,\\n to,\\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\\n );\\n }\\n\\n // force reserves to match balances\\n function sync() external lock {\\n _update(\\n IERC20(token0).balanceOf(address(this)),\\n IERC20(token1).balanceOf(address(this)),\\n reserve0,\\n reserve1\\n );\\n }\\n\\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\\n 1e18 +\\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\\n 1e18;\\n }\\n\\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (3 * x0 * ((y * y) / 1e18)) /\\n 1e18 +\\n ((((x0 * x0) / 1e18) * x0) / 1e18);\\n }\\n\\n function _get_y(\\n uint256 x0,\\n uint256 xy,\\n uint256 y\\n ) internal pure returns (uint256) {\\n for (uint256 i = 0; i < 255; i++) {\\n uint256 y_prev = y;\\n uint256 k = _f(x0, y);\\n if (k < xy) {\\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\\n y = y + dy;\\n } else {\\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getAmountOut(uint256 amountIn, address tokenIn)\\n external\\n view\\n returns (uint256)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n function _getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal view returns (uint256) {\\n if (stable) {\\n uint256 xy = _k(_reserve0, _reserve1);\\n _reserve0 = (_reserve0 * 1e18) / decimals0;\\n _reserve1 = (_reserve1 * 1e18) / decimals1;\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0\\n ? (amountIn * 1e18) / decimals0\\n : (amountIn * 1e18) / decimals1;\\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\\n } else {\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n return (amountIn * reserveB) / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\\n if (stable) {\\n uint256 _x = (x * 1e18) / decimals0;\\n uint256 _y = (y * 1e18) / decimals1;\\n uint256 _a = (_x * _y) / 1e18;\\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return (_a * _b) / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n\\n function _mint(address dst, uint256 amount) internal {\\n _updateFor(dst); // balances must be updated on mint/burn/transfer\\n totalSupply += amount;\\n balanceOf[dst] += amount;\\n emit Transfer(address(0), dst, amount);\\n }\\n\\n function _burn(address dst, uint256 amount) internal {\\n _updateFor(dst);\\n totalSupply -= amount;\\n balanceOf[dst] -= amount;\\n emit Transfer(dst, address(0), amount);\\n }\\n\\n function approve(address spender, uint256 amount) external returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external {\\n require(deadline >= block.timestamp, \\\"Pair: EXPIRED\\\");\\n DOMAIN_SEPARATOR = keccak256(\\n abi.encode(\\n keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n ),\\n keccak256(bytes(name)),\\n keccak256(bytes(\\\"1\\\")),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR,\\n keccak256(\\n abi.encode(\\n PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n );\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n require(\\n recoveredAddress != address(0) && recoveredAddress == owner,\\n \\\"Pair: INVALID_SIGNATURE\\\"\\n );\\n allowance[owner][spender] = value;\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function transfer(address dst, uint256 amount) external returns (bool) {\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 amount\\n ) external returns (bool) {\\n address spender = msg.sender;\\n uint256 spenderAllowance = allowance[src][spender];\\n\\n if (spender != src && spenderAllowance != type(uint256).max) {\\n uint256 newAllowance = spenderAllowance - amount;\\n allowance[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n function _transferTokens(\\n address src,\\n address dst,\\n uint256 amount\\n ) internal {\\n _updateFor(src); // update fee position for src\\n _updateFor(dst); // update fee position for dst\\n\\n balanceOf[src] -= amount;\\n balanceOf[dst] += amount;\\n\\n emit Transfer(src, dst, amount);\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x4f508747645f4480e0b0f23d952fa9b82af1d9bc60b15b8cd1f542ee136043d1\",\"license\":\"MIT\"},\"contracts/PairFees.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IERC20.sol';\\n\\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\\ncontract PairFees {\\n\\n address internal immutable pair; // The pair it is bonded to\\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\\n\\n constructor(address _token0, address _token1) {\\n pair = msg.sender;\\n token0 = _token0;\\n token1 = _token1;\\n }\\n\\n function _safeTransfer(address token,address to,uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n // Allow the pair to transfer fees to users\\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\\n require(msg.sender == pair);\\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\\n }\\n\\n}\\n\",\"keccak256\":\"0xb772e192bab353f8642e89a95ef4ef0255d1caef08444101d7fe34469c1000ca\",\"license\":\"MIT\"},\"contracts/factories/PairFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/Pair.sol';\\n\\ncontract PairFactory is IPairFactory {\\n\\n bool public isPaused;\\n address public pauser;\\n address public pendingPauser;\\n\\n uint256 public stableFee;\\n uint256 public volatileFee;\\n uint256 public constant MAX_FEE = 5; // 0.05%\\n address public feeManager;\\n address public pendingFeeManager;\\n\\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\\n address[] public allPairs;\\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\\n\\n address internal _temp0;\\n address internal _temp1;\\n bool internal _temp;\\n\\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\\n\\n constructor() {\\n pauser = msg.sender;\\n isPaused = false;\\n feeManager = msg.sender;\\n stableFee = 2; // 0.02%\\n volatileFee = 2;\\n }\\n\\n function allPairsLength() external view returns (uint) {\\n return allPairs.length;\\n }\\n\\n function setPauser(address _pauser) external {\\n require(msg.sender == pauser);\\n pendingPauser = _pauser;\\n }\\n\\n function acceptPauser() external {\\n require(msg.sender == pendingPauser);\\n pauser = pendingPauser;\\n }\\n\\n function setPause(bool _state) external {\\n require(msg.sender == pauser);\\n isPaused = _state;\\n }\\n\\n function setFeeManager(address _feeManager) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n pendingFeeManager = _feeManager;\\n }\\n\\n function acceptFeeManager() external {\\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\\n feeManager = pendingFeeManager;\\n }\\n\\n function setFee(bool _stable, uint256 _fee) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n require(_fee <= MAX_FEE, 'fee too high');\\n require(_fee != 0, 'fee must be nonzero');\\n if (_stable) {\\n stableFee = _fee;\\n } else {\\n volatileFee = _fee;\\n }\\n }\\n\\n function getFee(bool _stable) public view returns(uint256) {\\n return _stable ? stableFee : volatileFee;\\n }\\n\\n function pairCodeHash() external pure returns (bytes32) {\\n return keccak256(type(Pair).creationCode);\\n }\\n\\n function getInitializable() external view returns (address, address, bool) {\\n return (_temp0, _temp1, _temp);\\n }\\n\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\\n (_temp0, _temp1, _temp) = (token0, token1, stable);\\n pair = address(new Pair{salt:salt}());\\n getPair[token0][token1][stable] = pair;\\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\\n allPairs.push(pair);\\n isPair[pair] = true;\\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\\n }\\n}\\n\",\"keccak256\":\"0x9b7984117a5a32188aa9ddf42b6cff024240579ab30f3776f7a201285d813e4f\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairCallee.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairCallee {\\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x3ac2de2c7a08bf59fd1006e4d108b247916369de15fbd048b72ca2b7814023ca\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50600080546001600160a81b03191633610100810260ff1916919091178255600480546001600160a01b0319169091179055600280805560035561519190819061005a90396000f3fe60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea26469706673582212208b453bc7549999ab5f900d35221afe3ea71f11a1ef126003a17f9e83cda073b764736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea2646970667358221220a0e5d8be5a804858df78ae47f8fc2a744df9f79fa1277638415ca361262d388d64736f6c634300080d0033a2646970667358221220f746ba6d1ae747d9562e9ee216fb7ac76a7c799b9e95dff2eb578c8d39a9912864736f6c634300080d0033", - "deployedBytecode": "0x60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea26469706673582212208b453bc7549999ab5f900d35221afe3ea71f11a1ef126003a17f9e83cda073b764736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea2646970667358221220a0e5d8be5a804858df78ae47f8fc2a744df9f79fa1277638415ca361262d388d64736f6c634300080d0033a2646970667358221220f746ba6d1ae747d9562e9ee216fb7ac76a7c799b9e95dff2eb578c8d39a9912864736f6c634300080d0033", + "numDeployments": 8, + "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"PairCreated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_FEE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allPairs\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"allPairsLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"createPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getInitializable\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"name\":\"getPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pairCodeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingFeeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingPauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_feeManager\",\"type\":\"address\"}],\"name\":\"setFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_state\",\"type\":\"bool\"}],\"name\":\"setPause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pauser\",\"type\":\"address\"}],\"name\":\"setPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stableFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"volatileFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/PairFactory.sol\":\"PairFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Pair.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairCallee.sol\\\";\\nimport \\\"contracts/factories/PairFactory.sol\\\";\\nimport \\\"contracts/PairFees.sol\\\";\\n\\n// The base pair of pools, either stable or volatile\\ncontract Pair is IPair {\\n string public name;\\n string public symbol;\\n uint8 public constant decimals = 18;\\n\\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\\n bool public immutable stable;\\n\\n uint256 public totalSupply = 0;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n mapping(address => uint256) public balanceOf;\\n\\n bytes32 internal DOMAIN_SEPARATOR;\\n // keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 internal constant PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n mapping(address => uint256) public nonces;\\n\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n\\n address public immutable token0;\\n address public immutable token1;\\n address public immutable fees;\\n address immutable factory;\\n\\n // Structure to capture time period obervations every 30 minutes, used for local oracles\\n struct Observation {\\n uint256 timestamp;\\n uint256 reserve0Cumulative;\\n uint256 reserve1Cumulative;\\n }\\n\\n // Capture oracle reading every 30 minutes\\n uint256 constant periodSize = 1800;\\n\\n Observation[] public observations;\\n\\n uint256 internal immutable decimals0;\\n uint256 internal immutable decimals1;\\n\\n uint256 public reserve0;\\n uint256 public reserve1;\\n uint256 public blockTimestampLast;\\n\\n uint256 public reserve0CumulativeLast;\\n uint256 public reserve1CumulativeLast;\\n\\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \\\"clean\\\"\\n // this further allows LP holders to easily claim fees for tokens they have/staked\\n uint256 public index0 = 0;\\n uint256 public index1 = 0;\\n\\n // position assigned to each LP to track their current index0 & index1 vs the global position\\n mapping(address => uint256) public supplyIndex0;\\n mapping(address => uint256) public supplyIndex1;\\n\\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\\n mapping(address => uint256) public claimable0;\\n mapping(address => uint256) public claimable1;\\n\\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\\n event Burn(\\n address indexed sender,\\n uint256 amount0,\\n uint256 amount1,\\n address indexed to\\n );\\n event Swap(\\n address indexed sender,\\n uint256 amount0In,\\n uint256 amount1In,\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address indexed to\\n );\\n event Sync(uint256 reserve0, uint256 reserve1);\\n event Claim(\\n address indexed sender,\\n address indexed recipient,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 amount\\n );\\n\\n constructor() {\\n factory = msg.sender;\\n (address _token0, address _token1, bool _stable) = PairFactory(\\n msg.sender\\n ).getInitializable();\\n (token0, token1, stable) = (_token0, _token1, _stable);\\n fees = address(new PairFees(_token0, _token1));\\n if (_stable) {\\n name = string(\\n abi.encodePacked(\\n \\\"StableV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"sAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n } else {\\n name = string(\\n abi.encodePacked(\\n \\\"VolatileV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"vAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n }\\n\\n decimals0 = 10**IERC20(_token0).decimals();\\n decimals1 = 10**IERC20(_token1).decimals();\\n\\n observations.push(Observation(block.timestamp, 0, 0));\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function observationLength() external view returns (uint256) {\\n return observations.length;\\n }\\n\\n function lastObservation() public view returns (Observation memory) {\\n return observations[observations.length - 1];\\n }\\n\\n function metadata()\\n external\\n view\\n returns (\\n uint256 dec0,\\n uint256 dec1,\\n uint256 r0,\\n uint256 r1,\\n bool st,\\n address t0,\\n address t1\\n )\\n {\\n return (\\n decimals0,\\n decimals1,\\n reserve0,\\n reserve1,\\n stable,\\n token0,\\n token1\\n );\\n }\\n\\n function tokens() external view returns (address, address) {\\n return (token0, token1);\\n }\\n\\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\\n _updateFor(msg.sender);\\n\\n claimed0 = claimable0[msg.sender];\\n claimed1 = claimable1[msg.sender];\\n\\n if (claimed0 > 0 || claimed1 > 0) {\\n claimable0[msg.sender] = 0;\\n claimable1[msg.sender] = 0;\\n\\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\\n\\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n // Accrue fees on token0\\n function _update0(uint256 amount) internal {\\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index0 += _ratio;\\n }\\n emit Fees(msg.sender, amount, 0);\\n }\\n\\n // Accrue fees on token1\\n function _update1(uint256 amount) internal {\\n _safeTransfer(token1, fees, amount);\\n uint256 _ratio = (amount * 1e18) / totalSupply;\\n if (_ratio > 0) {\\n index1 += _ratio;\\n }\\n emit Fees(msg.sender, 0, amount);\\n }\\n\\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\\n // Fees are segregated from core funds, so fees can never put liquidity at risk\\n function _updateFor(address recipient) internal {\\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\\n if (_supplied > 0) {\\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\\n uint256 _supplyIndex1 = supplyIndex1[recipient];\\n uint256 _index0 = index0; // get global index0 for accumulated fees\\n uint256 _index1 = index1;\\n supplyIndex0[recipient] = _index0; // update user current position to global position\\n supplyIndex1[recipient] = _index1;\\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\\n uint256 _delta1 = _index1 - _supplyIndex1;\\n if (_delta0 > 0) {\\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\\n claimable0[recipient] += _share;\\n }\\n if (_delta1 > 0) {\\n uint256 _share = (_supplied * _delta1) / 1e18;\\n claimable1[recipient] += _share;\\n }\\n } else {\\n supplyIndex0[recipient] = index0; // new users are set to the default global state\\n supplyIndex1[recipient] = index1;\\n }\\n }\\n\\n function getReserves()\\n public\\n view\\n returns (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n )\\n {\\n _reserve0 = reserve0;\\n _reserve1 = reserve1;\\n _blockTimestampLast = blockTimestampLast;\\n }\\n\\n // update reserves and, on the first call per block, price accumulators\\n function _update(\\n uint256 balance0,\\n uint256 balance1,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal {\\n uint256 blockTimestamp = block.timestamp;\\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\\n reserve0CumulativeLast += _reserve0 * timeElapsed;\\n reserve1CumulativeLast += _reserve1 * timeElapsed;\\n }\\n\\n Observation memory _point = lastObservation();\\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\\n if (timeElapsed > periodSize) {\\n observations.push(\\n Observation(\\n blockTimestamp,\\n reserve0CumulativeLast,\\n reserve1CumulativeLast\\n )\\n );\\n }\\n reserve0 = balance0;\\n reserve1 = balance1;\\n blockTimestampLast = blockTimestamp;\\n emit Sync(reserve0, reserve1);\\n }\\n\\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\\n function currentCumulativePrices()\\n public\\n view\\n returns (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n uint256 blockTimestamp\\n )\\n {\\n blockTimestamp = block.timestamp;\\n reserve0Cumulative = reserve0CumulativeLast;\\n reserve1Cumulative = reserve1CumulativeLast;\\n\\n // if time has elapsed since the last update on the pair, mock the accumulated price values\\n (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n ) = getReserves();\\n if (_blockTimestampLast != blockTimestamp) {\\n // subtraction overflow is desired\\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\\n reserve0Cumulative += _reserve0 * timeElapsed;\\n reserve1Cumulative += _reserve1 * timeElapsed;\\n }\\n }\\n\\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\\n function current(address tokenIn, uint256 amountIn)\\n external\\n view\\n returns (uint256 amountOut)\\n {\\n Observation memory _observation = lastObservation();\\n (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n\\n ) = currentCumulativePrices();\\n if (block.timestamp == _observation.timestamp) {\\n _observation = observations[observations.length - 2];\\n }\\n\\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\\n uint256 _reserve0 = (reserve0Cumulative -\\n _observation.reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (reserve1Cumulative -\\n _observation.reserve1Cumulative) / timeElapsed;\\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n // as per `current`, however allows user configured granularity, up to the full window size\\n function quote(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 granularity\\n ) external view returns (uint256 amountOut) {\\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\\n uint256 priceAverageCumulative;\\n for (uint256 i = 0; i < _prices.length; i++) {\\n priceAverageCumulative += _prices[i];\\n }\\n return priceAverageCumulative / granularity;\\n }\\n\\n // returns a memory set of twap prices\\n function prices(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points\\n ) external view returns (uint256[] memory) {\\n return sample(tokenIn, amountIn, points, 1);\\n }\\n\\n function sample(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points,\\n uint256 window\\n ) public view returns (uint256[] memory) {\\n uint256[] memory _prices = new uint256[](points);\\n\\n uint256 length = observations.length - 1;\\n uint256 i = length - (points * window);\\n uint256 nextIndex = 0;\\n uint256 index = 0;\\n\\n for (; i < length; i += window) {\\n nextIndex = i + window;\\n uint256 timeElapsed = observations[nextIndex].timestamp -\\n observations[i].timestamp;\\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\\n observations[i].reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\\n observations[i].reserve1Cumulative) / timeElapsed;\\n _prices[index] = _getAmountOut(\\n amountIn,\\n tokenIn,\\n _reserve0,\\n _reserve1\\n );\\n // index < length; length cannot overflow\\n unchecked {\\n index = index + 1;\\n }\\n }\\n return _prices;\\n }\\n\\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\\n // standard uniswap v2 implementation\\n function mint(address to) external lock returns (uint256 liquidity) {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\\n uint256 _amount0 = _balance0 - _reserve0;\\n uint256 _amount1 = _balance1 - _reserve1;\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n if (_totalSupply == 0) {\\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\\n } else {\\n liquidity = MathDunks.min(\\n (_amount0 * _totalSupply) / _reserve0,\\n (_amount1 * _totalSupply) / _reserve1\\n );\\n }\\n require(liquidity > 0, \\\"ILM\\\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\\n _mint(to, liquidity);\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Mint(msg.sender, _amount0, _amount1);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n // standard uniswap v2 implementation\\n function burn(address to)\\n external\\n lock\\n returns (uint256 amount0, uint256 amount1)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n (address _token0, address _token1) = (token0, token1);\\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\\n uint256 _liquidity = balanceOf[address(this)];\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\\n require(amount0 > 0 && amount1 > 0, \\\"ILB\\\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\\n _burn(address(this), _liquidity);\\n _safeTransfer(_token0, to, amount0);\\n _safeTransfer(_token1, to, amount1);\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Burn(msg.sender, amount0, amount1, to);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n function swap(\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address to,\\n bytes calldata data\\n ) external lock {\\n require(!PairFactory(factory).isPaused());\\n require(amount0Out > 0 || amount1Out > 0, \\\"IOA\\\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \\\"IL\\\"); // Pair: INSUFFICIENT_LIQUIDITY\\n\\n uint256 _balance0;\\n uint256 _balance1;\\n {\\n // scope for _token{0,1}, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n require(to != _token0 && to != _token1, \\\"IT\\\"); // Pair: INVALID_TO\\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\\n if (data.length > 0)\\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n }\\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\\n ? _balance0 - (_reserve0 - amount0Out)\\n : 0;\\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\\n ? _balance1 - (_reserve1 - amount1Out)\\n : 0;\\n require(amount0In > 0 || amount1In > 0, \\\"IIA\\\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\\n {\\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n if (amount0In > 0)\\n _update0(\\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token0 and move them out of pool\\n if (amount1In > 0)\\n _update1(\\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token1 and move them out of pool\\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \\\"K\\\"); // Pair: K\\n }\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\\n }\\n\\n // force balances to match reserves\\n function skim(address to) external lock {\\n (address _token0, address _token1) = (token0, token1);\\n _safeTransfer(\\n _token0,\\n to,\\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\\n );\\n _safeTransfer(\\n _token1,\\n to,\\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\\n );\\n }\\n\\n // force reserves to match balances\\n function sync() external lock {\\n _update(\\n IERC20(token0).balanceOf(address(this)),\\n IERC20(token1).balanceOf(address(this)),\\n reserve0,\\n reserve1\\n );\\n }\\n\\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\\n 1e18 +\\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\\n 1e18;\\n }\\n\\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (3 * x0 * ((y * y) / 1e18)) /\\n 1e18 +\\n ((((x0 * x0) / 1e18) * x0) / 1e18);\\n }\\n\\n function _get_y(\\n uint256 x0,\\n uint256 xy,\\n uint256 y\\n ) internal pure returns (uint256) {\\n for (uint256 i = 0; i < 255; i++) {\\n uint256 y_prev = y;\\n uint256 k = _f(x0, y);\\n if (k < xy) {\\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\\n y = y + dy;\\n } else {\\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getAmountOut(uint256 amountIn, address tokenIn)\\n external\\n view\\n returns (uint256)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n function _getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal view returns (uint256) {\\n if (stable) {\\n uint256 xy = _k(_reserve0, _reserve1);\\n _reserve0 = (_reserve0 * 1e18) / decimals0;\\n _reserve1 = (_reserve1 * 1e18) / decimals1;\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0\\n ? (amountIn * 1e18) / decimals0\\n : (amountIn * 1e18) / decimals1;\\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\\n } else {\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n return (amountIn * reserveB) / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\\n if (stable) {\\n uint256 _x = (x * 1e18) / decimals0;\\n uint256 _y = (y * 1e18) / decimals1;\\n uint256 _a = (_x * _y) / 1e18;\\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return (_a * _b) / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n\\n function _mint(address dst, uint256 amount) internal {\\n _updateFor(dst); // balances must be updated on mint/burn/transfer\\n totalSupply += amount;\\n balanceOf[dst] += amount;\\n emit Transfer(address(0), dst, amount);\\n }\\n\\n function _burn(address dst, uint256 amount) internal {\\n _updateFor(dst);\\n totalSupply -= amount;\\n balanceOf[dst] -= amount;\\n emit Transfer(dst, address(0), amount);\\n }\\n\\n function approve(address spender, uint256 amount) external returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external {\\n require(deadline >= block.timestamp, \\\"Pair: EXPIRED\\\");\\n DOMAIN_SEPARATOR = keccak256(\\n abi.encode(\\n keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n ),\\n keccak256(bytes(name)),\\n keccak256(bytes(\\\"1\\\")),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR,\\n keccak256(\\n abi.encode(\\n PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n );\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n require(\\n recoveredAddress != address(0) && recoveredAddress == owner,\\n \\\"Pair: INVALID_SIGNATURE\\\"\\n );\\n allowance[owner][spender] = value;\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function transfer(address dst, uint256 amount) external returns (bool) {\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 amount\\n ) external returns (bool) {\\n address spender = msg.sender;\\n uint256 spenderAllowance = allowance[src][spender];\\n\\n if (spender != src && spenderAllowance != type(uint256).max) {\\n uint256 newAllowance = spenderAllowance - amount;\\n allowance[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n function _transferTokens(\\n address src,\\n address dst,\\n uint256 amount\\n ) internal {\\n _updateFor(src); // update fee position for src\\n _updateFor(dst); // update fee position for dst\\n\\n balanceOf[src] -= amount;\\n balanceOf[dst] += amount;\\n\\n emit Transfer(src, dst, amount);\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x4f508747645f4480e0b0f23d952fa9b82af1d9bc60b15b8cd1f542ee136043d1\",\"license\":\"MIT\"},\"contracts/PairFees.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IERC20.sol';\\n\\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\\ncontract PairFees {\\n\\n address internal immutable pair; // The pair it is bonded to\\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\\n\\n constructor(address _token0, address _token1) {\\n pair = msg.sender;\\n token0 = _token0;\\n token1 = _token1;\\n }\\n\\n function _safeTransfer(address token,address to,uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n // Allow the pair to transfer fees to users\\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\\n require(msg.sender == pair);\\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\\n }\\n\\n}\\n\",\"keccak256\":\"0xb772e192bab353f8642e89a95ef4ef0255d1caef08444101d7fe34469c1000ca\",\"license\":\"MIT\"},\"contracts/factories/PairFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/Pair.sol';\\n\\ncontract PairFactory is IPairFactory {\\n\\n bool public isPaused;\\n address public pauser;\\n address public pendingPauser;\\n\\n uint256 public stableFee;\\n uint256 public volatileFee;\\n uint256 public constant MAX_FEE = 5; // 0.05%\\n address public feeManager;\\n address public pendingFeeManager;\\n\\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\\n address[] public allPairs;\\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\\n\\n address internal _temp0;\\n address internal _temp1;\\n bool internal _temp;\\n\\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\\n\\n constructor() {\\n pauser = msg.sender;\\n isPaused = false;\\n feeManager = msg.sender;\\n stableFee = 2; // 0.02%\\n volatileFee = 2;\\n }\\n\\n function allPairsLength() external view returns (uint) {\\n return allPairs.length;\\n }\\n\\n function setPauser(address _pauser) external {\\n require(msg.sender == pauser);\\n pendingPauser = _pauser;\\n }\\n\\n function acceptPauser() external {\\n require(msg.sender == pendingPauser);\\n pauser = pendingPauser;\\n }\\n\\n function setPause(bool _state) external {\\n require(msg.sender == pauser);\\n isPaused = _state;\\n }\\n\\n function setFeeManager(address _feeManager) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n pendingFeeManager = _feeManager;\\n }\\n\\n function acceptFeeManager() external {\\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\\n feeManager = pendingFeeManager;\\n }\\n\\n function setFee(bool _stable, uint256 _fee) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n require(_fee <= MAX_FEE, 'fee too high');\\n require(_fee != 0, 'fee must be nonzero');\\n if (_stable) {\\n stableFee = _fee;\\n } else {\\n volatileFee = _fee;\\n }\\n }\\n\\n function getFee(bool _stable) public view returns(uint256) {\\n return _stable ? stableFee : volatileFee;\\n }\\n\\n function pairCodeHash() external pure returns (bytes32) {\\n return keccak256(type(Pair).creationCode);\\n }\\n\\n function getInitializable() external view returns (address, address, bool) {\\n return (_temp0, _temp1, _temp);\\n }\\n\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\\n (_temp0, _temp1, _temp) = (token0, token1, stable);\\n pair = address(new Pair{salt:salt}());\\n getPair[token0][token1][stable] = pair;\\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\\n allPairs.push(pair);\\n isPair[pair] = true;\\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\\n }\\n}\\n\",\"keccak256\":\"0x9b7984117a5a32188aa9ddf42b6cff024240579ab30f3776f7a201285d813e4f\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairCallee.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairCallee {\\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x3ac2de2c7a08bf59fd1006e4d108b247916369de15fbd048b72ca2b7814023ca\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50600080546001600160a81b03191633610100810260ff1916919091178255600480546001600160a01b0319169091179055600280805560035561519190819061005a90396000f3fe60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea26469706673582212209a81b6080f92b4404ef96a6f4be1eb720d086813c51978fa69228aa4a9475a0a64736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea264697066735822122001f7e6ebdc7c73c8cd4fc265ddf1f20b20d92174d591661f841bc8ad24c91c5364736f6c634300080d0033a2646970667358221220c135354976b334eda32c0379e423d9e6fc425df0ae93f17748c33d480901ab2764736f6c634300080d0033", + "deployedBytecode": "0x60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea26469706673582212209a81b6080f92b4404ef96a6f4be1eb720d086813c51978fa69228aa4a9475a0a64736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea264697066735822122001f7e6ebdc7c73c8cd4fc265ddf1f20b20d92174d591661f841bc8ad24c91c5364736f6c634300080d0033a2646970667358221220c135354976b334eda32c0379e423d9e6fc425df0ae93f17748c33d480901ab2764736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/RedemptionReceiver.json b/deployments/arbitrumGoerli/RedemptionReceiver.json index 85b51c2b..4ca87de2 100644 --- a/deployments/arbitrumGoerli/RedemptionReceiver.json +++ b/deployments/arbitrumGoerli/RedemptionReceiver.json @@ -1,5 +1,5 @@ { - "address": "0x08e352f2130d4b68d7B1264CD42191205B61b60f", + "address": "0x7eEE2ED1bD98dd7e103518405933D56Dac2bC9Df", "abi": [ { "inputs": [ @@ -323,33 +323,33 @@ "type": "function" } ], - "transactionHash": "0xf3acdd7467b958f2cfdef54cb5014fe6decea05a26c06c15f2ff9c5b519f2d18", + "transactionHash": "0x5b13661a7eabb59a780cf3f170d0dc5df51bcbb00337ea5d5992e1b34f7eb04c", "receipt": { "to": null, "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0x08e352f2130d4b68d7B1264CD42191205B61b60f", + "contractAddress": "0x7eEE2ED1bD98dd7e103518405933D56Dac2bC9Df", "transactionIndex": 1, - "gasUsed": "9877695", + "gasUsed": "19122626", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfb4dfca6f15c0239ae6fd9048744b536edfd666421a9c22a7f2a18ec92fa104d", - "transactionHash": "0xf3acdd7467b958f2cfdef54cb5014fe6decea05a26c06c15f2ff9c5b519f2d18", + "blockHash": "0xa5d1535c5893b986eeff581358eeb5a846f43dbf1ebd4f344b90d3327c83f1b2", + "transactionHash": "0x5b13661a7eabb59a780cf3f170d0dc5df51bcbb00337ea5d5992e1b34f7eb04c", "logs": [], - "blockNumber": 4195038, - "cumulativeGasUsed": "9877695", + "blockNumber": 4263703, + "cumulativeGasUsed": "19122626", "status": 1, "byzantium": true }, "args": [ "0x7F5c764cBc14f9669B88837ca1490cCa17c31607", - "0xe69b00A164047e7eB87B73971B0f340eEbFF9c81", + "0x162404E6Cd4633656925b90EF67237F29D5cc85c", 10012, "0x3c2269811836af69497E5F486A85D7316753cf62" ], - "numDeployments": 3, - "solcInputHash": "0faaa79d8b79020b765ba7705413c447", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_usdc\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_velo\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"_fantomChainId\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"_endpoint\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fantomSender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableUSDC\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableVELO\",\"type\":\"uint256\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ELIGIBLE_WEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"USDC\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VELO\",\"outputs\":[{\"internalType\":\"contract IVelo\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"toAddressBytes\",\"type\":\"bytes\"}],\"name\":\"addressFromPackedBytes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimLeftovers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endpoint\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomChainId\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_fantomSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableVELO\",\"type\":\"uint256\"}],\"name\":\"initializeReceiverWith\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"leftoverVELO\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"srcChainId\",\"type\":\"uint16\"},{\"internalType\":\"bytes\",\"name\":\"srcAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"lzReceive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountWEVE\",\"type\":\"uint256\"}],\"name\":\"previewRedeem\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"shareOfUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shareOfVELO\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableUSDC\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableVELO\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemedWEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process This contract is responsible for receiving the LZ message and distributing USDC + VELO\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/RedemptionReceiver.sol\":\"RedemptionReceiver\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"},\"contracts/redeem/RedemptionReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\\\";\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IVelo.sol\\\";\\n\\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\\ncontract RedemptionReceiver is ILayerZeroReceiver {\\n IERC20 public immutable USDC;\\n IVelo public immutable VELO;\\n\\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\\n address public immutable endpoint;\\n\\n address public team;\\n uint256 public immutable deployed;\\n\\n address public fantomSender;\\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\\n uint256 public redeemedWEVE;\\n uint256 public redeemableUSDC;\\n uint256 public redeemableVELO;\\n uint256 public leftoverVELO;\\n\\n constructor(\\n address _usdc,\\n address _velo,\\n uint16 _fantomChainId,\\n address _endpoint\\n ) {\\n require(_fantomChainId == 12 || _fantomChainId == 10012, \\\"CHAIN_ID_NOT_FTM\\\");\\n\\n USDC = IERC20(_usdc);\\n VELO = IVelo(_velo);\\n\\n fantomChainId = _fantomChainId;\\n endpoint = _endpoint;\\n\\n team = msg.sender;\\n deployed = block.timestamp;\\n }\\n\\n modifier onlyTeam() {\\n require(msg.sender == team, \\\"ONLY_TEAM\\\");\\n _;\\n }\\n\\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\\n\\n function initializeReceiverWith(\\n address _fantomSender,\\n uint256 _redeemableUSDC,\\n uint256 _redeemableVELO\\n ) external onlyTeam {\\n require(fantomSender == address(0), \\\"ALREADY_INITIALIZED\\\");\\n require(\\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n fantomSender = _fantomSender;\\n redeemableUSDC = _redeemableUSDC;\\n redeemableVELO = _redeemableVELO;\\n leftoverVELO = _redeemableVELO;\\n\\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\\n }\\n\\n function setTeam(address _team) external onlyTeam {\\n team = _team;\\n }\\n\\n function previewRedeem(uint256 amountWEVE)\\n public\\n view\\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\\n {\\n // pro rata USDC\\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\\n // pro rata VELO\\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\\n }\\n\\n function lzReceive(\\n uint16 srcChainId,\\n bytes memory srcAddress,\\n uint64,\\n bytes memory payload\\n ) external override {\\n require(fantomSender != address(0), \\\"NOT_INITIALIZED\\\");\\n require(\\n msg.sender == endpoint &&\\n srcChainId == fantomChainId &&\\n addressFromPackedBytes(srcAddress) == fantomSender,\\n \\\"UNAUTHORIZED_CALLER\\\"\\n );\\n\\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\\n payload,\\n (address, uint256)\\n );\\n\\n require(\\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\\n \\\"cannot redeem more than eligible\\\"\\n );\\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\\n\\n require(\\n USDC.transfer(redemptionAddress, shareOfUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n leftoverVELO -= shareOfVELO; // this will revert if underflows\\n require(\\n VELO.claim(redemptionAddress, shareOfVELO),\\n \\\"CLAIM_FAILED\\\"\\n );\\n }\\n\\n function addressFromPackedBytes(bytes memory toAddressBytes)\\n public\\n pure\\n returns (address toAddress)\\n {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n toAddress := mload(add(toAddressBytes, 20))\\n }\\n }\\n\\n function claimLeftovers() external onlyTeam {\\n require(block.timestamp >= deployed + 30 days, \\\"LEFTOVERS_NOT_CLAIMABLE\\\");\\n require(\\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n }\\n}\\n\",\"keccak256\":\"0xb5c76f083e5076206e2713b64eed8bfc782715c19f6993ac8e97b1db898ae304\",\"license\":\"MIT\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\nimport \\\"./ILayerZeroUserApplicationConfig.sol\\\";\\n\\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\\n // @param _dstChainId - the destination chain identifier\\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\\n // @param _payload - a custom bytes payload to send to the destination contract\\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\\n\\n // @notice used by the messaging library to publish verified payload\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source contract (as bytes) at the source chain\\n // @param _dstAddress - the address on destination chain\\n // @param _nonce - the unbound message ordering nonce\\n // @param _gasLimit - the gas limit for external contract execution\\n // @param _payload - verified payload to send to the destination contract\\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\\n\\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\\n\\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\\n // @param _srcAddress - the source chain contract address\\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\\n\\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\\n // @param _dstChainId - the destination chain identifier\\n // @param _userApplication - the user app address on this EVM chain\\n // @param _payload - the custom message to send over LayerZero\\n // @param _payInZRO - if false, user app pays the protocol fee in native token\\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\\n\\n // @notice get this Endpoint's immutable source identifier\\n function getChainId() external view returns (uint16);\\n\\n // @notice the interface to retry failed message on this Endpoint destination\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n // @param _payload - the payload to be retried\\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\\n\\n // @notice query if any STORED payload (message blocking) at the endpoint.\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\\n\\n // @notice query if the _libraryAddress is valid for sending msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getSendLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the _libraryAddress is valid for receiving msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the non-reentrancy guard for send() is on\\n // @return true if the guard is on. false otherwise\\n function isSendingPayload() external view returns (bool);\\n\\n // @notice query if the non-reentrancy guard for receive() is on\\n // @return true if the guard is on. false otherwise\\n function isReceivingPayload() external view returns (bool);\\n\\n // @notice get the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _userApplication - the contract address of the user application\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\\n\\n // @notice get the send() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getSendVersion(address _userApplication) external view returns (uint16);\\n\\n // @notice get the lzReceive() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getReceiveVersion(address _userApplication) external view returns (uint16);\\n}\\n\",\"keccak256\":\"0xbc2e0022d4d53d136830aa90037be2ed7a0966f5fd1b409bf5986185984c495f\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroReceiver {\\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\\n // @param _srcChainId - the source endpoint identifier\\n // @param _srcAddress - the source sending contract address from the source chain\\n // @param _nonce - the ordered message nonce\\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\\n}\\n\",\"keccak256\":\"0xd1617e455d90d41556bba636bc440627d301ec481de16ff04fbd520333c3c6f3\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroUserApplicationConfig {\\n // @notice set the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n // @param _config - configuration in the bytes. can encode arbitrary content.\\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\\n\\n // @notice set the send() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setSendVersion(uint16 _version) external;\\n\\n // @notice set the lzReceive() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setReceiveVersion(uint16 _version) external;\\n\\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\\n // @param _srcChainId - the chainId of the source chain\\n // @param _srcAddress - the contract address of the source contract at the source chain\\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\\n}\\n\",\"keccak256\":\"0xdc7e072cf3064081a8edf4a286ca43ddecc24330f2923d96f416f9d3f6538447\",\"license\":\"BUSL-1.1\"}},\"version\":1}", - "bytecode": "0x61012060405234801561001157600080fd5b50604051610f81380380610f81833981016040819052610030916100e2565b8161ffff16600c148061004857508161ffff1661271c145b61008b5760405162461bcd60e51b815260206004820152601060248201526f434841494e5f49445f4e4f545f46544d60801b604482015260640160405180910390fd5b6001600160a01b0393841660805291831660a05261ffff1660c0521660e052600080546001600160a01b03191633179055426101005261013f565b80516001600160a01b03811681146100dd57600080fd5b919050565b600080600080608085870312156100f857600080fd5b610101856100c6565b935061010f602086016100c6565b9250604085015161ffff8116811461012657600080fd5b9150610134606086016100c6565b905092959194509250565b60805160a05160c05160e05161010051610dcd6101b4600039600081816102d601526108c00152600081816101940152610352015260008181610245015261037c01526000818161027f015261059f01526000818161021e015281816104d70152818161078e015261094c0152610dcd6000f3fe608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a0eeb39a11610071578063a0eeb39a1461027a578063a408bb4c146102a1578063aaa8f2ef146102a9578063b8ea6281146102bc578063f905c15a146102d157600080fd5b80636bfd23a7146101fd57806385f2aef21461020657806389a3027114610219578063997a03b71461024057600080fd5b80634cdad506116100e95780634cdad506146101675780635e280f111461018f57806363b4eb8d146101ce57806368ecc6bc146101e15780636ac55083146101f457600080fd5b80621d35671461011a578063095cf5c61461012f578063221798ad1461014257806347db1a6a1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60045481565b6040519081526020015b60405180910390f35b61014b60035481565b61017a610175366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b6001546101b6906001600160a01b031681565b61012d6101ef366004610be5565b6106f3565b61014b60055481565b61014b60025481565b6000546101b6906001600160a01b031681565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6102677f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101b66102ca366004610c1a565b6014015190565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea264697066735822122063436f3755bf60d5767a51cb987ff704bae7ed446b1faa6c1311050a8b5dab6164736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a0eeb39a11610071578063a0eeb39a1461027a578063a408bb4c146102a1578063aaa8f2ef146102a9578063b8ea6281146102bc578063f905c15a146102d157600080fd5b80636bfd23a7146101fd57806385f2aef21461020657806389a3027114610219578063997a03b71461024057600080fd5b80634cdad506116100e95780634cdad506146101675780635e280f111461018f57806363b4eb8d146101ce57806368ecc6bc146101e15780636ac55083146101f457600080fd5b80621d35671461011a578063095cf5c61461012f578063221798ad1461014257806347db1a6a1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60045481565b6040519081526020015b60405180910390f35b61014b60035481565b61017a610175366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b6001546101b6906001600160a01b031681565b61012d6101ef366004610be5565b6106f3565b61014b60055481565b61014b60025481565b6000546101b6906001600160a01b031681565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6102677f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101b66102ca366004610c1a565b6014015190565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea264697066735822122063436f3755bf60d5767a51cb987ff704bae7ed446b1faa6c1311050a8b5dab6164736f6c634300080d0033", + "numDeployments": 5, + "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_usdc\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_velo\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"_fantomChainId\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"_endpoint\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fantomSender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableUSDC\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableVELO\",\"type\":\"uint256\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ELIGIBLE_WEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"USDC\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VELO\",\"outputs\":[{\"internalType\":\"contract IVelo\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"toAddressBytes\",\"type\":\"bytes\"}],\"name\":\"addressFromPackedBytes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimLeftovers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endpoint\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomChainId\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_fantomSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableVELO\",\"type\":\"uint256\"}],\"name\":\"initializeReceiverWith\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"leftoverVELO\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"srcChainId\",\"type\":\"uint16\"},{\"internalType\":\"bytes\",\"name\":\"srcAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"lzReceive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountWEVE\",\"type\":\"uint256\"}],\"name\":\"previewRedeem\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"shareOfUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shareOfVELO\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableUSDC\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableVELO\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemedWEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process This contract is responsible for receiving the LZ message and distributing USDC + VELO\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/RedemptionReceiver.sol\":\"RedemptionReceiver\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"},\"contracts/redeem/RedemptionReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\\\";\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IVelo.sol\\\";\\n\\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\\ncontract RedemptionReceiver is ILayerZeroReceiver {\\n IERC20 public immutable USDC;\\n IVelo public immutable VELO;\\n\\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\\n address public immutable endpoint;\\n\\n address public team;\\n uint256 public immutable deployed;\\n\\n address public fantomSender;\\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\\n uint256 public redeemedWEVE;\\n uint256 public redeemableUSDC;\\n uint256 public redeemableVELO;\\n uint256 public leftoverVELO;\\n\\n constructor(\\n address _usdc,\\n address _velo,\\n uint16 _fantomChainId,\\n address _endpoint\\n ) {\\n require(_fantomChainId == 12 || _fantomChainId == 10012, \\\"CHAIN_ID_NOT_FTM\\\");\\n\\n USDC = IERC20(_usdc);\\n VELO = IVelo(_velo);\\n\\n fantomChainId = _fantomChainId;\\n endpoint = _endpoint;\\n\\n team = msg.sender;\\n deployed = block.timestamp;\\n }\\n\\n modifier onlyTeam() {\\n require(msg.sender == team, \\\"ONLY_TEAM\\\");\\n _;\\n }\\n\\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\\n\\n function initializeReceiverWith(\\n address _fantomSender,\\n uint256 _redeemableUSDC,\\n uint256 _redeemableVELO\\n ) external onlyTeam {\\n require(fantomSender == address(0), \\\"ALREADY_INITIALIZED\\\");\\n require(\\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n fantomSender = _fantomSender;\\n redeemableUSDC = _redeemableUSDC;\\n redeemableVELO = _redeemableVELO;\\n leftoverVELO = _redeemableVELO;\\n\\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\\n }\\n\\n function setTeam(address _team) external onlyTeam {\\n team = _team;\\n }\\n\\n function previewRedeem(uint256 amountWEVE)\\n public\\n view\\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\\n {\\n // pro rata USDC\\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\\n // pro rata VELO\\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\\n }\\n\\n function lzReceive(\\n uint16 srcChainId,\\n bytes memory srcAddress,\\n uint64,\\n bytes memory payload\\n ) external override {\\n require(fantomSender != address(0), \\\"NOT_INITIALIZED\\\");\\n require(\\n msg.sender == endpoint &&\\n srcChainId == fantomChainId &&\\n addressFromPackedBytes(srcAddress) == fantomSender,\\n \\\"UNAUTHORIZED_CALLER\\\"\\n );\\n\\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\\n payload,\\n (address, uint256)\\n );\\n\\n require(\\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\\n \\\"cannot redeem more than eligible\\\"\\n );\\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\\n\\n require(\\n USDC.transfer(redemptionAddress, shareOfUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n leftoverVELO -= shareOfVELO; // this will revert if underflows\\n require(\\n VELO.claim(redemptionAddress, shareOfVELO),\\n \\\"CLAIM_FAILED\\\"\\n );\\n }\\n\\n function addressFromPackedBytes(bytes memory toAddressBytes)\\n public\\n pure\\n returns (address toAddress)\\n {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n toAddress := mload(add(toAddressBytes, 20))\\n }\\n }\\n\\n function claimLeftovers() external onlyTeam {\\n require(block.timestamp >= deployed + 30 days, \\\"LEFTOVERS_NOT_CLAIMABLE\\\");\\n require(\\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n }\\n}\\n\",\"keccak256\":\"0xb5c76f083e5076206e2713b64eed8bfc782715c19f6993ac8e97b1db898ae304\",\"license\":\"MIT\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\nimport \\\"./ILayerZeroUserApplicationConfig.sol\\\";\\n\\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\\n // @param _dstChainId - the destination chain identifier\\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\\n // @param _payload - a custom bytes payload to send to the destination contract\\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\\n\\n // @notice used by the messaging library to publish verified payload\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source contract (as bytes) at the source chain\\n // @param _dstAddress - the address on destination chain\\n // @param _nonce - the unbound message ordering nonce\\n // @param _gasLimit - the gas limit for external contract execution\\n // @param _payload - verified payload to send to the destination contract\\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\\n\\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\\n\\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\\n // @param _srcAddress - the source chain contract address\\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\\n\\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\\n // @param _dstChainId - the destination chain identifier\\n // @param _userApplication - the user app address on this EVM chain\\n // @param _payload - the custom message to send over LayerZero\\n // @param _payInZRO - if false, user app pays the protocol fee in native token\\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\\n\\n // @notice get this Endpoint's immutable source identifier\\n function getChainId() external view returns (uint16);\\n\\n // @notice the interface to retry failed message on this Endpoint destination\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n // @param _payload - the payload to be retried\\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\\n\\n // @notice query if any STORED payload (message blocking) at the endpoint.\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\\n\\n // @notice query if the _libraryAddress is valid for sending msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getSendLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the _libraryAddress is valid for receiving msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the non-reentrancy guard for send() is on\\n // @return true if the guard is on. false otherwise\\n function isSendingPayload() external view returns (bool);\\n\\n // @notice query if the non-reentrancy guard for receive() is on\\n // @return true if the guard is on. false otherwise\\n function isReceivingPayload() external view returns (bool);\\n\\n // @notice get the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _userApplication - the contract address of the user application\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\\n\\n // @notice get the send() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getSendVersion(address _userApplication) external view returns (uint16);\\n\\n // @notice get the lzReceive() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getReceiveVersion(address _userApplication) external view returns (uint16);\\n}\\n\",\"keccak256\":\"0xbc2e0022d4d53d136830aa90037be2ed7a0966f5fd1b409bf5986185984c495f\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroReceiver {\\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\\n // @param _srcChainId - the source endpoint identifier\\n // @param _srcAddress - the source sending contract address from the source chain\\n // @param _nonce - the ordered message nonce\\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\\n}\\n\",\"keccak256\":\"0xd1617e455d90d41556bba636bc440627d301ec481de16ff04fbd520333c3c6f3\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroUserApplicationConfig {\\n // @notice set the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n // @param _config - configuration in the bytes. can encode arbitrary content.\\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\\n\\n // @notice set the send() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setSendVersion(uint16 _version) external;\\n\\n // @notice set the lzReceive() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setReceiveVersion(uint16 _version) external;\\n\\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\\n // @param _srcChainId - the chainId of the source chain\\n // @param _srcAddress - the contract address of the source contract at the source chain\\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\\n}\\n\",\"keccak256\":\"0xdc7e072cf3064081a8edf4a286ca43ddecc24330f2923d96f416f9d3f6538447\",\"license\":\"BUSL-1.1\"}},\"version\":1}", + "bytecode": "0x61012060405234801561001157600080fd5b50604051610f81380380610f81833981016040819052610030916100e2565b8161ffff16600c148061004857508161ffff1661271c145b61008b5760405162461bcd60e51b815260206004820152601060248201526f434841494e5f49445f4e4f545f46544d60801b604482015260640160405180910390fd5b6001600160a01b0393841660805291831660a05261ffff1660c0521660e052600080546001600160a01b03191633179055426101005261013f565b80516001600160a01b03811681146100dd57600080fd5b919050565b600080600080608085870312156100f857600080fd5b610101856100c6565b935061010f602086016100c6565b9250604085015161ffff8116811461012657600080fd5b9150610134606086016100c6565b905092959194509250565b60805160a05160c05160e05161010051610dcd6101b4600039600081816102d601526108c00152600081816101940152610352015260008181610245015261037c01526000818161027f015261059f01526000818161021e015281816104d70152818161078e015261094c0152610dcd6000f3fe608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a0eeb39a11610071578063a0eeb39a1461027a578063a408bb4c146102a1578063aaa8f2ef146102a9578063b8ea6281146102bc578063f905c15a146102d157600080fd5b80636bfd23a7146101fd57806385f2aef21461020657806389a3027114610219578063997a03b71461024057600080fd5b80634cdad506116100e95780634cdad506146101675780635e280f111461018f57806363b4eb8d146101ce57806368ecc6bc146101e15780636ac55083146101f457600080fd5b80621d35671461011a578063095cf5c61461012f578063221798ad1461014257806347db1a6a1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60045481565b6040519081526020015b60405180910390f35b61014b60035481565b61017a610175366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b6001546101b6906001600160a01b031681565b61012d6101ef366004610be5565b6106f3565b61014b60055481565b61014b60025481565b6000546101b6906001600160a01b031681565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6102677f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101b66102ca366004610c1a565b6014015190565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea2646970667358221220fcc08a51d0a33b24a91a401bba0a9c91bdb72b806b020a47a1060a734e9c381764736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a0eeb39a11610071578063a0eeb39a1461027a578063a408bb4c146102a1578063aaa8f2ef146102a9578063b8ea6281146102bc578063f905c15a146102d157600080fd5b80636bfd23a7146101fd57806385f2aef21461020657806389a3027114610219578063997a03b71461024057600080fd5b80634cdad506116100e95780634cdad506146101675780635e280f111461018f57806363b4eb8d146101ce57806368ecc6bc146101e15780636ac55083146101f457600080fd5b80621d35671461011a578063095cf5c61461012f578063221798ad1461014257806347db1a6a1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60045481565b6040519081526020015b60405180910390f35b61014b60035481565b61017a610175366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b6001546101b6906001600160a01b031681565b61012d6101ef366004610be5565b6106f3565b61014b60055481565b61014b60025481565b6000546101b6906001600160a01b031681565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6102677f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101b66102ca366004610c1a565b6014015190565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea2646970667358221220fcc08a51d0a33b24a91a401bba0a9c91bdb72b806b020a47a1060a734e9c381764736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/RewardsDistributor.json b/deployments/arbitrumGoerli/RewardsDistributor.json index 0fd5f67f..89708c15 100644 --- a/deployments/arbitrumGoerli/RewardsDistributor.json +++ b/deployments/arbitrumGoerli/RewardsDistributor.json @@ -1,5 +1,5 @@ { - "address": "0xf6CdA702C6Bd15d5C0A325CE8f9f88219fE5F445", + "address": "0x3B2233FA015D316fdf6e79373470AD59672Ed3BD", "abi": [ { "inputs": [ @@ -351,45 +351,45 @@ "type": "function" } ], - "transactionHash": "0x4f6fe37d5a57f4d8d07132c4c0f36f39be601dbc51d30e578cfba82b684a60ce", + "transactionHash": "0x9d4fd2cfacaeb19936c3000747a9d30a0be6a6b1764d1262f3c38cca4cc0cde6", "receipt": { "to": null, "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0xf6CdA702C6Bd15d5C0A325CE8f9f88219fE5F445", + "contractAddress": "0x3B2233FA015D316fdf6e79373470AD59672Ed3BD", "transactionIndex": 1, - "gasUsed": "16135585", - "logsBloom": "0x00000800000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000200000000000000000200000200000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000008000000000000000000000000020000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010008000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x65c28893c6e6b16729b2470a5e51f63b6b568597bb301d8e6896f6f2e3fdf808", - "transactionHash": "0x4f6fe37d5a57f4d8d07132c4c0f36f39be601dbc51d30e578cfba82b684a60ce", + "gasUsed": "29355647", + "logsBloom": "0x00000000000000000000000000000000000000000000100800000000000000000000000000000000000000000000000000000000000000000000000000200000001000000000500000000000000000000000000000200000000000000000000000000000008000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x5b24f00319d65e48ac2a06fac0b683d601d48c7d933fcd1eb3577bbe08bcd62f", + "transactionHash": "0x9d4fd2cfacaeb19936c3000747a9d30a0be6a6b1764d1262f3c38cca4cc0cde6", "logs": [ { "transactionIndex": 1, - "blockNumber": 4195022, - "transactionHash": "0x4f6fe37d5a57f4d8d07132c4c0f36f39be601dbc51d30e578cfba82b684a60ce", - "address": "0xe69b00A164047e7eB87B73971B0f340eEbFF9c81", + "blockNumber": 4263691, + "transactionHash": "0x9d4fd2cfacaeb19936c3000747a9d30a0be6a6b1764d1262f3c38cca4cc0cde6", + "address": "0x162404E6Cd4633656925b90EF67237F29D5cc85c", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000f6cda702c6bd15d5c0a325ce8f9f88219fe5f445", - "0x0000000000000000000000006b938ba22fb5520ffb5d14c9c4fef82a48761497" + "0x0000000000000000000000003b2233fa015d316fdf6e79373470ad59672ed3bd", + "0x000000000000000000000000cdaf5f01849fff0a9e36d768b2ae7354a98360c0" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "logIndex": 0, - "blockHash": "0x65c28893c6e6b16729b2470a5e51f63b6b568597bb301d8e6896f6f2e3fdf808" + "blockHash": "0x5b24f00319d65e48ac2a06fac0b683d601d48c7d933fcd1eb3577bbe08bcd62f" } ], - "blockNumber": 4195022, - "cumulativeGasUsed": "16135585", + "blockNumber": 4263691, + "cumulativeGasUsed": "29355647", "status": 1, "byzantium": true }, "args": [ - "0x6b938BA22FB5520fFB5D14c9C4Fef82a48761497" + "0xCDAF5f01849Fff0a9E36D768B2ae7354A98360c0" ], - "numDeployments": 4, - "solcInputHash": "0faaa79d8b79020b765ba7705413c447", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voting_escrow\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"time\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"CheckpointToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"claim_epoch\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"max_epoch\",\"type\":\"uint256\"}],\"name\":\"Claimed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"checkpoint_token\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint_total_supply\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"_tokenIds\",\"type\":\"uint256[]\"}],\"name\":\"claim_many\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_token_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"}],\"name\":\"setDepositor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"start_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"time_cursor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"time_cursor_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token_last_balance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"tokens_per_week\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_epoch_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"ve_for_at\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ve_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voting_escrow\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RewardsDistributor.sol\":\"RewardsDistributor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/*\\n\\n@title Curve Fee Distribution modified for ve(3,3) emissions\\n@author Curve Finance, andrecronje\\n@license MIT\\n\\n*/\\n\\ncontract RewardsDistributor is IRewardsDistributor {\\n event CheckpointToken(uint256 time, uint256 tokens);\\n\\n event Claimed(\\n uint256 tokenId,\\n uint256 amount,\\n uint256 claim_epoch,\\n uint256 max_epoch\\n );\\n\\n uint256 constant WEEK = 7 * 86400;\\n\\n uint256 public start_time;\\n uint256 public time_cursor;\\n mapping(uint256 => uint256) public time_cursor_of;\\n mapping(uint256 => uint256) public user_epoch_of;\\n\\n uint256 public last_token_time;\\n uint256[1000000000000000] public tokens_per_week;\\n\\n address public voting_escrow;\\n address public token;\\n uint256 public token_last_balance;\\n\\n uint256[1000000000000000] public ve_supply;\\n\\n address public depositor;\\n\\n constructor(address _voting_escrow) {\\n uint256 _t = (block.timestamp / WEEK) * WEEK;\\n start_time = _t;\\n last_token_time = _t;\\n time_cursor = _t;\\n address _token = IVotingEscrow(_voting_escrow).token();\\n token = _token;\\n voting_escrow = _voting_escrow;\\n depositor = msg.sender;\\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\\n }\\n\\n function timestamp() external view returns (uint256) {\\n return (block.timestamp / WEEK) * WEEK;\\n }\\n\\n function _checkpoint_token() internal {\\n uint256 token_balance = IERC20(token).balanceOf(address(this));\\n uint256 to_distribute = token_balance - token_last_balance;\\n token_last_balance = token_balance;\\n\\n uint256 t = last_token_time;\\n uint256 since_last = block.timestamp - t;\\n last_token_time = block.timestamp;\\n uint256 this_week = (t / WEEK) * WEEK;\\n uint256 next_week = 0;\\n\\n for (uint256 i = 0; i < 20; i++) {\\n next_week = this_week + WEEK;\\n if (block.timestamp < next_week) {\\n if (since_last == 0 && block.timestamp == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (block.timestamp - t)) /\\n since_last;\\n }\\n break;\\n } else {\\n if (since_last == 0 && next_week == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (next_week - t)) /\\n since_last;\\n }\\n }\\n t = next_week;\\n this_week = next_week;\\n }\\n emit CheckpointToken(block.timestamp, to_distribute);\\n }\\n\\n function checkpoint_token() external {\\n assert(msg.sender == depositor);\\n _checkpoint_token();\\n }\\n\\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\\n internal\\n view\\n returns (uint256)\\n {\\n uint256 _min = 0;\\n uint256 _max = IVotingEscrow(ve).epoch();\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n _mid\\n );\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function _find_timestamp_user_epoch(\\n address ve,\\n uint256 tokenId,\\n uint256 _timestamp,\\n uint256 max_user_epoch\\n ) internal view returns (uint256) {\\n uint256 _min = 0;\\n uint256 _max = max_user_epoch;\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\\n .user_point_history(tokenId, _mid);\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\\n external\\n view\\n returns (uint256)\\n {\\n address ve = voting_escrow;\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _timestamp,\\n max_user_epoch\\n );\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n epoch\\n );\\n return\\n MathDunks.max(\\n uint256(\\n int256(\\n pt.bias -\\n pt.slope *\\n (int128(int256(_timestamp - pt.ts)))\\n )\\n ),\\n 0\\n );\\n }\\n\\n function _checkpoint_total_supply() internal {\\n address ve = voting_escrow;\\n uint256 t = time_cursor;\\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\\n IVotingEscrow(ve).checkpoint();\\n\\n for (uint256 i = 0; i < 20; i++) {\\n if (t > rounded_timestamp) {\\n break;\\n } else {\\n uint256 epoch = _find_timestamp_epoch(ve, t);\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n epoch\\n );\\n int128 dt = 0;\\n if (t > pt.ts) {\\n dt = int128(int256(t - pt.ts));\\n }\\n ve_supply[t] = MathDunks.max(\\n uint256(int256(pt.bias - pt.slope * dt)),\\n 0\\n );\\n }\\n t += WEEK;\\n }\\n time_cursor = t;\\n }\\n\\n function checkpoint_total_supply() external {\\n _checkpoint_total_supply();\\n }\\n\\n function _claim(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\\n user_epoch_of[_tokenId] = user_epoch;\\n time_cursor_of[_tokenId] = week_cursor;\\n\\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\\n\\n return to_distribute;\\n }\\n\\n function _claimable(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal view returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n return to_distribute;\\n }\\n\\n function claimable(uint256 _tokenId) external view returns (uint256) {\\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\\n return _claimable(_tokenId, voting_escrow, _last_token_time);\\n }\\n\\n function claim(uint256 _tokenId) external returns (uint256) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\\n token_last_balance -= amount;\\n }\\n return amount;\\n }\\n\\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n address _voting_escrow = voting_escrow;\\n uint256 total = 0;\\n\\n for (uint256 i = 0; i < _tokenIds.length; i++) {\\n uint256 _tokenId = _tokenIds[i];\\n if (_tokenId == 0) break;\\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\\n total += amount;\\n }\\n }\\n if (total != 0) {\\n token_last_balance -= total;\\n }\\n\\n return true;\\n }\\n\\n // Once off event on contract initialize\\n function setDepositor(address _depositor) external {\\n require(msg.sender == depositor);\\n depositor = _depositor;\\n }\\n}\\n\",\"keccak256\":\"0xdbcfb11d65c6ca7d63baba42fb2f1222478c6ca78d8e81970032eff5e034e09b\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b5060405162001b9f38038062001b9f83398101604081905262000034916200019f565b600062093a80620000468142620001d1565b620000529190620001f4565b90508060008190555080600481905550806001819055506000826001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000aa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d091906200019f565b66038d7ea4c6800680546001600160a01b038381166001600160a01b0319928316811790935566038d7ea4c6800580549188169183168217905566071afd498d00088054909216331790915560405163095ea7b360e01b8152600481019190915260001960248201529192509063095ea7b3906044016020604051808303816000875af115801562000166573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200018c919062000222565b6200019657600080fd5b50505062000246565b600060208284031215620001b257600080fd5b81516001600160a01b0381168114620001ca57600080fd5b9392505050565b600082620001ef57634e487b7160e01b600052601260045260246000fd5b500490565b60008160001904831182151516156200021d57634e487b7160e01b600052601160045260246000fd5b500290565b6000602082840312156200023557600080fd5b81518015158114620001ca57600080fd5b61194980620002566000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea2646970667358221220faa2ede3260adc0a11d81d56de5912df92f5289c5ac4e9b5ce7525019a4e773e64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea2646970667358221220faa2ede3260adc0a11d81d56de5912df92f5289c5ac4e9b5ce7525019a4e773e64736f6c634300080d0033", + "numDeployments": 7, + "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voting_escrow\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"time\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"CheckpointToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"claim_epoch\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"max_epoch\",\"type\":\"uint256\"}],\"name\":\"Claimed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"checkpoint_token\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint_total_supply\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"_tokenIds\",\"type\":\"uint256[]\"}],\"name\":\"claim_many\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_token_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"}],\"name\":\"setDepositor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"start_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"time_cursor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"time_cursor_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token_last_balance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"tokens_per_week\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_epoch_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"ve_for_at\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ve_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voting_escrow\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RewardsDistributor.sol\":\"RewardsDistributor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/*\\n\\n@title Curve Fee Distribution modified for ve(3,3) emissions\\n@author Curve Finance, andrecronje\\n@license MIT\\n\\n*/\\n\\ncontract RewardsDistributor is IRewardsDistributor {\\n event CheckpointToken(uint256 time, uint256 tokens);\\n\\n event Claimed(\\n uint256 tokenId,\\n uint256 amount,\\n uint256 claim_epoch,\\n uint256 max_epoch\\n );\\n\\n uint256 constant WEEK = 7 * 86400;\\n\\n uint256 public start_time;\\n uint256 public time_cursor;\\n mapping(uint256 => uint256) public time_cursor_of;\\n mapping(uint256 => uint256) public user_epoch_of;\\n\\n uint256 public last_token_time;\\n uint256[1000000000000000] public tokens_per_week;\\n\\n address public voting_escrow;\\n address public token;\\n uint256 public token_last_balance;\\n\\n uint256[1000000000000000] public ve_supply;\\n\\n address public depositor;\\n\\n constructor(address _voting_escrow) {\\n uint256 _t = (block.timestamp / WEEK) * WEEK;\\n start_time = _t;\\n last_token_time = _t;\\n time_cursor = _t;\\n address _token = IVotingEscrow(_voting_escrow).token();\\n token = _token;\\n voting_escrow = _voting_escrow;\\n depositor = msg.sender;\\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\\n }\\n\\n function timestamp() external view returns (uint256) {\\n return (block.timestamp / WEEK) * WEEK;\\n }\\n\\n function _checkpoint_token() internal {\\n uint256 token_balance = IERC20(token).balanceOf(address(this));\\n uint256 to_distribute = token_balance - token_last_balance;\\n token_last_balance = token_balance;\\n\\n uint256 t = last_token_time;\\n uint256 since_last = block.timestamp - t;\\n last_token_time = block.timestamp;\\n uint256 this_week = (t / WEEK) * WEEK;\\n uint256 next_week = 0;\\n\\n for (uint256 i = 0; i < 20; i++) {\\n next_week = this_week + WEEK;\\n if (block.timestamp < next_week) {\\n if (since_last == 0 && block.timestamp == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (block.timestamp - t)) /\\n since_last;\\n }\\n break;\\n } else {\\n if (since_last == 0 && next_week == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (next_week - t)) /\\n since_last;\\n }\\n }\\n t = next_week;\\n this_week = next_week;\\n }\\n emit CheckpointToken(block.timestamp, to_distribute);\\n }\\n\\n function checkpoint_token() external {\\n assert(msg.sender == depositor);\\n _checkpoint_token();\\n }\\n\\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\\n internal\\n view\\n returns (uint256)\\n {\\n uint256 _min = 0;\\n uint256 _max = IVotingEscrow(ve).epoch();\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n _mid\\n );\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function _find_timestamp_user_epoch(\\n address ve,\\n uint256 tokenId,\\n uint256 _timestamp,\\n uint256 max_user_epoch\\n ) internal view returns (uint256) {\\n uint256 _min = 0;\\n uint256 _max = max_user_epoch;\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\\n .user_point_history(tokenId, _mid);\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\\n external\\n view\\n returns (uint256)\\n {\\n address ve = voting_escrow;\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _timestamp,\\n max_user_epoch\\n );\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n epoch\\n );\\n return\\n MathDunks.max(\\n uint256(\\n int256(\\n pt.bias -\\n pt.slope *\\n (int128(int256(_timestamp - pt.ts)))\\n )\\n ),\\n 0\\n );\\n }\\n\\n function _checkpoint_total_supply() internal {\\n address ve = voting_escrow;\\n uint256 t = time_cursor;\\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\\n IVotingEscrow(ve).checkpoint();\\n\\n for (uint256 i = 0; i < 20; i++) {\\n if (t > rounded_timestamp) {\\n break;\\n } else {\\n uint256 epoch = _find_timestamp_epoch(ve, t);\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n epoch\\n );\\n int128 dt = 0;\\n if (t > pt.ts) {\\n dt = int128(int256(t - pt.ts));\\n }\\n ve_supply[t] = MathDunks.max(\\n uint256(int256(pt.bias - pt.slope * dt)),\\n 0\\n );\\n }\\n t += WEEK;\\n }\\n time_cursor = t;\\n }\\n\\n function checkpoint_total_supply() external {\\n _checkpoint_total_supply();\\n }\\n\\n function _claim(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\\n user_epoch_of[_tokenId] = user_epoch;\\n time_cursor_of[_tokenId] = week_cursor;\\n\\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\\n\\n return to_distribute;\\n }\\n\\n function _claimable(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal view returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n return to_distribute;\\n }\\n\\n function claimable(uint256 _tokenId) external view returns (uint256) {\\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\\n return _claimable(_tokenId, voting_escrow, _last_token_time);\\n }\\n\\n function claim(uint256 _tokenId) external returns (uint256) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\\n token_last_balance -= amount;\\n }\\n return amount;\\n }\\n\\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n address _voting_escrow = voting_escrow;\\n uint256 total = 0;\\n\\n for (uint256 i = 0; i < _tokenIds.length; i++) {\\n uint256 _tokenId = _tokenIds[i];\\n if (_tokenId == 0) break;\\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\\n total += amount;\\n }\\n }\\n if (total != 0) {\\n token_last_balance -= total;\\n }\\n\\n return true;\\n }\\n\\n // Once off event on contract initialize\\n function setDepositor(address _depositor) external {\\n require(msg.sender == depositor);\\n depositor = _depositor;\\n }\\n}\\n\",\"keccak256\":\"0xdbcfb11d65c6ca7d63baba42fb2f1222478c6ca78d8e81970032eff5e034e09b\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b5060405162001b9f38038062001b9f83398101604081905262000034916200019f565b600062093a80620000468142620001d1565b620000529190620001f4565b90508060008190555080600481905550806001819055506000826001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000aa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d091906200019f565b66038d7ea4c6800680546001600160a01b038381166001600160a01b0319928316811790935566038d7ea4c6800580549188169183168217905566071afd498d00088054909216331790915560405163095ea7b360e01b8152600481019190915260001960248201529192509063095ea7b3906044016020604051808303816000875af115801562000166573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200018c919062000222565b6200019657600080fd5b50505062000246565b600060208284031215620001b257600080fd5b81516001600160a01b0381168114620001ca57600080fd5b9392505050565b600082620001ef57634e487b7160e01b600052601260045260246000fd5b500490565b60008160001904831182151516156200021d57634e487b7160e01b600052601160045260246000fd5b500290565b6000602082840312156200023557600080fd5b81518015158114620001ca57600080fd5b61194980620002566000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea264697066735822122038f298ff421ca186346ca5ae24b719017aa28e10f5dd8ef97c7002e71e0bf94464736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea264697066735822122038f298ff421ca186346ca5ae24b719017aa28e10f5dd8ef97c7002e71e0bf94464736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/Router.json b/deployments/arbitrumGoerli/Router.json index fd18d25e..b7247e2d 100644 --- a/deployments/arbitrumGoerli/Router.json +++ b/deployments/arbitrumGoerli/Router.json @@ -1,5 +1,5 @@ { - "address": "0xCeaEA7A5cB3e7521DdE6717BCc99a4c8c60E07b6", + "address": "0x8562618F69ED7F313Ca699556Eb18A36FB2dB1e3", "abi": [ { "inputs": [ @@ -979,31 +979,31 @@ "type": "receive" } ], - "transactionHash": "0x941d082fc841e56456d6b4db26c1a309aa00922f4d13c3d7088172b13da20fab", + "transactionHash": "0x99fe8d1feb56c855fa474add22bb418a6d8d7921518c6536f4fbfee11a598e94", "receipt": { "to": null, "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0xCeaEA7A5cB3e7521DdE6717BCc99a4c8c60E07b6", + "contractAddress": "0x8562618F69ED7F313Ca699556Eb18A36FB2dB1e3", "transactionIndex": 1, - "gasUsed": "30613012", + "gasUsed": "55608083", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x7d9555496abbbd6cfec0e3f28a49f8101af207880f7e92cf05f18531291de64d", - "transactionHash": "0x941d082fc841e56456d6b4db26c1a309aa00922f4d13c3d7088172b13da20fab", + "blockHash": "0x49db2baff4b4114a9831368f9e4da8c4e602cb8c45a27cab2bacae0f6ec03d79", + "transactionHash": "0x99fe8d1feb56c855fa474add22bb418a6d8d7921518c6536f4fbfee11a598e94", "logs": [], - "blockNumber": 4195013, - "cumulativeGasUsed": "30613012", + "blockNumber": 4263676, + "cumulativeGasUsed": "55608083", "status": 1, "byzantium": true }, "args": [ - "0x7488AC81DC3908ff7141db4949e70D60A3Fd4DCc", + "0xcA698eA7f3A74b7D3D4229765dcF47F7A224859F", "0x4200000000000000000000000000000000000006" ], - "numDeployments": 5, - "solcInputHash": "0faaa79d8b79020b765ba7705413c447", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_weth\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"UNSAFE_swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"}],\"name\":\"getAmountsOut\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reserveA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"pairFor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"}],\"name\":\"quoteAddLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"name\":\"quoteRemoveLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityETHWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"}],\"name\":\"sortTokens\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactETHForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForETH\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenFrom\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenTo\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokensSimple\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weth\",\"outputs\":[{\"internalType\":\"contract IWETH\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Router.sol\":\"Router\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Router.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairFactory.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\nimport \\\"contracts/interfaces/IWETH.sol\\\";\\n\\ncontract Router is IRouter {\\n struct route {\\n address from;\\n address to;\\n bool stable;\\n }\\n\\n address public immutable factory;\\n IWETH public immutable weth;\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n bytes32 immutable pairCodeHash;\\n\\n modifier ensure(uint256 deadline) {\\n require(deadline >= block.timestamp, \\\"Router: EXPIRED\\\");\\n _;\\n }\\n\\n constructor(address _factory, address _weth) {\\n factory = _factory;\\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\\n weth = IWETH(_weth);\\n }\\n\\n receive() external payable {\\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\\n }\\n\\n function sortTokens(address tokenA, address tokenB)\\n public\\n pure\\n returns (address token0, address token1)\\n {\\n require(tokenA != tokenB, \\\"Router: IDENTICAL_ADDRESSES\\\");\\n (token0, token1) = tokenA < tokenB\\n ? (tokenA, tokenB)\\n : (tokenB, tokenA);\\n require(token0 != address(0), \\\"Router: ZERO_ADDRESS\\\");\\n }\\n\\n // calculates the CREATE2 address for a pair without making any external calls\\n function pairFor(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (address pair) {\\n (address token0, address token1) = sortTokens(tokenA, tokenB);\\n pair = address(\\n uint160(\\n uint256(\\n keccak256(\\n abi.encodePacked(\\n hex\\\"ff\\\",\\n factory,\\n keccak256(abi.encodePacked(token0, token1, stable)),\\n pairCodeHash // init code hash\\n )\\n )\\n )\\n )\\n );\\n }\\n\\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\\n function quoteLiquidity(\\n uint256 amountA,\\n uint256 reserveA,\\n uint256 reserveB\\n ) internal pure returns (uint256 amountB) {\\n require(amountA > 0, \\\"Router: INSUFFICIENT_AMOUNT\\\");\\n require(reserveA > 0 && reserveB > 0, \\\"Router: INSUFFICIENT_LIQUIDITY\\\");\\n amountB = (amountA * reserveB) / reserveA;\\n }\\n\\n // fetches and sorts the reserves for a pair\\n function getReserves(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (uint256 reserveA, uint256 reserveB) {\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (uint256 reserve0, uint256 reserve1, ) = IPair(\\n pairFor(tokenA, tokenB, stable)\\n ).getReserves();\\n (reserveA, reserveB) = tokenA == token0\\n ? (reserve0, reserve1)\\n : (reserve1, reserve0);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n address tokenOut\\n ) external view returns (uint256 amount, bool stable) {\\n address pair = pairFor(tokenIn, tokenOut, true);\\n uint256 amountStable;\\n uint256 amountVolatile;\\n if (IPairFactory(factory).isPair(pair)) {\\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n pair = pairFor(tokenIn, tokenOut, false);\\n if (IPairFactory(factory).isPair(pair)) {\\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n return\\n amountStable > amountVolatile\\n ? (amountStable, true)\\n : (amountVolatile, false);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountsOut(uint256 amountIn, route[] memory routes)\\n public\\n view\\n returns (uint256[] memory amounts)\\n {\\n require(routes.length >= 1, \\\"Router: INVALID_PATH\\\");\\n amounts = new uint256[](routes.length + 1);\\n amounts[0] = amountIn;\\n for (uint256 i = 0; i < routes.length; i++) {\\n address pair = pairFor(\\n routes[i].from,\\n routes[i].to,\\n routes[i].stable\\n );\\n if (IPairFactory(factory).isPair(pair)) {\\n amounts[i + 1] = IPair(pair).getAmountOut(\\n amounts[i],\\n routes[i].from\\n );\\n }\\n }\\n }\\n\\n function isPair(address pair) external view returns (bool) {\\n return IPairFactory(factory).isPair(pair);\\n }\\n\\n function quoteAddLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired\\n )\\n external\\n view\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n (uint256 reserveA, uint256 reserveB) = (0, 0);\\n uint256 _totalSupply = 0;\\n if (_pair != address(0)) {\\n _totalSupply = IERC20(_pair).totalSupply();\\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\\n }\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n }\\n }\\n }\\n\\n function quoteRemoveLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity\\n ) external view returns (uint256 amountA, uint256 amountB) {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n\\n if (_pair == address(0)) {\\n return (0, 0);\\n }\\n\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n uint256 _totalSupply = IERC20(_pair).totalSupply();\\n\\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\\n }\\n\\n function _addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin\\n ) internal returns (uint256 amountA, uint256 amountB) {\\n require(amountADesired >= amountAMin);\\n require(amountBDesired >= amountBMin);\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n if (_pair == address(0)) {\\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\\n }\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n require(\\n amountBOptimal >= amountBMin,\\n \\\"Router: INSUFFICIENT_B_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n assert(amountAOptimal <= amountADesired);\\n require(\\n amountAOptimal >= amountAMin,\\n \\\"Router: INSUFFICIENT_A_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n }\\n }\\n }\\n\\n function addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n ensure(deadline)\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n (amountA, amountB) = _addLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n amountADesired,\\n amountBDesired,\\n amountAMin,\\n amountBMin\\n );\\n address pair = pairFor(tokenA, tokenB, stable);\\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\\n liquidity = IPair(pair).mint(to);\\n }\\n\\n function addLiquidityETH(\\n address token,\\n bool stable,\\n uint256 amountTokenDesired,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n payable\\n ensure(deadline)\\n returns (\\n uint256 amountToken,\\n uint256 amountETH,\\n uint256 liquidity\\n )\\n {\\n (amountToken, amountETH) = _addLiquidity(\\n token,\\n address(weth),\\n stable,\\n amountTokenDesired,\\n msg.value,\\n amountTokenMin,\\n amountETHMin\\n );\\n address pair = pairFor(token, address(weth), stable);\\n _safeTransferFrom(token, msg.sender, pair, amountToken);\\n weth.deposit{value: amountETH}();\\n assert(weth.transfer(pair, amountETH));\\n liquidity = IPair(pair).mint(to);\\n // refund dust eth, if any\\n if (msg.value > amountETH)\\n _safeTransferETH(msg.sender, msg.value - amountETH);\\n }\\n\\n // **** REMOVE LIQUIDITY ****\\n function removeLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (amountA, amountB) = tokenA == token0\\n ? (amount0, amount1)\\n : (amount1, amount0);\\n require(amountA >= amountAMin, \\\"Router: INSUFFICIENT_A_AMOUNT\\\");\\n require(amountB >= amountBMin, \\\"Router: INSUFFICIENT_B_AMOUNT\\\");\\n }\\n\\n function removeLiquidityETH(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\\n (amountToken, amountETH) = removeLiquidity(\\n token,\\n address(weth),\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n address(this),\\n deadline\\n );\\n _safeTransfer(token, to, amountToken);\\n weth.withdraw(amountETH);\\n _safeTransferETH(to, amountETH);\\n }\\n\\n function removeLiquidityWithPermit(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n {\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(\\n msg.sender,\\n address(this),\\n value,\\n deadline,\\n v,\\n r,\\n s\\n );\\n }\\n\\n (amountA, amountB) = removeLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n liquidity,\\n amountAMin,\\n amountBMin,\\n to,\\n deadline\\n );\\n }\\n\\n function removeLiquidityETHWithPermit(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountToken, uint256 amountETH) {\\n address pair = pairFor(token, address(weth), stable);\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\\n (amountToken, amountETH) = removeLiquidityETH(\\n token,\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n to,\\n deadline\\n );\\n }\\n\\n // **** SWAP ****\\n // requires the initial amount to have already been sent to the first pair\\n function _swap(\\n uint256[] memory amounts,\\n route[] memory routes,\\n address _to\\n ) internal virtual {\\n for (uint256 i = 0; i < routes.length; i++) {\\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\\n uint256 amountOut = amounts[i + 1];\\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\\n ? (uint256(0), amountOut)\\n : (amountOut, uint256(0));\\n address to = i < routes.length - 1\\n ? pairFor(\\n routes[i + 1].from,\\n routes[i + 1].to,\\n routes[i + 1].stable\\n )\\n : _to;\\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\\n amount0Out,\\n amount1Out,\\n to,\\n new bytes(0)\\n );\\n }\\n }\\n\\n function swapExactTokensForTokensSimple(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n address tokenFrom,\\n address tokenTo,\\n bool stable,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n route[] memory routes = new route[](1);\\n routes[0].from = tokenFrom;\\n routes[0].to = tokenTo;\\n routes[0].stable = stable;\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForTokens(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactETHForTokens(\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\\n require(routes[0].from == address(weth), \\\"Router: INVALID_PATH\\\");\\n amounts = getAmountsOut(msg.value, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n weth.deposit{value: amounts[0]}();\\n assert(\\n weth.transfer(\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n )\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForETH(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n require(\\n routes[routes.length - 1].to == address(weth),\\n \\\"Router: INVALID_PATH\\\"\\n );\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, address(this));\\n weth.withdraw(amounts[amounts.length - 1]);\\n _safeTransferETH(to, amounts[amounts.length - 1]);\\n }\\n\\n function UNSAFE_swapExactTokensForTokens(\\n uint256[] memory amounts,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory) {\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n return amounts;\\n }\\n\\n function _safeTransferETH(address to, uint256 value) internal {\\n (bool success, ) = to.call{value: value}(new bytes(0));\\n require(success, \\\"TransferHelper: ETH_TRANSFER_FAILED\\\");\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x3d84c846129d645eec66c37a493bb7fb401a2524497f450eaced155088305ead\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"},\"contracts/interfaces/IWETH.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n function transfer(address to, uint256 value) external returns (bool);\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0x20ad0b3a319a36e3430f0d8512ee3755de8f85a80effe78d06f333f5326ee3d7\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x60e06040523480156200001157600080fd5b50604051620039bc380380620039bc8339810160408190526200003491620000d8565b6001600160a01b038216608081905260408051631355724960e31b81529051639aab9248916004808201926020929091908290030181865afa1580156200007f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000a5919062000110565b60c0526001600160a01b031660a052506200012a565b80516001600160a01b0381168114620000d357600080fd5b919050565b60008060408385031215620000ec57600080fd5b620000f783620000bb565b91506200010760208401620000bb565b90509250929050565b6000602082840312156200012357600080fd5b5051919050565b60805160a05160c0516137c8620001f46000396000610ef901526000818161013e0152818161020b0152818161091901528181610b5801528181610da901528181611470015281816115830152818161161101528181611de901528181611e1f01528181611e5401528181611ee901528181612028015261207801526000818161042d01528181610c3e01528181610ebe015281816111770152818161128b0152818161199601528181611b0a01528181612115015281816126ff01526127a001526137c86000f3fe60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea264697066735822122061c9ed8dec3ddb93963ec08aa04769e1e1c77f8f8cb927af407b5c9994f2ad8d64736f6c634300080d0033", - "deployedBytecode": "0x60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea264697066735822122061c9ed8dec3ddb93963ec08aa04769e1e1c77f8f8cb927af407b5c9994f2ad8d64736f6c634300080d0033", + "numDeployments": 8, + "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_weth\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"UNSAFE_swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"}],\"name\":\"getAmountsOut\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reserveA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"pairFor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"}],\"name\":\"quoteAddLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"name\":\"quoteRemoveLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityETHWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"}],\"name\":\"sortTokens\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactETHForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForETH\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenFrom\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenTo\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokensSimple\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weth\",\"outputs\":[{\"internalType\":\"contract IWETH\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Router.sol\":\"Router\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Router.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairFactory.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\nimport \\\"contracts/interfaces/IWETH.sol\\\";\\n\\ncontract Router is IRouter {\\n struct route {\\n address from;\\n address to;\\n bool stable;\\n }\\n\\n address public immutable factory;\\n IWETH public immutable weth;\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n bytes32 immutable pairCodeHash;\\n\\n modifier ensure(uint256 deadline) {\\n require(deadline >= block.timestamp, \\\"Router: EXPIRED\\\");\\n _;\\n }\\n\\n constructor(address _factory, address _weth) {\\n factory = _factory;\\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\\n weth = IWETH(_weth);\\n }\\n\\n receive() external payable {\\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\\n }\\n\\n function sortTokens(address tokenA, address tokenB)\\n public\\n pure\\n returns (address token0, address token1)\\n {\\n require(tokenA != tokenB, \\\"Router: IDENTICAL_ADDRESSES\\\");\\n (token0, token1) = tokenA < tokenB\\n ? (tokenA, tokenB)\\n : (tokenB, tokenA);\\n require(token0 != address(0), \\\"Router: ZERO_ADDRESS\\\");\\n }\\n\\n // calculates the CREATE2 address for a pair without making any external calls\\n function pairFor(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (address pair) {\\n (address token0, address token1) = sortTokens(tokenA, tokenB);\\n pair = address(\\n uint160(\\n uint256(\\n keccak256(\\n abi.encodePacked(\\n hex\\\"ff\\\",\\n factory,\\n keccak256(abi.encodePacked(token0, token1, stable)),\\n pairCodeHash // init code hash\\n )\\n )\\n )\\n )\\n );\\n }\\n\\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\\n function quoteLiquidity(\\n uint256 amountA,\\n uint256 reserveA,\\n uint256 reserveB\\n ) internal pure returns (uint256 amountB) {\\n require(amountA > 0, \\\"Router: INSUFFICIENT_AMOUNT\\\");\\n require(reserveA > 0 && reserveB > 0, \\\"Router: INSUFFICIENT_LIQUIDITY\\\");\\n amountB = (amountA * reserveB) / reserveA;\\n }\\n\\n // fetches and sorts the reserves for a pair\\n function getReserves(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (uint256 reserveA, uint256 reserveB) {\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (uint256 reserve0, uint256 reserve1, ) = IPair(\\n pairFor(tokenA, tokenB, stable)\\n ).getReserves();\\n (reserveA, reserveB) = tokenA == token0\\n ? (reserve0, reserve1)\\n : (reserve1, reserve0);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n address tokenOut\\n ) external view returns (uint256 amount, bool stable) {\\n address pair = pairFor(tokenIn, tokenOut, true);\\n uint256 amountStable;\\n uint256 amountVolatile;\\n if (IPairFactory(factory).isPair(pair)) {\\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n pair = pairFor(tokenIn, tokenOut, false);\\n if (IPairFactory(factory).isPair(pair)) {\\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n return\\n amountStable > amountVolatile\\n ? (amountStable, true)\\n : (amountVolatile, false);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountsOut(uint256 amountIn, route[] memory routes)\\n public\\n view\\n returns (uint256[] memory amounts)\\n {\\n require(routes.length >= 1, \\\"Router: INVALID_PATH\\\");\\n amounts = new uint256[](routes.length + 1);\\n amounts[0] = amountIn;\\n for (uint256 i = 0; i < routes.length; i++) {\\n address pair = pairFor(\\n routes[i].from,\\n routes[i].to,\\n routes[i].stable\\n );\\n if (IPairFactory(factory).isPair(pair)) {\\n amounts[i + 1] = IPair(pair).getAmountOut(\\n amounts[i],\\n routes[i].from\\n );\\n }\\n }\\n }\\n\\n function isPair(address pair) external view returns (bool) {\\n return IPairFactory(factory).isPair(pair);\\n }\\n\\n function quoteAddLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired\\n )\\n external\\n view\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n (uint256 reserveA, uint256 reserveB) = (0, 0);\\n uint256 _totalSupply = 0;\\n if (_pair != address(0)) {\\n _totalSupply = IERC20(_pair).totalSupply();\\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\\n }\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n }\\n }\\n }\\n\\n function quoteRemoveLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity\\n ) external view returns (uint256 amountA, uint256 amountB) {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n\\n if (_pair == address(0)) {\\n return (0, 0);\\n }\\n\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n uint256 _totalSupply = IERC20(_pair).totalSupply();\\n\\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\\n }\\n\\n function _addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin\\n ) internal returns (uint256 amountA, uint256 amountB) {\\n require(amountADesired >= amountAMin);\\n require(amountBDesired >= amountBMin);\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n if (_pair == address(0)) {\\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\\n }\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n require(\\n amountBOptimal >= amountBMin,\\n \\\"Router: INSUFFICIENT_B_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n assert(amountAOptimal <= amountADesired);\\n require(\\n amountAOptimal >= amountAMin,\\n \\\"Router: INSUFFICIENT_A_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n }\\n }\\n }\\n\\n function addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n ensure(deadline)\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n (amountA, amountB) = _addLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n amountADesired,\\n amountBDesired,\\n amountAMin,\\n amountBMin\\n );\\n address pair = pairFor(tokenA, tokenB, stable);\\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\\n liquidity = IPair(pair).mint(to);\\n }\\n\\n function addLiquidityETH(\\n address token,\\n bool stable,\\n uint256 amountTokenDesired,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n payable\\n ensure(deadline)\\n returns (\\n uint256 amountToken,\\n uint256 amountETH,\\n uint256 liquidity\\n )\\n {\\n (amountToken, amountETH) = _addLiquidity(\\n token,\\n address(weth),\\n stable,\\n amountTokenDesired,\\n msg.value,\\n amountTokenMin,\\n amountETHMin\\n );\\n address pair = pairFor(token, address(weth), stable);\\n _safeTransferFrom(token, msg.sender, pair, amountToken);\\n weth.deposit{value: amountETH}();\\n assert(weth.transfer(pair, amountETH));\\n liquidity = IPair(pair).mint(to);\\n // refund dust eth, if any\\n if (msg.value > amountETH)\\n _safeTransferETH(msg.sender, msg.value - amountETH);\\n }\\n\\n // **** REMOVE LIQUIDITY ****\\n function removeLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (amountA, amountB) = tokenA == token0\\n ? (amount0, amount1)\\n : (amount1, amount0);\\n require(amountA >= amountAMin, \\\"Router: INSUFFICIENT_A_AMOUNT\\\");\\n require(amountB >= amountBMin, \\\"Router: INSUFFICIENT_B_AMOUNT\\\");\\n }\\n\\n function removeLiquidityETH(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\\n (amountToken, amountETH) = removeLiquidity(\\n token,\\n address(weth),\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n address(this),\\n deadline\\n );\\n _safeTransfer(token, to, amountToken);\\n weth.withdraw(amountETH);\\n _safeTransferETH(to, amountETH);\\n }\\n\\n function removeLiquidityWithPermit(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n {\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(\\n msg.sender,\\n address(this),\\n value,\\n deadline,\\n v,\\n r,\\n s\\n );\\n }\\n\\n (amountA, amountB) = removeLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n liquidity,\\n amountAMin,\\n amountBMin,\\n to,\\n deadline\\n );\\n }\\n\\n function removeLiquidityETHWithPermit(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountToken, uint256 amountETH) {\\n address pair = pairFor(token, address(weth), stable);\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\\n (amountToken, amountETH) = removeLiquidityETH(\\n token,\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n to,\\n deadline\\n );\\n }\\n\\n // **** SWAP ****\\n // requires the initial amount to have already been sent to the first pair\\n function _swap(\\n uint256[] memory amounts,\\n route[] memory routes,\\n address _to\\n ) internal virtual {\\n for (uint256 i = 0; i < routes.length; i++) {\\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\\n uint256 amountOut = amounts[i + 1];\\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\\n ? (uint256(0), amountOut)\\n : (amountOut, uint256(0));\\n address to = i < routes.length - 1\\n ? pairFor(\\n routes[i + 1].from,\\n routes[i + 1].to,\\n routes[i + 1].stable\\n )\\n : _to;\\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\\n amount0Out,\\n amount1Out,\\n to,\\n new bytes(0)\\n );\\n }\\n }\\n\\n function swapExactTokensForTokensSimple(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n address tokenFrom,\\n address tokenTo,\\n bool stable,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n route[] memory routes = new route[](1);\\n routes[0].from = tokenFrom;\\n routes[0].to = tokenTo;\\n routes[0].stable = stable;\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForTokens(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactETHForTokens(\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\\n require(routes[0].from == address(weth), \\\"Router: INVALID_PATH\\\");\\n amounts = getAmountsOut(msg.value, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n weth.deposit{value: amounts[0]}();\\n assert(\\n weth.transfer(\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n )\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForETH(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n require(\\n routes[routes.length - 1].to == address(weth),\\n \\\"Router: INVALID_PATH\\\"\\n );\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, address(this));\\n weth.withdraw(amounts[amounts.length - 1]);\\n _safeTransferETH(to, amounts[amounts.length - 1]);\\n }\\n\\n function UNSAFE_swapExactTokensForTokens(\\n uint256[] memory amounts,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory) {\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n return amounts;\\n }\\n\\n function _safeTransferETH(address to, uint256 value) internal {\\n (bool success, ) = to.call{value: value}(new bytes(0));\\n require(success, \\\"TransferHelper: ETH_TRANSFER_FAILED\\\");\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x3d84c846129d645eec66c37a493bb7fb401a2524497f450eaced155088305ead\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"},\"contracts/interfaces/IWETH.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n function transfer(address to, uint256 value) external returns (bool);\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0x20ad0b3a319a36e3430f0d8512ee3755de8f85a80effe78d06f333f5326ee3d7\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x60e06040523480156200001157600080fd5b50604051620039bc380380620039bc8339810160408190526200003491620000d8565b6001600160a01b038216608081905260408051631355724960e31b81529051639aab9248916004808201926020929091908290030181865afa1580156200007f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000a5919062000110565b60c0526001600160a01b031660a052506200012a565b80516001600160a01b0381168114620000d357600080fd5b919050565b60008060408385031215620000ec57600080fd5b620000f783620000bb565b91506200010760208401620000bb565b90509250929050565b6000602082840312156200012357600080fd5b5051919050565b60805160a05160c0516137c8620001f46000396000610ef901526000818161013e0152818161020b0152818161091901528181610b5801528181610da901528181611470015281816115830152818161161101528181611de901528181611e1f01528181611e5401528181611ee901528181612028015261207801526000818161042d01528181610c3e01528181610ebe015281816111770152818161128b0152818161199601528181611b0a01528181612115015281816126ff01526127a001526137c86000f3fe60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea26469706673582212201f35e2970aea09da0502317678d6baed4a758797d319082c046f53f0070c23e364736f6c634300080d0033", + "deployedBytecode": "0x60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea26469706673582212201f35e2970aea09da0502317678d6baed4a758797d319082c046f53f0070c23e364736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/VeArtProxy.json b/deployments/arbitrumGoerli/VeArtProxy.json index fba3ebf5..5e031367 100644 --- a/deployments/arbitrumGoerli/VeArtProxy.json +++ b/deployments/arbitrumGoerli/VeArtProxy.json @@ -1,5 +1,5 @@ { - "address": "0x5e7569D02214289490d16bCE4F96B38071db1aD8", + "address": "0xB143E062f93E7d4F9f7B2b7127861c72Fb2ADF82", "abi": [ { "inputs": [ @@ -36,28 +36,28 @@ "type": "function" } ], - "transactionHash": "0x64c172576980de0bc037dc48f1a0336c76d244b0f6615e48b1473165127ad5af", + "transactionHash": "0xcf453a376d54dcf123c4b44a29b8dae43b316dc7862d73fe10dc42322937d6dd", "receipt": { "to": null, "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0x5e7569D02214289490d16bCE4F96B38071db1aD8", + "contractAddress": "0xB143E062f93E7d4F9f7B2b7127861c72Fb2ADF82", "transactionIndex": 1, - "gasUsed": "8226871", + "gasUsed": "15137628", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x365257e039acdb508014dcef6f26eea346febbf1dc77fb83da1df099ec229869", - "transactionHash": "0x64c172576980de0bc037dc48f1a0336c76d244b0f6615e48b1473165127ad5af", + "blockHash": "0x56b817b010cc0513d7646de82ba80ad09b54d0577b89aca1a9158ea606f948df", + "transactionHash": "0xcf453a376d54dcf123c4b44a29b8dae43b316dc7862d73fe10dc42322937d6dd", "logs": [], - "blockNumber": 4195017, - "cumulativeGasUsed": "8226871", + "blockNumber": 4263688, + "cumulativeGasUsed": "15137628", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 4, - "solcInputHash": "0faaa79d8b79020b765ba7705413c447", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_locked_end\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"_tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"output\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VeArtProxy.sol\":\"VeArtProxy\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\nimport {Base64} from \\\"contracts/libraries/Base64.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\n\\ncontract VeArtProxy is IVeArtProxy {\\n function toString(uint value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT license\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint temp = value;\\n uint digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\\n output = '';\\n output = string(abi.encodePacked(output, \\\"token \\\", toString(_tokenId), ''));\\n output = string(abi.encodePacked(output, \\\"balanceOf \\\", toString(_balanceOf), ''));\\n output = string(abi.encodePacked(output, \\\"locked_end \\\", toString(_locked_end), ''));\\n output = string(abi.encodePacked(output, \\\"value \\\", toString(_value), ''));\\n\\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\\\"name\\\": \\\"lock #', toString(_tokenId), '\\\", \\\"description\\\": \\\"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\\\", \\\"image\\\": \\\"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\\\"}'))));\\n output = string(abi.encodePacked('data:application/json;base64,', json));\\n }\\n}\\n\",\"keccak256\":\"0x8757d8095922dcad7af8c6820415049fd7d5af61a5580719210e5e91a31d80b1\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/libraries/Base64.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n/// [MIT License]\\n/// @title Base64\\n/// @notice Provides a function for encoding some bytes in base64\\n/// @author Brecht Devos \\nlibrary Base64 {\\n bytes internal constant TABLE = \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\";\\n\\n /// @notice Encodes some bytes to the base64 representation\\n function encode(bytes memory data) internal pure returns (string memory) {\\n uint len = data.length;\\n if (len == 0) return \\\"\\\";\\n\\n // multiply by 4/3 rounded up\\n uint encodedLen = 4 * ((len + 2) / 3);\\n\\n // Add some extra buffer at the end\\n bytes memory result = new bytes(encodedLen + 32);\\n\\n bytes memory table = TABLE;\\n\\n assembly {\\n let tablePtr := add(table, 1)\\n let resultPtr := add(result, 32)\\n\\n for {\\n let i := 0\\n } lt(i, len) {\\n\\n } {\\n i := add(i, 3)\\n let input := and(mload(add(data, i)), 0xffffff)\\n\\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\\n out := shl(224, out)\\n\\n mstore(resultPtr, out)\\n\\n resultPtr := add(resultPtr, 4)\\n }\\n\\n switch mod(len, 3)\\n case 1 {\\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\\n }\\n case 2 {\\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\\n }\\n\\n mstore(result, encodedLen)\\n }\\n\\n return string(result);\\n }\\n}\\n\",\"keccak256\":\"0x55535e1e0a14bbac370fe5f25df23aa88c678b915af53517672130f9a54f7e3e\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50610a2b806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f64726f6d65206c6f636010918401918201527f6b732c2063616e206265207573656420746f20626f6f7374206761756765207960308201527f69656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c206160508201527f6e64207265636569766520627269626573222c2022696d616765223a2022646160708201527f74613a696d6167652f7376672b786d6c3b6261736536342c0000000000000000609082015283516107718160a8840160208801610435565b61227d60f01b60a8929091019182015260aa01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220abfc8dcf4be5f263f1c7db4795f195a980c77a740eaa4ece8d9746af53e2be4364736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f64726f6d65206c6f636010918401918201527f6b732c2063616e206265207573656420746f20626f6f7374206761756765207960308201527f69656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c206160508201527f6e64207265636569766520627269626573222c2022696d616765223a2022646160708201527f74613a696d6167652f7376672b786d6c3b6261736536342c0000000000000000609082015283516107718160a8840160208801610435565b61227d60f01b60a8929091019182015260aa01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220abfc8dcf4be5f263f1c7db4795f195a980c77a740eaa4ece8d9746af53e2be4364736f6c634300080d0033", + "numDeployments": 7, + "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_locked_end\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"_tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"output\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VeArtProxy.sol\":\"VeArtProxy\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\nimport {Base64} from \\\"contracts/libraries/Base64.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\n\\ncontract VeArtProxy is IVeArtProxy {\\n function toString(uint value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT license\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint temp = value;\\n uint digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\\n output = '';\\n output = string(abi.encodePacked(output, \\\"token \\\", toString(_tokenId), ''));\\n output = string(abi.encodePacked(output, \\\"balanceOf \\\", toString(_balanceOf), ''));\\n output = string(abi.encodePacked(output, \\\"locked_end \\\", toString(_locked_end), ''));\\n output = string(abi.encodePacked(output, \\\"value \\\", toString(_value), ''));\\n\\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\\\"name\\\": \\\"lock #', toString(_tokenId), '\\\", \\\"description\\\": \\\"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\\\", \\\"image\\\": \\\"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\\\"}'))));\\n output = string(abi.encodePacked('data:application/json;base64,', json));\\n }\\n}\\n\",\"keccak256\":\"0x8757d8095922dcad7af8c6820415049fd7d5af61a5580719210e5e91a31d80b1\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/libraries/Base64.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n/// [MIT License]\\n/// @title Base64\\n/// @notice Provides a function for encoding some bytes in base64\\n/// @author Brecht Devos \\nlibrary Base64 {\\n bytes internal constant TABLE = \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\";\\n\\n /// @notice Encodes some bytes to the base64 representation\\n function encode(bytes memory data) internal pure returns (string memory) {\\n uint len = data.length;\\n if (len == 0) return \\\"\\\";\\n\\n // multiply by 4/3 rounded up\\n uint encodedLen = 4 * ((len + 2) / 3);\\n\\n // Add some extra buffer at the end\\n bytes memory result = new bytes(encodedLen + 32);\\n\\n bytes memory table = TABLE;\\n\\n assembly {\\n let tablePtr := add(table, 1)\\n let resultPtr := add(result, 32)\\n\\n for {\\n let i := 0\\n } lt(i, len) {\\n\\n } {\\n i := add(i, 3)\\n let input := and(mload(add(data, i)), 0xffffff)\\n\\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\\n out := shl(224, out)\\n\\n mstore(resultPtr, out)\\n\\n resultPtr := add(resultPtr, 4)\\n }\\n\\n switch mod(len, 3)\\n case 1 {\\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\\n }\\n case 2 {\\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\\n }\\n\\n mstore(result, encodedLen)\\n }\\n\\n return string(result);\\n }\\n}\\n\",\"keccak256\":\"0x55535e1e0a14bbac370fe5f25df23aa88c678b915af53517672130f9a54f7e3e\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610a2b806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f64726f6d65206c6f636010918401918201527f6b732c2063616e206265207573656420746f20626f6f7374206761756765207960308201527f69656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c206160508201527f6e64207265636569766520627269626573222c2022696d616765223a2022646160708201527f74613a696d6167652f7376672b786d6c3b6261736536342c0000000000000000609082015283516107718160a8840160208801610435565b61227d60f01b60a8929091019182015260aa01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212201586b6c87e32cb6d7584ee4fc014e36ccdf48dd4c8e3b693a3631810e74f917364736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f64726f6d65206c6f636010918401918201527f6b732c2063616e206265207573656420746f20626f6f7374206761756765207960308201527f69656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c206160508201527f6e64207265636569766520627269626573222c2022696d616765223a2022646160708201527f74613a696d6167652f7376672b786d6c3b6261736536342c0000000000000000609082015283516107718160a8840160208801610435565b61227d60f01b60a8929091019182015260aa01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212201586b6c87e32cb6d7584ee4fc014e36ccdf48dd4c8e3b693a3631810e74f917364736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/Velo.json b/deployments/arbitrumGoerli/Velo.json index 5c3cb706..c40f44af 100644 --- a/deployments/arbitrumGoerli/Velo.json +++ b/deployments/arbitrumGoerli/Velo.json @@ -1,5 +1,5 @@ { - "address": "0xe69b00A164047e7eB87B73971B0f340eEbFF9c81", + "address": "0x162404E6Cd4633656925b90EF67237F29D5cc85c", "abi": [ { "inputs": [], @@ -381,22 +381,22 @@ "type": "function" } ], - "transactionHash": "0x8c100b2c979d9c2518478168d49380e5049bc8ec1f04f58b7217ff7b85ea8447", + "transactionHash": "0xc4fe1ef3bd2c9531ba9f3fe41ca788f79076df1241d1838f586067f566752ef6", "receipt": { "to": null, "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0xe69b00A164047e7eB87B73971B0f340eEbFF9c81", + "contractAddress": "0x162404E6Cd4633656925b90EF67237F29D5cc85c", "transactionIndex": 1, - "gasUsed": "6812425", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000200000000000000000000000000000000000000000000008000000000000000000000000000040000000000000000000020000000000000000000800000000000000000000000010000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000400000000000000000000000000020000000008000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x060d1f20218f44cc143168d1501b1f1bb70b22e8076c71027ca17b9f26c30420", - "transactionHash": "0x8c100b2c979d9c2518478168d49380e5049bc8ec1f04f58b7217ff7b85ea8447", + "gasUsed": "12494147", + "logsBloom": "0x00000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000400000000008000000000000000000000000000040000000000000000000020000000000000000000800000000000000000000000010000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000400000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x030240c8f3f6499c33f4c32c669372151316fddca42d0d9f7abdf5567802923d", + "transactionHash": "0xc4fe1ef3bd2c9531ba9f3fe41ca788f79076df1241d1838f586067f566752ef6", "logs": [ { "transactionIndex": 1, - "blockNumber": 4195003, - "transactionHash": "0x8c100b2c979d9c2518478168d49380e5049bc8ec1f04f58b7217ff7b85ea8447", - "address": "0xe69b00A164047e7eB87B73971B0f340eEbFF9c81", + "blockNumber": 4263666, + "transactionHash": "0xc4fe1ef3bd2c9531ba9f3fe41ca788f79076df1241d1838f586067f566752ef6", + "address": "0x162404E6Cd4633656925b90EF67237F29D5cc85c", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x0000000000000000000000000000000000000000000000000000000000000000", @@ -404,20 +404,20 @@ ], "data": "0x0000000000000000000000000000000000000000000000000000000000000000", "logIndex": 0, - "blockHash": "0x060d1f20218f44cc143168d1501b1f1bb70b22e8076c71027ca17b9f26c30420" + "blockHash": "0x030240c8f3f6499c33f4c32c669372151316fddca42d0d9f7abdf5567802923d" } ], - "blockNumber": 4195003, - "cumulativeGasUsed": "6812425", + "blockNumber": 4263666, + "cumulativeGasUsed": "12494147", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 5, - "solcInputHash": "0faaa79d8b79020b765ba7705413c447", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"initialMint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialMinted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleClaim\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redemptionReceiver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_merkleClaim\",\"type\":\"address\"}],\"name\":\"setMerkleClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"setMinter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_receiver\",\"type\":\"address\"}],\"name\":\"setRedemptionReceiver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Velo.sol\":\"Velo\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Velo.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IVelo.sol\\\";\\n\\ncontract Velo is IVelo {\\n\\n string public constant name = \\\"Velodrome\\\";\\n string public constant symbol = \\\"VELO\\\";\\n uint8 public constant decimals = 18;\\n uint public totalSupply = 0;\\n\\n mapping(address => uint) public balanceOf;\\n mapping(address => mapping(address => uint)) public allowance;\\n\\n bool public initialMinted;\\n address public minter;\\n address public redemptionReceiver;\\n address public merkleClaim;\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n\\n constructor() {\\n minter = msg.sender;\\n _mint(msg.sender, 0);\\n }\\n\\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\\n function setMinter(address _minter) external {\\n require(msg.sender == minter);\\n minter = _minter;\\n }\\n\\n function setRedemptionReceiver(address _receiver) external {\\n require(msg.sender == minter);\\n redemptionReceiver = _receiver;\\n }\\n\\n function setMerkleClaim(address _merkleClaim) external {\\n require(msg.sender == minter);\\n merkleClaim = _merkleClaim;\\n }\\n\\n // Initial mint: total 82M\\n // 4M for \\\"Genesis\\\" pools\\n // 30M for liquid team allocation (40M excl init veNFT)\\n // 48M for future partners\\n function initialMint(address _recipient) external {\\n require(msg.sender == minter && !initialMinted);\\n initialMinted = true;\\n _mint(_recipient, 82 * 1e6 * 1e18);\\n }\\n\\n function approve(address _spender, uint _value) external returns (bool) {\\n allowance[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n function _mint(address _to, uint _amount) internal returns (bool) {\\n totalSupply += _amount;\\n unchecked {\\n balanceOf[_to] += _amount;\\n }\\n emit Transfer(address(0x0), _to, _amount);\\n return true;\\n }\\n\\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\\n balanceOf[_from] -= _value;\\n unchecked {\\n balanceOf[_to] += _value;\\n }\\n emit Transfer(_from, _to, _value);\\n return true;\\n }\\n\\n function transfer(address _to, uint _value) external returns (bool) {\\n return _transfer(msg.sender, _to, _value);\\n }\\n\\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\\n uint allowed_from = allowance[_from][msg.sender];\\n if (allowed_from != type(uint).max) {\\n allowance[_from][msg.sender] -= _value;\\n }\\n return _transfer(_from, _to, _value);\\n }\\n\\n function mint(address account, uint amount) external returns (bool) {\\n require(msg.sender == minter);\\n _mint(account, amount);\\n return true;\\n }\\n\\n function claim(address account, uint amount) external returns (bool) {\\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\\n _mint(account, amount);\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xb5231de79b43d576febc9d6a0ebee8c4f251ec109869ce7a3e0afc2a185d0246\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"}},\"version\":1}", - "bytecode": "0x60806040526000805534801561001457600080fd5b5060038054610100600160a81b0319163361010081029190911790915561003c906000610042565b506100d9565b60008160008082825461005591906100b3565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a350600192915050565b600082198211156100d457634e487b7160e01b600052601160045260246000fd5b500190565b61082c806100e86000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ac578063dd62ed3e146102bf578063e752c44a146102ea578063ec676a25146102fd578063fca3b5aa1461031057600080fd5b806395d89b4114610241578063a9059cbb14610264578063aad3ec9614610277578063c268f9ba1461028a578063ca1c4de91461029f57600080fd5b806323b872dd116100f457806323b872dd146101ce578063313ce567146101e157806340c10f19146101fb5780635e05fe501461020e57806370a082311461022157600080fd5b806306fdde03146101265780630754617214610164578063095ea7b31461019457806318160ddd146101b7575b600080fd5b61014e6040518060400160405280600981526020016856656c6f64726f6d6560b81b81525081565b60405161015b919061068c565b60405180910390f35b60035461017c9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015b565b6101a76101a23660046106fd565b610323565b604051901515815260200161015b565b6101c060005481565b60405190815260200161015b565b6101a76101dc366004610727565b61038f565b6101e9601281565b60405160ff909116815260200161015b565b6101a76102093660046106fd565b610409565b60045461017c906001600160a01b031681565b6101c061022f366004610763565b60016020526000908152604090205481565b61014e6040518060400160405280600481526020016356454c4f60e01b81525081565b6101a76102723660046106fd565b61043c565b6101a76102853660046106fd565b610450565b61029d610298366004610763565b61047f565b005b6003546101a79060ff1681565b61029d6102ba366004610763565b6104d0565b6101c06102cd36600461077e565b600260209081526000928352604080842090915290825290205481565b60055461017c906001600160a01b031681565b61029d61030b366004610763565b61050e565b61029d61031e366004610763565b61054c565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259061037e9086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f5576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103ef9084906107c7565b90915550505b610400858585610590565b95945050505050565b60035460009061010090046001600160a01b0316331461042857600080fd5b6104328383610627565b5060019392505050565b6000610449338484610590565b9392505050565b6004546000906001600160a01b031633148061047657506005546001600160a01b031633145b61042857600080fd5b60035461010090046001600160a01b0316331480156104a1575060035460ff16155b6104aa57600080fd5b6003805460ff191660011790556104cc816a43d42ce83da41d92000000610627565b5050565b60035461010090046001600160a01b031633146104ec57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052a57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056857600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105ba9084906107c7565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106159086815260200190565b60405180910390a35060019392505050565b60008160008082825461063a91906107de565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910161037e565b600060208083528351808285015260005b818110156106b95785810183015185820160400152820161069d565b818111156106cb576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106f857600080fd5b919050565b6000806040838503121561071057600080fd5b610719836106e1565b946020939093013593505050565b60008060006060848603121561073c57600080fd5b610745846106e1565b9250610753602085016106e1565b9150604084013590509250925092565b60006020828403121561077557600080fd5b610449826106e1565b6000806040838503121561079157600080fd5b61079a836106e1565b91506107a8602084016106e1565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107d9576107d96107b1565b500390565b600082198211156107f1576107f16107b1565b50019056fea2646970667358221220bebc3a2234b72bd2fd84b02793c989f9dfae6f8feb95470b1dc74a79df11e23a64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ac578063dd62ed3e146102bf578063e752c44a146102ea578063ec676a25146102fd578063fca3b5aa1461031057600080fd5b806395d89b4114610241578063a9059cbb14610264578063aad3ec9614610277578063c268f9ba1461028a578063ca1c4de91461029f57600080fd5b806323b872dd116100f457806323b872dd146101ce578063313ce567146101e157806340c10f19146101fb5780635e05fe501461020e57806370a082311461022157600080fd5b806306fdde03146101265780630754617214610164578063095ea7b31461019457806318160ddd146101b7575b600080fd5b61014e6040518060400160405280600981526020016856656c6f64726f6d6560b81b81525081565b60405161015b919061068c565b60405180910390f35b60035461017c9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015b565b6101a76101a23660046106fd565b610323565b604051901515815260200161015b565b6101c060005481565b60405190815260200161015b565b6101a76101dc366004610727565b61038f565b6101e9601281565b60405160ff909116815260200161015b565b6101a76102093660046106fd565b610409565b60045461017c906001600160a01b031681565b6101c061022f366004610763565b60016020526000908152604090205481565b61014e6040518060400160405280600481526020016356454c4f60e01b81525081565b6101a76102723660046106fd565b61043c565b6101a76102853660046106fd565b610450565b61029d610298366004610763565b61047f565b005b6003546101a79060ff1681565b61029d6102ba366004610763565b6104d0565b6101c06102cd36600461077e565b600260209081526000928352604080842090915290825290205481565b60055461017c906001600160a01b031681565b61029d61030b366004610763565b61050e565b61029d61031e366004610763565b61054c565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259061037e9086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f5576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103ef9084906107c7565b90915550505b610400858585610590565b95945050505050565b60035460009061010090046001600160a01b0316331461042857600080fd5b6104328383610627565b5060019392505050565b6000610449338484610590565b9392505050565b6004546000906001600160a01b031633148061047657506005546001600160a01b031633145b61042857600080fd5b60035461010090046001600160a01b0316331480156104a1575060035460ff16155b6104aa57600080fd5b6003805460ff191660011790556104cc816a43d42ce83da41d92000000610627565b5050565b60035461010090046001600160a01b031633146104ec57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052a57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056857600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105ba9084906107c7565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106159086815260200190565b60405180910390a35060019392505050565b60008160008082825461063a91906107de565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910161037e565b600060208083528351808285015260005b818110156106b95785810183015185820160400152820161069d565b818111156106cb576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106f857600080fd5b919050565b6000806040838503121561071057600080fd5b610719836106e1565b946020939093013593505050565b60008060006060848603121561073c57600080fd5b610745846106e1565b9250610753602085016106e1565b9150604084013590509250925092565b60006020828403121561077557600080fd5b610449826106e1565b6000806040838503121561079157600080fd5b61079a836106e1565b91506107a8602084016106e1565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107d9576107d96107b1565b500390565b600082198211156107f1576107f16107b1565b50019056fea2646970667358221220bebc3a2234b72bd2fd84b02793c989f9dfae6f8feb95470b1dc74a79df11e23a64736f6c634300080d0033", + "numDeployments": 8, + "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"initialMint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialMinted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleClaim\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redemptionReceiver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_merkleClaim\",\"type\":\"address\"}],\"name\":\"setMerkleClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"setMinter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_receiver\",\"type\":\"address\"}],\"name\":\"setRedemptionReceiver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Velo.sol\":\"Velo\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Velo.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IVelo.sol\\\";\\n\\ncontract Velo is IVelo {\\n\\n string public constant name = \\\"Velodrome\\\";\\n string public constant symbol = \\\"VELO\\\";\\n uint8 public constant decimals = 18;\\n uint public totalSupply = 0;\\n\\n mapping(address => uint) public balanceOf;\\n mapping(address => mapping(address => uint)) public allowance;\\n\\n bool public initialMinted;\\n address public minter;\\n address public redemptionReceiver;\\n address public merkleClaim;\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n\\n constructor() {\\n minter = msg.sender;\\n _mint(msg.sender, 0);\\n }\\n\\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\\n function setMinter(address _minter) external {\\n require(msg.sender == minter);\\n minter = _minter;\\n }\\n\\n function setRedemptionReceiver(address _receiver) external {\\n require(msg.sender == minter);\\n redemptionReceiver = _receiver;\\n }\\n\\n function setMerkleClaim(address _merkleClaim) external {\\n require(msg.sender == minter);\\n merkleClaim = _merkleClaim;\\n }\\n\\n // Initial mint: total 82M\\n // 4M for \\\"Genesis\\\" pools\\n // 30M for liquid team allocation (40M excl init veNFT)\\n // 48M for future partners\\n function initialMint(address _recipient) external {\\n require(msg.sender == minter && !initialMinted);\\n initialMinted = true;\\n _mint(_recipient, 82 * 1e6 * 1e18);\\n }\\n\\n function approve(address _spender, uint _value) external returns (bool) {\\n allowance[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n function _mint(address _to, uint _amount) internal returns (bool) {\\n totalSupply += _amount;\\n unchecked {\\n balanceOf[_to] += _amount;\\n }\\n emit Transfer(address(0x0), _to, _amount);\\n return true;\\n }\\n\\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\\n balanceOf[_from] -= _value;\\n unchecked {\\n balanceOf[_to] += _value;\\n }\\n emit Transfer(_from, _to, _value);\\n return true;\\n }\\n\\n function transfer(address _to, uint _value) external returns (bool) {\\n return _transfer(msg.sender, _to, _value);\\n }\\n\\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\\n uint allowed_from = allowance[_from][msg.sender];\\n if (allowed_from != type(uint).max) {\\n allowance[_from][msg.sender] -= _value;\\n }\\n return _transfer(_from, _to, _value);\\n }\\n\\n function mint(address account, uint amount) external returns (bool) {\\n require(msg.sender == minter);\\n _mint(account, amount);\\n return true;\\n }\\n\\n function claim(address account, uint amount) external returns (bool) {\\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\\n _mint(account, amount);\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xb5231de79b43d576febc9d6a0ebee8c4f251ec109869ce7a3e0afc2a185d0246\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"}},\"version\":1}", + "bytecode": "0x60806040526000805534801561001457600080fd5b5060038054610100600160a81b0319163361010081029190911790915561003c906000610042565b506100d9565b60008160008082825461005591906100b3565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a350600192915050565b600082198211156100d457634e487b7160e01b600052601160045260246000fd5b500190565b61082c806100e86000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ac578063dd62ed3e146102bf578063e752c44a146102ea578063ec676a25146102fd578063fca3b5aa1461031057600080fd5b806395d89b4114610241578063a9059cbb14610264578063aad3ec9614610277578063c268f9ba1461028a578063ca1c4de91461029f57600080fd5b806323b872dd116100f457806323b872dd146101ce578063313ce567146101e157806340c10f19146101fb5780635e05fe501461020e57806370a082311461022157600080fd5b806306fdde03146101265780630754617214610164578063095ea7b31461019457806318160ddd146101b7575b600080fd5b61014e6040518060400160405280600981526020016856656c6f64726f6d6560b81b81525081565b60405161015b919061068c565b60405180910390f35b60035461017c9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015b565b6101a76101a23660046106fd565b610323565b604051901515815260200161015b565b6101c060005481565b60405190815260200161015b565b6101a76101dc366004610727565b61038f565b6101e9601281565b60405160ff909116815260200161015b565b6101a76102093660046106fd565b610409565b60045461017c906001600160a01b031681565b6101c061022f366004610763565b60016020526000908152604090205481565b61014e6040518060400160405280600481526020016356454c4f60e01b81525081565b6101a76102723660046106fd565b61043c565b6101a76102853660046106fd565b610450565b61029d610298366004610763565b61047f565b005b6003546101a79060ff1681565b61029d6102ba366004610763565b6104d0565b6101c06102cd36600461077e565b600260209081526000928352604080842090915290825290205481565b60055461017c906001600160a01b031681565b61029d61030b366004610763565b61050e565b61029d61031e366004610763565b61054c565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259061037e9086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f5576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103ef9084906107c7565b90915550505b610400858585610590565b95945050505050565b60035460009061010090046001600160a01b0316331461042857600080fd5b6104328383610627565b5060019392505050565b6000610449338484610590565b9392505050565b6004546000906001600160a01b031633148061047657506005546001600160a01b031633145b61042857600080fd5b60035461010090046001600160a01b0316331480156104a1575060035460ff16155b6104aa57600080fd5b6003805460ff191660011790556104cc816a43d42ce83da41d92000000610627565b5050565b60035461010090046001600160a01b031633146104ec57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052a57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056857600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105ba9084906107c7565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106159086815260200190565b60405180910390a35060019392505050565b60008160008082825461063a91906107de565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910161037e565b600060208083528351808285015260005b818110156106b95785810183015185820160400152820161069d565b818111156106cb576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106f857600080fd5b919050565b6000806040838503121561071057600080fd5b610719836106e1565b946020939093013593505050565b60008060006060848603121561073c57600080fd5b610745846106e1565b9250610753602085016106e1565b9150604084013590509250925092565b60006020828403121561077557600080fd5b610449826106e1565b6000806040838503121561079157600080fd5b61079a836106e1565b91506107a8602084016106e1565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107d9576107d96107b1565b500390565b600082198211156107f1576107f16107b1565b50019056fea26469706673582212200ee48cb937aa2a18763edead8de90507d9439e6b529b100360b93838fc56165d64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ac578063dd62ed3e146102bf578063e752c44a146102ea578063ec676a25146102fd578063fca3b5aa1461031057600080fd5b806395d89b4114610241578063a9059cbb14610264578063aad3ec9614610277578063c268f9ba1461028a578063ca1c4de91461029f57600080fd5b806323b872dd116100f457806323b872dd146101ce578063313ce567146101e157806340c10f19146101fb5780635e05fe501461020e57806370a082311461022157600080fd5b806306fdde03146101265780630754617214610164578063095ea7b31461019457806318160ddd146101b7575b600080fd5b61014e6040518060400160405280600981526020016856656c6f64726f6d6560b81b81525081565b60405161015b919061068c565b60405180910390f35b60035461017c9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015b565b6101a76101a23660046106fd565b610323565b604051901515815260200161015b565b6101c060005481565b60405190815260200161015b565b6101a76101dc366004610727565b61038f565b6101e9601281565b60405160ff909116815260200161015b565b6101a76102093660046106fd565b610409565b60045461017c906001600160a01b031681565b6101c061022f366004610763565b60016020526000908152604090205481565b61014e6040518060400160405280600481526020016356454c4f60e01b81525081565b6101a76102723660046106fd565b61043c565b6101a76102853660046106fd565b610450565b61029d610298366004610763565b61047f565b005b6003546101a79060ff1681565b61029d6102ba366004610763565b6104d0565b6101c06102cd36600461077e565b600260209081526000928352604080842090915290825290205481565b60055461017c906001600160a01b031681565b61029d61030b366004610763565b61050e565b61029d61031e366004610763565b61054c565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259061037e9086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f5576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103ef9084906107c7565b90915550505b610400858585610590565b95945050505050565b60035460009061010090046001600160a01b0316331461042857600080fd5b6104328383610627565b5060019392505050565b6000610449338484610590565b9392505050565b6004546000906001600160a01b031633148061047657506005546001600160a01b031633145b61042857600080fd5b60035461010090046001600160a01b0316331480156104a1575060035460ff16155b6104aa57600080fd5b6003805460ff191660011790556104cc816a43d42ce83da41d92000000610627565b5050565b60035461010090046001600160a01b031633146104ec57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052a57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056857600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105ba9084906107c7565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106159086815260200190565b60405180910390a35060019392505050565b60008160008082825461063a91906107de565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910161037e565b600060208083528351808285015260005b818110156106b95785810183015185820160400152820161069d565b818111156106cb576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106f857600080fd5b919050565b6000806040838503121561071057600080fd5b610719836106e1565b946020939093013593505050565b60008060006060848603121561073c57600080fd5b610745846106e1565b9250610753602085016106e1565b9150604084013590509250925092565b60006020828403121561077557600080fd5b610449826106e1565b6000806040838503121561079157600080fd5b61079a836106e1565b91506107a8602084016106e1565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107d9576107d96107b1565b500390565b600082198211156107f1576107f16107b1565b50019056fea26469706673582212200ee48cb937aa2a18763edead8de90507d9439e6b529b100360b93838fc56165d64736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/VeloGovernor.json b/deployments/arbitrumGoerli/VeloGovernor.json index 8cacd3f8..c5cc4e9f 100644 --- a/deployments/arbitrumGoerli/VeloGovernor.json +++ b/deployments/arbitrumGoerli/VeloGovernor.json @@ -1,5 +1,5 @@ { - "address": "0x588ADD83f24690BceEbaa4266cd8DC65709DDa4d", + "address": "0xF2bf0557E4b13bFA4c256F59a026A2F95b238479", "abi": [ { "inputs": [ @@ -1055,43 +1055,43 @@ "type": "receive" } ], - "transactionHash": "0xc18cb1e92e23ab919bfab4ca664330e7c363affcd02e6ae98747baf66adecbac", + "transactionHash": "0xbea3b33607b7287abef3796a8010ceca6d11f688a78720b3c9f1cf8810ffc12d", "receipt": { "to": null, "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0x588ADD83f24690BceEbaa4266cd8DC65709DDa4d", + "contractAddress": "0xF2bf0557E4b13bFA4c256F59a026A2F95b238479", "transactionIndex": 1, - "gasUsed": "30055138", - "logsBloom": "0x00000000000000000100000000001000000800000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x7526fdc29a3710d3feed1075b4a5fb9e8833a49264dc170bde90e11923fe7b8f", - "transactionHash": "0xc18cb1e92e23ab919bfab4ca664330e7c363affcd02e6ae98747baf66adecbac", + "gasUsed": "57985095", + "logsBloom": "0x00000000000000000100000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x452398a6f23bab1a7b573f24801f0eac7b46f85af713e67de63e16fc3fdfe64f", + "transactionHash": "0xbea3b33607b7287abef3796a8010ceca6d11f688a78720b3c9f1cf8810ffc12d", "logs": [ { "transactionIndex": 1, - "blockNumber": 4195032, - "transactionHash": "0xc18cb1e92e23ab919bfab4ca664330e7c363affcd02e6ae98747baf66adecbac", - "address": "0x588ADD83f24690BceEbaa4266cd8DC65709DDa4d", + "blockNumber": 4263700, + "transactionHash": "0xbea3b33607b7287abef3796a8010ceca6d11f688a78720b3c9f1cf8810ffc12d", + "address": "0xF2bf0557E4b13bFA4c256F59a026A2F95b238479", "topics": [ "0x0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997" ], "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004", "logIndex": 0, - "blockHash": "0x7526fdc29a3710d3feed1075b4a5fb9e8833a49264dc170bde90e11923fe7b8f" + "blockHash": "0x452398a6f23bab1a7b573f24801f0eac7b46f85af713e67de63e16fc3fdfe64f" } ], - "blockNumber": 4195032, - "cumulativeGasUsed": "30055138", + "blockNumber": 4263700, + "cumulativeGasUsed": "57985095", "status": 1, "byzantium": true }, "args": [ - "0x6b938BA22FB5520fFB5D14c9C4Fef82a48761497" + "0xCDAF5f01849Fff0a9E36D768B2ae7354A98360c0" ], - "numDeployments": 3, - "solcInputHash": "0faaa79d8b79020b765ba7705413c447", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"_ve\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"Empty\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"proposer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"string[]\",\"name\":\"signatures\",\"type\":\"string[]\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"ProposalCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldQuorumNumerator\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"QuorumNumeratorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"VoteCast\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"VoteCastWithParams\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"COUNTING_MODE\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EXTENDED_BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_PROPOSAL_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROPOSAL_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"}],\"name\":\"castVote\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"castVoteWithReason\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"castVoteWithReasonAndParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteWithReasonAndParamsBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"execute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"getVotesWithParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasVoted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"hashProposal\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalDeadline\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalSnapshot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"againstVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"forVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"abstainVotes\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"propose\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"quorum\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumDenominator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"}],\"name\":\"setProposalNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTeam\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"state\",\"outputs\":[{\"internalType\":\"enum IGovernor.ProposalState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"updateQuorumNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"Empty()\":[{\"details\":\"An operation (e.g. {front}) couldn't be completed due to the queue being empty.\"}]},\"kind\":\"dev\",\"methods\":{\"COUNTING_MODE()\":{\"details\":\"See {IGovernor-COUNTING_MODE}.\"},\"castVote(uint256,uint8)\":{\"details\":\"See {IGovernor-castVote}.\"},\"castVoteBySig(uint256,uint8,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteBySig}.\"},\"castVoteWithReason(uint256,uint8,string)\":{\"details\":\"See {IGovernor-castVoteWithReason}.\"},\"castVoteWithReasonAndParams(uint256,uint8,string,bytes)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParams}.\"},\"castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParamsBySig}.\"},\"execute(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-execute}.\"},\"getVotes(address,uint256)\":{\"details\":\"See {IGovernor-getVotes}.\"},\"getVotesWithParams(address,uint256,bytes)\":{\"details\":\"See {IGovernor-getVotesWithParams}.\"},\"hasVoted(uint256,address)\":{\"details\":\"See {IGovernor-hasVoted}.\"},\"hashProposal(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-hashProposal}. The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in advance, before the proposal is submitted. Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the same proposal (with same operation and same description) will have the same id if submitted on multiple governors across multiple networks. This also means that in order to execute the same operation twice (on the same governor) the proposer will have to change the description in order to avoid proposal id conflicts.\"},\"name()\":{\"details\":\"See {IGovernor-name}.\"},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155BatchReceived}.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155Received}.\"},\"onERC721Received(address,address,uint256,bytes)\":{\"details\":\"See {IERC721Receiver-onERC721Received}.\"},\"proposalDeadline(uint256)\":{\"details\":\"See {IGovernor-proposalDeadline}.\"},\"proposalSnapshot(uint256)\":{\"details\":\"See {IGovernor-proposalSnapshot}.\"},\"proposalThreshold()\":{\"details\":\"Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\"},\"proposalVotes(uint256)\":{\"details\":\"Accessor to the internal vote counts.\"},\"propose(address[],uint256[],bytes[],string)\":{\"details\":\"See {IGovernor-propose}.\"},\"quorum(uint256)\":{\"details\":\"Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\"},\"quorumDenominator()\":{\"details\":\"Returns the quorum denominator. Defaults to 100, but may be overridden.\"},\"quorumNumerator()\":{\"details\":\"Returns the current quorum numerator. See {quorumDenominator}.\"},\"relay(address,uint256,bytes)\":{\"details\":\"Relays a transaction or function call to an arbitrary target. In cases where the governance executor is some contract other than the governor itself, like when using a timelock, this function can be invoked in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake. Note that if the executor is simply the governor itself, use of `relay` is redundant.\"},\"state(uint256)\":{\"details\":\"See {IGovernor-state}.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"updateQuorumNumerator(uint256)\":{\"details\":\"Changes the quorum numerator. Emits a {QuorumNumeratorUpdated} event. Requirements: - Must be called through a governance proposal. - New numerator must be smaller or equal to the denominator.\"},\"version()\":{\"details\":\"See {IGovernor-version}.\"},\"votingDelay()\":{\"details\":\"Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\"},\"votingPeriod()\":{\"details\":\"Delay, in number of blocks, between the vote start and vote ends. NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting duration compared to the voting delay.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"votingDelay()\":{\"notice\":\"module:user-config\"},\"votingPeriod()\":{\"notice\":\"module:user-config\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VeloGovernor.sol\":\"VeloGovernor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VeloGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IGovernor} from \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\nimport {L2GovernorCountingSimple} from \\\"contracts/governance/L2GovernorCountingSimple.sol\\\";\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\nimport {L2GovernorVotesQuorumFraction} from \\\"contracts/governance/L2GovernorVotesQuorumFraction.sol\\\";\\n\\ncontract VeloGovernor is\\n L2Governor,\\n L2GovernorCountingSimple,\\n L2GovernorVotes,\\n L2GovernorVotesQuorumFraction\\n{\\n address public team;\\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\\n uint256 public proposalNumerator = 2; // start at 0.02%\\n\\n constructor(IVotes _ve)\\n L2Governor(\\\"Velodrome Governor\\\")\\n L2GovernorVotes(_ve)\\n L2GovernorVotesQuorumFraction(4) // 4%\\n {\\n team = msg.sender;\\n }\\n\\n function votingDelay() public pure override(IGovernor) returns (uint256) {\\n return 15 minutes; // 1 block\\n }\\n\\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\\n return 1 weeks;\\n }\\n\\n function setTeam(address newTeam) external {\\n require(msg.sender == team, \\\"not team\\\");\\n team = newTeam;\\n }\\n\\n function setProposalNumerator(uint256 numerator) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \\\"numerator too high\\\");\\n proposalNumerator = numerator;\\n }\\n\\n function proposalThreshold()\\n public\\n view\\n override(L2Governor)\\n returns (uint256)\\n {\\n return\\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\\n PROPOSAL_DENOMINATOR;\\n }\\n}\\n\",\"keccak256\":\"0xbdbc34fd1c78fdffb528f7a2f450e75457cb089369204f4671ec241aa0eb3a7e\",\"license\":\"MIT\"},\"contracts/governance/L2Governor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Address.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Context.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\\n *\\n * @dev Core of the governance system, designed to be extended though various modules.\\n *\\n * This contract is abstract and requires several function to be implemented in various modules:\\n *\\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\\n * - A voting module must implement {_getVotes}\\n * - Additionanly, the {votingPeriod} must also be implemented\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\\n using SafeCast for uint256;\\n using Timers for Timers.Timestamp;\\n\\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\\\"Ballot(uint256 proposalId,uint8 support)\\\");\\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\\n keccak256(\\\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\\\");\\n\\n struct ProposalCore {\\n Timers.Timestamp voteStart;\\n Timers.Timestamp voteEnd;\\n bool executed;\\n bool canceled;\\n }\\n\\n string private _name;\\n\\n mapping(uint256 => ProposalCore) private _proposals;\\n\\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\\n\\n /**\\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\\n * parameter setters in {GovernorSettings} are protected using this modifier.\\n *\\n * The governance executing address may be different from the Governor's own address, for example it could be a\\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\\n * for example, additional timelock proposers are not able to change governance parameters without going through the\\n * governance protocol (since v4.6).\\n */\\n modifier onlyGovernance() {\\n require(_msgSender() == _executor(), \\\"Governor: onlyGovernance\\\");\\n if (_executor() != address(this)) {\\n bytes32 msgDataHash = keccak256(_msgData());\\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\\n while (_governanceCall.popFront() != msgDataHash) {}\\n }\\n _;\\n }\\n\\n /**\\n * @dev Sets the value for {name} and {version}\\n */\\n constructor(string memory name_) EIP712(name_, version()) {\\n _name = name_;\\n }\\n\\n /**\\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\\n */\\n receive() external payable virtual {\\n require(_executor() == address(this));\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\\n // include the castVoteWithReasonAndParams() function as standard\\n return\\n interfaceId ==\\n (type(IGovernor).interfaceId ^\\n this.castVoteWithReasonAndParams.selector ^\\n this.castVoteWithReasonAndParamsBySig.selector ^\\n this.getVotesWithParams.selector) ||\\n interfaceId == type(IGovernor).interfaceId ||\\n interfaceId == type(IERC1155Receiver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IGovernor-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IGovernor-version}.\\n */\\n function version() public view virtual override returns (string memory) {\\n return \\\"1\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hashProposal}.\\n *\\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\\n * advance, before the proposal is submitted.\\n *\\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual override returns (uint256) {\\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\\n }\\n\\n /**\\n * @dev See {IGovernor-state}.\\n */\\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n\\n if (proposal.executed) {\\n return ProposalState.Executed;\\n }\\n\\n if (proposal.canceled) {\\n return ProposalState.Canceled;\\n }\\n\\n uint256 start = proposalSnapshot(proposalId);\\n\\n if (start == 0) {\\n revert(\\\"Governor: unknown proposal id\\\");\\n }\\n\\n if (start >= block.timestamp) {\\n return ProposalState.Pending;\\n }\\n\\n uint256 deadline = proposalDeadline(proposalId);\\n\\n if (deadline >= block.timestamp) {\\n return ProposalState.Active;\\n }\\n\\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\\n return ProposalState.Succeeded;\\n } else {\\n return ProposalState.Defeated;\\n }\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalSnapshot}.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteStart.getDeadline();\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalDeadline}.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteEnd.getDeadline();\\n }\\n\\n /**\\n * @dev Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\\n */\\n function proposalThreshold() public view virtual returns (uint256) {\\n return 0;\\n }\\n\\n /**\\n * @dev Amount of votes already cast passes the threshold limit.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Is the proposal successful or not.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) internal view virtual returns (uint256);\\n\\n /**\\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\\n *\\n * Note: Support is generic and can represent various things depending on the voting system used.\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory params\\n ) internal virtual;\\n\\n /**\\n * @dev Default additional encoded parameters used by castVote methods that don't include them\\n *\\n * Note: Should be overridden by specific implementations to use an appropriate value, the\\n * meaning of the additional params, in the context of that implementation\\n */\\n function _defaultParams() internal view virtual returns (bytes memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-propose}.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual override returns (uint256) {\\n require(\\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\\n \\\"Governor: proposer votes below proposal threshold\\\"\\n );\\n\\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\\n\\n require(targets.length == values.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length == calldatas.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length > 0, \\\"Governor: empty proposal\\\");\\n\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(proposal.voteStart.isUnset(), \\\"Governor: proposal already exists\\\");\\n\\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\\n uint64 deadline = start + votingPeriod().toUint64();\\n\\n proposal.voteStart.setDeadline(start);\\n proposal.voteEnd.setDeadline(deadline);\\n\\n emit ProposalCreated(\\n proposalId,\\n _msgSender(),\\n targets,\\n values,\\n new string[](targets.length),\\n calldatas,\\n start,\\n deadline,\\n description\\n );\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-execute}.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual override returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n\\n ProposalState status = state(proposalId);\\n require(\\n status == ProposalState.Succeeded || status == ProposalState.Queued,\\n \\\"Governor: proposal not successful\\\"\\n );\\n _proposals[proposalId].executed = true;\\n\\n emit ProposalExecuted(proposalId);\\n\\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\\n _execute(proposalId, targets, values, calldatas, descriptionHash);\\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\\n */\\n function _execute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n string memory errorMessage = \\\"Governor: call reverted without message\\\";\\n for (uint256 i = 0; i < targets.length; ++i) {\\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\\n Address.verifyCallResult(success, returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Hook before execution is triggered.\\n */\\n function _beforeExecute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory, /* values */\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n for (uint256 i = 0; i < targets.length; ++i) {\\n if (targets[i] == address(this)) {\\n _governanceCall.pushBack(keccak256(calldatas[i]));\\n }\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook after execution is triggered.\\n */\\n function _afterExecute(\\n uint256, /* proposalId */\\n address[] memory, /* targets */\\n uint256[] memory, /* values */\\n bytes[] memory, /* calldatas */\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n if (!_governanceCall.empty()) {\\n _governanceCall.clear();\\n }\\n }\\n }\\n\\n /**\\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\\n * canceled to allow distinguishing it from executed proposals.\\n *\\n * Emits a {IGovernor-ProposalCanceled} event.\\n */\\n function _cancel(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) internal virtual returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n ProposalState status = state(proposalId);\\n\\n require(\\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\\n \\\"Governor: proposal not active\\\"\\n );\\n _proposals[proposalId].canceled = true;\\n\\n emit ProposalCanceled(proposalId);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotes}.\\n */\\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, _defaultParams());\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotesWithParams}.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVote}.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReason}.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteBySig}.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\\n v,\\n r,\\n s\\n );\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(\\n keccak256(\\n abi.encode(\\n EXTENDED_BALLOT_TYPEHASH,\\n proposalId,\\n support,\\n keccak256(bytes(reason)),\\n keccak256(params)\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason\\n ) internal virtual returns (uint256) {\\n return _castVote(proposalId, account, support, reason, _defaultParams());\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason,\\n bytes memory params\\n ) internal virtual returns (uint256) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(state(proposalId) == ProposalState.Active, \\\"Governor: vote not currently active\\\");\\n\\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\\n _countVote(proposalId, account, support, weight, params);\\n\\n if (params.length == 0) {\\n emit VoteCast(account, proposalId, support, weight, reason);\\n } else {\\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\\n }\\n\\n return weight;\\n }\\n\\n /**\\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\\n */\\n function relay(\\n address target,\\n uint256 value,\\n bytes calldata data\\n ) external virtual onlyGovernance {\\n Address.functionCallWithValue(target, data, value);\\n }\\n\\n /**\\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\\n * through another contract such as a timelock.\\n */\\n function _executor() internal view virtual returns (address) {\\n return address(this);\\n }\\n\\n /**\\n * @dev See {IERC721Receiver-onERC721Received}.\\n */\\n function onERC721Received(\\n address,\\n address,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155Received}.\\n */\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\\n */\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] memory,\\n uint256[] memory,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155BatchReceived.selector;\\n }\\n}\\n\",\"keccak256\":\"0xa2846313b89a871807cdebd0225b0bf8f23b17505ab8b3288549ec54a5a4a71b\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorCountingSimple.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\\n *\\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorCountingSimple is L2Governor {\\n /**\\n * @dev Supported vote types. Matches Governor Bravo ordering.\\n */\\n enum VoteType {\\n Against,\\n For,\\n Abstain\\n }\\n\\n struct ProposalVote {\\n uint256 againstVotes;\\n uint256 forVotes;\\n uint256 abstainVotes;\\n mapping(address => bool) hasVoted;\\n }\\n\\n mapping(uint256 => ProposalVote) private _proposalVotes;\\n\\n /**\\n * @dev See {IGovernor-COUNTING_MODE}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual override returns (string memory) {\\n return \\\"support=bravo&quorum=for,abstain\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hasVoted}.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\\n return _proposalVotes[proposalId].hasVoted[account];\\n }\\n\\n /**\\n * @dev Accessor to the internal vote counts.\\n */\\n function proposalVotes(uint256 proposalId)\\n public\\n view\\n virtual\\n returns (\\n uint256 againstVotes,\\n uint256 forVotes,\\n uint256 abstainVotes\\n )\\n {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\\n }\\n\\n /**\\n * @dev See {Governor-_quorumReached}.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return proposalvote.forVotes > proposalvote.againstVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory // params\\n ) internal virtual override {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n require(!proposalvote.hasVoted[account], \\\"GovernorVotingSimple: vote already cast\\\");\\n proposalvote.hasVoted[account] = true;\\n\\n if (support == uint8(VoteType.Against)) {\\n proposalvote.againstVotes += weight;\\n } else if (support == uint8(VoteType.For)) {\\n proposalvote.forVotes += weight;\\n } else if (support == uint8(VoteType.Abstain)) {\\n proposalvote.abstainVotes += weight;\\n } else {\\n revert(\\\"GovernorVotingSimple: invalid value for enum VoteType\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xdc37daa24118a6e6ba5208b4abefa1632af2ff340135ca6c6d7237f70102d5db\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotes is L2Governor {\\n IVotes public immutable token;\\n\\n constructor(IVotes tokenAddress) {\\n token = tokenAddress;\\n }\\n\\n /**\\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory /*params*/\\n ) internal view virtual override returns (uint256) {\\n return token.getPastVotes(account, blockTimestamp);\\n }\\n}\\n\",\"keccak256\":\"0x605a7de71228dda3cb8fd878cac313a86bc5841fd34d7344214346ba46e63af1\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotesQuorumFraction.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\\n * fraction of the total supply.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\\n uint256 private _quorumNumerator;\\n\\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\\n\\n /**\\n * @dev Initialize quorum as a fraction of the token's total supply.\\n *\\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\\n * customized by overriding {quorumDenominator}.\\n */\\n constructor(uint256 quorumNumeratorValue) {\\n _updateQuorumNumerator(quorumNumeratorValue);\\n }\\n\\n /**\\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\\n */\\n function quorumNumerator() public view virtual returns (uint256) {\\n return _quorumNumerator;\\n }\\n\\n /**\\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\\n */\\n function quorumDenominator() public view virtual returns (uint256) {\\n return 100;\\n }\\n\\n /**\\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\\n */\\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - Must be called through a governance proposal.\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\\n _updateQuorumNumerator(newQuorumNumerator);\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\\n require(\\n newQuorumNumerator <= quorumDenominator(),\\n \\\"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\\\"\\n );\\n\\n uint256 oldQuorumNumerator = _quorumNumerator;\\n _quorumNumerator = newQuorumNumerator;\\n\\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\\n }\\n}\\n\",\"keccak256\":\"0xe66d29c0ffd2274de933d80e11d68891f3acc3f078be4560a2b493b7d88dcb7f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Interface of the {Governor} core.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract IGovernor is IERC165 {\\n enum ProposalState {\\n Pending,\\n Active,\\n Canceled,\\n Defeated,\\n Succeeded,\\n Queued,\\n Expired,\\n Executed\\n }\\n\\n /**\\n * @dev Emitted when a proposal is created.\\n */\\n event ProposalCreated(\\n uint256 proposalId,\\n address proposer,\\n address[] targets,\\n uint256[] values,\\n string[] signatures,\\n bytes[] calldatas,\\n uint256 startBlock,\\n uint256 endBlock,\\n string description\\n );\\n\\n /**\\n * @dev Emitted when a proposal is canceled.\\n */\\n event ProposalCanceled(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a proposal is executed.\\n */\\n event ProposalExecuted(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a vote is cast without params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n */\\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\\n\\n /**\\n * @dev Emitted when a vote is cast with params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\\n */\\n event VoteCastWithParams(\\n address indexed voter,\\n uint256 proposalId,\\n uint8 support,\\n uint256 weight,\\n string reason,\\n bytes params\\n );\\n\\n /**\\n * @notice module:core\\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\\n */\\n function name() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \\\"1\\\"\\n */\\n function version() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:voting\\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\\n *\\n * There are 2 standard keys: `support` and `quorum`.\\n *\\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\\n * - `quorum=bravo` means that only For votes are counted towards quorum.\\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\\n *\\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\\n * name that describes the behavior. For example:\\n *\\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\\n *\\n * NOTE: The string can be decoded by the standard\\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\\n * JavaScript class.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Current state of a proposal, following Compound's convention\\n */\\n function state(uint256 proposalId) public view virtual returns (ProposalState);\\n\\n /**\\n * @notice module:core\\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\\n * beginning of the following block.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\\n * during this block.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\\n */\\n function votingDelay() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of blocks, between the vote start and vote ends.\\n *\\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\\n * duration compared to the voting delay.\\n */\\n function votingPeriod() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Minimum number of cast voted required for a proposal to be successful.\\n *\\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\\n */\\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber`.\\n *\\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\\n * multiple), {ERC20Votes} tokens.\\n */\\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockNumber,\\n bytes memory params\\n ) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:voting\\n * @dev Returns whether `account` has cast a vote on `proposalId`.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\\n\\n /**\\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\\n * {IGovernor-votingPeriod} blocks after the voting starts.\\n *\\n * Emits a {ProposalCreated} event.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\\n * deadline to be reached.\\n *\\n * Emits a {ProposalExecuted} event.\\n *\\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Cast a vote\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xa52d593ff06a2353f78fa149da31f2ca94f03d1eff99bde41977fa2fe985a92f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2e53602b96c1bf97c731ed3e2a981b4f85e23a9410a5ebd36e549a4cc93340dc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x2626d8ab3dfdad0fad630c212ad146d59473d0f48b771784c61a7c1dbbea1f3f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Tooling for timepoints, timers and delays\\n */\\nlibrary Timers {\\n struct Timestamp {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(Timestamp storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(Timestamp memory timer) internal view returns (bool) {\\n return timer._deadline > block.timestamp;\\n }\\n\\n function isExpired(Timestamp memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.timestamp;\\n }\\n\\n struct BlockNumber {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(BlockNumber storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(BlockNumber memory timer) internal view returns (bool) {\\n return timer._deadline > block.number;\\n }\\n\\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.number;\\n }\\n}\\n\",\"keccak256\":\"0x29791a62950a7983e02a673639c1a781d1e448691800456c2ce4b99715391b14\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS,\\n InvalidSignatureV // Deprecated in v4.8\\n }\\n\\n function _throwError(RecoverError error) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert(\\\"ECDSA: invalid signature\\\");\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert(\\\"ECDSA: invalid signature 's' value\\\");\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature` or error string. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\\n if (signature.length == 65) {\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n /// @solidity memory-safe-assembly\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n return tryRecover(hash, v, r, s);\\n } else {\\n return (address(0), RecoverError.InvalidSignatureLength);\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, signature);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n *\\n * _Available since v4.2._\\n */\\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature);\\n }\\n\\n return (signer, RecoverError.NoError);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from `s`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", Strings.toString(s.length), s));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Typed Data, created from a\\n * `domainSeparator` and a `structHash`. This produces hash corresponding\\n * to the one signed with the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\\n * JSON-RPC method as part of EIP-712.\\n *\\n * See {recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n }\\n}\\n\",\"keccak256\":\"0x54ee424bfc83ce63b2a918b9a1efb5090a0fb68dbd1de3b10bc667776885dd4f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ECDSA.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n /* solhint-disable var-name-mixedcase */\\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n // invalidate the cached domain separator if the chain id changes.\\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n uint256 private immutable _CACHED_CHAIN_ID;\\n address private immutable _CACHED_THIS;\\n\\n bytes32 private immutable _HASHED_NAME;\\n bytes32 private immutable _HASHED_VERSION;\\n bytes32 private immutable _TYPE_HASH;\\n\\n /* solhint-enable var-name-mixedcase */\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n constructor(string memory name, string memory version) {\\n bytes32 hashedName = keccak256(bytes(name));\\n bytes32 hashedVersion = keccak256(bytes(version));\\n bytes32 typeHash = keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n );\\n _HASHED_NAME = hashedName;\\n _HASHED_VERSION = hashedVersion;\\n _CACHED_CHAIN_ID = block.chainid;\\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n _CACHED_THIS = address(this);\\n _TYPE_HASH = typeHash;\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\\n return _CACHED_DOMAIN_SEPARATOR;\\n } else {\\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n }\\n }\\n\\n function _buildDomainSeparator(\\n bytes32 typeHash,\\n bytes32 nameHash,\\n bytes32 versionHash\\n ) private view returns (bytes32) {\\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\\n }\\n}\\n\",\"keccak256\":\"0x948d8b2d18f38141ec78c5229d770d950ebc781ed3f44cc9e3ccbb9fded5846a\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\\n\\nimport \\\"./EIP712.sol\\\";\\n\",\"keccak256\":\"0xea30c402170bc240354b74e6c6f6a8e5bdb1935d90d168cc58c0654461c6a72b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3546b156d97633f7f8cad536d5454c81d1d604687c02b2eb105fdc33cb962b41\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\\npragma solidity ^0.8.4;\\n\\nimport \\\"../math/SafeCast.sol\\\";\\n\\n/**\\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\\n * the existing queue contents are left in storage.\\n *\\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\\n * used in storage, and not in memory.\\n * ```\\n * DoubleEndedQueue.Bytes32Deque queue;\\n * ```\\n *\\n * _Available since v4.6._\\n */\\nlibrary DoubleEndedQueue {\\n /**\\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\\n */\\n error Empty();\\n\\n /**\\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\\n */\\n error OutOfBounds();\\n\\n /**\\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\\n *\\n * Struct members have an underscore prefix indicating that they are \\\"private\\\" and should not be read or written to\\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\\n * lead to unexpected behavior.\\n *\\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\\n * data[end - 1].\\n */\\n struct Bytes32Deque {\\n int128 _begin;\\n int128 _end;\\n mapping(int128 => bytes32) _data;\\n }\\n\\n /**\\n * @dev Inserts an item at the end of the queue.\\n */\\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 backIndex = deque._end;\\n deque._data[backIndex] = value;\\n unchecked {\\n deque._end = backIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Removes the item at the end of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n value = deque._data[backIndex];\\n delete deque._data[backIndex];\\n deque._end = backIndex;\\n }\\n\\n /**\\n * @dev Inserts an item at the beginning of the queue.\\n */\\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 frontIndex;\\n unchecked {\\n frontIndex = deque._begin - 1;\\n }\\n deque._data[frontIndex] = value;\\n deque._begin = frontIndex;\\n }\\n\\n /**\\n * @dev Removes the item at the beginning of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n value = deque._data[frontIndex];\\n delete deque._data[frontIndex];\\n unchecked {\\n deque._begin = frontIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Returns the item at the beginning of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n return deque._data[frontIndex];\\n }\\n\\n /**\\n * @dev Returns the item at the end of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n return deque._data[backIndex];\\n }\\n\\n /**\\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\\n * `length(deque) - 1`.\\n *\\n * Reverts with `OutOfBounds` if the index is out of bounds.\\n */\\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\\n // int256(deque._begin) is a safe upcast\\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\\n if (idx >= deque._end) revert OutOfBounds();\\n return deque._data[idx];\\n }\\n\\n /**\\n * @dev Resets the queue back to being empty.\\n *\\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\\n * out on potential gas refunds.\\n */\\n function clear(Bytes32Deque storage deque) internal {\\n deque._begin = 0;\\n deque._end = 0;\\n }\\n\\n /**\\n * @dev Returns the number of items in the queue.\\n */\\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\\n // We also assume there are at most int256.max items in the queue.\\n unchecked {\\n return uint256(int256(deque._end) - int256(deque._begin));\\n }\\n }\\n\\n /**\\n * @dev Returns true if the queue is empty.\\n */\\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\\n return deque._end <= deque._begin;\\n }\\n}\\n\",\"keccak256\":\"0x4859ffd6dd69382a1462930c00b6e394007da80e78e510f56930271034737bf2\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x61016060405260026007553480156200001757600080fd5b506040516200328f3803806200328f8339810160408190526200003a91620002e1565b600481604051806040016040528060128152602001712b32b637b23937b6b29023b7bb32b93737b960711b81525080620000796200015360201b60201c565b815160208084019190912082518383012060e08290526101008190524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81880181905281830187905260608201869052608082019490945230818401528151808203909301835260c00190528051940193909320919290916080523060c05261012052505082516200011f92506000915060208401906200023b565b50506001600160a01b03166101405262000139816200016e565b5050600680546001600160a01b031916331790556200034f565b6040805180820190915260018152603160f81b602082015290565b6064811115620001f65760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a40160405180910390fd5b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b828054620002499062000313565b90600052602060002090601f0160209004810192826200026d5760008555620002b8565b82601f106200028857805160ff1916838001178555620002b8565b82800160010185558215620002b8579182015b82811115620002b85782518255916020019190600101906200029b565b50620002c6929150620002ca565b5090565b5b80821115620002c65760008155600101620002cb565b600060208284031215620002f457600080fd5b81516001600160a01b03811681146200030c57600080fd5b9392505050565b600181811c908216806200032857607f821691505b6020821081036200034957634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e051610100516101205161014051612ed0620003bf600039600081816107df0152818161120f015281816113e40152611a0601526000611b2301526000611b7201526000611b4d01526000611aa601526000611ad001526000611afa0152612ed06000f3fe6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220fff679e9a49aa645f41ec6b78c9165ce8e728c549ab43d25df657d05e22c9d7664736f6c634300080d0033", - "deployedBytecode": "0x6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220fff679e9a49aa645f41ec6b78c9165ce8e728c549ab43d25df657d05e22c9d7664736f6c634300080d0033", + "numDeployments": 5, + "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"_ve\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"Empty\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"proposer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"string[]\",\"name\":\"signatures\",\"type\":\"string[]\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"ProposalCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldQuorumNumerator\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"QuorumNumeratorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"VoteCast\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"VoteCastWithParams\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"COUNTING_MODE\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EXTENDED_BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_PROPOSAL_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROPOSAL_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"}],\"name\":\"castVote\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"castVoteWithReason\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"castVoteWithReasonAndParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteWithReasonAndParamsBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"execute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"getVotesWithParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasVoted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"hashProposal\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalDeadline\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalSnapshot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"againstVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"forVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"abstainVotes\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"propose\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"quorum\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumDenominator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"}],\"name\":\"setProposalNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTeam\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"state\",\"outputs\":[{\"internalType\":\"enum IGovernor.ProposalState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"updateQuorumNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"Empty()\":[{\"details\":\"An operation (e.g. {front}) couldn't be completed due to the queue being empty.\"}]},\"kind\":\"dev\",\"methods\":{\"COUNTING_MODE()\":{\"details\":\"See {IGovernor-COUNTING_MODE}.\"},\"castVote(uint256,uint8)\":{\"details\":\"See {IGovernor-castVote}.\"},\"castVoteBySig(uint256,uint8,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteBySig}.\"},\"castVoteWithReason(uint256,uint8,string)\":{\"details\":\"See {IGovernor-castVoteWithReason}.\"},\"castVoteWithReasonAndParams(uint256,uint8,string,bytes)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParams}.\"},\"castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParamsBySig}.\"},\"execute(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-execute}.\"},\"getVotes(address,uint256)\":{\"details\":\"See {IGovernor-getVotes}.\"},\"getVotesWithParams(address,uint256,bytes)\":{\"details\":\"See {IGovernor-getVotesWithParams}.\"},\"hasVoted(uint256,address)\":{\"details\":\"See {IGovernor-hasVoted}.\"},\"hashProposal(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-hashProposal}. The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in advance, before the proposal is submitted. Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the same proposal (with same operation and same description) will have the same id if submitted on multiple governors across multiple networks. This also means that in order to execute the same operation twice (on the same governor) the proposer will have to change the description in order to avoid proposal id conflicts.\"},\"name()\":{\"details\":\"See {IGovernor-name}.\"},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155BatchReceived}.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155Received}.\"},\"onERC721Received(address,address,uint256,bytes)\":{\"details\":\"See {IERC721Receiver-onERC721Received}.\"},\"proposalDeadline(uint256)\":{\"details\":\"See {IGovernor-proposalDeadline}.\"},\"proposalSnapshot(uint256)\":{\"details\":\"See {IGovernor-proposalSnapshot}.\"},\"proposalThreshold()\":{\"details\":\"Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\"},\"proposalVotes(uint256)\":{\"details\":\"Accessor to the internal vote counts.\"},\"propose(address[],uint256[],bytes[],string)\":{\"details\":\"See {IGovernor-propose}.\"},\"quorum(uint256)\":{\"details\":\"Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\"},\"quorumDenominator()\":{\"details\":\"Returns the quorum denominator. Defaults to 100, but may be overridden.\"},\"quorumNumerator()\":{\"details\":\"Returns the current quorum numerator. See {quorumDenominator}.\"},\"relay(address,uint256,bytes)\":{\"details\":\"Relays a transaction or function call to an arbitrary target. In cases where the governance executor is some contract other than the governor itself, like when using a timelock, this function can be invoked in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake. Note that if the executor is simply the governor itself, use of `relay` is redundant.\"},\"state(uint256)\":{\"details\":\"See {IGovernor-state}.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"updateQuorumNumerator(uint256)\":{\"details\":\"Changes the quorum numerator. Emits a {QuorumNumeratorUpdated} event. Requirements: - Must be called through a governance proposal. - New numerator must be smaller or equal to the denominator.\"},\"version()\":{\"details\":\"See {IGovernor-version}.\"},\"votingDelay()\":{\"details\":\"Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\"},\"votingPeriod()\":{\"details\":\"Delay, in number of blocks, between the vote start and vote ends. NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting duration compared to the voting delay.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"votingDelay()\":{\"notice\":\"module:user-config\"},\"votingPeriod()\":{\"notice\":\"module:user-config\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VeloGovernor.sol\":\"VeloGovernor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VeloGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IGovernor} from \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\nimport {L2GovernorCountingSimple} from \\\"contracts/governance/L2GovernorCountingSimple.sol\\\";\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\nimport {L2GovernorVotesQuorumFraction} from \\\"contracts/governance/L2GovernorVotesQuorumFraction.sol\\\";\\n\\ncontract VeloGovernor is\\n L2Governor,\\n L2GovernorCountingSimple,\\n L2GovernorVotes,\\n L2GovernorVotesQuorumFraction\\n{\\n address public team;\\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\\n uint256 public proposalNumerator = 2; // start at 0.02%\\n\\n constructor(IVotes _ve)\\n L2Governor(\\\"Velodrome Governor\\\")\\n L2GovernorVotes(_ve)\\n L2GovernorVotesQuorumFraction(4) // 4%\\n {\\n team = msg.sender;\\n }\\n\\n function votingDelay() public pure override(IGovernor) returns (uint256) {\\n return 15 minutes; // 1 block\\n }\\n\\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\\n return 1 weeks;\\n }\\n\\n function setTeam(address newTeam) external {\\n require(msg.sender == team, \\\"not team\\\");\\n team = newTeam;\\n }\\n\\n function setProposalNumerator(uint256 numerator) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \\\"numerator too high\\\");\\n proposalNumerator = numerator;\\n }\\n\\n function proposalThreshold()\\n public\\n view\\n override(L2Governor)\\n returns (uint256)\\n {\\n return\\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\\n PROPOSAL_DENOMINATOR;\\n }\\n}\\n\",\"keccak256\":\"0xbdbc34fd1c78fdffb528f7a2f450e75457cb089369204f4671ec241aa0eb3a7e\",\"license\":\"MIT\"},\"contracts/governance/L2Governor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Address.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Context.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\\n *\\n * @dev Core of the governance system, designed to be extended though various modules.\\n *\\n * This contract is abstract and requires several function to be implemented in various modules:\\n *\\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\\n * - A voting module must implement {_getVotes}\\n * - Additionanly, the {votingPeriod} must also be implemented\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\\n using SafeCast for uint256;\\n using Timers for Timers.Timestamp;\\n\\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\\\"Ballot(uint256 proposalId,uint8 support)\\\");\\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\\n keccak256(\\\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\\\");\\n\\n struct ProposalCore {\\n Timers.Timestamp voteStart;\\n Timers.Timestamp voteEnd;\\n bool executed;\\n bool canceled;\\n }\\n\\n string private _name;\\n\\n mapping(uint256 => ProposalCore) private _proposals;\\n\\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\\n\\n /**\\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\\n * parameter setters in {GovernorSettings} are protected using this modifier.\\n *\\n * The governance executing address may be different from the Governor's own address, for example it could be a\\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\\n * for example, additional timelock proposers are not able to change governance parameters without going through the\\n * governance protocol (since v4.6).\\n */\\n modifier onlyGovernance() {\\n require(_msgSender() == _executor(), \\\"Governor: onlyGovernance\\\");\\n if (_executor() != address(this)) {\\n bytes32 msgDataHash = keccak256(_msgData());\\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\\n while (_governanceCall.popFront() != msgDataHash) {}\\n }\\n _;\\n }\\n\\n /**\\n * @dev Sets the value for {name} and {version}\\n */\\n constructor(string memory name_) EIP712(name_, version()) {\\n _name = name_;\\n }\\n\\n /**\\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\\n */\\n receive() external payable virtual {\\n require(_executor() == address(this));\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\\n // include the castVoteWithReasonAndParams() function as standard\\n return\\n interfaceId ==\\n (type(IGovernor).interfaceId ^\\n this.castVoteWithReasonAndParams.selector ^\\n this.castVoteWithReasonAndParamsBySig.selector ^\\n this.getVotesWithParams.selector) ||\\n interfaceId == type(IGovernor).interfaceId ||\\n interfaceId == type(IERC1155Receiver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IGovernor-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IGovernor-version}.\\n */\\n function version() public view virtual override returns (string memory) {\\n return \\\"1\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hashProposal}.\\n *\\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\\n * advance, before the proposal is submitted.\\n *\\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual override returns (uint256) {\\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\\n }\\n\\n /**\\n * @dev See {IGovernor-state}.\\n */\\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n\\n if (proposal.executed) {\\n return ProposalState.Executed;\\n }\\n\\n if (proposal.canceled) {\\n return ProposalState.Canceled;\\n }\\n\\n uint256 start = proposalSnapshot(proposalId);\\n\\n if (start == 0) {\\n revert(\\\"Governor: unknown proposal id\\\");\\n }\\n\\n if (start >= block.timestamp) {\\n return ProposalState.Pending;\\n }\\n\\n uint256 deadline = proposalDeadline(proposalId);\\n\\n if (deadline >= block.timestamp) {\\n return ProposalState.Active;\\n }\\n\\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\\n return ProposalState.Succeeded;\\n } else {\\n return ProposalState.Defeated;\\n }\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalSnapshot}.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteStart.getDeadline();\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalDeadline}.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteEnd.getDeadline();\\n }\\n\\n /**\\n * @dev Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\\n */\\n function proposalThreshold() public view virtual returns (uint256) {\\n return 0;\\n }\\n\\n /**\\n * @dev Amount of votes already cast passes the threshold limit.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Is the proposal successful or not.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) internal view virtual returns (uint256);\\n\\n /**\\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\\n *\\n * Note: Support is generic and can represent various things depending on the voting system used.\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory params\\n ) internal virtual;\\n\\n /**\\n * @dev Default additional encoded parameters used by castVote methods that don't include them\\n *\\n * Note: Should be overridden by specific implementations to use an appropriate value, the\\n * meaning of the additional params, in the context of that implementation\\n */\\n function _defaultParams() internal view virtual returns (bytes memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-propose}.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual override returns (uint256) {\\n require(\\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\\n \\\"Governor: proposer votes below proposal threshold\\\"\\n );\\n\\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\\n\\n require(targets.length == values.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length == calldatas.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length > 0, \\\"Governor: empty proposal\\\");\\n\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(proposal.voteStart.isUnset(), \\\"Governor: proposal already exists\\\");\\n\\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\\n uint64 deadline = start + votingPeriod().toUint64();\\n\\n proposal.voteStart.setDeadline(start);\\n proposal.voteEnd.setDeadline(deadline);\\n\\n emit ProposalCreated(\\n proposalId,\\n _msgSender(),\\n targets,\\n values,\\n new string[](targets.length),\\n calldatas,\\n start,\\n deadline,\\n description\\n );\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-execute}.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual override returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n\\n ProposalState status = state(proposalId);\\n require(\\n status == ProposalState.Succeeded || status == ProposalState.Queued,\\n \\\"Governor: proposal not successful\\\"\\n );\\n _proposals[proposalId].executed = true;\\n\\n emit ProposalExecuted(proposalId);\\n\\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\\n _execute(proposalId, targets, values, calldatas, descriptionHash);\\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\\n */\\n function _execute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n string memory errorMessage = \\\"Governor: call reverted without message\\\";\\n for (uint256 i = 0; i < targets.length; ++i) {\\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\\n Address.verifyCallResult(success, returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Hook before execution is triggered.\\n */\\n function _beforeExecute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory, /* values */\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n for (uint256 i = 0; i < targets.length; ++i) {\\n if (targets[i] == address(this)) {\\n _governanceCall.pushBack(keccak256(calldatas[i]));\\n }\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook after execution is triggered.\\n */\\n function _afterExecute(\\n uint256, /* proposalId */\\n address[] memory, /* targets */\\n uint256[] memory, /* values */\\n bytes[] memory, /* calldatas */\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n if (!_governanceCall.empty()) {\\n _governanceCall.clear();\\n }\\n }\\n }\\n\\n /**\\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\\n * canceled to allow distinguishing it from executed proposals.\\n *\\n * Emits a {IGovernor-ProposalCanceled} event.\\n */\\n function _cancel(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) internal virtual returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n ProposalState status = state(proposalId);\\n\\n require(\\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\\n \\\"Governor: proposal not active\\\"\\n );\\n _proposals[proposalId].canceled = true;\\n\\n emit ProposalCanceled(proposalId);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotes}.\\n */\\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, _defaultParams());\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotesWithParams}.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVote}.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReason}.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteBySig}.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\\n v,\\n r,\\n s\\n );\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(\\n keccak256(\\n abi.encode(\\n EXTENDED_BALLOT_TYPEHASH,\\n proposalId,\\n support,\\n keccak256(bytes(reason)),\\n keccak256(params)\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason\\n ) internal virtual returns (uint256) {\\n return _castVote(proposalId, account, support, reason, _defaultParams());\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason,\\n bytes memory params\\n ) internal virtual returns (uint256) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(state(proposalId) == ProposalState.Active, \\\"Governor: vote not currently active\\\");\\n\\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\\n _countVote(proposalId, account, support, weight, params);\\n\\n if (params.length == 0) {\\n emit VoteCast(account, proposalId, support, weight, reason);\\n } else {\\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\\n }\\n\\n return weight;\\n }\\n\\n /**\\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\\n */\\n function relay(\\n address target,\\n uint256 value,\\n bytes calldata data\\n ) external virtual onlyGovernance {\\n Address.functionCallWithValue(target, data, value);\\n }\\n\\n /**\\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\\n * through another contract such as a timelock.\\n */\\n function _executor() internal view virtual returns (address) {\\n return address(this);\\n }\\n\\n /**\\n * @dev See {IERC721Receiver-onERC721Received}.\\n */\\n function onERC721Received(\\n address,\\n address,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155Received}.\\n */\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\\n */\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] memory,\\n uint256[] memory,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155BatchReceived.selector;\\n }\\n}\\n\",\"keccak256\":\"0xa2846313b89a871807cdebd0225b0bf8f23b17505ab8b3288549ec54a5a4a71b\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorCountingSimple.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\\n *\\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorCountingSimple is L2Governor {\\n /**\\n * @dev Supported vote types. Matches Governor Bravo ordering.\\n */\\n enum VoteType {\\n Against,\\n For,\\n Abstain\\n }\\n\\n struct ProposalVote {\\n uint256 againstVotes;\\n uint256 forVotes;\\n uint256 abstainVotes;\\n mapping(address => bool) hasVoted;\\n }\\n\\n mapping(uint256 => ProposalVote) private _proposalVotes;\\n\\n /**\\n * @dev See {IGovernor-COUNTING_MODE}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual override returns (string memory) {\\n return \\\"support=bravo&quorum=for,abstain\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hasVoted}.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\\n return _proposalVotes[proposalId].hasVoted[account];\\n }\\n\\n /**\\n * @dev Accessor to the internal vote counts.\\n */\\n function proposalVotes(uint256 proposalId)\\n public\\n view\\n virtual\\n returns (\\n uint256 againstVotes,\\n uint256 forVotes,\\n uint256 abstainVotes\\n )\\n {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\\n }\\n\\n /**\\n * @dev See {Governor-_quorumReached}.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return proposalvote.forVotes > proposalvote.againstVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory // params\\n ) internal virtual override {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n require(!proposalvote.hasVoted[account], \\\"GovernorVotingSimple: vote already cast\\\");\\n proposalvote.hasVoted[account] = true;\\n\\n if (support == uint8(VoteType.Against)) {\\n proposalvote.againstVotes += weight;\\n } else if (support == uint8(VoteType.For)) {\\n proposalvote.forVotes += weight;\\n } else if (support == uint8(VoteType.Abstain)) {\\n proposalvote.abstainVotes += weight;\\n } else {\\n revert(\\\"GovernorVotingSimple: invalid value for enum VoteType\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xdc37daa24118a6e6ba5208b4abefa1632af2ff340135ca6c6d7237f70102d5db\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotes is L2Governor {\\n IVotes public immutable token;\\n\\n constructor(IVotes tokenAddress) {\\n token = tokenAddress;\\n }\\n\\n /**\\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory /*params*/\\n ) internal view virtual override returns (uint256) {\\n return token.getPastVotes(account, blockTimestamp);\\n }\\n}\\n\",\"keccak256\":\"0x605a7de71228dda3cb8fd878cac313a86bc5841fd34d7344214346ba46e63af1\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotesQuorumFraction.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\\n * fraction of the total supply.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\\n uint256 private _quorumNumerator;\\n\\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\\n\\n /**\\n * @dev Initialize quorum as a fraction of the token's total supply.\\n *\\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\\n * customized by overriding {quorumDenominator}.\\n */\\n constructor(uint256 quorumNumeratorValue) {\\n _updateQuorumNumerator(quorumNumeratorValue);\\n }\\n\\n /**\\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\\n */\\n function quorumNumerator() public view virtual returns (uint256) {\\n return _quorumNumerator;\\n }\\n\\n /**\\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\\n */\\n function quorumDenominator() public view virtual returns (uint256) {\\n return 100;\\n }\\n\\n /**\\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\\n */\\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - Must be called through a governance proposal.\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\\n _updateQuorumNumerator(newQuorumNumerator);\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\\n require(\\n newQuorumNumerator <= quorumDenominator(),\\n \\\"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\\\"\\n );\\n\\n uint256 oldQuorumNumerator = _quorumNumerator;\\n _quorumNumerator = newQuorumNumerator;\\n\\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\\n }\\n}\\n\",\"keccak256\":\"0xe66d29c0ffd2274de933d80e11d68891f3acc3f078be4560a2b493b7d88dcb7f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Interface of the {Governor} core.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract IGovernor is IERC165 {\\n enum ProposalState {\\n Pending,\\n Active,\\n Canceled,\\n Defeated,\\n Succeeded,\\n Queued,\\n Expired,\\n Executed\\n }\\n\\n /**\\n * @dev Emitted when a proposal is created.\\n */\\n event ProposalCreated(\\n uint256 proposalId,\\n address proposer,\\n address[] targets,\\n uint256[] values,\\n string[] signatures,\\n bytes[] calldatas,\\n uint256 startBlock,\\n uint256 endBlock,\\n string description\\n );\\n\\n /**\\n * @dev Emitted when a proposal is canceled.\\n */\\n event ProposalCanceled(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a proposal is executed.\\n */\\n event ProposalExecuted(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a vote is cast without params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n */\\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\\n\\n /**\\n * @dev Emitted when a vote is cast with params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\\n */\\n event VoteCastWithParams(\\n address indexed voter,\\n uint256 proposalId,\\n uint8 support,\\n uint256 weight,\\n string reason,\\n bytes params\\n );\\n\\n /**\\n * @notice module:core\\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\\n */\\n function name() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \\\"1\\\"\\n */\\n function version() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:voting\\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\\n *\\n * There are 2 standard keys: `support` and `quorum`.\\n *\\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\\n * - `quorum=bravo` means that only For votes are counted towards quorum.\\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\\n *\\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\\n * name that describes the behavior. For example:\\n *\\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\\n *\\n * NOTE: The string can be decoded by the standard\\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\\n * JavaScript class.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Current state of a proposal, following Compound's convention\\n */\\n function state(uint256 proposalId) public view virtual returns (ProposalState);\\n\\n /**\\n * @notice module:core\\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\\n * beginning of the following block.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\\n * during this block.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\\n */\\n function votingDelay() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of blocks, between the vote start and vote ends.\\n *\\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\\n * duration compared to the voting delay.\\n */\\n function votingPeriod() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Minimum number of cast voted required for a proposal to be successful.\\n *\\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\\n */\\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber`.\\n *\\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\\n * multiple), {ERC20Votes} tokens.\\n */\\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockNumber,\\n bytes memory params\\n ) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:voting\\n * @dev Returns whether `account` has cast a vote on `proposalId`.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\\n\\n /**\\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\\n * {IGovernor-votingPeriod} blocks after the voting starts.\\n *\\n * Emits a {ProposalCreated} event.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\\n * deadline to be reached.\\n *\\n * Emits a {ProposalExecuted} event.\\n *\\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Cast a vote\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xa52d593ff06a2353f78fa149da31f2ca94f03d1eff99bde41977fa2fe985a92f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2e53602b96c1bf97c731ed3e2a981b4f85e23a9410a5ebd36e549a4cc93340dc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x2626d8ab3dfdad0fad630c212ad146d59473d0f48b771784c61a7c1dbbea1f3f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Tooling for timepoints, timers and delays\\n */\\nlibrary Timers {\\n struct Timestamp {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(Timestamp storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(Timestamp memory timer) internal view returns (bool) {\\n return timer._deadline > block.timestamp;\\n }\\n\\n function isExpired(Timestamp memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.timestamp;\\n }\\n\\n struct BlockNumber {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(BlockNumber storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(BlockNumber memory timer) internal view returns (bool) {\\n return timer._deadline > block.number;\\n }\\n\\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.number;\\n }\\n}\\n\",\"keccak256\":\"0x29791a62950a7983e02a673639c1a781d1e448691800456c2ce4b99715391b14\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS,\\n InvalidSignatureV // Deprecated in v4.8\\n }\\n\\n function _throwError(RecoverError error) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert(\\\"ECDSA: invalid signature\\\");\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert(\\\"ECDSA: invalid signature 's' value\\\");\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature` or error string. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\\n if (signature.length == 65) {\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n /// @solidity memory-safe-assembly\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n return tryRecover(hash, v, r, s);\\n } else {\\n return (address(0), RecoverError.InvalidSignatureLength);\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, signature);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n *\\n * _Available since v4.2._\\n */\\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature);\\n }\\n\\n return (signer, RecoverError.NoError);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from `s`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", Strings.toString(s.length), s));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Typed Data, created from a\\n * `domainSeparator` and a `structHash`. This produces hash corresponding\\n * to the one signed with the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\\n * JSON-RPC method as part of EIP-712.\\n *\\n * See {recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n }\\n}\\n\",\"keccak256\":\"0x54ee424bfc83ce63b2a918b9a1efb5090a0fb68dbd1de3b10bc667776885dd4f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ECDSA.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n /* solhint-disable var-name-mixedcase */\\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n // invalidate the cached domain separator if the chain id changes.\\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n uint256 private immutable _CACHED_CHAIN_ID;\\n address private immutable _CACHED_THIS;\\n\\n bytes32 private immutable _HASHED_NAME;\\n bytes32 private immutable _HASHED_VERSION;\\n bytes32 private immutable _TYPE_HASH;\\n\\n /* solhint-enable var-name-mixedcase */\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n constructor(string memory name, string memory version) {\\n bytes32 hashedName = keccak256(bytes(name));\\n bytes32 hashedVersion = keccak256(bytes(version));\\n bytes32 typeHash = keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n );\\n _HASHED_NAME = hashedName;\\n _HASHED_VERSION = hashedVersion;\\n _CACHED_CHAIN_ID = block.chainid;\\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n _CACHED_THIS = address(this);\\n _TYPE_HASH = typeHash;\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\\n return _CACHED_DOMAIN_SEPARATOR;\\n } else {\\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n }\\n }\\n\\n function _buildDomainSeparator(\\n bytes32 typeHash,\\n bytes32 nameHash,\\n bytes32 versionHash\\n ) private view returns (bytes32) {\\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\\n }\\n}\\n\",\"keccak256\":\"0x948d8b2d18f38141ec78c5229d770d950ebc781ed3f44cc9e3ccbb9fded5846a\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\\n\\nimport \\\"./EIP712.sol\\\";\\n\",\"keccak256\":\"0xea30c402170bc240354b74e6c6f6a8e5bdb1935d90d168cc58c0654461c6a72b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3546b156d97633f7f8cad536d5454c81d1d604687c02b2eb105fdc33cb962b41\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\\npragma solidity ^0.8.4;\\n\\nimport \\\"../math/SafeCast.sol\\\";\\n\\n/**\\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\\n * the existing queue contents are left in storage.\\n *\\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\\n * used in storage, and not in memory.\\n * ```\\n * DoubleEndedQueue.Bytes32Deque queue;\\n * ```\\n *\\n * _Available since v4.6._\\n */\\nlibrary DoubleEndedQueue {\\n /**\\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\\n */\\n error Empty();\\n\\n /**\\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\\n */\\n error OutOfBounds();\\n\\n /**\\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\\n *\\n * Struct members have an underscore prefix indicating that they are \\\"private\\\" and should not be read or written to\\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\\n * lead to unexpected behavior.\\n *\\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\\n * data[end - 1].\\n */\\n struct Bytes32Deque {\\n int128 _begin;\\n int128 _end;\\n mapping(int128 => bytes32) _data;\\n }\\n\\n /**\\n * @dev Inserts an item at the end of the queue.\\n */\\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 backIndex = deque._end;\\n deque._data[backIndex] = value;\\n unchecked {\\n deque._end = backIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Removes the item at the end of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n value = deque._data[backIndex];\\n delete deque._data[backIndex];\\n deque._end = backIndex;\\n }\\n\\n /**\\n * @dev Inserts an item at the beginning of the queue.\\n */\\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 frontIndex;\\n unchecked {\\n frontIndex = deque._begin - 1;\\n }\\n deque._data[frontIndex] = value;\\n deque._begin = frontIndex;\\n }\\n\\n /**\\n * @dev Removes the item at the beginning of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n value = deque._data[frontIndex];\\n delete deque._data[frontIndex];\\n unchecked {\\n deque._begin = frontIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Returns the item at the beginning of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n return deque._data[frontIndex];\\n }\\n\\n /**\\n * @dev Returns the item at the end of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n return deque._data[backIndex];\\n }\\n\\n /**\\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\\n * `length(deque) - 1`.\\n *\\n * Reverts with `OutOfBounds` if the index is out of bounds.\\n */\\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\\n // int256(deque._begin) is a safe upcast\\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\\n if (idx >= deque._end) revert OutOfBounds();\\n return deque._data[idx];\\n }\\n\\n /**\\n * @dev Resets the queue back to being empty.\\n *\\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\\n * out on potential gas refunds.\\n */\\n function clear(Bytes32Deque storage deque) internal {\\n deque._begin = 0;\\n deque._end = 0;\\n }\\n\\n /**\\n * @dev Returns the number of items in the queue.\\n */\\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\\n // We also assume there are at most int256.max items in the queue.\\n unchecked {\\n return uint256(int256(deque._end) - int256(deque._begin));\\n }\\n }\\n\\n /**\\n * @dev Returns true if the queue is empty.\\n */\\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\\n return deque._end <= deque._begin;\\n }\\n}\\n\",\"keccak256\":\"0x4859ffd6dd69382a1462930c00b6e394007da80e78e510f56930271034737bf2\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x61016060405260026007553480156200001757600080fd5b506040516200328f3803806200328f8339810160408190526200003a91620002e1565b600481604051806040016040528060128152602001712b32b637b23937b6b29023b7bb32b93737b960711b81525080620000796200015360201b60201c565b815160208084019190912082518383012060e08290526101008190524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81880181905281830187905260608201869052608082019490945230818401528151808203909301835260c00190528051940193909320919290916080523060c05261012052505082516200011f92506000915060208401906200023b565b50506001600160a01b03166101405262000139816200016e565b5050600680546001600160a01b031916331790556200034f565b6040805180820190915260018152603160f81b602082015290565b6064811115620001f65760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a40160405180910390fd5b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b828054620002499062000313565b90600052602060002090601f0160209004810192826200026d5760008555620002b8565b82601f106200028857805160ff1916838001178555620002b8565b82800160010185558215620002b8579182015b82811115620002b85782518255916020019190600101906200029b565b50620002c6929150620002ca565b5090565b5b80821115620002c65760008155600101620002cb565b600060208284031215620002f457600080fd5b81516001600160a01b03811681146200030c57600080fd5b9392505050565b600181811c908216806200032857607f821691505b6020821081036200034957634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e051610100516101205161014051612ed0620003bf600039600081816107df0152818161120f015281816113e40152611a0601526000611b2301526000611b7201526000611b4d01526000611aa601526000611ad001526000611afa0152612ed06000f3fe6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220da19b0886c70f281039e6002f39d70a76440f06ae01c8b38d718c3ab4457695f64736f6c634300080d0033", + "deployedBytecode": "0x6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220da19b0886c70f281039e6002f39d70a76440f06ae01c8b38d718c3ab4457695f64736f6c634300080d0033", "devdoc": { "errors": { "Empty()": [ diff --git a/deployments/arbitrumGoerli/VelodromeLibrary.json b/deployments/arbitrumGoerli/VelodromeLibrary.json index 7ed248e2..e5c49fce 100644 --- a/deployments/arbitrumGoerli/VelodromeLibrary.json +++ b/deployments/arbitrumGoerli/VelodromeLibrary.json @@ -1,5 +1,5 @@ { - "address": "0x233ed5d7FAed19F7b8A28844E2845FBF0F145Be2", + "address": "0x0B2D0b9983dc6Ecd01c3CbE836FBb642B75Ae752", "abi": [ { "inputs": [ @@ -188,30 +188,30 @@ "type": "function" } ], - "transactionHash": "0xf0eab16bc0468726fdb1b4a50c842a9b8f0cbb15ab4412a36413aca09091f354", + "transactionHash": "0xf0fc854d9afb44f3aa07d62b17de20ac841406cde1ca20e20dd4eb71b983c9ea", "receipt": { "to": null, "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0x233ed5d7FAed19F7b8A28844E2845FBF0F145Be2", + "contractAddress": "0x0B2D0b9983dc6Ecd01c3CbE836FBb642B75Ae752", "transactionIndex": 1, - "gasUsed": "9031975", + "gasUsed": "16464071", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xe561c641dd7efbe9c84d2d477b154d7c9b6ad54bba72181943437038772a4b4d", - "transactionHash": "0xf0eab16bc0468726fdb1b4a50c842a9b8f0cbb15ab4412a36413aca09091f354", + "blockHash": "0x690098e045fde1edf9947aa388198ceed3a14abf5430ed26c8d4eb788be509d3", + "transactionHash": "0xf0fc854d9afb44f3aa07d62b17de20ac841406cde1ca20e20dd4eb71b983c9ea", "logs": [], - "blockNumber": 4195016, - "cumulativeGasUsed": "9031975", + "blockNumber": 4263683, + "cumulativeGasUsed": "16464071", "status": 1, "byzantium": true }, "args": [ - "0xCeaEA7A5cB3e7521DdE6717BCc99a4c8c60E07b6" + "0x8562618F69ED7F313Ca699556Eb18A36FB2dB1e3" ], - "numDeployments": 4, - "solcInputHash": "0faaa79d8b79020b765ba7705413c447", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getMinimumValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getSample\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VelodromeLibrary.sol\":\"VelodromeLibrary\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VelodromeLibrary.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\n\\ncontract VelodromeLibrary {\\n IRouter internal immutable router;\\n\\n constructor(address _router) {\\n router = IRouter(_router);\\n }\\n\\n function _f(uint x0, uint y) internal pure returns (uint) {\\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\\n }\\n\\n function _d(uint x0, uint y) internal pure returns (uint) {\\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\\n }\\n\\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\\n for (uint i = 0; i < 255; i++) {\\n uint y_prev = y;\\n uint k = _f(x0, y);\\n if (k < xy) {\\n uint dy = (xy - k)*1e18/_d(x0, y);\\n y = y + dy;\\n } else {\\n uint dy = (k - xy)*1e18/_d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n }\\n\\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return (sample, r0, r1);\\n }\\n\\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\\n if (stable) {\\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\\n _reserve0 = _reserve0 * 1e18 / decimals0;\\n _reserve1 = _reserve1 * 1e18 / decimals1;\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\\n } else {\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n return amountIn * reserveB / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\\n if (stable) {\\n uint _x = x * 1e18 / decimals0;\\n uint _y = y * 1e18 / decimals1;\\n uint _a = (_x * _y) / 1e18;\\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return _a * _b / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n \\n}\\n\",\"keccak256\":\"0x01df9d4f97d905560776a0b2d29e6dc1337dc952fdc3d8bfbfde99a510a62c1c\",\"license\":\"MIT\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"}},\"version\":1}", - "bytecode": "0x60a060405234801561001057600080fd5b5060405161100238038061100283398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051610f626100a06000396000818161010c015281816102730152818161043701526105cb0152610f626000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea264697066735822122015bc5301a8c944c3cc07f793e4c65b7813134e5409dcbb6cdc0a4a1f3cf42a2e64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea264697066735822122015bc5301a8c944c3cc07f793e4c65b7813134e5409dcbb6cdc0a4a1f3cf42a2e64736f6c634300080d0033", + "numDeployments": 7, + "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getMinimumValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getSample\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VelodromeLibrary.sol\":\"VelodromeLibrary\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VelodromeLibrary.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\n\\ncontract VelodromeLibrary {\\n IRouter internal immutable router;\\n\\n constructor(address _router) {\\n router = IRouter(_router);\\n }\\n\\n function _f(uint x0, uint y) internal pure returns (uint) {\\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\\n }\\n\\n function _d(uint x0, uint y) internal pure returns (uint) {\\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\\n }\\n\\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\\n for (uint i = 0; i < 255; i++) {\\n uint y_prev = y;\\n uint k = _f(x0, y);\\n if (k < xy) {\\n uint dy = (xy - k)*1e18/_d(x0, y);\\n y = y + dy;\\n } else {\\n uint dy = (k - xy)*1e18/_d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n }\\n\\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return (sample, r0, r1);\\n }\\n\\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\\n if (stable) {\\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\\n _reserve0 = _reserve0 * 1e18 / decimals0;\\n _reserve1 = _reserve1 * 1e18 / decimals1;\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\\n } else {\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n return amountIn * reserveB / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\\n if (stable) {\\n uint _x = x * 1e18 / decimals0;\\n uint _y = y * 1e18 / decimals1;\\n uint _a = (_x * _y) / 1e18;\\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return _a * _b / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n \\n}\\n\",\"keccak256\":\"0x01df9d4f97d905560776a0b2d29e6dc1337dc952fdc3d8bfbfde99a510a62c1c\",\"license\":\"MIT\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"}},\"version\":1}", + "bytecode": "0x60a060405234801561001057600080fd5b5060405161100238038061100283398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051610f626100a06000396000818161010c015281816102730152818161043701526105cb0152610f626000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea2646970667358221220c9f5e9283840569934e74e4aad058121f7875c44a1155be3299fa9c2ea9c6b6c64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea2646970667358221220c9f5e9283840569934e74e4aad058121f7875c44a1155be3299fa9c2ea9c6b6c64736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/Voter.json b/deployments/arbitrumGoerli/Voter.json index 6b991390..d166e0e4 100644 --- a/deployments/arbitrumGoerli/Voter.json +++ b/deployments/arbitrumGoerli/Voter.json @@ -1,5 +1,5 @@ { - "address": "0x574607c69f369f0535E77C5F7C35767Aee04879A", + "address": "0x19E081b804AB558cF6f7B629a2902F7c79ADa9cD", "abi": [ { "inputs": [ @@ -1141,33 +1141,33 @@ "type": "function" } ], - "transactionHash": "0x863a7c9537e8bb10b2707a78c987cdbd068dc5e29785757d2ab4c0345f3da75f", + "transactionHash": "0x31badff59af423d1e93363365c69c1a4256ede69af484077bc8544ff287bbfa7", "receipt": { "to": null, "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0x574607c69f369f0535E77C5F7C35767Aee04879A", + "contractAddress": "0x19E081b804AB558cF6f7B629a2902F7c79ADa9cD", "transactionIndex": 1, - "gasUsed": "30733498", + "gasUsed": "55972824", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfc9c943e85b7244024dc971ca02ed5f6ddf6a55352731bd5806c62f354ec813f", - "transactionHash": "0x863a7c9537e8bb10b2707a78c987cdbd068dc5e29785757d2ab4c0345f3da75f", + "blockHash": "0x3fade8135639bde4350276fb8772a6ff288e712661a99c085431928da4457a49", + "transactionHash": "0x31badff59af423d1e93363365c69c1a4256ede69af484077bc8544ff287bbfa7", "logs": [], - "blockNumber": 4195024, - "cumulativeGasUsed": "30733498", + "blockNumber": 4263692, + "cumulativeGasUsed": "55972824", "status": 1, "byzantium": true }, "args": [ - "0x6b938BA22FB5520fFB5D14c9C4Fef82a48761497", - "0x7488AC81DC3908ff7141db4949e70D60A3Fd4DCc", - "0x1Ac3032Dfd7e206BA6d08F453f38593b9A583052", - "0x5542edb529F7c963583e9B8e5339121cFCf4B606" + "0xCDAF5f01849Fff0a9E36D768B2ae7354A98360c0", + "0xcA698eA7f3A74b7D3D4229765dcF47F7A224859F", + "0x9974354d3a16C4801cce829349Cf17663b2c58a5", + "0x679e8fED0Cd87abAFB0BA481F32b7BDd8b272789" ], - "numDeployments": 3, - "solcInputHash": "0faaa79d8b79020b765ba7705413c447", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_gauges\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_bribes\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Abstained\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Attach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Detach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributeReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"internal_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"external_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"name\":\"GaugeCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeKilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeRevived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"reward\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NotifyReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Voted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"whitelister\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"Whitelisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"attachTokenToGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bribefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_bribes\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimBribes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_fees\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"}],\"name\":\"claimRewards\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"detachTokenFromGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"finish\",\"type\":\"uint256\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distributeFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distro\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"emergencyCouncil\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"external_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gaugefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"gauges\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_tokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"internal_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isAlive\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isGauge\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isWhitelisted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"killGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"lastVoted\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"length\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"notifyRewardAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"poke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolForGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"poolVote\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"reset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"reviveGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_council\",\"type\":\"address\"}],\"name\":\"setEmergencyCouncil\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"setGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalWeight\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"updateFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"name\":\"updateForRange\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"updateGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedWeights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"_poolVote\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_weights\",\"type\":\"uint256[]\"}],\"name\":\"vote\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"votes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"weights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"whitelist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Voter.sol\":\"Voter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Voter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/libraries/Math.sol';\\nimport 'contracts/interfaces/IBribe.sol';\\nimport 'contracts/interfaces/IBribeFactory.sol';\\nimport 'contracts/interfaces/IGauge.sol';\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/interfaces/IERC20.sol';\\nimport 'contracts/interfaces/IMinter.sol';\\nimport 'contracts/interfaces/IPair.sol';\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/interfaces/IVoter.sol';\\nimport 'contracts/interfaces/IVotingEscrow.sol';\\n\\ncontract Voter is IVoter {\\n\\n address public immutable _ve; // the ve token that governs these contracts\\n address public immutable factory; // the PairFactory\\n address internal immutable base;\\n address public immutable gaugefactory;\\n address public immutable bribefactory;\\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\\n address public minter;\\n address public governor; // should be set to an IGovernor\\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\\n\\n uint public totalWeight; // total voting weight\\n\\n address[] public pools; // all pools viable for incentives\\n mapping(address => address) public gauges; // pool => gauge\\n mapping(address => address) public poolForGauge; // gauge => pool\\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\\n mapping(address => uint256) public weights; // pool => weight\\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\\n mapping(uint => address[]) public poolVote; // nft => pools\\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\\n mapping(address => bool) public isGauge;\\n mapping(address => bool) public isWhitelisted;\\n mapping(address => bool) public isAlive;\\n\\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\\n event GaugeKilled(address indexed gauge);\\n event GaugeRevived(address indexed gauge);\\n event Voted(address indexed voter, uint tokenId, uint256 weight);\\n event Abstained(uint tokenId, uint256 weight);\\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\\n event Whitelisted(address indexed whitelister, address indexed token);\\n\\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\\n _ve = __ve;\\n factory = _factory;\\n base = IVotingEscrow(__ve).token();\\n gaugefactory = _gauges;\\n bribefactory = _bribes;\\n minter = msg.sender;\\n governor = msg.sender;\\n emergencyCouncil = msg.sender;\\n }\\n\\n // simple re-entrancy check\\n uint internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n modifier onlyNewEpoch(uint _tokenId) {\\n // ensure new epoch since last vote \\n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \\\"TOKEN_ALREADY_VOTED_THIS_EPOCH\\\");\\n _;\\n }\\n\\n function initialize(address[] memory _tokens, address _minter) external {\\n require(msg.sender == minter);\\n for (uint i = 0; i < _tokens.length; i++) {\\n _whitelist(_tokens[i]);\\n }\\n minter = _minter;\\n }\\n\\n function setGovernor(address _governor) public {\\n require(msg.sender == governor);\\n governor = _governor;\\n }\\n\\n function setEmergencyCouncil(address _council) public {\\n require(msg.sender == emergencyCouncil);\\n emergencyCouncil = _council;\\n }\\n\\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n lastVoted[_tokenId] = block.timestamp;\\n _reset(_tokenId);\\n IVotingEscrow(_ve).abstain(_tokenId);\\n }\\n\\n function _reset(uint _tokenId) internal {\\n address[] storage _poolVote = poolVote[_tokenId];\\n uint _poolVoteCnt = _poolVote.length;\\n uint256 _totalWeight = 0;\\n\\n for (uint i = 0; i < _poolVoteCnt; i ++) {\\n address _pool = _poolVote[i];\\n uint256 _votes = votes[_tokenId][_pool];\\n\\n if (_votes != 0) {\\n _updateFor(gauges[_pool]);\\n weights[_pool] -= _votes;\\n votes[_tokenId][_pool] -= _votes;\\n if (_votes > 0) {\\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n _totalWeight += _votes;\\n } else {\\n _totalWeight -= _votes;\\n }\\n emit Abstained(_tokenId, _votes);\\n }\\n }\\n totalWeight -= uint256(_totalWeight);\\n usedWeights[_tokenId] = 0;\\n delete poolVote[_tokenId];\\n }\\n\\n function poke(uint _tokenId) external {\\n address[] memory _poolVote = poolVote[_tokenId];\\n uint _poolCnt = _poolVote.length;\\n uint256[] memory _weights = new uint256[](_poolCnt);\\n\\n for (uint i = 0; i < _poolCnt; i ++) {\\n _weights[i] = votes[_tokenId][_poolVote[i]];\\n }\\n\\n _vote(_tokenId, _poolVote, _weights);\\n }\\n\\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\\n _reset(_tokenId);\\n uint _poolCnt = _poolVote.length;\\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\\n uint256 _totalVoteWeight = 0;\\n uint256 _totalWeight = 0;\\n uint256 _usedWeight = 0;\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n _totalVoteWeight += _weights[i];\\n }\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n address _pool = _poolVote[i];\\n address _gauge = gauges[_pool];\\n\\n if (isGauge[_gauge]) {\\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\\n require(votes[_tokenId][_pool] == 0);\\n require(_poolWeight != 0);\\n _updateFor(_gauge);\\n\\n poolVote[_tokenId].push(_pool);\\n\\n weights[_pool] += _poolWeight;\\n votes[_tokenId][_pool] += _poolWeight;\\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n _usedWeight += _poolWeight;\\n _totalWeight += _poolWeight;\\n emit Voted(msg.sender, _tokenId, _poolWeight);\\n }\\n }\\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\\n totalWeight += uint256(_totalWeight);\\n usedWeights[_tokenId] = uint256(_usedWeight);\\n }\\n\\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n require(_poolVote.length == _weights.length);\\n lastVoted[tokenId] = block.timestamp;\\n _vote(tokenId, _poolVote, _weights);\\n }\\n\\n function whitelist(address _token) public {\\n require(msg.sender == governor);\\n _whitelist(_token);\\n }\\n\\n function _whitelist(address _token) internal {\\n require(!isWhitelisted[_token]);\\n isWhitelisted[_token] = true;\\n emit Whitelisted(msg.sender, _token);\\n }\\n\\n function createGauge(address _pool) external returns (address) {\\n require(gauges[_pool] == address(0x0), \\\"exists\\\");\\n address[] memory allowedRewards = new address[](3);\\n address[] memory internalRewards = new address[](2);\\n bool isPair = IPairFactory(factory).isPair(_pool);\\n address tokenA;\\n address tokenB;\\n\\n if (isPair) {\\n (tokenA, tokenB) = IPair(_pool).tokens();\\n allowedRewards[0] = tokenA;\\n allowedRewards[1] = tokenB;\\n internalRewards[0] = tokenA;\\n internalRewards[1] = tokenB;\\n\\n if (base != tokenA && base != tokenB) {\\n allowedRewards[2] = base;\\n }\\n }\\n\\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\\n require(isPair, \\\"!_pool\\\");\\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \\\"!whitelisted\\\");\\n }\\n\\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\\n\\n IERC20(base).approve(_gauge, type(uint).max);\\n internal_bribes[_gauge] = _internal_bribe;\\n external_bribes[_gauge] = _external_bribe;\\n gauges[_pool] = _gauge;\\n poolForGauge[_gauge] = _pool;\\n isGauge[_gauge] = true;\\n isAlive[_gauge] = true;\\n _updateFor(_gauge);\\n pools.push(_pool);\\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\\n return _gauge;\\n }\\n\\n function killGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(isAlive[_gauge], \\\"gauge already dead\\\");\\n isAlive[_gauge] = false;\\n claimable[_gauge] = 0;\\n emit GaugeKilled(_gauge);\\n }\\n\\n function reviveGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(!isAlive[_gauge], \\\"gauge already alive\\\");\\n isAlive[_gauge] = true;\\n emit GaugeRevived(_gauge);\\n }\\n\\n function attachTokenToGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\\n emit Attach(account, msg.sender, tokenId);\\n }\\n\\n function emitDeposit(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]);\\n emit Deposit(account, msg.sender, tokenId, amount);\\n }\\n\\n function detachTokenFromGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\\n emit Detach(account, msg.sender, tokenId);\\n }\\n\\n function emitWithdraw(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n emit Withdraw(account, msg.sender, tokenId, amount);\\n }\\n\\n function length() external view returns (uint) {\\n return pools.length;\\n }\\n\\n uint internal index;\\n mapping(address => uint) internal supplyIndex;\\n mapping(address => uint) public claimable;\\n\\n function notifyRewardAmount(uint amount) external {\\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index += _ratio;\\n }\\n emit NotifyReward(msg.sender, base, amount);\\n }\\n\\n function updateFor(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n _updateFor(_gauges[i]);\\n }\\n }\\n\\n function updateForRange(uint start, uint end) public {\\n for (uint i = start; i < end; i++) {\\n _updateFor(gauges[pools[i]]);\\n }\\n }\\n\\n function updateAll() external {\\n updateForRange(0, pools.length);\\n }\\n\\n function updateGauge(address _gauge) external {\\n _updateFor(_gauge);\\n }\\n\\n function _updateFor(address _gauge) internal {\\n address _pool = poolForGauge[_gauge];\\n uint256 _supplied = weights[_pool];\\n if (_supplied > 0) {\\n uint _supplyIndex = supplyIndex[_gauge];\\n uint _index = index; // get global index0 for accumulated distro\\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\\n if (_delta > 0) {\\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\\n if (isAlive[_gauge]) {\\n claimable[_gauge] += _share;\\n }\\n }\\n } else {\\n supplyIndex[_gauge] = index; // new users are set to the default global state\\n }\\n }\\n\\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\\n }\\n }\\n\\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _bribes.length; i++) {\\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _fees.length; i++) {\\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function distributeFees(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n if (IGauge(_gauges[i]).isForPair()){\\n IGauge(_gauges[i]).claimFees();\\n }\\n }\\n }\\n\\n function distribute(address _gauge) public lock {\\n IMinter(minter).update_period();\\n _updateFor(_gauge); // should set claimable to 0 if killed\\n uint _claimable = claimable[_gauge];\\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\\n claimable[_gauge] = 0;\\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\\n emit DistributeReward(msg.sender, _gauge, _claimable);\\n }\\n }\\n\\n function distro() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute(uint start, uint finish) public {\\n for (uint x = start; x < finish; x++) {\\n distribute(gauges[pools[x]]);\\n }\\n }\\n\\n function distribute(address[] memory _gauges) external {\\n for (uint x = 0; x < _gauges.length; x++) {\\n distribute(_gauges[x]);\\n }\\n }\\n\\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2ff3fc2765dfa0c54870e428d3a2c625f413fb6e10ed7742e786ab4404aae6dc\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x61012060405260016011553480156200001757600080fd5b5060405162003656380380620036568339810160408190526200003a916200011c565b6001600160a01b03808516608081905290841660a05260408051637e062a3560e11b8152905163fc0c546a916004808201926020929091908290030181865afa1580156200008c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b2919062000179565b6001600160a01b0390811660c05291821660e0521661010052505060008054336001600160a01b03199182168117909255600180548216831790556002805490911690911790556200019e565b80516001600160a01b03811681146200011757600080fd5b919050565b600080600080608085870312156200013357600080fd5b6200013e85620000ff565b93506200014e60208601620000ff565b92506200015e60408601620000ff565b91506200016e60608601620000ff565b905092959194509250565b6000602082840312156200018c57600080fd5b6200019782620000ff565b9392505050565b60805160a05160c05160e051610100516133e062000276600039600081816103e701528181611c680152611ce60152600081816104d30152611d79015260008181610b9401528181610c0d01528181610edd01528181610f9901528181611acd01528181611b0601528181611b380152611e5a0152600081816106fc015261192401526000818161058c0152818161092b015281816109d701528181610c9a01528181611069015281816111ea0152818161131a015281816114d901528181611dab015281816125e501526129a801526133e06000f3fe608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea26469706673582212204288741f0c7e0bf9fdc3fcd46932b025210387817a5bfe199a16d22292942a6064736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea26469706673582212204288741f0c7e0bf9fdc3fcd46932b025210387817a5bfe199a16d22292942a6064736f6c634300080d0033", + "numDeployments": 5, + "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_gauges\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_bribes\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Abstained\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Attach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Detach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributeReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"internal_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"external_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"name\":\"GaugeCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeKilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeRevived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"reward\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NotifyReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Voted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"whitelister\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"Whitelisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"attachTokenToGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bribefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_bribes\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimBribes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_fees\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"}],\"name\":\"claimRewards\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"detachTokenFromGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"finish\",\"type\":\"uint256\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distributeFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distro\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"emergencyCouncil\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"external_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gaugefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"gauges\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_tokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"internal_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isAlive\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isGauge\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isWhitelisted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"killGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"lastVoted\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"length\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"notifyRewardAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"poke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolForGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"poolVote\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"reset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"reviveGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_council\",\"type\":\"address\"}],\"name\":\"setEmergencyCouncil\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"setGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalWeight\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"updateFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"name\":\"updateForRange\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"updateGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedWeights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"_poolVote\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_weights\",\"type\":\"uint256[]\"}],\"name\":\"vote\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"votes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"weights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"whitelist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Voter.sol\":\"Voter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Voter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/libraries/Math.sol';\\nimport 'contracts/interfaces/IBribe.sol';\\nimport 'contracts/interfaces/IBribeFactory.sol';\\nimport 'contracts/interfaces/IGauge.sol';\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/interfaces/IERC20.sol';\\nimport 'contracts/interfaces/IMinter.sol';\\nimport 'contracts/interfaces/IPair.sol';\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/interfaces/IVoter.sol';\\nimport 'contracts/interfaces/IVotingEscrow.sol';\\n\\ncontract Voter is IVoter {\\n\\n address public immutable _ve; // the ve token that governs these contracts\\n address public immutable factory; // the PairFactory\\n address internal immutable base;\\n address public immutable gaugefactory;\\n address public immutable bribefactory;\\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\\n address public minter;\\n address public governor; // should be set to an IGovernor\\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\\n\\n uint public totalWeight; // total voting weight\\n\\n address[] public pools; // all pools viable for incentives\\n mapping(address => address) public gauges; // pool => gauge\\n mapping(address => address) public poolForGauge; // gauge => pool\\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\\n mapping(address => uint256) public weights; // pool => weight\\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\\n mapping(uint => address[]) public poolVote; // nft => pools\\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\\n mapping(address => bool) public isGauge;\\n mapping(address => bool) public isWhitelisted;\\n mapping(address => bool) public isAlive;\\n\\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\\n event GaugeKilled(address indexed gauge);\\n event GaugeRevived(address indexed gauge);\\n event Voted(address indexed voter, uint tokenId, uint256 weight);\\n event Abstained(uint tokenId, uint256 weight);\\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\\n event Whitelisted(address indexed whitelister, address indexed token);\\n\\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\\n _ve = __ve;\\n factory = _factory;\\n base = IVotingEscrow(__ve).token();\\n gaugefactory = _gauges;\\n bribefactory = _bribes;\\n minter = msg.sender;\\n governor = msg.sender;\\n emergencyCouncil = msg.sender;\\n }\\n\\n // simple re-entrancy check\\n uint internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n modifier onlyNewEpoch(uint _tokenId) {\\n // ensure new epoch since last vote \\n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \\\"TOKEN_ALREADY_VOTED_THIS_EPOCH\\\");\\n _;\\n }\\n\\n function initialize(address[] memory _tokens, address _minter) external {\\n require(msg.sender == minter);\\n for (uint i = 0; i < _tokens.length; i++) {\\n _whitelist(_tokens[i]);\\n }\\n minter = _minter;\\n }\\n\\n function setGovernor(address _governor) public {\\n require(msg.sender == governor);\\n governor = _governor;\\n }\\n\\n function setEmergencyCouncil(address _council) public {\\n require(msg.sender == emergencyCouncil);\\n emergencyCouncil = _council;\\n }\\n\\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n lastVoted[_tokenId] = block.timestamp;\\n _reset(_tokenId);\\n IVotingEscrow(_ve).abstain(_tokenId);\\n }\\n\\n function _reset(uint _tokenId) internal {\\n address[] storage _poolVote = poolVote[_tokenId];\\n uint _poolVoteCnt = _poolVote.length;\\n uint256 _totalWeight = 0;\\n\\n for (uint i = 0; i < _poolVoteCnt; i ++) {\\n address _pool = _poolVote[i];\\n uint256 _votes = votes[_tokenId][_pool];\\n\\n if (_votes != 0) {\\n _updateFor(gauges[_pool]);\\n weights[_pool] -= _votes;\\n votes[_tokenId][_pool] -= _votes;\\n if (_votes > 0) {\\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n _totalWeight += _votes;\\n } else {\\n _totalWeight -= _votes;\\n }\\n emit Abstained(_tokenId, _votes);\\n }\\n }\\n totalWeight -= uint256(_totalWeight);\\n usedWeights[_tokenId] = 0;\\n delete poolVote[_tokenId];\\n }\\n\\n function poke(uint _tokenId) external {\\n address[] memory _poolVote = poolVote[_tokenId];\\n uint _poolCnt = _poolVote.length;\\n uint256[] memory _weights = new uint256[](_poolCnt);\\n\\n for (uint i = 0; i < _poolCnt; i ++) {\\n _weights[i] = votes[_tokenId][_poolVote[i]];\\n }\\n\\n _vote(_tokenId, _poolVote, _weights);\\n }\\n\\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\\n _reset(_tokenId);\\n uint _poolCnt = _poolVote.length;\\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\\n uint256 _totalVoteWeight = 0;\\n uint256 _totalWeight = 0;\\n uint256 _usedWeight = 0;\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n _totalVoteWeight += _weights[i];\\n }\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n address _pool = _poolVote[i];\\n address _gauge = gauges[_pool];\\n\\n if (isGauge[_gauge]) {\\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\\n require(votes[_tokenId][_pool] == 0);\\n require(_poolWeight != 0);\\n _updateFor(_gauge);\\n\\n poolVote[_tokenId].push(_pool);\\n\\n weights[_pool] += _poolWeight;\\n votes[_tokenId][_pool] += _poolWeight;\\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n _usedWeight += _poolWeight;\\n _totalWeight += _poolWeight;\\n emit Voted(msg.sender, _tokenId, _poolWeight);\\n }\\n }\\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\\n totalWeight += uint256(_totalWeight);\\n usedWeights[_tokenId] = uint256(_usedWeight);\\n }\\n\\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n require(_poolVote.length == _weights.length);\\n lastVoted[tokenId] = block.timestamp;\\n _vote(tokenId, _poolVote, _weights);\\n }\\n\\n function whitelist(address _token) public {\\n require(msg.sender == governor);\\n _whitelist(_token);\\n }\\n\\n function _whitelist(address _token) internal {\\n require(!isWhitelisted[_token]);\\n isWhitelisted[_token] = true;\\n emit Whitelisted(msg.sender, _token);\\n }\\n\\n function createGauge(address _pool) external returns (address) {\\n require(gauges[_pool] == address(0x0), \\\"exists\\\");\\n address[] memory allowedRewards = new address[](3);\\n address[] memory internalRewards = new address[](2);\\n bool isPair = IPairFactory(factory).isPair(_pool);\\n address tokenA;\\n address tokenB;\\n\\n if (isPair) {\\n (tokenA, tokenB) = IPair(_pool).tokens();\\n allowedRewards[0] = tokenA;\\n allowedRewards[1] = tokenB;\\n internalRewards[0] = tokenA;\\n internalRewards[1] = tokenB;\\n\\n if (base != tokenA && base != tokenB) {\\n allowedRewards[2] = base;\\n }\\n }\\n\\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\\n require(isPair, \\\"!_pool\\\");\\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \\\"!whitelisted\\\");\\n }\\n\\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\\n\\n IERC20(base).approve(_gauge, type(uint).max);\\n internal_bribes[_gauge] = _internal_bribe;\\n external_bribes[_gauge] = _external_bribe;\\n gauges[_pool] = _gauge;\\n poolForGauge[_gauge] = _pool;\\n isGauge[_gauge] = true;\\n isAlive[_gauge] = true;\\n _updateFor(_gauge);\\n pools.push(_pool);\\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\\n return _gauge;\\n }\\n\\n function killGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(isAlive[_gauge], \\\"gauge already dead\\\");\\n isAlive[_gauge] = false;\\n claimable[_gauge] = 0;\\n emit GaugeKilled(_gauge);\\n }\\n\\n function reviveGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(!isAlive[_gauge], \\\"gauge already alive\\\");\\n isAlive[_gauge] = true;\\n emit GaugeRevived(_gauge);\\n }\\n\\n function attachTokenToGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\\n emit Attach(account, msg.sender, tokenId);\\n }\\n\\n function emitDeposit(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]);\\n emit Deposit(account, msg.sender, tokenId, amount);\\n }\\n\\n function detachTokenFromGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\\n emit Detach(account, msg.sender, tokenId);\\n }\\n\\n function emitWithdraw(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n emit Withdraw(account, msg.sender, tokenId, amount);\\n }\\n\\n function length() external view returns (uint) {\\n return pools.length;\\n }\\n\\n uint internal index;\\n mapping(address => uint) internal supplyIndex;\\n mapping(address => uint) public claimable;\\n\\n function notifyRewardAmount(uint amount) external {\\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index += _ratio;\\n }\\n emit NotifyReward(msg.sender, base, amount);\\n }\\n\\n function updateFor(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n _updateFor(_gauges[i]);\\n }\\n }\\n\\n function updateForRange(uint start, uint end) public {\\n for (uint i = start; i < end; i++) {\\n _updateFor(gauges[pools[i]]);\\n }\\n }\\n\\n function updateAll() external {\\n updateForRange(0, pools.length);\\n }\\n\\n function updateGauge(address _gauge) external {\\n _updateFor(_gauge);\\n }\\n\\n function _updateFor(address _gauge) internal {\\n address _pool = poolForGauge[_gauge];\\n uint256 _supplied = weights[_pool];\\n if (_supplied > 0) {\\n uint _supplyIndex = supplyIndex[_gauge];\\n uint _index = index; // get global index0 for accumulated distro\\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\\n if (_delta > 0) {\\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\\n if (isAlive[_gauge]) {\\n claimable[_gauge] += _share;\\n }\\n }\\n } else {\\n supplyIndex[_gauge] = index; // new users are set to the default global state\\n }\\n }\\n\\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\\n }\\n }\\n\\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _bribes.length; i++) {\\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _fees.length; i++) {\\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function distributeFees(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n if (IGauge(_gauges[i]).isForPair()){\\n IGauge(_gauges[i]).claimFees();\\n }\\n }\\n }\\n\\n function distribute(address _gauge) public lock {\\n IMinter(minter).update_period();\\n _updateFor(_gauge); // should set claimable to 0 if killed\\n uint _claimable = claimable[_gauge];\\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\\n claimable[_gauge] = 0;\\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\\n emit DistributeReward(msg.sender, _gauge, _claimable);\\n }\\n }\\n\\n function distro() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute(uint start, uint finish) public {\\n for (uint x = start; x < finish; x++) {\\n distribute(gauges[pools[x]]);\\n }\\n }\\n\\n function distribute(address[] memory _gauges) external {\\n for (uint x = 0; x < _gauges.length; x++) {\\n distribute(_gauges[x]);\\n }\\n }\\n\\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2ff3fc2765dfa0c54870e428d3a2c625f413fb6e10ed7742e786ab4404aae6dc\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x61012060405260016011553480156200001757600080fd5b5060405162003656380380620036568339810160408190526200003a916200011c565b6001600160a01b03808516608081905290841660a05260408051637e062a3560e11b8152905163fc0c546a916004808201926020929091908290030181865afa1580156200008c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b2919062000179565b6001600160a01b0390811660c05291821660e0521661010052505060008054336001600160a01b03199182168117909255600180548216831790556002805490911690911790556200019e565b80516001600160a01b03811681146200011757600080fd5b919050565b600080600080608085870312156200013357600080fd5b6200013e85620000ff565b93506200014e60208601620000ff565b92506200015e60408601620000ff565b91506200016e60608601620000ff565b905092959194509250565b6000602082840312156200018c57600080fd5b6200019782620000ff565b9392505050565b60805160a05160c05160e051610100516133e062000276600039600081816103e701528181611c680152611ce60152600081816104d30152611d79015260008181610b9401528181610c0d01528181610edd01528181610f9901528181611acd01528181611b0601528181611b380152611e5a0152600081816106fc015261192401526000818161058c0152818161092b015281816109d701528181610c9a01528181611069015281816111ea0152818161131a015281816114d901528181611dab015281816125e501526129a801526133e06000f3fe608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea2646970667358221220efdf32d446dea7220cae45ea22975b1081b44ec8e633c8802ff0585e94e083c564736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea2646970667358221220efdf32d446dea7220cae45ea22975b1081b44ec8e633c8802ff0585e94e083c564736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/VotingEscrow.json b/deployments/arbitrumGoerli/VotingEscrow.json index 842958fb..e9e3d429 100644 --- a/deployments/arbitrumGoerli/VotingEscrow.json +++ b/deployments/arbitrumGoerli/VotingEscrow.json @@ -1,5 +1,5 @@ { - "address": "0x6b938BA22FB5520fFB5D14c9C4Fef82a48761497", + "address": "0xCDAF5f01849Fff0a9E36D768B2ae7354A98360c0", "abi": [ { "inputs": [ @@ -1521,62 +1521,62 @@ "type": "function" } ], - "transactionHash": "0xe05d10a4cc87b56cdd16015b6af08bcda78ccecebe822f74b7ca5aaf6a83b5b6", + "transactionHash": "0x514a01a37dfc40d4174ba7a26e0059366c7412e6fd3390ccdd879b0dce4c5422", "receipt": { "to": null, "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0x6b938BA22FB5520fFB5D14c9C4Fef82a48761497", + "contractAddress": "0xCDAF5f01849Fff0a9E36D768B2ae7354A98360c0", "transactionIndex": 1, - "gasUsed": "44732908", - "logsBloom": "0x00000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000400000000000008000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000010000000000000000000000000000020000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000020000000000000000000000002000000000000000000000000000000000000000000", - "blockHash": "0x375ed9ee32d98b6b4e0d006b9633efa2410d424c5b2a9d6cfe4faab534eca831", - "transactionHash": "0xe05d10a4cc87b56cdd16015b6af08bcda78ccecebe822f74b7ca5aaf6a83b5b6", + "gasUsed": "81633251", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000008000000000000000000200000000000000000000000000000028000000000000000000800000000000000000000000010000000000000000000800000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000400", + "blockHash": "0x3ec3c1b2a1ad06a8f20452cab4fa8be7b5f90e901a92921de7e4c6878f75fea5", + "transactionHash": "0x514a01a37dfc40d4174ba7a26e0059366c7412e6fd3390ccdd879b0dce4c5422", "logs": [ { "transactionIndex": 1, - "blockNumber": 4195018, - "transactionHash": "0xe05d10a4cc87b56cdd16015b6af08bcda78ccecebe822f74b7ca5aaf6a83b5b6", - "address": "0x6b938BA22FB5520fFB5D14c9C4Fef82a48761497", + "blockNumber": 4263689, + "transactionHash": "0x514a01a37dfc40d4174ba7a26e0059366c7412e6fd3390ccdd879b0dce4c5422", + "address": "0xCDAF5f01849Fff0a9E36D768B2ae7354A98360c0", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000006b938ba22fb5520ffb5d14c9c4fef82a48761497", + "0x000000000000000000000000cdaf5f01849fff0a9e36d768b2ae7354a98360c0", "0x0000000000000000000000000000000000000000000000000000000000000000" ], "data": "0x", "logIndex": 0, - "blockHash": "0x375ed9ee32d98b6b4e0d006b9633efa2410d424c5b2a9d6cfe4faab534eca831" + "blockHash": "0x3ec3c1b2a1ad06a8f20452cab4fa8be7b5f90e901a92921de7e4c6878f75fea5" }, { "transactionIndex": 1, - "blockNumber": 4195018, - "transactionHash": "0xe05d10a4cc87b56cdd16015b6af08bcda78ccecebe822f74b7ca5aaf6a83b5b6", - "address": "0x6b938BA22FB5520fFB5D14c9C4Fef82a48761497", + "blockNumber": 4263689, + "transactionHash": "0x514a01a37dfc40d4174ba7a26e0059366c7412e6fd3390ccdd879b0dce4c5422", + "address": "0xCDAF5f01849Fff0a9E36D768B2ae7354A98360c0", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x0000000000000000000000006b938ba22fb5520ffb5d14c9c4fef82a48761497", + "0x000000000000000000000000cdaf5f01849fff0a9e36d768b2ae7354a98360c0", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000" ], "data": "0x", "logIndex": 1, - "blockHash": "0x375ed9ee32d98b6b4e0d006b9633efa2410d424c5b2a9d6cfe4faab534eca831" + "blockHash": "0x3ec3c1b2a1ad06a8f20452cab4fa8be7b5f90e901a92921de7e4c6878f75fea5" } ], - "blockNumber": 4195018, - "cumulativeGasUsed": "44732908", + "blockNumber": 4263689, + "cumulativeGasUsed": "81633251", "status": 1, "byzantium": true }, "args": [ - "0xe69b00A164047e7eB87B73971B0f340eEbFF9c81", - "0x5e7569D02214289490d16bCE4F96B38071db1aD8" + "0x162404E6Cd4633656925b90EF67237F29D5cc85c", + "0xB143E062f93E7d4F9f7B2b7127861c72Fb2ADF82" ], - "numDeployments": 4, - "solcInputHash": "0faaa79d8b79020b765ba7705413c447", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token_addr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"art_proxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromDelegate\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toDelegate\",\"type\":\"address\"}],\"name\":\"DelegateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"DelegateVotesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"locktime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum VotingEscrow.DepositType\",\"name\":\"deposit_type\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"prevSupply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"supply\",\"type\":\"uint256\"}],\"name\":\"Supply\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DELEGATION_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_DELEGATES\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"abstain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_approved\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"artProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"attach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"attachments\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"balanceOfAtNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_t\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFTAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"block_number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"checkpoints\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"create_lock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"create_lock_for\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"}],\"name\":\"delegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"delegateBySig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"}],\"name\":\"delegates\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"deposit_for\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"detach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastTotalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotesIndex\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"get_last_user_slope\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"increase_amount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"increase_unlock_time\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"isApprovedOrOwner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"locked\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"amount\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"locked__end\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_from\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_to\",\"type\":\"uint256\"}],\"name\":\"merge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"numCheckpoints\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ownership_change\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_proxy\",\"type\":\"address\"}],\"name\":\"setArtProxy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voter\",\"type\":\"address\"}],\"name\":\"setVoter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"slope_changes\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenIndex\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"t\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAtT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_idx\",\"type\":\"uint256\"}],\"name\":\"user_point_history__ts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"voted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"voting\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\",\"details\":\"Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\",\"kind\":\"dev\",\"methods\":{\"approve(address,uint256)\":{\"details\":\"Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address. Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner. Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP) Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"Address to be approved for the given NFT ID.\",\"_tokenId\":\"ID of the token to be approved.\"}},\"balanceOf(address)\":{\"details\":\"Returns the number of NFTs owned by `_owner`. Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\",\"params\":{\"_owner\":\"Address for whom to query the balance.\"}},\"constructor\":{\"params\":{\"token_addr\":\"`VELO` token address\"}},\"create_lock(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_value\":\"Amount to deposit\"}},\"create_lock_for(uint256,uint256,address)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_to\":\"Address to deposit\",\"_value\":\"Amount to deposit\"}},\"delegate(address)\":{\"params\":{\"delegatee\":\"The address to delegate votes to\"}},\"delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Delegates votes from signer to `delegatee`.\"},\"deposit_for(uint256,uint256)\":{\"details\":\"Anyone (even a smart contract) can deposit for someone else, but cannot extend their locktime and deposit for a brand new user\",\"params\":{\"_tokenId\":\"lock NFT\",\"_value\":\"Amount to add to user's lock\"}},\"getApproved(uint256)\":{\"details\":\"Get the approved address for a single NFT.\",\"params\":{\"_tokenId\":\"ID of the NFT to query the approval of.\"}},\"getVotes(address)\":{\"params\":{\"account\":\"The address to get votes balance\"},\"returns\":{\"_0\":\"The number of current votes for `account`\"}},\"get_last_user_slope(uint256)\":{\"params\":{\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Value of the slope\"}},\"increase_amount(uint256,uint256)\":{\"params\":{\"_value\":\"Amount of tokens to deposit and add to the lock\"}},\"increase_unlock_time(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"New number of seconds until tokens unlock\"}},\"isApprovedForAll(address,address)\":{\"details\":\"Checks if `_operator` is an approved operator for `_owner`.\",\"params\":{\"_operator\":\"The address that acts on behalf of the owner.\",\"_owner\":\"The address that owns the NFTs.\"}},\"locked__end(uint256)\":{\"params\":{\"_tokenId\":\"User NFT\"},\"returns\":{\"_0\":\"Epoch time of the lock end\"}},\"ownerOf(uint256)\":{\"details\":\"Returns the address of the owner of the NFT.\",\"params\":{\"_tokenId\":\"The identifier for an NFT.\"}},\"safeTransferFrom(address,address,uint256)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"safeTransferFrom(address,address,uint256,bytes)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_data\":\"Additional data with no specified format, sent in call to `_to`.\",\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"details\":\"Enables or disables approval for a third party (\\\"operator\\\") to manage all of `msg.sender`'s assets. It also emits the ApprovalForAll event. Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"True if the operators is approved, false to revoke approval.\",\"_operator\":\"Address to add to the set of authorized operators.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Interface identification is specified in ERC-165.\",\"params\":{\"_interfaceID\":\"Id of the interface\"}},\"tokenOfOwnerByIndex(address,uint256)\":{\"details\":\"Get token by index\"},\"tokenURI(uint256)\":{\"details\":\"Returns current token URI metadata\",\"params\":{\"_tokenId\":\"Token ID to fetch URI for.\"}},\"totalSupplyAt(uint256)\":{\"params\":{\"_block\":\"Block to calculate the total voting power at\"},\"returns\":{\"_0\":\"Total voting power at `_block`\"}},\"totalSupplyAtT(uint256)\":{\"details\":\"Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\",\"returns\":{\"_0\":\"Total voting power\"}},\"transferFrom(address,address,uint256)\":{\"details\":\"Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"user_point_history__ts(uint256,uint256)\":{\"params\":{\"_idx\":\"User epoch number\",\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Epoch time of the checkpoint\"}},\"withdraw(uint256)\":{\"details\":\"Only possible if the lock has expired\"}},\"stateVariables\":{\"ERC165_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC165\"},\"ERC721_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721\"},\"ERC721_METADATA_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721Metadata\"},\"_not_entered\":{\"details\":\"reentrancy guard\"},\"idToApprovals\":{\"details\":\"Mapping from NFT ID to approved address.\"},\"idToOwner\":{\"details\":\"Mapping from NFT ID to the address that owns it.\"},\"name\":{\"details\":\"Returns the token collection name.\"},\"ownerToNFTokenCount\":{\"details\":\"Mapping from owner address to count of his tokens.\"},\"ownerToNFTokenIdList\":{\"details\":\"Mapping from owner address to mapping of index to tokenIds\"},\"ownerToOperators\":{\"details\":\"Mapping from owner address to mapping of operator addresses.\"},\"supportedInterfaces\":{\"details\":\"Mapping of interface id to bool about whether or not it's supported\"},\"symbol\":{\"details\":\"Returns the token collection symbol.\"},\"tokenId\":{\"details\":\"Current count of token\"},\"tokenToOwnerIndex\":{\"details\":\"Mapping from NFT ID to index of owner\"}},\"title\":\"Voting Escrow\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DELEGATION_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the delegation struct used by the contract\"},\"DOMAIN_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the contract's domain\"},\"checkpoint()\":{\"notice\":\"Record global data to checkpoint\"},\"checkpoints(address,uint32)\":{\"notice\":\"A record of delegated token checkpoints for each account, by index\"},\"constructor\":{\"notice\":\"Contract constructor\"},\"create_lock(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\"},\"create_lock_for(uint256,uint256,address)\":{\"notice\":\"Deposit `_value` tokens for `_to` and lock for `_lock_duration`\"},\"delegate(address)\":{\"notice\":\"Delegate votes from `msg.sender` to `delegatee`\"},\"delegates(address)\":{\"notice\":\"Overrides the standard `Comp.sol` delegates mapping to return the delegator's own address if they haven't delegated. This avoids having to delegate to oneself.\"},\"deposit_for(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `_tokenId` and add to the lock\"},\"getVotes(address)\":{\"notice\":\"Gets the current votes balance for `account`\"},\"get_last_user_slope(uint256)\":{\"notice\":\"Get the most recently recorded rate of voting power decrease for `_tokenId`\"},\"increase_amount(uint256,uint256)\":{\"notice\":\"Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\"},\"increase_unlock_time(uint256,uint256)\":{\"notice\":\"Extend the unlock time for `_tokenId`\"},\"locked__end(uint256)\":{\"notice\":\"Get timestamp when `_tokenId`'s lock finishes\"},\"nonces(address)\":{\"notice\":\"A record of states for signing / validating signatures\"},\"numCheckpoints(address)\":{\"notice\":\"The number of checkpoints for each account\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"This works even if sender doesn't own any tokens at the time.\"},\"totalSupplyAt(uint256)\":{\"notice\":\"Calculate total voting power at some point in the past\"},\"totalSupplyAtT(uint256)\":{\"notice\":\"Calculate total voting power\"},\"transferFrom(address,address,uint256)\":{\"notice\":\"The caller is responsible to confirm that `_to` is capable of receiving NFTs or else they maybe be permanently lost.\"},\"user_point_history__ts(uint256,uint256)\":{\"notice\":\"Get the timestamp for checkpoint `_idx` for `_tokenId`\"},\"withdraw(uint256)\":{\"notice\":\"Withdraw all tokens for `_tokenId`\"}},\"notice\":\"veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFTVotes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VotingEscrow.sol\":\"VotingEscrow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733323636393538333833\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VotingEscrow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IERC721, IERC721Metadata} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {IERC721Receiver} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {IERC20} from \\\"contracts/interfaces/IERC20.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\nimport {IVotingEscrow} from \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/// @title Voting Escrow\\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\\n enum DepositType {\\n DEPOSIT_FOR_TYPE,\\n CREATE_LOCK_TYPE,\\n INCREASE_LOCK_AMOUNT,\\n INCREASE_UNLOCK_TIME,\\n MERGE_TYPE\\n }\\n\\n struct LockedBalance {\\n int128 amount;\\n uint end;\\n }\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint ts;\\n uint blk; // block\\n }\\n /* We cannot really do block numbers per se b/c slope is per time, not per block\\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\\n * What we can do is to extrapolate ***At functions */\\n\\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\\n struct Checkpoint {\\n uint timestamp;\\n uint[] tokenIds;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Deposit(\\n address indexed provider,\\n uint tokenId,\\n uint value,\\n uint indexed locktime,\\n DepositType deposit_type,\\n uint ts\\n );\\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\\n event Supply(uint prevSupply, uint supply);\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n address public immutable token;\\n address public voter;\\n address public team;\\n address public artProxy;\\n\\n mapping(uint => Point) public point_history; // epoch -> unsigned point\\n\\n /// @dev Mapping of interface id to bool about whether or not it's supported\\n mapping(bytes4 => bool) internal supportedInterfaces;\\n\\n /// @dev ERC165 interface ID of ERC165\\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\\n\\n /// @dev ERC165 interface ID of ERC721\\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\\n\\n /// @dev ERC165 interface ID of ERC721Metadata\\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\\n\\n /// @dev Current count of token\\n uint internal tokenId;\\n\\n /// @notice Contract constructor\\n /// @param token_addr `VELO` token address\\n constructor(address token_addr, address art_proxy) {\\n token = token_addr;\\n voter = msg.sender;\\n team = msg.sender;\\n artProxy = art_proxy;\\n\\n point_history[0].blk = block.number;\\n point_history[0].ts = block.timestamp;\\n\\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\\n\\n // mint-ish\\n emit Transfer(address(0), address(this), tokenId);\\n // burn-ish\\n emit Transfer(address(this), address(0), tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n MODIFIERS\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev reentrancy guard\\n uint8 internal constant _not_entered = 1;\\n uint8 internal constant _entered = 2;\\n uint8 internal _entered_state = 1;\\n modifier nonreentrant() {\\n require(_entered_state == _not_entered);\\n _entered_state = _entered;\\n _;\\n _entered_state = _not_entered;\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string constant public name = \\\"veNFT\\\";\\n string constant public symbol = \\\"veNFT\\\";\\n string constant public version = \\\"1.0.0\\\";\\n uint8 constant public decimals = 18;\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team);\\n team = _team;\\n }\\n\\n function setArtProxy(address _proxy) external {\\n require(msg.sender == team);\\n artProxy = _proxy;\\n }\\n\\n /// @dev Returns current token URI metadata\\n /// @param _tokenId Token ID to fetch URI for.\\n function tokenURI(uint _tokenId) external view returns (string memory) {\\n require(idToOwner[_tokenId] != address(0), \\\"Query for nonexistent token\\\");\\n LockedBalance memory _locked = locked[_tokenId];\\n return IVeArtProxy(artProxy)._tokenURI(\\n _tokenId,\\n _balanceOfNFT(_tokenId, block.timestamp),\\n _locked.end,\\n uint(int256(_locked.amount))\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 BALANCE/OWNER STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to the address that owns it.\\n mapping(uint => address) internal idToOwner;\\n\\n /// @dev Mapping from owner address to count of his tokens.\\n mapping(address => uint) internal ownerToNFTokenCount;\\n\\n /// @dev Returns the address of the owner of the NFT.\\n /// @param _tokenId The identifier for an NFT.\\n function ownerOf(uint _tokenId) public view returns (address) {\\n return idToOwner[_tokenId];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function _balance(address _owner) internal view returns (uint) {\\n return ownerToNFTokenCount[_owner];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function balanceOf(address _owner) external view returns (uint) {\\n return _balance(_owner);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 APPROVAL STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to approved address.\\n mapping(uint => address) internal idToApprovals;\\n\\n /// @dev Mapping from owner address to mapping of operator addresses.\\n mapping(address => mapping(address => bool)) internal ownerToOperators;\\n\\n mapping(uint => uint) public ownership_change;\\n\\n /// @dev Get the approved address for a single NFT.\\n /// @param _tokenId ID of the NFT to query the approval of.\\n function getApproved(uint _tokenId) external view returns (address) {\\n return idToApprovals[_tokenId];\\n }\\n\\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\\n /// @param _owner The address that owns the NFTs.\\n /// @param _operator The address that acts on behalf of the owner.\\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\\n return (ownerToOperators[_owner])[_operator];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\\n /// @param _approved Address to be approved for the given NFT ID.\\n /// @param _tokenId ID of the token to be approved.\\n function approve(address _approved, uint _tokenId) public {\\n address owner = idToOwner[_tokenId];\\n // Throws if `_tokenId` is not a valid NFT\\n require(owner != address(0));\\n // Throws if `_approved` is the current owner\\n require(_approved != owner);\\n // Check requirements\\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\\n require(senderIsOwner || senderIsApprovedForAll);\\n // Set the approval\\n idToApprovals[_tokenId] = _approved;\\n emit Approval(owner, _approved, _tokenId);\\n }\\n\\n /// @dev Enables or disables approval for a third party (\\\"operator\\\") to manage all of\\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\\n /// @notice This works even if sender doesn't own any tokens at the time.\\n /// @param _operator Address to add to the set of authorized operators.\\n /// @param _approved True if the operators is approved, false to revoke approval.\\n function setApprovalForAll(address _operator, bool _approved) external {\\n // Throws if `_operator` is the `msg.sender`\\n assert(_operator != msg.sender);\\n ownerToOperators[msg.sender][_operator] = _approved;\\n emit ApprovalForAll(msg.sender, _operator, _approved);\\n }\\n\\n /* TRANSFER FUNCTIONS */\\n /// @dev Clear an approval of a given address\\n /// Throws if `_owner` is not the current owner.\\n function _clearApproval(address _owner, uint _tokenId) internal {\\n // Throws if `_owner` is not the current owner\\n assert(idToOwner[_tokenId] == _owner);\\n if (idToApprovals[_tokenId] != address(0)) {\\n // Reset approvals\\n idToApprovals[_tokenId] = address(0);\\n }\\n }\\n\\n /// @dev Returns whether the given spender can transfer a given token ID\\n /// @param _spender address of the spender to query\\n /// @param _tokenId uint ID of the token to be transferred\\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\\n address owner = idToOwner[_tokenId];\\n bool spenderIsOwner = owner == _spender;\\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\\n }\\n\\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\\n return _isApprovedOrOwner(_spender, _tokenId);\\n }\\n\\n /// @dev Exeute transfer of a NFT.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_tokenId` is not a valid NFT.\\n function _transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n address _sender\\n ) internal {\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n // Check requirements\\n require(_isApprovedOrOwner(_sender, _tokenId));\\n // Clear approval. Throws if `_from` is not the current owner\\n _clearApproval(_from, _tokenId);\\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\\n _removeTokenFrom(_from, _tokenId);\\n // auto re-delegate\\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\\n // Add NFT\\n _addTokenTo(_to, _tokenId);\\n // Set the block of ownership transfer (for Flash NFT protection)\\n ownership_change[_tokenId] = block.number;\\n // Log the transfer\\n emit Transfer(_from, _to, _tokenId);\\n }\\n\\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\\n /// they maybe be permanently lost.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n safeTransferFrom(_from, _to, _tokenId, \\\"\\\");\\n }\\n\\n function _isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n uint size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n /// @param _data Additional data with no specified format, sent in call to `_to`.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n bytes memory _data\\n ) public {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n\\n if (_isContract(_to)) {\\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\\n revert(\\\"ERC721: ERC721Receiver rejected tokens\\\");\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert('ERC721: transfer to non ERC721Receiver implementer');\\n } else {\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC165 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Interface identification is specified in ERC-165.\\n /// @param _interfaceID Id of the interface\\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\\n return supportedInterfaces[_interfaceID];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from owner address to mapping of index to tokenIds\\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\\n\\n /// @dev Mapping from NFT ID to index of owner\\n mapping(uint => uint) internal tokenToOwnerIndex;\\n\\n /// @dev Get token by index\\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\\n return ownerToNFTokenIdList[_owner][_tokenIndex];\\n }\\n\\n /// @dev Add a NFT to an index mapping to a given address\\n /// @param _to address of the receiver\\n /// @param _tokenId uint ID Of the token to be added\\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\\n uint current_count = _balance(_to);\\n\\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\\n tokenToOwnerIndex[_tokenId] = current_count;\\n }\\n\\n /// @dev Add a NFT to a given address\\n /// Throws if `_tokenId` is owned by someone.\\n function _addTokenTo(address _to, uint _tokenId) internal {\\n // Throws if `_tokenId` is owned by someone\\n assert(idToOwner[_tokenId] == address(0));\\n // Change the owner\\n idToOwner[_tokenId] = _to;\\n // Update owner token index tracking\\n _addTokenToOwnerList(_to, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_to] += 1;\\n }\\n\\n /// @dev Function to mint tokens\\n /// Throws if `_to` is zero address.\\n /// Throws if `_tokenId` is owned by someone.\\n /// @param _to The address that will receive the minted tokens.\\n /// @param _tokenId The token id to mint.\\n /// @return A boolean that indicates if the operation was successful.\\n function _mint(address _to, uint _tokenId) internal returns (bool) {\\n // Throws if `_to` is zero address\\n assert(_to != address(0));\\n // checkpoint for gov\\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\\n // Add NFT. Throws if `_tokenId` is owned by someone\\n _addTokenTo(_to, _tokenId);\\n emit Transfer(address(0), _to, _tokenId);\\n return true;\\n }\\n\\n /// @dev Remove a NFT from an index mapping to a given address\\n /// @param _from address of the sender\\n /// @param _tokenId uint ID Of the token to be removed\\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\\n // Delete\\n uint current_count = _balance(_from) - 1;\\n uint current_index = tokenToOwnerIndex[_tokenId];\\n\\n if (current_count == current_index) {\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n } else {\\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\\n\\n // Add\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[lastTokenId] = current_index;\\n\\n // Delete\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n }\\n }\\n\\n /// @dev Remove a NFT from a given address\\n /// Throws if `_from` is not the current owner.\\n function _removeTokenFrom(address _from, uint _tokenId) internal {\\n // Throws if `_from` is not the current owner\\n assert(idToOwner[_tokenId] == _from);\\n // Change the owner\\n idToOwner[_tokenId] = address(0);\\n // Update owner token index tracking\\n _removeTokenFromOwnerList(_from, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_from] -= 1;\\n }\\n\\n function _burn(uint _tokenId) internal {\\n require(_isApprovedOrOwner(msg.sender, _tokenId), \\\"caller is not owner nor approved\\\");\\n\\n address owner = ownerOf(_tokenId);\\n\\n // Clear approval\\n approve(address(0), _tokenId);\\n // checkpoint for gov\\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\\n // Remove token\\n _removeTokenFrom(msg.sender, _tokenId);\\n emit Transfer(owner, address(0), _tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public user_point_epoch;\\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\\n mapping(uint => LockedBalance) public locked;\\n uint public epoch;\\n mapping(uint => int128) public slope_changes; // time -> signed slope change\\n uint public supply;\\n\\n uint internal constant WEEK = 1 weeks;\\n uint internal constant MAXTIME = 4 * 365 * 86400;\\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\\n uint internal constant MULTIPLIER = 1 ether;\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @return Value of the slope\\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\\n uint uepoch = user_point_epoch[_tokenId];\\n return user_point_history[_tokenId][uepoch].slope;\\n }\\n\\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @param _idx User epoch number\\n /// @return Epoch time of the checkpoint\\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\\n return user_point_history[_tokenId][_idx].ts;\\n }\\n\\n /// @notice Get timestamp when `_tokenId`'s lock finishes\\n /// @param _tokenId User NFT\\n /// @return Epoch time of the lock end\\n function locked__end(uint _tokenId) external view returns (uint) {\\n return locked[_tokenId].end;\\n }\\n\\n /// @notice Record global and per-user data to checkpoint\\n /// @param _tokenId NFT token ID. No user checkpoint if 0\\n /// @param old_locked Pevious locked amount / end lock time for the user\\n /// @param new_locked New locked amount / end lock time for the user\\n function _checkpoint(\\n uint _tokenId,\\n LockedBalance memory old_locked,\\n LockedBalance memory new_locked\\n ) internal {\\n Point memory u_old;\\n Point memory u_new;\\n int128 old_dslope = 0;\\n int128 new_dslope = 0;\\n uint _epoch = epoch;\\n\\n if (_tokenId != 0) {\\n // Calculate slopes and biases\\n // Kept at zero when they have to\\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\\n u_old.slope = old_locked.amount / iMAXTIME;\\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\\n }\\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\\n u_new.slope = new_locked.amount / iMAXTIME;\\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\\n }\\n\\n // Read values of scheduled changes in the slope\\n // old_locked.end can be in the past and in the future\\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\\n old_dslope = slope_changes[old_locked.end];\\n if (new_locked.end != 0) {\\n if (new_locked.end == old_locked.end) {\\n new_dslope = old_dslope;\\n } else {\\n new_dslope = slope_changes[new_locked.end];\\n }\\n }\\n }\\n\\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\\n if (_epoch > 0) {\\n last_point = point_history[_epoch];\\n }\\n uint last_checkpoint = last_point.ts;\\n // initial_last_point is used for extrapolation to calculate block number\\n // (approximately, for *At methods) and save them\\n // as we cannot figure that out exactly from inside the contract\\n Point memory initial_last_point = last_point;\\n uint block_slope = 0; // dblock/dt\\n if (block.timestamp > last_point.ts) {\\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\\n }\\n // If last point is already recorded in this block, slope=0\\n // But that's ok b/c we know the block in such case\\n\\n // Go over weeks to fill history and calculate what the current point is\\n {\\n uint t_i = (last_checkpoint / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n // Hopefully it won't happen that this won't get used in 5 years!\\n // If it does, users will be able to withdraw but vote weight will be broken\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > block.timestamp) {\\n t_i = block.timestamp;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\\n last_point.slope += d_slope;\\n if (last_point.bias < 0) {\\n // This can happen\\n last_point.bias = 0;\\n }\\n if (last_point.slope < 0) {\\n // This cannot happen - just in case\\n last_point.slope = 0;\\n }\\n last_checkpoint = t_i;\\n last_point.ts = t_i;\\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\\n _epoch += 1;\\n if (t_i == block.timestamp) {\\n last_point.blk = block.number;\\n break;\\n } else {\\n point_history[_epoch] = last_point;\\n }\\n }\\n }\\n\\n epoch = _epoch;\\n // Now point_history is filled until t=now\\n\\n if (_tokenId != 0) {\\n // If last point was in this block, the slope change has been applied already\\n // But in such case we have 0 slope(s)\\n last_point.slope += (u_new.slope - u_old.slope);\\n last_point.bias += (u_new.bias - u_old.bias);\\n if (last_point.slope < 0) {\\n last_point.slope = 0;\\n }\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n }\\n\\n // Record the changed point into history\\n point_history[_epoch] = last_point;\\n\\n if (_tokenId != 0) {\\n // Schedule the slope changes (slope is going down)\\n // We subtract new_user_slope from [new_locked.end]\\n // and add old_user_slope to [old_locked.end]\\n if (old_locked.end > block.timestamp) {\\n // old_dslope was - u_old.slope, so we cancel that\\n old_dslope += u_old.slope;\\n if (new_locked.end == old_locked.end) {\\n old_dslope -= u_new.slope; // It was a new deposit, not extension\\n }\\n slope_changes[old_locked.end] = old_dslope;\\n }\\n\\n if (new_locked.end > block.timestamp) {\\n if (new_locked.end > old_locked.end) {\\n new_dslope -= u_new.slope; // old slope disappeared at this point\\n slope_changes[new_locked.end] = new_dslope;\\n }\\n // else: we recorded it already in old_dslope\\n }\\n // Now handle user history\\n uint user_epoch = user_point_epoch[_tokenId] + 1;\\n\\n user_point_epoch[_tokenId] = user_epoch;\\n u_new.ts = block.timestamp;\\n u_new.blk = block.number;\\n user_point_history[_tokenId][user_epoch] = u_new;\\n }\\n }\\n\\n /// @notice Deposit and lock tokens for a user\\n /// @param _tokenId NFT that holds lock\\n /// @param _value Amount to deposit\\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\\n /// @param locked_balance Previous locked amount / timestamp\\n /// @param deposit_type The type of deposit\\n function _deposit_for(\\n uint _tokenId,\\n uint _value,\\n uint unlock_time,\\n LockedBalance memory locked_balance,\\n DepositType deposit_type\\n ) internal {\\n LockedBalance memory _locked = locked_balance;\\n uint supply_before = supply;\\n\\n supply = supply_before + _value;\\n LockedBalance memory old_locked;\\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\\n // Adding to existing lock, or if a lock is expired - creating a new one\\n _locked.amount += int128(int256(_value));\\n if (unlock_time != 0) {\\n _locked.end = unlock_time;\\n }\\n locked[_tokenId] = _locked;\\n\\n // Possibilities:\\n // Both old_locked.end could be current or expired (>/< block.timestamp)\\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\\n // _locked.end > block.timestamp (always)\\n _checkpoint(_tokenId, old_locked, _locked);\\n\\n address from = msg.sender;\\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\\n assert(IERC20(token).transferFrom(from, address(this), _value));\\n }\\n\\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\\n emit Supply(supply_before, supply_before + _value);\\n }\\n\\n function block_number() external view returns (uint) {\\n return block.number;\\n }\\n\\n /// @notice Record global data to checkpoint\\n function checkpoint() external {\\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\\n }\\n\\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\\n /// cannot extend their locktime and deposit for a brand new user\\n /// @param _tokenId lock NFT\\n /// @param _value Amount to add to user's lock\\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n require(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_value > 0); // dev: need non-zero value\\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n ++tokenId;\\n uint _tokenId = tokenId;\\n _mint(_to, _tokenId);\\n\\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\\n return _tokenId;\\n }\\n\\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, msg.sender);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, _to);\\n }\\n\\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\\n /// @param _value Amount of tokens to deposit and add to the lock\\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n assert(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\\n }\\n\\n /// @notice Extend the unlock time for `_tokenId`\\n /// @param _lock_duration New number of seconds until tokens unlock\\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_locked.end > block.timestamp, 'Lock expired');\\n require(_locked.amount > 0, 'Nothing is locked');\\n require(unlock_time > _locked.end, 'Can only increase lock duration');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\\n }\\n\\n /// @notice Withdraw all tokens for `_tokenId`\\n /// @dev Only possible if the lock has expired\\n function withdraw(uint _tokenId) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n require(block.timestamp >= _locked.end, \\\"The lock didn't expire\\\");\\n uint value = uint(int256(_locked.amount));\\n\\n locked[_tokenId] = LockedBalance(0,0);\\n uint supply_before = supply;\\n supply = supply_before - value;\\n\\n // old_locked can have either expired <= timestamp or zero end\\n // _locked has only 0 end\\n // Both can have >= 0 amount\\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\\n\\n assert(IERC20(token).transfer(msg.sender, value));\\n\\n // Burn the NFT\\n _burn(_tokenId);\\n\\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\\n emit Supply(supply_before, supply_before - value);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\\n // They measure the weights for the purpose of voting, so they don't represent\\n // real coins.\\n\\n /// @notice Binary search to estimate timestamp for block number\\n /// @param _block Block to find\\n /// @param max_epoch Don't go beyond this epoch\\n /// @return Approximate timestamp for block\\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\\n // Binary search\\n uint _min = 0;\\n uint _max = max_epoch;\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (point_history[_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n /// @notice Get the current voting power for `_tokenId`\\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\\n /// @param _tokenId NFT for lock\\n /// @param _t Epoch time to return voting power at\\n /// @return User voting power\\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\\n uint _epoch = user_point_epoch[_tokenId];\\n if (_epoch == 0) {\\n return 0;\\n } else {\\n Point memory last_point = user_point_history[_tokenId][_epoch];\\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(int256(last_point.bias));\\n }\\n }\\n\\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\\n if (ownership_change[_tokenId] == block.number) return 0;\\n return _balanceOfNFT(_tokenId, block.timestamp);\\n }\\n\\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\\n return _balanceOfNFT(_tokenId, _t);\\n }\\n\\n /// @notice Measure voting power of `_tokenId` at block height `_block`\\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\\n /// @param _tokenId User's wallet NFT\\n /// @param _block Block to calculate the voting power at\\n /// @return Voting power\\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\\n // Copying and pasting totalSupply code because Vyper cannot pass by\\n // reference yet\\n assert(_block <= block.number);\\n\\n // Binary search\\n uint _min = 0;\\n uint _max = user_point_epoch[_tokenId];\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (user_point_history[_tokenId][_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n\\n Point memory upoint = user_point_history[_tokenId][_min];\\n\\n uint max_epoch = epoch;\\n uint _epoch = _find_block_epoch(_block, max_epoch);\\n Point memory point_0 = point_history[_epoch];\\n uint d_block = 0;\\n uint d_t = 0;\\n if (_epoch < max_epoch) {\\n Point memory point_1 = point_history[_epoch + 1];\\n d_block = point_1.blk - point_0.blk;\\n d_t = point_1.ts - point_0.ts;\\n } else {\\n d_block = block.number - point_0.blk;\\n d_t = block.timestamp - point_0.ts;\\n }\\n uint block_time = point_0.ts;\\n if (d_block != 0) {\\n block_time += (d_t * (_block - point_0.blk)) / d_block;\\n }\\n\\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\\n if (upoint.bias >= 0) {\\n return uint(uint128(upoint.bias));\\n } else {\\n return 0;\\n }\\n }\\n\\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\\n return _balanceOfAtNFT(_tokenId, _block);\\n }\\n\\n /// @notice Calculate total voting power at some point in the past\\n /// @param _block Block to calculate the total voting power at\\n /// @return Total voting power at `_block`\\n function totalSupplyAt(uint _block) external view returns (uint) {\\n assert(_block <= block.number);\\n uint _epoch = epoch;\\n uint target_epoch = _find_block_epoch(_block, _epoch);\\n\\n Point memory point = point_history[target_epoch];\\n uint dt = 0;\\n if (target_epoch < _epoch) {\\n Point memory point_next = point_history[target_epoch + 1];\\n if (point.blk != point_next.blk) {\\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\\n }\\n } else {\\n if (point.blk != block.number) {\\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\\n }\\n }\\n // Now dt contains info on how far are we beyond point\\n return _supply_at(point, point.ts + dt);\\n }\\n /// @notice Calculate total voting power at some point in the past\\n /// @param point The point (bias/slope) to start search from\\n /// @param t Time to calculate the total voting power at\\n /// @return Total voting power at that time\\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\\n Point memory last_point = point;\\n uint t_i = (last_point.ts / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > t) {\\n t_i = t;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\\n if (t_i == t) {\\n break;\\n }\\n last_point.slope += d_slope;\\n last_point.ts = t_i;\\n }\\n\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(uint128(last_point.bias));\\n }\\n\\n function totalSupply() external view returns (uint) {\\n return totalSupplyAtT(block.timestamp);\\n }\\n\\n /// @notice Calculate total voting power\\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\\n /// @return Total voting power\\n function totalSupplyAtT(uint t) public view returns (uint) {\\n uint _epoch = epoch;\\n Point memory last_point = point_history[_epoch];\\n return _supply_at(last_point, t);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public attachments;\\n mapping(uint => bool) public voted;\\n\\n function setVoter(address _voter) external {\\n require(msg.sender == voter);\\n voter = _voter;\\n }\\n\\n function voting(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = true;\\n }\\n\\n function abstain(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = false;\\n }\\n\\n function attach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] + 1;\\n }\\n\\n function detach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] - 1;\\n }\\n\\n function merge(uint _from, uint _to) external {\\n require(attachments[_from] == 0 && !voted[_from], \\\"attached\\\");\\n require(_from != _to);\\n require(_isApprovedOrOwner(msg.sender, _from));\\n require(_isApprovedOrOwner(msg.sender, _to));\\n\\n LockedBalance memory _locked0 = locked[_from];\\n LockedBalance memory _locked1 = locked[_to];\\n uint value0 = uint(int256(_locked0.amount));\\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\\n\\n locked[_from] = LockedBalance(0, 0);\\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\\n _burn(_from);\\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of each accounts delegate\\n mapping(address => address) private _delegates;\\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\\n\\n /// @notice A record of delegated token checkpoints for each account, by index\\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint32) public numCheckpoints;\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping(address => uint) public nonces;\\n\\n /**\\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\\n * the delegator's own address if they haven't delegated.\\n * This avoids having to delegate to oneself.\\n */\\n function delegates(address delegator) public view returns (address) {\\n address current = _delegates[delegator];\\n return current == address(0) ? delegator : current;\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getVotes(address account) external view returns (uint) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n votes = votes + _balanceOfNFT(tId, block.timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint storage cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPastVotes(address account, uint timestamp)\\n public\\n view\\n returns (uint)\\n {\\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\\n // Sum votes\\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n // Use the provided input timestamp here to get the right decay\\n votes = votes + _balanceOfNFT(tId, timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\\n return totalSupplyAtT(timestamp);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _moveTokenDelegates(\\n address srcRep,\\n address dstRep,\\n uint _tokenId\\n ) internal {\\n if (srcRep != dstRep && _tokenId > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except _tokenId\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (tId != _tokenId) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n // All the same plus _tokenId\\n require(\\n dstRepOld.length + 1 <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n dstRepNew.push(_tokenId);\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _findWhatCheckpointToWrite(address account)\\n internal\\n view\\n returns (uint32)\\n {\\n uint _timestamp = block.timestamp;\\n uint32 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n return _nCheckPoints - 1;\\n } else {\\n return _nCheckPoints;\\n }\\n }\\n\\n function _moveAllDelegates(\\n address owner,\\n address srcRep,\\n address dstRep\\n ) internal {\\n // You can only redelegate what you own\\n if (srcRep != dstRep) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except what owner owns\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (idToOwner[tId] != owner) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n uint ownerTokenCount = ownerToNFTokenCount[owner];\\n require(\\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n // All the same\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n // Plus all that's owned\\n for (uint i = 0; i < ownerTokenCount; i++) {\\n uint tId = ownerToNFTokenIdList[owner][i];\\n dstRepNew.push(tId);\\n }\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\\n address currentDelegate = delegates(delegator);\\n\\n _delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n _moveAllDelegates(delegator, currentDelegate, delegatee);\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n if (delegatee == address(0)) delegatee = msg.sender;\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n function delegateBySig(\\n address delegatee,\\n uint nonce,\\n uint expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public {\\n bytes32 domainSeparator = keccak256(\\n abi.encode(\\n DOMAIN_TYPEHASH,\\n keccak256(bytes(name)),\\n keccak256(bytes(version)),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 structHash = keccak256(\\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash)\\n );\\n address signatory = ecrecover(digest, v, r, s);\\n require(\\n signatory != address(0),\\n \\\"VotingEscrow::delegateBySig: invalid signature\\\"\\n );\\n require(\\n nonce == nonces[signatory]++,\\n \\\"VotingEscrow::delegateBySig: invalid nonce\\\"\\n );\\n require(\\n block.timestamp <= expiry,\\n \\\"VotingEscrow::delegateBySig: signature expired\\\"\\n );\\n return _delegate(signatory, delegatee);\\n }\\n}\\n\",\"keccak256\":\"0x37e5ee306472a946a665be22bc1d370d566a575a1fac84f72f97b0575571d40d\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x41bbb2c41036ca64b2f6c9e973e8cfaa113ebc42af86702cd0d267f915a7e886\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60a06040526006805460ff191660011790553480156200001e57600080fd5b5060405162004a1c38038062004a1c8339810160408190526200004191620001b8565b6001600160a01b0382811660805260008054336001600160a01b031991821681178355600180548316909117815560028054909216938516939093179055437f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f0155427f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f005560046020527f9fe05126d2d9ecf60592e254dead906a4b2e492f36cca727682c38e9008c6ac1805460ff1990811684179091557f4267c0a6fd96b7a87f183ee8744f24d011423cd0e0142b3f563f183d8d9a456b8054821684179055635b5e139f60e01b82527e24030bcf4927897dffe721c2d8dda4bfd8910861687c42b03a463b43b04147805490911690921790915560055460405190913091600080516020620049fc833981519152908290a46005546040516000903090600080516020620049fc833981519152908390a45050620001f0565b80516001600160a01b0381168114620001b357600080fd5b919050565b60008060408385031215620001cc57600080fd5b620001d7836200019b565b9150620001e7602084016200019b565b90509250929050565b6080516147e26200021a60003960008181610b220152818161101801526133b501526147e26000f3fe608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea2646970667358221220c2ef8dcbebf2610bd708916a1bc05e287f34d3bec992b138a8433fc96f6e1d1164736f6c634300080d0033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea2646970667358221220c2ef8dcbebf2610bd708916a1bc05e287f34d3bec992b138a8433fc96f6e1d1164736f6c634300080d0033", + "numDeployments": 7, + "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token_addr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"art_proxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromDelegate\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toDelegate\",\"type\":\"address\"}],\"name\":\"DelegateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"DelegateVotesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"locktime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum VotingEscrow.DepositType\",\"name\":\"deposit_type\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"prevSupply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"supply\",\"type\":\"uint256\"}],\"name\":\"Supply\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DELEGATION_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_DELEGATES\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"abstain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_approved\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"artProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"attach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"attachments\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"balanceOfAtNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_t\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFTAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"block_number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"checkpoints\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"create_lock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"create_lock_for\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"}],\"name\":\"delegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"delegateBySig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"}],\"name\":\"delegates\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"deposit_for\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"detach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastTotalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotesIndex\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"get_last_user_slope\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"increase_amount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"increase_unlock_time\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"isApprovedOrOwner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"locked\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"amount\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"locked__end\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_from\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_to\",\"type\":\"uint256\"}],\"name\":\"merge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"numCheckpoints\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ownership_change\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_proxy\",\"type\":\"address\"}],\"name\":\"setArtProxy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voter\",\"type\":\"address\"}],\"name\":\"setVoter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"slope_changes\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenIndex\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"t\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAtT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_idx\",\"type\":\"uint256\"}],\"name\":\"user_point_history__ts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"voted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"voting\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\",\"details\":\"Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\",\"kind\":\"dev\",\"methods\":{\"approve(address,uint256)\":{\"details\":\"Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address. Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner. Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP) Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"Address to be approved for the given NFT ID.\",\"_tokenId\":\"ID of the token to be approved.\"}},\"balanceOf(address)\":{\"details\":\"Returns the number of NFTs owned by `_owner`. Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\",\"params\":{\"_owner\":\"Address for whom to query the balance.\"}},\"constructor\":{\"params\":{\"token_addr\":\"`VELO` token address\"}},\"create_lock(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_value\":\"Amount to deposit\"}},\"create_lock_for(uint256,uint256,address)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_to\":\"Address to deposit\",\"_value\":\"Amount to deposit\"}},\"delegate(address)\":{\"params\":{\"delegatee\":\"The address to delegate votes to\"}},\"delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Delegates votes from signer to `delegatee`.\"},\"deposit_for(uint256,uint256)\":{\"details\":\"Anyone (even a smart contract) can deposit for someone else, but cannot extend their locktime and deposit for a brand new user\",\"params\":{\"_tokenId\":\"lock NFT\",\"_value\":\"Amount to add to user's lock\"}},\"getApproved(uint256)\":{\"details\":\"Get the approved address for a single NFT.\",\"params\":{\"_tokenId\":\"ID of the NFT to query the approval of.\"}},\"getVotes(address)\":{\"params\":{\"account\":\"The address to get votes balance\"},\"returns\":{\"_0\":\"The number of current votes for `account`\"}},\"get_last_user_slope(uint256)\":{\"params\":{\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Value of the slope\"}},\"increase_amount(uint256,uint256)\":{\"params\":{\"_value\":\"Amount of tokens to deposit and add to the lock\"}},\"increase_unlock_time(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"New number of seconds until tokens unlock\"}},\"isApprovedForAll(address,address)\":{\"details\":\"Checks if `_operator` is an approved operator for `_owner`.\",\"params\":{\"_operator\":\"The address that acts on behalf of the owner.\",\"_owner\":\"The address that owns the NFTs.\"}},\"locked__end(uint256)\":{\"params\":{\"_tokenId\":\"User NFT\"},\"returns\":{\"_0\":\"Epoch time of the lock end\"}},\"ownerOf(uint256)\":{\"details\":\"Returns the address of the owner of the NFT.\",\"params\":{\"_tokenId\":\"The identifier for an NFT.\"}},\"safeTransferFrom(address,address,uint256)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"safeTransferFrom(address,address,uint256,bytes)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_data\":\"Additional data with no specified format, sent in call to `_to`.\",\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"details\":\"Enables or disables approval for a third party (\\\"operator\\\") to manage all of `msg.sender`'s assets. It also emits the ApprovalForAll event. Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"True if the operators is approved, false to revoke approval.\",\"_operator\":\"Address to add to the set of authorized operators.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Interface identification is specified in ERC-165.\",\"params\":{\"_interfaceID\":\"Id of the interface\"}},\"tokenOfOwnerByIndex(address,uint256)\":{\"details\":\"Get token by index\"},\"tokenURI(uint256)\":{\"details\":\"Returns current token URI metadata\",\"params\":{\"_tokenId\":\"Token ID to fetch URI for.\"}},\"totalSupplyAt(uint256)\":{\"params\":{\"_block\":\"Block to calculate the total voting power at\"},\"returns\":{\"_0\":\"Total voting power at `_block`\"}},\"totalSupplyAtT(uint256)\":{\"details\":\"Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\",\"returns\":{\"_0\":\"Total voting power\"}},\"transferFrom(address,address,uint256)\":{\"details\":\"Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"user_point_history__ts(uint256,uint256)\":{\"params\":{\"_idx\":\"User epoch number\",\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Epoch time of the checkpoint\"}},\"withdraw(uint256)\":{\"details\":\"Only possible if the lock has expired\"}},\"stateVariables\":{\"ERC165_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC165\"},\"ERC721_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721\"},\"ERC721_METADATA_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721Metadata\"},\"_not_entered\":{\"details\":\"reentrancy guard\"},\"idToApprovals\":{\"details\":\"Mapping from NFT ID to approved address.\"},\"idToOwner\":{\"details\":\"Mapping from NFT ID to the address that owns it.\"},\"name\":{\"details\":\"Returns the token collection name.\"},\"ownerToNFTokenCount\":{\"details\":\"Mapping from owner address to count of his tokens.\"},\"ownerToNFTokenIdList\":{\"details\":\"Mapping from owner address to mapping of index to tokenIds\"},\"ownerToOperators\":{\"details\":\"Mapping from owner address to mapping of operator addresses.\"},\"supportedInterfaces\":{\"details\":\"Mapping of interface id to bool about whether or not it's supported\"},\"symbol\":{\"details\":\"Returns the token collection symbol.\"},\"tokenId\":{\"details\":\"Current count of token\"},\"tokenToOwnerIndex\":{\"details\":\"Mapping from NFT ID to index of owner\"}},\"title\":\"Voting Escrow\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DELEGATION_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the delegation struct used by the contract\"},\"DOMAIN_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the contract's domain\"},\"checkpoint()\":{\"notice\":\"Record global data to checkpoint\"},\"checkpoints(address,uint32)\":{\"notice\":\"A record of delegated token checkpoints for each account, by index\"},\"constructor\":{\"notice\":\"Contract constructor\"},\"create_lock(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\"},\"create_lock_for(uint256,uint256,address)\":{\"notice\":\"Deposit `_value` tokens for `_to` and lock for `_lock_duration`\"},\"delegate(address)\":{\"notice\":\"Delegate votes from `msg.sender` to `delegatee`\"},\"delegates(address)\":{\"notice\":\"Overrides the standard `Comp.sol` delegates mapping to return the delegator's own address if they haven't delegated. This avoids having to delegate to oneself.\"},\"deposit_for(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `_tokenId` and add to the lock\"},\"getVotes(address)\":{\"notice\":\"Gets the current votes balance for `account`\"},\"get_last_user_slope(uint256)\":{\"notice\":\"Get the most recently recorded rate of voting power decrease for `_tokenId`\"},\"increase_amount(uint256,uint256)\":{\"notice\":\"Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\"},\"increase_unlock_time(uint256,uint256)\":{\"notice\":\"Extend the unlock time for `_tokenId`\"},\"locked__end(uint256)\":{\"notice\":\"Get timestamp when `_tokenId`'s lock finishes\"},\"nonces(address)\":{\"notice\":\"A record of states for signing / validating signatures\"},\"numCheckpoints(address)\":{\"notice\":\"The number of checkpoints for each account\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"This works even if sender doesn't own any tokens at the time.\"},\"totalSupplyAt(uint256)\":{\"notice\":\"Calculate total voting power at some point in the past\"},\"totalSupplyAtT(uint256)\":{\"notice\":\"Calculate total voting power\"},\"transferFrom(address,address,uint256)\":{\"notice\":\"The caller is responsible to confirm that `_to` is capable of receiving NFTs or else they maybe be permanently lost.\"},\"user_point_history__ts(uint256,uint256)\":{\"notice\":\"Get the timestamp for checkpoint `_idx` for `_tokenId`\"},\"withdraw(uint256)\":{\"notice\":\"Withdraw all tokens for `_tokenId`\"}},\"notice\":\"veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFTVotes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VotingEscrow.sol\":\"VotingEscrow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VotingEscrow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IERC721, IERC721Metadata} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {IERC721Receiver} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {IERC20} from \\\"contracts/interfaces/IERC20.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\nimport {IVotingEscrow} from \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/// @title Voting Escrow\\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\\n enum DepositType {\\n DEPOSIT_FOR_TYPE,\\n CREATE_LOCK_TYPE,\\n INCREASE_LOCK_AMOUNT,\\n INCREASE_UNLOCK_TIME,\\n MERGE_TYPE\\n }\\n\\n struct LockedBalance {\\n int128 amount;\\n uint end;\\n }\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint ts;\\n uint blk; // block\\n }\\n /* We cannot really do block numbers per se b/c slope is per time, not per block\\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\\n * What we can do is to extrapolate ***At functions */\\n\\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\\n struct Checkpoint {\\n uint timestamp;\\n uint[] tokenIds;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Deposit(\\n address indexed provider,\\n uint tokenId,\\n uint value,\\n uint indexed locktime,\\n DepositType deposit_type,\\n uint ts\\n );\\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\\n event Supply(uint prevSupply, uint supply);\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n address public immutable token;\\n address public voter;\\n address public team;\\n address public artProxy;\\n\\n mapping(uint => Point) public point_history; // epoch -> unsigned point\\n\\n /// @dev Mapping of interface id to bool about whether or not it's supported\\n mapping(bytes4 => bool) internal supportedInterfaces;\\n\\n /// @dev ERC165 interface ID of ERC165\\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\\n\\n /// @dev ERC165 interface ID of ERC721\\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\\n\\n /// @dev ERC165 interface ID of ERC721Metadata\\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\\n\\n /// @dev Current count of token\\n uint internal tokenId;\\n\\n /// @notice Contract constructor\\n /// @param token_addr `VELO` token address\\n constructor(address token_addr, address art_proxy) {\\n token = token_addr;\\n voter = msg.sender;\\n team = msg.sender;\\n artProxy = art_proxy;\\n\\n point_history[0].blk = block.number;\\n point_history[0].ts = block.timestamp;\\n\\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\\n\\n // mint-ish\\n emit Transfer(address(0), address(this), tokenId);\\n // burn-ish\\n emit Transfer(address(this), address(0), tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n MODIFIERS\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev reentrancy guard\\n uint8 internal constant _not_entered = 1;\\n uint8 internal constant _entered = 2;\\n uint8 internal _entered_state = 1;\\n modifier nonreentrant() {\\n require(_entered_state == _not_entered);\\n _entered_state = _entered;\\n _;\\n _entered_state = _not_entered;\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string constant public name = \\\"veNFT\\\";\\n string constant public symbol = \\\"veNFT\\\";\\n string constant public version = \\\"1.0.0\\\";\\n uint8 constant public decimals = 18;\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team);\\n team = _team;\\n }\\n\\n function setArtProxy(address _proxy) external {\\n require(msg.sender == team);\\n artProxy = _proxy;\\n }\\n\\n /// @dev Returns current token URI metadata\\n /// @param _tokenId Token ID to fetch URI for.\\n function tokenURI(uint _tokenId) external view returns (string memory) {\\n require(idToOwner[_tokenId] != address(0), \\\"Query for nonexistent token\\\");\\n LockedBalance memory _locked = locked[_tokenId];\\n return IVeArtProxy(artProxy)._tokenURI(\\n _tokenId,\\n _balanceOfNFT(_tokenId, block.timestamp),\\n _locked.end,\\n uint(int256(_locked.amount))\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 BALANCE/OWNER STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to the address that owns it.\\n mapping(uint => address) internal idToOwner;\\n\\n /// @dev Mapping from owner address to count of his tokens.\\n mapping(address => uint) internal ownerToNFTokenCount;\\n\\n /// @dev Returns the address of the owner of the NFT.\\n /// @param _tokenId The identifier for an NFT.\\n function ownerOf(uint _tokenId) public view returns (address) {\\n return idToOwner[_tokenId];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function _balance(address _owner) internal view returns (uint) {\\n return ownerToNFTokenCount[_owner];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function balanceOf(address _owner) external view returns (uint) {\\n return _balance(_owner);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 APPROVAL STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to approved address.\\n mapping(uint => address) internal idToApprovals;\\n\\n /// @dev Mapping from owner address to mapping of operator addresses.\\n mapping(address => mapping(address => bool)) internal ownerToOperators;\\n\\n mapping(uint => uint) public ownership_change;\\n\\n /// @dev Get the approved address for a single NFT.\\n /// @param _tokenId ID of the NFT to query the approval of.\\n function getApproved(uint _tokenId) external view returns (address) {\\n return idToApprovals[_tokenId];\\n }\\n\\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\\n /// @param _owner The address that owns the NFTs.\\n /// @param _operator The address that acts on behalf of the owner.\\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\\n return (ownerToOperators[_owner])[_operator];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\\n /// @param _approved Address to be approved for the given NFT ID.\\n /// @param _tokenId ID of the token to be approved.\\n function approve(address _approved, uint _tokenId) public {\\n address owner = idToOwner[_tokenId];\\n // Throws if `_tokenId` is not a valid NFT\\n require(owner != address(0));\\n // Throws if `_approved` is the current owner\\n require(_approved != owner);\\n // Check requirements\\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\\n require(senderIsOwner || senderIsApprovedForAll);\\n // Set the approval\\n idToApprovals[_tokenId] = _approved;\\n emit Approval(owner, _approved, _tokenId);\\n }\\n\\n /// @dev Enables or disables approval for a third party (\\\"operator\\\") to manage all of\\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\\n /// @notice This works even if sender doesn't own any tokens at the time.\\n /// @param _operator Address to add to the set of authorized operators.\\n /// @param _approved True if the operators is approved, false to revoke approval.\\n function setApprovalForAll(address _operator, bool _approved) external {\\n // Throws if `_operator` is the `msg.sender`\\n assert(_operator != msg.sender);\\n ownerToOperators[msg.sender][_operator] = _approved;\\n emit ApprovalForAll(msg.sender, _operator, _approved);\\n }\\n\\n /* TRANSFER FUNCTIONS */\\n /// @dev Clear an approval of a given address\\n /// Throws if `_owner` is not the current owner.\\n function _clearApproval(address _owner, uint _tokenId) internal {\\n // Throws if `_owner` is not the current owner\\n assert(idToOwner[_tokenId] == _owner);\\n if (idToApprovals[_tokenId] != address(0)) {\\n // Reset approvals\\n idToApprovals[_tokenId] = address(0);\\n }\\n }\\n\\n /// @dev Returns whether the given spender can transfer a given token ID\\n /// @param _spender address of the spender to query\\n /// @param _tokenId uint ID of the token to be transferred\\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\\n address owner = idToOwner[_tokenId];\\n bool spenderIsOwner = owner == _spender;\\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\\n }\\n\\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\\n return _isApprovedOrOwner(_spender, _tokenId);\\n }\\n\\n /// @dev Exeute transfer of a NFT.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_tokenId` is not a valid NFT.\\n function _transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n address _sender\\n ) internal {\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n // Check requirements\\n require(_isApprovedOrOwner(_sender, _tokenId));\\n // Clear approval. Throws if `_from` is not the current owner\\n _clearApproval(_from, _tokenId);\\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\\n _removeTokenFrom(_from, _tokenId);\\n // auto re-delegate\\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\\n // Add NFT\\n _addTokenTo(_to, _tokenId);\\n // Set the block of ownership transfer (for Flash NFT protection)\\n ownership_change[_tokenId] = block.number;\\n // Log the transfer\\n emit Transfer(_from, _to, _tokenId);\\n }\\n\\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\\n /// they maybe be permanently lost.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n safeTransferFrom(_from, _to, _tokenId, \\\"\\\");\\n }\\n\\n function _isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n uint size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n /// @param _data Additional data with no specified format, sent in call to `_to`.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n bytes memory _data\\n ) public {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n\\n if (_isContract(_to)) {\\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\\n revert(\\\"ERC721: ERC721Receiver rejected tokens\\\");\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert('ERC721: transfer to non ERC721Receiver implementer');\\n } else {\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC165 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Interface identification is specified in ERC-165.\\n /// @param _interfaceID Id of the interface\\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\\n return supportedInterfaces[_interfaceID];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from owner address to mapping of index to tokenIds\\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\\n\\n /// @dev Mapping from NFT ID to index of owner\\n mapping(uint => uint) internal tokenToOwnerIndex;\\n\\n /// @dev Get token by index\\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\\n return ownerToNFTokenIdList[_owner][_tokenIndex];\\n }\\n\\n /// @dev Add a NFT to an index mapping to a given address\\n /// @param _to address of the receiver\\n /// @param _tokenId uint ID Of the token to be added\\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\\n uint current_count = _balance(_to);\\n\\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\\n tokenToOwnerIndex[_tokenId] = current_count;\\n }\\n\\n /// @dev Add a NFT to a given address\\n /// Throws if `_tokenId` is owned by someone.\\n function _addTokenTo(address _to, uint _tokenId) internal {\\n // Throws if `_tokenId` is owned by someone\\n assert(idToOwner[_tokenId] == address(0));\\n // Change the owner\\n idToOwner[_tokenId] = _to;\\n // Update owner token index tracking\\n _addTokenToOwnerList(_to, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_to] += 1;\\n }\\n\\n /// @dev Function to mint tokens\\n /// Throws if `_to` is zero address.\\n /// Throws if `_tokenId` is owned by someone.\\n /// @param _to The address that will receive the minted tokens.\\n /// @param _tokenId The token id to mint.\\n /// @return A boolean that indicates if the operation was successful.\\n function _mint(address _to, uint _tokenId) internal returns (bool) {\\n // Throws if `_to` is zero address\\n assert(_to != address(0));\\n // checkpoint for gov\\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\\n // Add NFT. Throws if `_tokenId` is owned by someone\\n _addTokenTo(_to, _tokenId);\\n emit Transfer(address(0), _to, _tokenId);\\n return true;\\n }\\n\\n /// @dev Remove a NFT from an index mapping to a given address\\n /// @param _from address of the sender\\n /// @param _tokenId uint ID Of the token to be removed\\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\\n // Delete\\n uint current_count = _balance(_from) - 1;\\n uint current_index = tokenToOwnerIndex[_tokenId];\\n\\n if (current_count == current_index) {\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n } else {\\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\\n\\n // Add\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[lastTokenId] = current_index;\\n\\n // Delete\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n }\\n }\\n\\n /// @dev Remove a NFT from a given address\\n /// Throws if `_from` is not the current owner.\\n function _removeTokenFrom(address _from, uint _tokenId) internal {\\n // Throws if `_from` is not the current owner\\n assert(idToOwner[_tokenId] == _from);\\n // Change the owner\\n idToOwner[_tokenId] = address(0);\\n // Update owner token index tracking\\n _removeTokenFromOwnerList(_from, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_from] -= 1;\\n }\\n\\n function _burn(uint _tokenId) internal {\\n require(_isApprovedOrOwner(msg.sender, _tokenId), \\\"caller is not owner nor approved\\\");\\n\\n address owner = ownerOf(_tokenId);\\n\\n // Clear approval\\n approve(address(0), _tokenId);\\n // checkpoint for gov\\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\\n // Remove token\\n _removeTokenFrom(msg.sender, _tokenId);\\n emit Transfer(owner, address(0), _tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public user_point_epoch;\\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\\n mapping(uint => LockedBalance) public locked;\\n uint public epoch;\\n mapping(uint => int128) public slope_changes; // time -> signed slope change\\n uint public supply;\\n\\n uint internal constant WEEK = 1 weeks;\\n uint internal constant MAXTIME = 4 * 365 * 86400;\\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\\n uint internal constant MULTIPLIER = 1 ether;\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @return Value of the slope\\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\\n uint uepoch = user_point_epoch[_tokenId];\\n return user_point_history[_tokenId][uepoch].slope;\\n }\\n\\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @param _idx User epoch number\\n /// @return Epoch time of the checkpoint\\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\\n return user_point_history[_tokenId][_idx].ts;\\n }\\n\\n /// @notice Get timestamp when `_tokenId`'s lock finishes\\n /// @param _tokenId User NFT\\n /// @return Epoch time of the lock end\\n function locked__end(uint _tokenId) external view returns (uint) {\\n return locked[_tokenId].end;\\n }\\n\\n /// @notice Record global and per-user data to checkpoint\\n /// @param _tokenId NFT token ID. No user checkpoint if 0\\n /// @param old_locked Pevious locked amount / end lock time for the user\\n /// @param new_locked New locked amount / end lock time for the user\\n function _checkpoint(\\n uint _tokenId,\\n LockedBalance memory old_locked,\\n LockedBalance memory new_locked\\n ) internal {\\n Point memory u_old;\\n Point memory u_new;\\n int128 old_dslope = 0;\\n int128 new_dslope = 0;\\n uint _epoch = epoch;\\n\\n if (_tokenId != 0) {\\n // Calculate slopes and biases\\n // Kept at zero when they have to\\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\\n u_old.slope = old_locked.amount / iMAXTIME;\\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\\n }\\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\\n u_new.slope = new_locked.amount / iMAXTIME;\\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\\n }\\n\\n // Read values of scheduled changes in the slope\\n // old_locked.end can be in the past and in the future\\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\\n old_dslope = slope_changes[old_locked.end];\\n if (new_locked.end != 0) {\\n if (new_locked.end == old_locked.end) {\\n new_dslope = old_dslope;\\n } else {\\n new_dslope = slope_changes[new_locked.end];\\n }\\n }\\n }\\n\\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\\n if (_epoch > 0) {\\n last_point = point_history[_epoch];\\n }\\n uint last_checkpoint = last_point.ts;\\n // initial_last_point is used for extrapolation to calculate block number\\n // (approximately, for *At methods) and save them\\n // as we cannot figure that out exactly from inside the contract\\n Point memory initial_last_point = last_point;\\n uint block_slope = 0; // dblock/dt\\n if (block.timestamp > last_point.ts) {\\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\\n }\\n // If last point is already recorded in this block, slope=0\\n // But that's ok b/c we know the block in such case\\n\\n // Go over weeks to fill history and calculate what the current point is\\n {\\n uint t_i = (last_checkpoint / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n // Hopefully it won't happen that this won't get used in 5 years!\\n // If it does, users will be able to withdraw but vote weight will be broken\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > block.timestamp) {\\n t_i = block.timestamp;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\\n last_point.slope += d_slope;\\n if (last_point.bias < 0) {\\n // This can happen\\n last_point.bias = 0;\\n }\\n if (last_point.slope < 0) {\\n // This cannot happen - just in case\\n last_point.slope = 0;\\n }\\n last_checkpoint = t_i;\\n last_point.ts = t_i;\\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\\n _epoch += 1;\\n if (t_i == block.timestamp) {\\n last_point.blk = block.number;\\n break;\\n } else {\\n point_history[_epoch] = last_point;\\n }\\n }\\n }\\n\\n epoch = _epoch;\\n // Now point_history is filled until t=now\\n\\n if (_tokenId != 0) {\\n // If last point was in this block, the slope change has been applied already\\n // But in such case we have 0 slope(s)\\n last_point.slope += (u_new.slope - u_old.slope);\\n last_point.bias += (u_new.bias - u_old.bias);\\n if (last_point.slope < 0) {\\n last_point.slope = 0;\\n }\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n }\\n\\n // Record the changed point into history\\n point_history[_epoch] = last_point;\\n\\n if (_tokenId != 0) {\\n // Schedule the slope changes (slope is going down)\\n // We subtract new_user_slope from [new_locked.end]\\n // and add old_user_slope to [old_locked.end]\\n if (old_locked.end > block.timestamp) {\\n // old_dslope was - u_old.slope, so we cancel that\\n old_dslope += u_old.slope;\\n if (new_locked.end == old_locked.end) {\\n old_dslope -= u_new.slope; // It was a new deposit, not extension\\n }\\n slope_changes[old_locked.end] = old_dslope;\\n }\\n\\n if (new_locked.end > block.timestamp) {\\n if (new_locked.end > old_locked.end) {\\n new_dslope -= u_new.slope; // old slope disappeared at this point\\n slope_changes[new_locked.end] = new_dslope;\\n }\\n // else: we recorded it already in old_dslope\\n }\\n // Now handle user history\\n uint user_epoch = user_point_epoch[_tokenId] + 1;\\n\\n user_point_epoch[_tokenId] = user_epoch;\\n u_new.ts = block.timestamp;\\n u_new.blk = block.number;\\n user_point_history[_tokenId][user_epoch] = u_new;\\n }\\n }\\n\\n /// @notice Deposit and lock tokens for a user\\n /// @param _tokenId NFT that holds lock\\n /// @param _value Amount to deposit\\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\\n /// @param locked_balance Previous locked amount / timestamp\\n /// @param deposit_type The type of deposit\\n function _deposit_for(\\n uint _tokenId,\\n uint _value,\\n uint unlock_time,\\n LockedBalance memory locked_balance,\\n DepositType deposit_type\\n ) internal {\\n LockedBalance memory _locked = locked_balance;\\n uint supply_before = supply;\\n\\n supply = supply_before + _value;\\n LockedBalance memory old_locked;\\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\\n // Adding to existing lock, or if a lock is expired - creating a new one\\n _locked.amount += int128(int256(_value));\\n if (unlock_time != 0) {\\n _locked.end = unlock_time;\\n }\\n locked[_tokenId] = _locked;\\n\\n // Possibilities:\\n // Both old_locked.end could be current or expired (>/< block.timestamp)\\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\\n // _locked.end > block.timestamp (always)\\n _checkpoint(_tokenId, old_locked, _locked);\\n\\n address from = msg.sender;\\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\\n assert(IERC20(token).transferFrom(from, address(this), _value));\\n }\\n\\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\\n emit Supply(supply_before, supply_before + _value);\\n }\\n\\n function block_number() external view returns (uint) {\\n return block.number;\\n }\\n\\n /// @notice Record global data to checkpoint\\n function checkpoint() external {\\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\\n }\\n\\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\\n /// cannot extend their locktime and deposit for a brand new user\\n /// @param _tokenId lock NFT\\n /// @param _value Amount to add to user's lock\\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n require(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_value > 0); // dev: need non-zero value\\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n ++tokenId;\\n uint _tokenId = tokenId;\\n _mint(_to, _tokenId);\\n\\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\\n return _tokenId;\\n }\\n\\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, msg.sender);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, _to);\\n }\\n\\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\\n /// @param _value Amount of tokens to deposit and add to the lock\\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n assert(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\\n }\\n\\n /// @notice Extend the unlock time for `_tokenId`\\n /// @param _lock_duration New number of seconds until tokens unlock\\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_locked.end > block.timestamp, 'Lock expired');\\n require(_locked.amount > 0, 'Nothing is locked');\\n require(unlock_time > _locked.end, 'Can only increase lock duration');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\\n }\\n\\n /// @notice Withdraw all tokens for `_tokenId`\\n /// @dev Only possible if the lock has expired\\n function withdraw(uint _tokenId) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n require(block.timestamp >= _locked.end, \\\"The lock didn't expire\\\");\\n uint value = uint(int256(_locked.amount));\\n\\n locked[_tokenId] = LockedBalance(0,0);\\n uint supply_before = supply;\\n supply = supply_before - value;\\n\\n // old_locked can have either expired <= timestamp or zero end\\n // _locked has only 0 end\\n // Both can have >= 0 amount\\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\\n\\n assert(IERC20(token).transfer(msg.sender, value));\\n\\n // Burn the NFT\\n _burn(_tokenId);\\n\\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\\n emit Supply(supply_before, supply_before - value);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\\n // They measure the weights for the purpose of voting, so they don't represent\\n // real coins.\\n\\n /// @notice Binary search to estimate timestamp for block number\\n /// @param _block Block to find\\n /// @param max_epoch Don't go beyond this epoch\\n /// @return Approximate timestamp for block\\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\\n // Binary search\\n uint _min = 0;\\n uint _max = max_epoch;\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (point_history[_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n /// @notice Get the current voting power for `_tokenId`\\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\\n /// @param _tokenId NFT for lock\\n /// @param _t Epoch time to return voting power at\\n /// @return User voting power\\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\\n uint _epoch = user_point_epoch[_tokenId];\\n if (_epoch == 0) {\\n return 0;\\n } else {\\n Point memory last_point = user_point_history[_tokenId][_epoch];\\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(int256(last_point.bias));\\n }\\n }\\n\\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\\n if (ownership_change[_tokenId] == block.number) return 0;\\n return _balanceOfNFT(_tokenId, block.timestamp);\\n }\\n\\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\\n return _balanceOfNFT(_tokenId, _t);\\n }\\n\\n /// @notice Measure voting power of `_tokenId` at block height `_block`\\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\\n /// @param _tokenId User's wallet NFT\\n /// @param _block Block to calculate the voting power at\\n /// @return Voting power\\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\\n // Copying and pasting totalSupply code because Vyper cannot pass by\\n // reference yet\\n assert(_block <= block.number);\\n\\n // Binary search\\n uint _min = 0;\\n uint _max = user_point_epoch[_tokenId];\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (user_point_history[_tokenId][_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n\\n Point memory upoint = user_point_history[_tokenId][_min];\\n\\n uint max_epoch = epoch;\\n uint _epoch = _find_block_epoch(_block, max_epoch);\\n Point memory point_0 = point_history[_epoch];\\n uint d_block = 0;\\n uint d_t = 0;\\n if (_epoch < max_epoch) {\\n Point memory point_1 = point_history[_epoch + 1];\\n d_block = point_1.blk - point_0.blk;\\n d_t = point_1.ts - point_0.ts;\\n } else {\\n d_block = block.number - point_0.blk;\\n d_t = block.timestamp - point_0.ts;\\n }\\n uint block_time = point_0.ts;\\n if (d_block != 0) {\\n block_time += (d_t * (_block - point_0.blk)) / d_block;\\n }\\n\\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\\n if (upoint.bias >= 0) {\\n return uint(uint128(upoint.bias));\\n } else {\\n return 0;\\n }\\n }\\n\\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\\n return _balanceOfAtNFT(_tokenId, _block);\\n }\\n\\n /// @notice Calculate total voting power at some point in the past\\n /// @param _block Block to calculate the total voting power at\\n /// @return Total voting power at `_block`\\n function totalSupplyAt(uint _block) external view returns (uint) {\\n assert(_block <= block.number);\\n uint _epoch = epoch;\\n uint target_epoch = _find_block_epoch(_block, _epoch);\\n\\n Point memory point = point_history[target_epoch];\\n uint dt = 0;\\n if (target_epoch < _epoch) {\\n Point memory point_next = point_history[target_epoch + 1];\\n if (point.blk != point_next.blk) {\\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\\n }\\n } else {\\n if (point.blk != block.number) {\\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\\n }\\n }\\n // Now dt contains info on how far are we beyond point\\n return _supply_at(point, point.ts + dt);\\n }\\n /// @notice Calculate total voting power at some point in the past\\n /// @param point The point (bias/slope) to start search from\\n /// @param t Time to calculate the total voting power at\\n /// @return Total voting power at that time\\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\\n Point memory last_point = point;\\n uint t_i = (last_point.ts / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > t) {\\n t_i = t;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\\n if (t_i == t) {\\n break;\\n }\\n last_point.slope += d_slope;\\n last_point.ts = t_i;\\n }\\n\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(uint128(last_point.bias));\\n }\\n\\n function totalSupply() external view returns (uint) {\\n return totalSupplyAtT(block.timestamp);\\n }\\n\\n /// @notice Calculate total voting power\\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\\n /// @return Total voting power\\n function totalSupplyAtT(uint t) public view returns (uint) {\\n uint _epoch = epoch;\\n Point memory last_point = point_history[_epoch];\\n return _supply_at(last_point, t);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public attachments;\\n mapping(uint => bool) public voted;\\n\\n function setVoter(address _voter) external {\\n require(msg.sender == voter);\\n voter = _voter;\\n }\\n\\n function voting(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = true;\\n }\\n\\n function abstain(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = false;\\n }\\n\\n function attach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] + 1;\\n }\\n\\n function detach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] - 1;\\n }\\n\\n function merge(uint _from, uint _to) external {\\n require(attachments[_from] == 0 && !voted[_from], \\\"attached\\\");\\n require(_from != _to);\\n require(_isApprovedOrOwner(msg.sender, _from));\\n require(_isApprovedOrOwner(msg.sender, _to));\\n\\n LockedBalance memory _locked0 = locked[_from];\\n LockedBalance memory _locked1 = locked[_to];\\n uint value0 = uint(int256(_locked0.amount));\\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\\n\\n locked[_from] = LockedBalance(0, 0);\\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\\n _burn(_from);\\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of each accounts delegate\\n mapping(address => address) private _delegates;\\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\\n\\n /// @notice A record of delegated token checkpoints for each account, by index\\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint32) public numCheckpoints;\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping(address => uint) public nonces;\\n\\n /**\\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\\n * the delegator's own address if they haven't delegated.\\n * This avoids having to delegate to oneself.\\n */\\n function delegates(address delegator) public view returns (address) {\\n address current = _delegates[delegator];\\n return current == address(0) ? delegator : current;\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getVotes(address account) external view returns (uint) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n votes = votes + _balanceOfNFT(tId, block.timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint storage cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPastVotes(address account, uint timestamp)\\n public\\n view\\n returns (uint)\\n {\\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\\n // Sum votes\\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n // Use the provided input timestamp here to get the right decay\\n votes = votes + _balanceOfNFT(tId, timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\\n return totalSupplyAtT(timestamp);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _moveTokenDelegates(\\n address srcRep,\\n address dstRep,\\n uint _tokenId\\n ) internal {\\n if (srcRep != dstRep && _tokenId > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except _tokenId\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (tId != _tokenId) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n // All the same plus _tokenId\\n require(\\n dstRepOld.length + 1 <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n dstRepNew.push(_tokenId);\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _findWhatCheckpointToWrite(address account)\\n internal\\n view\\n returns (uint32)\\n {\\n uint _timestamp = block.timestamp;\\n uint32 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n return _nCheckPoints - 1;\\n } else {\\n return _nCheckPoints;\\n }\\n }\\n\\n function _moveAllDelegates(\\n address owner,\\n address srcRep,\\n address dstRep\\n ) internal {\\n // You can only redelegate what you own\\n if (srcRep != dstRep) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except what owner owns\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (idToOwner[tId] != owner) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n uint ownerTokenCount = ownerToNFTokenCount[owner];\\n require(\\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n // All the same\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n // Plus all that's owned\\n for (uint i = 0; i < ownerTokenCount; i++) {\\n uint tId = ownerToNFTokenIdList[owner][i];\\n dstRepNew.push(tId);\\n }\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\\n address currentDelegate = delegates(delegator);\\n\\n _delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n _moveAllDelegates(delegator, currentDelegate, delegatee);\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n if (delegatee == address(0)) delegatee = msg.sender;\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n function delegateBySig(\\n address delegatee,\\n uint nonce,\\n uint expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public {\\n bytes32 domainSeparator = keccak256(\\n abi.encode(\\n DOMAIN_TYPEHASH,\\n keccak256(bytes(name)),\\n keccak256(bytes(version)),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 structHash = keccak256(\\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash)\\n );\\n address signatory = ecrecover(digest, v, r, s);\\n require(\\n signatory != address(0),\\n \\\"VotingEscrow::delegateBySig: invalid signature\\\"\\n );\\n require(\\n nonce == nonces[signatory]++,\\n \\\"VotingEscrow::delegateBySig: invalid nonce\\\"\\n );\\n require(\\n block.timestamp <= expiry,\\n \\\"VotingEscrow::delegateBySig: signature expired\\\"\\n );\\n return _delegate(signatory, delegatee);\\n }\\n}\\n\",\"keccak256\":\"0x37e5ee306472a946a665be22bc1d370d566a575a1fac84f72f97b0575571d40d\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x41bbb2c41036ca64b2f6c9e973e8cfaa113ebc42af86702cd0d267f915a7e886\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a06040526006805460ff191660011790553480156200001e57600080fd5b5060405162004a1c38038062004a1c8339810160408190526200004191620001b8565b6001600160a01b0382811660805260008054336001600160a01b031991821681178355600180548316909117815560028054909216938516939093179055437f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f0155427f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f005560046020527f9fe05126d2d9ecf60592e254dead906a4b2e492f36cca727682c38e9008c6ac1805460ff1990811684179091557f4267c0a6fd96b7a87f183ee8744f24d011423cd0e0142b3f563f183d8d9a456b8054821684179055635b5e139f60e01b82527e24030bcf4927897dffe721c2d8dda4bfd8910861687c42b03a463b43b04147805490911690921790915560055460405190913091600080516020620049fc833981519152908290a46005546040516000903090600080516020620049fc833981519152908390a45050620001f0565b80516001600160a01b0381168114620001b357600080fd5b919050565b60008060408385031215620001cc57600080fd5b620001d7836200019b565b9150620001e7602084016200019b565b90509250929050565b6080516147e26200021a60003960008181610b220152818161101801526133b501526147e26000f3fe608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea26469706673582212201dd8736f6bb54556070cca6edc44b533d010e5fbaca1866c9ae688ee4938ced064736f6c634300080d0033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea26469706673582212201dd8736f6bb54556070cca6edc44b533d010e5fbaca1866c9ae688ee4938ced064736f6c634300080d0033", "devdoc": { "author": "Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)", "details": "Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).", diff --git a/deployments/arbitrumGoerli/solcInputs/52dedb568751596f5f7bda36f8e139c0.json b/deployments/arbitrumGoerli/solcInputs/52dedb568751596f5f7bda36f8e139c0.json new file mode 100644 index 00000000..08f67481 --- /dev/null +++ b/deployments/arbitrumGoerli/solcInputs/52dedb568751596f5f7bda36f8e139c0.json @@ -0,0 +1,238 @@ +{ + "language": "Solidity", + "sources": { + "contracts/ExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/factories/BribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" + }, + "contracts/factories/GaugeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" + }, + "contracts/factories/PairFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" + }, + "contracts/factories/WrappedExternalBribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" + }, + "contracts/Gauge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/governance/L2Governor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" + }, + "contracts/governance/L2GovernorCountingSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" + }, + "contracts/governance/L2GovernorVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" + }, + "contracts/governance/L2GovernorVotesQuorumFraction.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" + }, + "contracts/interfaces/IBribe.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IBribeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IERC20.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" + }, + "contracts/interfaces/IGauge.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" + }, + "contracts/interfaces/IGaugeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IMinter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" + }, + "contracts/interfaces/IPair.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IPairCallee.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" + }, + "contracts/interfaces/IPairFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" + }, + "contracts/interfaces/IRewardsDistributor.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" + }, + "contracts/interfaces/IRouter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" + }, + "contracts/interfaces/IVeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" + }, + "contracts/interfaces/IVelo.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" + }, + "contracts/interfaces/IVoter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" + }, + "contracts/interfaces/IVotingEscrow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" + }, + "contracts/interfaces/IWETH.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" + }, + "contracts/InternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/libraries/Base64.sol": { + "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" + }, + "contracts/libraries/Math.sol": { + "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" + }, + "contracts/Minter.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" + }, + "contracts/Pair.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/PairFees.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" + }, + "contracts/redeem/MerkleClaim.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" + }, + "contracts/redeem/RedemptionReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" + }, + "contracts/redeem/RedemptionSender.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" + }, + "contracts/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" + }, + "contracts/Router.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" + }, + "contracts/Velo.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" + }, + "contracts/VelodromeLibrary.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" + }, + "contracts/VeloGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" + }, + "contracts/Voter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VotingEscrow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" + }, + "contracts/WrappedExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + }, + "libraries": { + "": { + "__CACHE_BREAKER__": "0x0000000000000031363733343336323330373831" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/55f774ad815c4347b8fbe726bc77554f.json b/deployments/arbitrumGoerli/solcInputs/55f774ad815c4347b8fbe726bc77554f.json new file mode 100644 index 00000000..9a06aa66 --- /dev/null +++ b/deployments/arbitrumGoerli/solcInputs/55f774ad815c4347b8fbe726bc77554f.json @@ -0,0 +1,238 @@ +{ + "language": "Solidity", + "sources": { + "contracts/ExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/factories/BribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" + }, + "contracts/factories/GaugeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" + }, + "contracts/factories/PairFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" + }, + "contracts/factories/WrappedExternalBribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" + }, + "contracts/Gauge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/governance/L2Governor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" + }, + "contracts/governance/L2GovernorCountingSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" + }, + "contracts/governance/L2GovernorVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" + }, + "contracts/governance/L2GovernorVotesQuorumFraction.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" + }, + "contracts/interfaces/IBribe.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IBribeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IERC20.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" + }, + "contracts/interfaces/IGauge.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" + }, + "contracts/interfaces/IGaugeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IMinter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" + }, + "contracts/interfaces/IPair.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IPairCallee.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" + }, + "contracts/interfaces/IPairFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" + }, + "contracts/interfaces/IRewardsDistributor.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" + }, + "contracts/interfaces/IRouter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" + }, + "contracts/interfaces/IVeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" + }, + "contracts/interfaces/IVelo.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" + }, + "contracts/interfaces/IVoter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" + }, + "contracts/interfaces/IVotingEscrow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" + }, + "contracts/interfaces/IWETH.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" + }, + "contracts/InternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/libraries/Base64.sol": { + "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" + }, + "contracts/libraries/Math.sol": { + "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" + }, + "contracts/Minter.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" + }, + "contracts/Pair.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/PairFees.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" + }, + "contracts/redeem/MerkleClaim.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" + }, + "contracts/redeem/RedemptionReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" + }, + "contracts/redeem/RedemptionSender.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" + }, + "contracts/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" + }, + "contracts/Router.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" + }, + "contracts/Velo.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" + }, + "contracts/VelodromeLibrary.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" + }, + "contracts/VeloGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" + }, + "contracts/Voter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VotingEscrow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" + }, + "contracts/WrappedExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + }, + "libraries": { + "": { + "__CACHE_BREAKER__": "0x0000000000000031363733343334303532363533" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/7fabbf584e02c1cd20d7799a434dc4a7.json b/deployments/arbitrumGoerli/solcInputs/7fabbf584e02c1cd20d7799a434dc4a7.json new file mode 100644 index 00000000..affb14c3 --- /dev/null +++ b/deployments/arbitrumGoerli/solcInputs/7fabbf584e02c1cd20d7799a434dc4a7.json @@ -0,0 +1,238 @@ +{ + "language": "Solidity", + "sources": { + "contracts/ExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/factories/BribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" + }, + "contracts/factories/GaugeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" + }, + "contracts/factories/PairFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" + }, + "contracts/factories/WrappedExternalBribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" + }, + "contracts/Gauge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/governance/L2Governor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" + }, + "contracts/governance/L2GovernorCountingSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" + }, + "contracts/governance/L2GovernorVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" + }, + "contracts/governance/L2GovernorVotesQuorumFraction.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" + }, + "contracts/interfaces/IBribe.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IBribeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IERC20.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" + }, + "contracts/interfaces/IGauge.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" + }, + "contracts/interfaces/IGaugeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IMinter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" + }, + "contracts/interfaces/IPair.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IPairCallee.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" + }, + "contracts/interfaces/IPairFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" + }, + "contracts/interfaces/IRewardsDistributor.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" + }, + "contracts/interfaces/IRouter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" + }, + "contracts/interfaces/IVeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" + }, + "contracts/interfaces/IVelo.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" + }, + "contracts/interfaces/IVoter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" + }, + "contracts/interfaces/IVotingEscrow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" + }, + "contracts/interfaces/IWETH.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" + }, + "contracts/InternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/libraries/Base64.sol": { + "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" + }, + "contracts/libraries/Math.sol": { + "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" + }, + "contracts/Minter.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" + }, + "contracts/Pair.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/PairFees.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" + }, + "contracts/redeem/MerkleClaim.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" + }, + "contracts/redeem/RedemptionReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" + }, + "contracts/redeem/RedemptionSender.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" + }, + "contracts/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" + }, + "contracts/Router.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" + }, + "contracts/Velo.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" + }, + "contracts/VelodromeLibrary.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" + }, + "contracts/VeloGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" + }, + "contracts/Voter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VotingEscrow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" + }, + "contracts/WrappedExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + }, + "libraries": { + "": { + "__CACHE_BREAKER__": "0x0000000000000031363733343336363832383931" + } + } + } +} \ No newline at end of file diff --git a/package.json b/package.json index 96d228d5..25f35b09 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "lib": "lib" }, "devDependencies": { - "@nomiclabs/hardhat-ethers": "^2.0.6", + "@nomiclabs/hardhat-ethers": "yarn:hardhat-deploy-ethers", "@nomiclabs/hardhat-etherscan": "^3.1.4", "@nomiclabs/hardhat-waffle": "^2.0.3", "@typechain/ethers-v5": "^10.0.0", diff --git a/yarn.lock b/yarn.lock index 76e960ee..1aaf132c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -677,10 +677,10 @@ "@nomicfoundation/solidity-analyzer-win32-ia32-msvc" "0.1.0" "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.0" -"@nomiclabs/hardhat-ethers@^2.0.6": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.2.1.tgz#8057b43566a0e41abeb8142064a3c0d3f23dca86" - integrity sha512-RHWYwnxryWR8hzRmU4Jm/q4gzvXpetUOJ4OPlwH2YARcDB+j79+yAYCwO0lN1SUOb4++oOTJEe6AWLEc42LIvg== +"@nomiclabs/hardhat-ethers@yarn:hardhat-deploy-ethers": + version "0.3.0-beta.13" + resolved "https://registry.yarnpkg.com/hardhat-deploy-ethers/-/hardhat-deploy-ethers-0.3.0-beta.13.tgz#b96086ff768ddf69928984d5eb0a8d78cfca9366" + integrity sha512-PdWVcKB9coqWV1L7JTpfXRCI91Cgwsm7KLmBcwZ8f0COSm1xtABHZTyz3fvF6p42cTnz1VM0QnfDvMFlIRkSNw== "@nomiclabs/hardhat-etherscan@^3.1.4": version "3.1.4" From 8a2574389af638ffd8e8210a4d4fba831785e5cd Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Sun, 15 Jan 2023 01:33:43 +1100 Subject: [PATCH 09/43] script to cleanup contract list + add contracts list to readme --- .gitignore | 3 +- contractNameAndAddress.ts | 17 ++ dist/checkEnv.d.ts | 1 + dist/checkEnv.js | 24 +++ dist/deploy/00_velo.d.ts | 3 + dist/deploy/00_velo.js | 16 ++ dist/deploy/01_gaugeFactory.d.ts | 3 + dist/deploy/01_gaugeFactory.js | 16 ++ dist/deploy/02_bribeFactory.d.ts | 3 + dist/deploy/02_bribeFactory.js | 16 ++ dist/deploy/04_pairFactory.d.ts | 3 + dist/deploy/04_pairFactory.js | 16 ++ dist/deploy/05_router.d.ts | 3 + dist/deploy/05_router.js | 22 +++ dist/deploy/06_library.d.ts | 3 + dist/deploy/06_library.js | 17 ++ dist/deploy/07_veArtProxy.d.ts | 3 + dist/deploy/07_veArtProxy.js | 16 ++ dist/deploy/08_votingEscrow.d.ts | 3 + dist/deploy/08_votingEscrow.js | 18 ++ dist/deploy/09_rewardsDist.d.ts | 3 + dist/deploy/09_rewardsDist.js | 17 ++ dist/deploy/10_voter.d.ts | 3 + dist/deploy/10_voter.js | 25 +++ dist/deploy/11_minter.d.ts | 3 + dist/deploy/11_minter.js | 19 ++ dist/deploy/12_veloGovernor.d.ts | 3 + dist/deploy/12_veloGovernor.js | 17 ++ dist/deploy/13_redemptionReceiver.d.ts | 3 + dist/deploy/13_redemptionReceiver.js | 29 +++ dist/deploy/14_merkleClaim.d.ts | 3 + dist/deploy/14_merkleClaim.js | 22 +++ dist/deploy/15_init.d.ts | 3 + dist/deploy/15_init.js | 50 +++++ dist/deploy/16_whitelist.d.ts | 3 + dist/deploy/16_whitelist.js | 22 +++ dist/deploy/17_dist.d.ts | 3 + dist/deploy/17_dist.js | 19 ++ dist/hardhat.config.d.ts | 11 ++ dist/hardhat.config.js | 111 +++++++++++ dist/tasks/deploy/arb.d.ts | 1 + dist/tasks/deploy/arb.js | 121 ++++++++++++ dist/tasks/deploy/arbHardhat.d.ts | 1 + dist/tasks/deploy/arbHardhat.js | 121 ++++++++++++ dist/tasks/deploy/arbTest.d.ts | 1 + dist/tasks/deploy/arbTest.js | 176 ++++++++++++++++++ dist/tasks/deploy/constants/arbConfig.d.ts | 16 ++ dist/tasks/deploy/constants/arbConfig.js | 82 ++++++++ .../deploy/constants/arbHardhatConfig.d.ts | 16 ++ .../deploy/constants/arbHardhatConfig.js | 82 ++++++++ .../deploy/constants/arbTestnetConfig.d.ts | 16 ++ .../deploy/constants/arbTestnetConfig.js | 82 ++++++++ dist/tasks/deploy/constants/deployed.d.ts | 5 + dist/tasks/deploy/constants/deployed.js | 7 + dist/tasks/deploy/constants/fantomConfig.d.ts | 6 + dist/tasks/deploy/constants/fantomConfig.js | 8 + dist/tasks/deploy/constants/index.d.ts | 0 dist/tasks/deploy/constants/index.js | 1 + .../deploy/constants/optimismConfig.d.ts | 16 ++ dist/tasks/deploy/constants/optimismConfig.js | 88 +++++++++ .../deploy/constants/testFantomConfig.d.ts | 6 + .../deploy/constants/testFantomConfig.js | 8 + .../deploy/constants/testOptimismConfig.d.ts | 16 ++ .../deploy/constants/testOptimismConfig.js | 59 ++++++ dist/tasks/deploy/ftm.d.ts | 1 + dist/tasks/deploy/ftm.js | 27 +++ dist/tasks/deploy/index.d.ts | 6 + dist/tasks/deploy/index.js | 8 + dist/tasks/deploy/init.d.ts | 0 dist/tasks/deploy/init.js | 34 ++++ dist/tasks/deploy/op.d.ts | 1 + dist/tasks/deploy/op.js | 120 ++++++++++++ jsonFromFile.js | 23 +++ package.json | 5 +- readme.md | 47 ++--- 75 files changed, 1749 insertions(+), 33 deletions(-) create mode 100644 contractNameAndAddress.ts create mode 100644 dist/checkEnv.d.ts create mode 100644 dist/checkEnv.js create mode 100644 dist/deploy/00_velo.d.ts create mode 100644 dist/deploy/00_velo.js create mode 100644 dist/deploy/01_gaugeFactory.d.ts create mode 100644 dist/deploy/01_gaugeFactory.js create mode 100644 dist/deploy/02_bribeFactory.d.ts create mode 100644 dist/deploy/02_bribeFactory.js create mode 100644 dist/deploy/04_pairFactory.d.ts create mode 100644 dist/deploy/04_pairFactory.js create mode 100644 dist/deploy/05_router.d.ts create mode 100644 dist/deploy/05_router.js create mode 100644 dist/deploy/06_library.d.ts create mode 100644 dist/deploy/06_library.js create mode 100644 dist/deploy/07_veArtProxy.d.ts create mode 100644 dist/deploy/07_veArtProxy.js create mode 100644 dist/deploy/08_votingEscrow.d.ts create mode 100644 dist/deploy/08_votingEscrow.js create mode 100644 dist/deploy/09_rewardsDist.d.ts create mode 100644 dist/deploy/09_rewardsDist.js create mode 100644 dist/deploy/10_voter.d.ts create mode 100644 dist/deploy/10_voter.js create mode 100644 dist/deploy/11_minter.d.ts create mode 100644 dist/deploy/11_minter.js create mode 100644 dist/deploy/12_veloGovernor.d.ts create mode 100644 dist/deploy/12_veloGovernor.js create mode 100644 dist/deploy/13_redemptionReceiver.d.ts create mode 100644 dist/deploy/13_redemptionReceiver.js create mode 100644 dist/deploy/14_merkleClaim.d.ts create mode 100644 dist/deploy/14_merkleClaim.js create mode 100644 dist/deploy/15_init.d.ts create mode 100644 dist/deploy/15_init.js create mode 100644 dist/deploy/16_whitelist.d.ts create mode 100644 dist/deploy/16_whitelist.js create mode 100644 dist/deploy/17_dist.d.ts create mode 100644 dist/deploy/17_dist.js create mode 100644 dist/hardhat.config.d.ts create mode 100644 dist/hardhat.config.js create mode 100644 dist/tasks/deploy/arb.d.ts create mode 100644 dist/tasks/deploy/arb.js create mode 100644 dist/tasks/deploy/arbHardhat.d.ts create mode 100644 dist/tasks/deploy/arbHardhat.js create mode 100644 dist/tasks/deploy/arbTest.d.ts create mode 100644 dist/tasks/deploy/arbTest.js create mode 100644 dist/tasks/deploy/constants/arbConfig.d.ts create mode 100644 dist/tasks/deploy/constants/arbConfig.js create mode 100644 dist/tasks/deploy/constants/arbHardhatConfig.d.ts create mode 100644 dist/tasks/deploy/constants/arbHardhatConfig.js create mode 100644 dist/tasks/deploy/constants/arbTestnetConfig.d.ts create mode 100644 dist/tasks/deploy/constants/arbTestnetConfig.js create mode 100644 dist/tasks/deploy/constants/deployed.d.ts create mode 100644 dist/tasks/deploy/constants/deployed.js create mode 100644 dist/tasks/deploy/constants/fantomConfig.d.ts create mode 100644 dist/tasks/deploy/constants/fantomConfig.js create mode 100644 dist/tasks/deploy/constants/index.d.ts create mode 100644 dist/tasks/deploy/constants/index.js create mode 100644 dist/tasks/deploy/constants/optimismConfig.d.ts create mode 100644 dist/tasks/deploy/constants/optimismConfig.js create mode 100644 dist/tasks/deploy/constants/testFantomConfig.d.ts create mode 100644 dist/tasks/deploy/constants/testFantomConfig.js create mode 100644 dist/tasks/deploy/constants/testOptimismConfig.d.ts create mode 100644 dist/tasks/deploy/constants/testOptimismConfig.js create mode 100644 dist/tasks/deploy/ftm.d.ts create mode 100644 dist/tasks/deploy/ftm.js create mode 100644 dist/tasks/deploy/index.d.ts create mode 100644 dist/tasks/deploy/index.js create mode 100644 dist/tasks/deploy/init.d.ts create mode 100644 dist/tasks/deploy/init.js create mode 100644 dist/tasks/deploy/op.d.ts create mode 100644 dist/tasks/deploy/op.js create mode 100644 jsonFromFile.js diff --git a/.gitignore b/.gitignore index a5e7f5d1..93b74371 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ # for verify args.js - +/contracts/deploy/ .env # Foundry @@ -32,3 +32,4 @@ lib/openzeppelin-contracts lib/forge-std lib/LayerZero lib/forge-std +deployments/arbitrumGoerli/solcInputs/ diff --git a/contractNameAndAddress.ts b/contractNameAndAddress.ts new file mode 100644 index 00000000..5a134846 --- /dev/null +++ b/contractNameAndAddress.ts @@ -0,0 +1,17 @@ +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' + +const func: GetContractNames = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments + + const { deployer } = await getNamedAccounts() + + await deploy('GaugeFactory', { + from: deployer, + args: [], + log: true, + skipIfAlreadyDeployed: true + }) +} +export default func diff --git a/dist/checkEnv.d.ts b/dist/checkEnv.d.ts new file mode 100644 index 00000000..cb0ff5c3 --- /dev/null +++ b/dist/checkEnv.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/checkEnv.js b/dist/checkEnv.js new file mode 100644 index 00000000..93e4ccf9 --- /dev/null +++ b/dist/checkEnv.js @@ -0,0 +1,24 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const zod_1 = require("zod"); +const schema = zod_1.z.object({ + ALCHEMY_GOERLI_ARBITRUM_API_KEY: zod_1.z.string().min(1), + ARB_SCAN_API_KEY: zod_1.z.string().min(1), +}); +const destructedEnv = { + ALCHEMY_GOERLI_ARBITRUM_API_KEY: process.env.ALCHEMY_GOERLI_ARBITRUM_API_KEY, + ARB_SCAN_API_KEY: process.env.ARB_SCAN_API_KEY, +}; +const _env = schema.safeParse(destructedEnv); +const formatErrors = (errors) => { + return Object.entries(errors) + .map(([name, value]) => { + if (value && "_errors" in value) + return `${name}: ${value._errors.join(", ")}\n`; + }) + .filter(Boolean); +}; +if (!_env.success) { + console.error("❌ Invalid environment variables:\n", ...formatErrors(_env.error.format())); + throw new Error("Invalid environment variables"); +} diff --git a/dist/deploy/00_velo.d.ts b/dist/deploy/00_velo.d.ts new file mode 100644 index 00000000..68b368bb --- /dev/null +++ b/dist/deploy/00_velo.d.ts @@ -0,0 +1,3 @@ +import { DeployFunction } from "hardhat-deploy/types"; +declare const func: DeployFunction; +export default func; diff --git a/dist/deploy/00_velo.js b/dist/deploy/00_velo.js new file mode 100644 index 00000000..abe1df7b --- /dev/null +++ b/dist/deploy/00_velo.js @@ -0,0 +1,16 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const func = async function (hre) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + await deploy("Velo", { + from: deployer, + args: [], + log: true, + skipIfAlreadyDeployed: true, + }); +}; +exports.default = func; +func.tags = ["Velo"]; +func.id = "velo"; diff --git a/dist/deploy/01_gaugeFactory.d.ts b/dist/deploy/01_gaugeFactory.d.ts new file mode 100644 index 00000000..68b368bb --- /dev/null +++ b/dist/deploy/01_gaugeFactory.d.ts @@ -0,0 +1,3 @@ +import { DeployFunction } from "hardhat-deploy/types"; +declare const func: DeployFunction; +export default func; diff --git a/dist/deploy/01_gaugeFactory.js b/dist/deploy/01_gaugeFactory.js new file mode 100644 index 00000000..b355c9fa --- /dev/null +++ b/dist/deploy/01_gaugeFactory.js @@ -0,0 +1,16 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const func = async function (hre) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + await deploy("GaugeFactory", { + from: deployer, + args: [], + log: true, + skipIfAlreadyDeployed: true, + }); +}; +exports.default = func; +func.tags = ["GaugeFactory"]; +func.id = "gaugeFactory"; diff --git a/dist/deploy/02_bribeFactory.d.ts b/dist/deploy/02_bribeFactory.d.ts new file mode 100644 index 00000000..68b368bb --- /dev/null +++ b/dist/deploy/02_bribeFactory.d.ts @@ -0,0 +1,3 @@ +import { DeployFunction } from "hardhat-deploy/types"; +declare const func: DeployFunction; +export default func; diff --git a/dist/deploy/02_bribeFactory.js b/dist/deploy/02_bribeFactory.js new file mode 100644 index 00000000..cef38939 --- /dev/null +++ b/dist/deploy/02_bribeFactory.js @@ -0,0 +1,16 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const func = async function (hre) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + await deploy("BribeFactory", { + from: deployer, + args: [], + log: true, + skipIfAlreadyDeployed: true, + }); +}; +exports.default = func; +func.tags = ["BribeFactory"]; +func.id = "bribeFactory"; diff --git a/dist/deploy/04_pairFactory.d.ts b/dist/deploy/04_pairFactory.d.ts new file mode 100644 index 00000000..68b368bb --- /dev/null +++ b/dist/deploy/04_pairFactory.d.ts @@ -0,0 +1,3 @@ +import { DeployFunction } from "hardhat-deploy/types"; +declare const func: DeployFunction; +export default func; diff --git a/dist/deploy/04_pairFactory.js b/dist/deploy/04_pairFactory.js new file mode 100644 index 00000000..2d8c7294 --- /dev/null +++ b/dist/deploy/04_pairFactory.js @@ -0,0 +1,16 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const func = async function (hre) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + await deploy("PairFactory", { + from: deployer, + args: [], + log: true, + skipIfAlreadyDeployed: true, + }); +}; +exports.default = func; +func.tags = ["PairFactory"]; +func.id = "pairFactory"; diff --git a/dist/deploy/05_router.d.ts b/dist/deploy/05_router.d.ts new file mode 100644 index 00000000..68b368bb --- /dev/null +++ b/dist/deploy/05_router.d.ts @@ -0,0 +1,3 @@ +import { DeployFunction } from "hardhat-deploy/types"; +declare const func: DeployFunction; +export default func; diff --git a/dist/deploy/05_router.js b/dist/deploy/05_router.js new file mode 100644 index 00000000..cfe59952 --- /dev/null +++ b/dist/deploy/05_router.js @@ -0,0 +1,22 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const arbTestnetConfig_1 = __importDefault(require("../tasks/deploy/constants/arbTestnetConfig")); +const ARB_TEST_CONFIG = arbTestnetConfig_1.default; +const func = async function (hre) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + const pairFactory = await deployments.get("PairFactory"); + await deploy("Router", { + from: deployer, + args: [pairFactory.address, ARB_TEST_CONFIG.WETH], + log: true, + skipIfAlreadyDeployed: true, + }); +}; +exports.default = func; +func.tags = ["Router"]; +func.id = "router"; diff --git a/dist/deploy/06_library.d.ts b/dist/deploy/06_library.d.ts new file mode 100644 index 00000000..68b368bb --- /dev/null +++ b/dist/deploy/06_library.d.ts @@ -0,0 +1,3 @@ +import { DeployFunction } from "hardhat-deploy/types"; +declare const func: DeployFunction; +export default func; diff --git a/dist/deploy/06_library.js b/dist/deploy/06_library.js new file mode 100644 index 00000000..90f0de52 --- /dev/null +++ b/dist/deploy/06_library.js @@ -0,0 +1,17 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const func = async function (hre) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + const router = await deployments.get("Router"); + await deploy("VelodromeLibrary", { + from: deployer, + args: [router.address], + log: true, + skipIfAlreadyDeployed: true, + }); +}; +exports.default = func; +func.tags = ["VelodromeLibrary"]; +func.id = "velodromeLibrary"; diff --git a/dist/deploy/07_veArtProxy.d.ts b/dist/deploy/07_veArtProxy.d.ts new file mode 100644 index 00000000..68b368bb --- /dev/null +++ b/dist/deploy/07_veArtProxy.d.ts @@ -0,0 +1,3 @@ +import { DeployFunction } from "hardhat-deploy/types"; +declare const func: DeployFunction; +export default func; diff --git a/dist/deploy/07_veArtProxy.js b/dist/deploy/07_veArtProxy.js new file mode 100644 index 00000000..350c6d9f --- /dev/null +++ b/dist/deploy/07_veArtProxy.js @@ -0,0 +1,16 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const func = async function (hre) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + await deploy("VeArtProxy", { + from: deployer, + args: [], + log: true, + skipIfAlreadyDeployed: true, + }); +}; +exports.default = func; +func.tags = ["VeArtProxy"]; +func.id = "veArtProxy"; diff --git a/dist/deploy/08_votingEscrow.d.ts b/dist/deploy/08_votingEscrow.d.ts new file mode 100644 index 00000000..68b368bb --- /dev/null +++ b/dist/deploy/08_votingEscrow.d.ts @@ -0,0 +1,3 @@ +import { DeployFunction } from "hardhat-deploy/types"; +declare const func: DeployFunction; +export default func; diff --git a/dist/deploy/08_votingEscrow.js b/dist/deploy/08_votingEscrow.js new file mode 100644 index 00000000..77ee759c --- /dev/null +++ b/dist/deploy/08_votingEscrow.js @@ -0,0 +1,18 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const func = async function (hre) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + const velo = await deployments.get("Velo"); + const veArtProxy = await deployments.get("VeArtProxy"); + await deploy("VotingEscrow", { + from: deployer, + args: [velo.address, veArtProxy.address], + log: true, + skipIfAlreadyDeployed: true, + }); +}; +exports.default = func; +func.tags = ["VotingEscrow"]; +func.id = "votingEscrow"; diff --git a/dist/deploy/09_rewardsDist.d.ts b/dist/deploy/09_rewardsDist.d.ts new file mode 100644 index 00000000..68b368bb --- /dev/null +++ b/dist/deploy/09_rewardsDist.d.ts @@ -0,0 +1,3 @@ +import { DeployFunction } from "hardhat-deploy/types"; +declare const func: DeployFunction; +export default func; diff --git a/dist/deploy/09_rewardsDist.js b/dist/deploy/09_rewardsDist.js new file mode 100644 index 00000000..6e4864d7 --- /dev/null +++ b/dist/deploy/09_rewardsDist.js @@ -0,0 +1,17 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const func = async function (hre) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + const escrow = await deployments.get("VotingEscrow"); + await deploy("RewardsDistributor", { + from: deployer, + args: [escrow.address], + log: true, + skipIfAlreadyDeployed: true, + }); +}; +exports.default = func; +func.tags = ["RewardsDistributor"]; +func.id = "rewardsDistributor"; diff --git a/dist/deploy/10_voter.d.ts b/dist/deploy/10_voter.d.ts new file mode 100644 index 00000000..68b368bb --- /dev/null +++ b/dist/deploy/10_voter.d.ts @@ -0,0 +1,3 @@ +import { DeployFunction } from "hardhat-deploy/types"; +declare const func: DeployFunction; +export default func; diff --git a/dist/deploy/10_voter.js b/dist/deploy/10_voter.js new file mode 100644 index 00000000..f775df1c --- /dev/null +++ b/dist/deploy/10_voter.js @@ -0,0 +1,25 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const func = async function (hre) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + const escrow = await deployments.get("VotingEscrow"); + const pairFactory = await deployments.get("PairFactory"); + const gaugeFactory = await deployments.get("GaugeFactory"); + const bribeFactory = await deployments.get("BribeFactory"); + await deploy("Voter", { + from: deployer, + args: [ + escrow.address, + pairFactory.address, + gaugeFactory.address, + bribeFactory.address, + ], + log: true, + skipIfAlreadyDeployed: true, + }); +}; +exports.default = func; +func.tags = ["Voter"]; +func.id = "voter"; diff --git a/dist/deploy/11_minter.d.ts b/dist/deploy/11_minter.d.ts new file mode 100644 index 00000000..68b368bb --- /dev/null +++ b/dist/deploy/11_minter.d.ts @@ -0,0 +1,3 @@ +import { DeployFunction } from "hardhat-deploy/types"; +declare const func: DeployFunction; +export default func; diff --git a/dist/deploy/11_minter.js b/dist/deploy/11_minter.js new file mode 100644 index 00000000..e6fc2686 --- /dev/null +++ b/dist/deploy/11_minter.js @@ -0,0 +1,19 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const func = async function (hre) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + const escrow = await deployments.get("VotingEscrow"); + const voter = await deployments.get("Voter"); + const dist = await deployments.get("RewardsDistributor"); + await deploy("Minter", { + from: deployer, + args: [voter.address, escrow.address, dist.address], + log: true, + skipIfAlreadyDeployed: true, + }); +}; +exports.default = func; +func.tags = ["Minter"]; +func.id = "minter"; diff --git a/dist/deploy/12_veloGovernor.d.ts b/dist/deploy/12_veloGovernor.d.ts new file mode 100644 index 00000000..68b368bb --- /dev/null +++ b/dist/deploy/12_veloGovernor.d.ts @@ -0,0 +1,3 @@ +import { DeployFunction } from "hardhat-deploy/types"; +declare const func: DeployFunction; +export default func; diff --git a/dist/deploy/12_veloGovernor.js b/dist/deploy/12_veloGovernor.js new file mode 100644 index 00000000..d38c5667 --- /dev/null +++ b/dist/deploy/12_veloGovernor.js @@ -0,0 +1,17 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const func = async function (hre) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + const escrow = await deployments.get("VotingEscrow"); + await deploy("VeloGovernor", { + from: deployer, + args: [escrow.address], + log: true, + skipIfAlreadyDeployed: true, + }); +}; +exports.default = func; +func.tags = ["VeloGovernor"]; +func.id = "veloGovernor"; diff --git a/dist/deploy/13_redemptionReceiver.d.ts b/dist/deploy/13_redemptionReceiver.d.ts new file mode 100644 index 00000000..68b368bb --- /dev/null +++ b/dist/deploy/13_redemptionReceiver.d.ts @@ -0,0 +1,3 @@ +import { DeployFunction } from "hardhat-deploy/types"; +declare const func: DeployFunction; +export default func; diff --git a/dist/deploy/13_redemptionReceiver.js b/dist/deploy/13_redemptionReceiver.js new file mode 100644 index 00000000..c991aa49 --- /dev/null +++ b/dist/deploy/13_redemptionReceiver.js @@ -0,0 +1,29 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const arbTestnetConfig_1 = __importDefault(require("../tasks/deploy/constants/arbTestnetConfig")); +const testFantomConfig_1 = __importDefault(require("../tasks/deploy/constants/testFantomConfig")); +const ARB_TEST_CONFIG = arbTestnetConfig_1.default; +const FTM_CONFIG = testFantomConfig_1.default; +const func = async function (hre) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + const velo = await deployments.get("Velo"); + await deploy("RedemptionReceiver", { + from: deployer, + args: [ + ARB_TEST_CONFIG.USDC, + velo.address, + FTM_CONFIG.lzChainId, + ARB_TEST_CONFIG.lzEndpoint, + ], + log: true, + skipIfAlreadyDeployed: true, + }); +}; +exports.default = func; +func.tags = ["RedemptionReceiver"]; +func.id = "redemptionReceiver"; diff --git a/dist/deploy/14_merkleClaim.d.ts b/dist/deploy/14_merkleClaim.d.ts new file mode 100644 index 00000000..68b368bb --- /dev/null +++ b/dist/deploy/14_merkleClaim.d.ts @@ -0,0 +1,3 @@ +import { DeployFunction } from "hardhat-deploy/types"; +declare const func: DeployFunction; +export default func; diff --git a/dist/deploy/14_merkleClaim.js b/dist/deploy/14_merkleClaim.js new file mode 100644 index 00000000..962094e9 --- /dev/null +++ b/dist/deploy/14_merkleClaim.js @@ -0,0 +1,22 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const arbTestnetConfig_1 = __importDefault(require("../tasks/deploy/constants/arbTestnetConfig")); +const ARB_TEST_CONFIG = arbTestnetConfig_1.default; +const func = async function (hre) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + const velo = await deployments.get("Velo"); + await deploy("MerkleClaim", { + from: deployer, + args: [velo.address, ARB_TEST_CONFIG.merkleRoot], + log: true, + skipIfAlreadyDeployed: true, + }); +}; +exports.default = func; +func.tags = ["MerkleClaim"]; +func.id = "merkleClaim"; diff --git a/dist/deploy/15_init.d.ts b/dist/deploy/15_init.d.ts new file mode 100644 index 00000000..68b368bb --- /dev/null +++ b/dist/deploy/15_init.d.ts @@ -0,0 +1,3 @@ +import { DeployFunction } from "hardhat-deploy/types"; +declare const func: DeployFunction; +export default func; diff --git a/dist/deploy/15_init.js b/dist/deploy/15_init.js new file mode 100644 index 00000000..575d14d7 --- /dev/null +++ b/dist/deploy/15_init.js @@ -0,0 +1,50 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const arbTestnetConfig_1 = __importDefault(require("../tasks/deploy/constants/arbTestnetConfig")); +const ARB_TEST_CONFIG = arbTestnetConfig_1.default; +const func = async function (hre) { + const { deployments, ethers } = hre; + const velo = await ethers.getContract("Velo"); + const pairFactory = await ethers.getContract("PairFactory"); + const escrow = await ethers.getContract("VotingEscrow"); + const voter = await ethers.getContract("Voter"); + const distributor = await ethers.getContract("RewardsDistributor"); + const governor = await ethers.getContract("VeloGovernor"); + const minter = await ethers.getContract("Minter"); + const receiver = await ethers.getContract("RedemptionReceiver"); + const claim = await deployments.get("MerkleClaim"); + // Initialize + await velo.initialMint(ARB_TEST_CONFIG.teamEOA); + console.log("Initial minted"); + await velo.setRedemptionReceiver(receiver.address); + console.log("RedemptionReceiver set"); + await velo.setMerkleClaim(claim.address); + console.log("MerkleClaim set"); + await velo.setMinter(minter.address); + console.log("Minter set"); + await pairFactory.setPauser(ARB_TEST_CONFIG.teamMultisig); + console.log("Pauser set"); + await escrow.setVoter(voter.address); + console.log("Voter set", "voter address: ", voter.address, "escrow address: ", escrow.address); + await escrow.setTeam(ARB_TEST_CONFIG.teamMultisig); + console.log("Team set for escrow"); + await voter.setGovernor(ARB_TEST_CONFIG.teamMultisig); + console.log("Governor set"); + await voter.setEmergencyCouncil(ARB_TEST_CONFIG.teamMultisig); + console.log("Emergency Council set"); + await distributor.setDepositor(minter.address); + console.log("Depositor set"); + await receiver.setTeam(ARB_TEST_CONFIG.teamMultisig); + console.log("Team set for receiver"); + await governor.setTeam(ARB_TEST_CONFIG.teamMultisig); + console.log("Team set for governor"); + await minter.setTeam(ARB_TEST_CONFIG.teamMultisig); + console.log("Team set for minter"); + return true; +}; +exports.default = func; +func.tags = ["init_deploy"]; +func.id = "init_deploy"; diff --git a/dist/deploy/16_whitelist.d.ts b/dist/deploy/16_whitelist.d.ts new file mode 100644 index 00000000..68b368bb --- /dev/null +++ b/dist/deploy/16_whitelist.d.ts @@ -0,0 +1,3 @@ +import { DeployFunction } from "hardhat-deploy/types"; +declare const func: DeployFunction; +export default func; diff --git a/dist/deploy/16_whitelist.js b/dist/deploy/16_whitelist.js new file mode 100644 index 00000000..41fa82d1 --- /dev/null +++ b/dist/deploy/16_whitelist.js @@ -0,0 +1,22 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const arbTestnetConfig_1 = __importDefault(require("../tasks/deploy/constants/arbTestnetConfig")); +const ARB_TEST_CONFIG = arbTestnetConfig_1.default; +const func = async function (hre) { + const { ethers } = hre; + const velo = await ethers.getContract("Velo"); + const voter = await ethers.getContract("Voter"); + const minter = await ethers.getContract("Minter"); + // Whitelist + const nativeToken = [velo.address]; + const tokenWhitelist = nativeToken.concat(ARB_TEST_CONFIG.tokenWhitelist); + await voter.initialize(tokenWhitelist, minter.address); + console.log("Whitelist set"); + return true; +}; +exports.default = func; +func.tags = ["whitelist"]; +func.id = "whitelist"; diff --git a/dist/deploy/17_dist.d.ts b/dist/deploy/17_dist.d.ts new file mode 100644 index 00000000..68b368bb --- /dev/null +++ b/dist/deploy/17_dist.d.ts @@ -0,0 +1,3 @@ +import { DeployFunction } from "hardhat-deploy/types"; +declare const func: DeployFunction; +export default func; diff --git a/dist/deploy/17_dist.js b/dist/deploy/17_dist.js new file mode 100644 index 00000000..9d3bead7 --- /dev/null +++ b/dist/deploy/17_dist.js @@ -0,0 +1,19 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const arbTestnetConfig_1 = __importDefault(require("../tasks/deploy/constants/arbTestnetConfig")); +const ARB_TEST_CONFIG = arbTestnetConfig_1.default; +const func = async function (hre) { + const { ethers } = hre; + const minter = await ethers.getContract("Minter"); + // Initial veVELO distro + await minter.initialize(ARB_TEST_CONFIG.partnerAddrs, ARB_TEST_CONFIG.partnerAmts, ARB_TEST_CONFIG.partnerMax); + console.log("veVELO distributed"); + console.log("Arbitrum Goerli Velocimeter Instruments deployed"); + return true; +}; +exports.default = func; +func.tags = ["initial_dist"]; +func.id = "initial_dist"; diff --git a/dist/hardhat.config.d.ts b/dist/hardhat.config.d.ts new file mode 100644 index 00000000..fcac00df --- /dev/null +++ b/dist/hardhat.config.d.ts @@ -0,0 +1,11 @@ +import "@nomiclabs/hardhat-ethers"; +import "@nomiclabs/hardhat-etherscan"; +import "@nomiclabs/hardhat-waffle"; +import "@typechain/hardhat"; +import "hardhat-preprocessor"; +import "hardhat-abi-exporter"; +import "hardhat-deploy"; +import { HardhatUserConfig } from "hardhat/config"; +import "./checkEnv"; +declare const config: HardhatUserConfig; +export default config; diff --git a/dist/hardhat.config.js b/dist/hardhat.config.js new file mode 100644 index 00000000..298ab360 --- /dev/null +++ b/dist/hardhat.config.js @@ -0,0 +1,111 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +require("@nomiclabs/hardhat-ethers"); +require("@nomiclabs/hardhat-etherscan"); +require("@nomiclabs/hardhat-waffle"); +require("@typechain/hardhat"); +require("hardhat-preprocessor"); +require("hardhat-abi-exporter"); +require("hardhat-deploy"); +const fs_1 = __importDefault(require("fs")); +const path_1 = require("path"); +const dotenv_1 = require("dotenv"); +(0, dotenv_1.config)({ path: (0, path_1.resolve)(__dirname, "./.env") }); +require("./checkEnv"); +const remappings = fs_1.default + .readFileSync("remappings.txt", "utf8") + .split("\n") + .filter(Boolean) + .map((line) => line.trim().split("=")); +const config = { + networks: { + hardhat: { + initialBaseFeePerGas: 0, + forking: { + url: `https://arb-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY}`, + blockNumber: 16051852, + }, + }, + opera: { + url: "https://rpc.fantom.network", + accounts: [process.env.PRIVATE_KEY], + }, + arbitrum: { + url: `https://arb-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY}`, + accounts: [process.env.PRIVATE_KEY], + chainId: 42161, + saveDeployments: true, + verify: { + etherscan: { + apiUrl: "https://api.arbiscan.io/api", + }, + }, + }, + arbitrumGoerli: { + url: `https://arb-goerli.g.alchemy.com/v2/${process.env.ALCHEMY_GOERLI_ARBITRUM_API_KEY}`, + accounts: [process.env.PRIVATE_KEY], + chainId: 421613, + saveDeployments: true, + verify: { + etherscan: { + apiUrl: "https://api-goerli.arbiscan.io/", + apiKey: process.env.ARB_SCAN_API_KEY, + }, + }, + }, + ftmTestnet: { + url: "https://rpc.testnet.fantom.network", + accounts: [process.env.PRIVATE_KEY], + }, + optimisticEthereum: { + url: "https://mainnet.optimism.io", + accounts: [process.env.PRIVATE_KEY], + }, + optimisticKovan: { + url: "https://kovan.optimism.io", + accounts: [process.env.PRIVATE_KEY], + }, + }, + solidity: { + version: "0.8.13", + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, + namedAccounts: { + deployer: 0, + }, + // This fully resolves paths for imports in the ./lib directory for Hardhat + preprocess: { + eachLine: (hre) => ({ + transform: (line) => { + if (!line.match(/^\s*import /i)) { + return line; + } + const remapping = remappings.find(([find]) => line.match('"' + find)); + if (!remapping) { + return line; + } + const [find, replace] = remapping; + return line.replace('"' + find, '"' + replace); + }, + }), + }, + etherscan: { + apiKey: { + opera: process.env.FTM_SCAN_API_KEY, + ftmTestnet: process.env.FTM_SCAN_API_KEY, + optimisticEthereum: process.env.OP_SCAN_API_KEY, + optimisticKovan: process.env.OP_SCAN_API_KEY, + arbitrum: process.env.ARB_SCAN_API_KEY, + arbitrumGoerli: process.env.ARB_SCAN_API_KEY, + }, + }, +}; +exports.default = config; diff --git a/dist/tasks/deploy/arb.d.ts b/dist/tasks/deploy/arb.d.ts new file mode 100644 index 00000000..cb0ff5c3 --- /dev/null +++ b/dist/tasks/deploy/arb.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/tasks/deploy/arb.js b/dist/tasks/deploy/arb.js new file mode 100644 index 00000000..1f3694b6 --- /dev/null +++ b/dist/tasks/deploy/arb.js @@ -0,0 +1,121 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const config_1 = require("hardhat/config"); +const arbConfig_1 = __importDefault(require("./constants/arbConfig")); +const arbTestnetConfig_1 = __importDefault(require("./constants/arbTestnetConfig")); +const fantomConfig_1 = __importDefault(require("./constants/fantomConfig")); +const testFantomConfig_1 = __importDefault(require("./constants/testFantomConfig")); +(0, config_1.task)('deploy:arb', 'Deploys Arbitrum contracts').setAction(async function (taskArguments, { ethers }) { + const mainnet = true; + const ARB_CONFIG = mainnet ? arbConfig_1.default : arbTestnetConfig_1.default; + const FTM_CONFIG = mainnet ? fantomConfig_1.default : testFantomConfig_1.default; + console.log('ALCHEMY_MAINNET_ARBITRUM_API_KEY: ', process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY); + // Load + const [Velo, GaugeFactory, BribeFactory, PairFactory, Router, Library, VeArtProxy, VotingEscrow, RewardsDistributor, Voter, Minter, VeloGovernor, RedemptionReceiver, MerkleClaim] = await Promise.all([ + ethers.getContractFactory('Velo'), + ethers.getContractFactory('GaugeFactory'), + ethers.getContractFactory('BribeFactory'), + ethers.getContractFactory('PairFactory'), + ethers.getContractFactory('Router'), + ethers.getContractFactory('VelodromeLibrary'), + ethers.getContractFactory('VeArtProxy'), + ethers.getContractFactory('VotingEscrow'), + ethers.getContractFactory('RewardsDistributor'), + ethers.getContractFactory('Voter'), + ethers.getContractFactory('Minter'), + ethers.getContractFactory('VeloGovernor'), + ethers.getContractFactory('RedemptionReceiver'), + ethers.getContractFactory('MerkleClaim') + ]); + const velo = await Velo.deploy(); + await velo.deployed(); + console.log('Velo deployed to dunks: ', velo.address); + const gaugeFactory = await GaugeFactory.deploy(); + await gaugeFactory.deployed(); + console.log('GaugeFactory deployed to: ', gaugeFactory.address); + const bribeFactory = await BribeFactory.deploy(); + await bribeFactory.deployed(); + console.log('BribeFactory deployed to: ', bribeFactory.address); + const pairFactory = await PairFactory.deploy(); + await pairFactory.deployed(); + console.log('PairFactory deployed to: ', pairFactory.address); + const router = await Router.deploy(pairFactory.address, ARB_CONFIG.WETH); + await router.deployed(); + console.log('Router deployed to: ', router.address); + console.log('Args: ', pairFactory.address, ARB_CONFIG.WETH, '\n'); + const library = await Library.deploy(router.address); + await library.deployed(); + console.log('VelodromeLibrary deployed to: ', library.address); + console.log('Args: ', router.address, '\n'); + const artProxy = await VeArtProxy.deploy(); + await artProxy.deployed(); + console.log('VeArtProxy deployed to: ', artProxy.address); + const escrow = await VotingEscrow.deploy(velo.address, artProxy.address); + await escrow.deployed(); + console.log('VotingEscrow deployed to: ', escrow.address); + console.log('Args: ', velo.address, artProxy.address, '\n'); + const distributor = await RewardsDistributor.deploy(escrow.address); + await distributor.deployed(); + console.log('RewardsDistributor deployed to: ', distributor.address); + console.log('Args: ', escrow.address, '\n'); + const voter = await Voter.deploy(escrow.address, pairFactory.address, gaugeFactory.address, bribeFactory.address); + await voter.deployed(); + console.log('Voter deployed to: ', voter.address); + console.log('Args: ', escrow.address, pairFactory.address, gaugeFactory.address, bribeFactory.address, '\n'); + const minter = await Minter.deploy(voter.address, escrow.address, distributor.address); + await minter.deployed(); + console.log('Minter deployed to: ', minter.address); + console.log('Args: ', voter.address, escrow.address, distributor.address, '\n'); + const receiver = await RedemptionReceiver.deploy(ARB_CONFIG.USDC, velo.address, FTM_CONFIG.lzChainId, ARB_CONFIG.lzEndpoint); + await receiver.deployed(); + console.log('RedemptionReceiver deployed to: ', receiver.address); + console.log('Args: ', ARB_CONFIG.USDC, velo.address, FTM_CONFIG.lzChainId, ARB_CONFIG.lzEndpoint, '\n'); + const governor = await VeloGovernor.deploy(escrow.address); + await governor.deployed(); + console.log('VeloGovernor deployed to: ', governor.address); + console.log('Args: ', escrow.address, '\n'); + // Airdrop + const claim = await MerkleClaim.deploy(velo.address, ARB_CONFIG.merkleRoot); + await claim.deployed(); + console.log('MerkleClaim deployed to: ', claim.address); + console.log('Args: ', velo.address, ARB_CONFIG.merkleRoot, '\n'); + // Initialize + await velo.initialMint(ARB_CONFIG.teamEOA); + console.log('Initial minted'); + await velo.setRedemptionReceiver(receiver.address); + console.log('RedemptionReceiver set'); + await velo.setMerkleClaim(claim.address); + console.log('MerkleClaim set'); + await velo.setMinter(minter.address); + console.log('Minter set'); + await pairFactory.setPauser(ARB_CONFIG.teamMultisig); + console.log('Pauser set'); + await escrow.setVoter(voter.address); + console.log('Voter set'); + await escrow.setTeam(ARB_CONFIG.teamMultisig); + console.log('Team set for escrow'); + await voter.setGovernor(ARB_CONFIG.teamMultisig); + console.log('Governor set'); + await voter.setEmergencyCouncil(ARB_CONFIG.teamMultisig); + console.log('Emergency Council set'); + await distributor.setDepositor(minter.address); + console.log('Depositor set'); + await receiver.setTeam(ARB_CONFIG.teamMultisig); + console.log('Team set for receiver'); + await governor.setTeam(ARB_CONFIG.teamMultisig); + console.log('Team set for governor'); + // Whitelist + const nativeToken = [velo.address]; + const tokenWhitelist = nativeToken.concat(ARB_CONFIG.tokenWhitelist); + await voter.initialize(tokenWhitelist, minter.address); + console.log('Whitelist set'); + // Initial veVELO distro + await minter.initialize(ARB_CONFIG.partnerAddrs, ARB_CONFIG.partnerAmts, ARB_CONFIG.partnerMax); + console.log('veVELO distributed'); + await minter.setTeam(ARB_CONFIG.teamMultisig); + console.log('Team set for minter'); + console.log('Arbitrum contracts deployed'); +}); diff --git a/dist/tasks/deploy/arbHardhat.d.ts b/dist/tasks/deploy/arbHardhat.d.ts new file mode 100644 index 00000000..cb0ff5c3 --- /dev/null +++ b/dist/tasks/deploy/arbHardhat.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/tasks/deploy/arbHardhat.js b/dist/tasks/deploy/arbHardhat.js new file mode 100644 index 00000000..f3f593d2 --- /dev/null +++ b/dist/tasks/deploy/arbHardhat.js @@ -0,0 +1,121 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const config_1 = require("hardhat/config"); +const arbConfig_1 = __importDefault(require("./constants/arbConfig")); +const arbHardhatConfig_1 = __importDefault(require("./constants/arbHardhatConfig")); +const fantomConfig_1 = __importDefault(require("./constants/fantomConfig")); +const testFantomConfig_1 = __importDefault(require("./constants/testFantomConfig")); +(0, config_1.task)('deploy:arbHardhat', 'Deploys Arbitrum forked chain contracts').setAction(async function (taskArguments, { ethers }) { + const mainnet = false; + const ARB_CONFIG = mainnet ? arbConfig_1.default : arbHardhatConfig_1.default; + const FTM_CONFIG = mainnet ? fantomConfig_1.default : testFantomConfig_1.default; + console.log('ALCHEMY_MAINNET_ARBITRUM_API_KEY: ', process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY); + // Load + const [Velo, GaugeFactory, BribeFactory, PairFactory, Router, Library, VeArtProxy, VotingEscrow, RewardsDistributor, Voter, Minter, VeloGovernor, RedemptionReceiver, MerkleClaim] = await Promise.all([ + ethers.getContractFactory('Velo'), + ethers.getContractFactory('GaugeFactory'), + ethers.getContractFactory('BribeFactory'), + ethers.getContractFactory('PairFactory'), + ethers.getContractFactory('Router'), + ethers.getContractFactory('VelodromeLibrary'), + ethers.getContractFactory('VeArtProxy'), + ethers.getContractFactory('VotingEscrow'), + ethers.getContractFactory('RewardsDistributor'), + ethers.getContractFactory('Voter'), + ethers.getContractFactory('Minter'), + ethers.getContractFactory('VeloGovernor'), + ethers.getContractFactory('RedemptionReceiver'), + ethers.getContractFactory('MerkleClaim') + ]); + const velo = await Velo.deploy(); + await velo.deployed(); + console.log('Velo deployed to dunks: ', velo.address); + const gaugeFactory = await GaugeFactory.deploy(); + await gaugeFactory.deployed(); + console.log('GaugeFactory deployed to: ', gaugeFactory.address); + const bribeFactory = await BribeFactory.deploy(); + await bribeFactory.deployed(); + console.log('BribeFactory deployed to: ', bribeFactory.address); + const pairFactory = await PairFactory.deploy(); + await pairFactory.deployed(); + console.log('PairFactory deployed to: ', pairFactory.address); + const router = await Router.deploy(pairFactory.address, ARB_CONFIG.WETH); + await router.deployed(); + console.log('Router deployed to: ', router.address); + console.log('Args: ', pairFactory.address, ARB_CONFIG.WETH, '\n'); + const library = await Library.deploy(router.address); + await library.deployed(); + console.log('VelodromeLibrary deployed to: ', library.address); + console.log('Args: ', router.address, '\n'); + const artProxy = await VeArtProxy.deploy(); + await artProxy.deployed(); + console.log('VeArtProxy deployed to: ', artProxy.address); + const escrow = await VotingEscrow.deploy(velo.address, artProxy.address); + await escrow.deployed(); + console.log('VotingEscrow deployed to: ', escrow.address); + console.log('Args: ', velo.address, artProxy.address, '\n'); + const distributor = await RewardsDistributor.deploy(escrow.address); + await distributor.deployed(); + console.log('RewardsDistributor deployed to: ', distributor.address); + console.log('Args: ', escrow.address, '\n'); + const voter = await Voter.deploy(escrow.address, pairFactory.address, gaugeFactory.address, bribeFactory.address); + await voter.deployed(); + console.log('Voter deployed to: ', voter.address); + console.log('Args: ', escrow.address, pairFactory.address, gaugeFactory.address, bribeFactory.address, '\n'); + const minter = await Minter.deploy(voter.address, escrow.address, distributor.address); + await minter.deployed(); + console.log('Minter deployed to: ', minter.address); + console.log('Args: ', voter.address, escrow.address, distributor.address, '\n'); + const receiver = await RedemptionReceiver.deploy(ARB_CONFIG.USDC, velo.address, FTM_CONFIG.lzChainId, ARB_CONFIG.lzEndpoint); + await receiver.deployed(); + console.log('RedemptionReceiver deployed to: ', receiver.address); + console.log('Args: ', ARB_CONFIG.USDC, velo.address, FTM_CONFIG.lzChainId, ARB_CONFIG.lzEndpoint, '\n'); + const governor = await VeloGovernor.deploy(escrow.address); + await governor.deployed(); + console.log('VeloGovernor deployed to: ', governor.address); + console.log('Args: ', escrow.address, '\n'); + // Airdrop + const claim = await MerkleClaim.deploy(velo.address, ARB_CONFIG.merkleRoot); + await claim.deployed(); + console.log('MerkleClaim deployed to: ', claim.address); + console.log('Args: ', velo.address, ARB_CONFIG.merkleRoot, '\n'); + // Initialize + await velo.initialMint(ARB_CONFIG.teamEOA); + console.log('Initial minted'); + await velo.setRedemptionReceiver(receiver.address); + console.log('RedemptionReceiver set'); + await velo.setMerkleClaim(claim.address); + console.log('MerkleClaim set'); + await velo.setMinter(minter.address); + console.log('Minter set'); + await pairFactory.setPauser(ARB_CONFIG.teamMultisig); + console.log('Pauser set'); + await escrow.setVoter(voter.address); + console.log('Voter set'); + await escrow.setTeam(ARB_CONFIG.teamMultisig); + console.log('Team set for escrow'); + await voter.setGovernor(ARB_CONFIG.teamMultisig); + console.log('Governor set'); + await voter.setEmergencyCouncil(ARB_CONFIG.teamMultisig); + console.log('Emergency Council set'); + await distributor.setDepositor(minter.address); + console.log('Depositor set'); + await receiver.setTeam(ARB_CONFIG.teamMultisig); + console.log('Team set for receiver'); + await governor.setTeam(ARB_CONFIG.teamMultisig); + console.log('Team set for governor'); + // Whitelist + const nativeToken = [velo.address]; + const tokenWhitelist = nativeToken.concat(ARB_CONFIG.tokenWhitelist); + await voter.initialize(tokenWhitelist, minter.address); + console.log('Whitelist set'); + // Initial veVELO distro + await minter.initialize(ARB_CONFIG.partnerAddrs, ARB_CONFIG.partnerAmts, ARB_CONFIG.partnerMax); + console.log('veVELO distributed'); + await minter.setTeam(ARB_CONFIG.teamMultisig); + console.log('Team set for minter'); + console.log('Arbitrum Forked Chain contracts deployed'); +}); diff --git a/dist/tasks/deploy/arbTest.d.ts b/dist/tasks/deploy/arbTest.d.ts new file mode 100644 index 00000000..cb0ff5c3 --- /dev/null +++ b/dist/tasks/deploy/arbTest.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/tasks/deploy/arbTest.js b/dist/tasks/deploy/arbTest.js new file mode 100644 index 00000000..9981b8df --- /dev/null +++ b/dist/tasks/deploy/arbTest.js @@ -0,0 +1,176 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const config_1 = require("hardhat/config"); +var fs = require('fs'); +const optimismConfig_1 = __importDefault(require("./constants/optimismConfig")); +const testOptimismConfig_1 = __importDefault(require("./constants/testOptimismConfig")); +const fantomConfig_1 = __importDefault(require("./constants/fantomConfig")); +const testFantomConfig_1 = __importDefault(require("./constants/testFantomConfig")); +(0, config_1.task)('deploy:arbTest', 'Deploys Optimism contracts').setAction(async function (taskArguments, { ethers }) { + const mainnet = false; + const OP_CONFIG = mainnet ? optimismConfig_1.default : testOptimismConfig_1.default; + const FTM_CONFIG = mainnet ? fantomConfig_1.default : testFantomConfig_1.default; + // Load + const [Velo, GaugeFactory, BribeFactory, PairFactory, Router, Library, VeArtProxy, VotingEscrow, RewardsDistributor, Voter, Minter, VeloGovernor, RedemptionReceiver, MerkleClaim] = await Promise.all([ + ethers.getContractFactory('Velo'), + ethers.getContractFactory('GaugeFactory'), + ethers.getContractFactory('BribeFactory'), + ethers.getContractFactory('PairFactory'), + ethers.getContractFactory('Router'), + ethers.getContractFactory('VelodromeLibrary'), + ethers.getContractFactory('VeArtProxy'), + ethers.getContractFactory('VotingEscrow'), + ethers.getContractFactory('RewardsDistributor'), + ethers.getContractFactory('Voter'), + ethers.getContractFactory('Minter'), + ethers.getContractFactory('VeloGovernor'), + ethers.getContractFactory('RedemptionReceiver'), + ethers.getContractFactory('MerkleClaim') + ]); + //WIP wait for 5 block transactions to ensure deployment before verifying + // https://stackoverflow.com/questions/72916701/hardhat-compile-deploy-and-verify-in-a-single-script + // https://github.com/profullstackdeveloper/contract-deploy-verify-hardhat + // shows how to save deployments and verify but for a single contract only... Need to find a better example to loop through them all save to /deployments and then verify... + // await Promise.all.deployTransaction.wait(5) + // //verify + // await hre.run('verify:verify', { + // address: velo.address, + // contract: 'contracts/Velo.sol:MyContract', //Filename.sol:ClassName + // constructorArguments: [arg1, arg2, arg3] + // }) + // WIP ^^ + const velo = await Velo.deploy(); + await velo.deployed(); + console.log('Velo deployed to: ', velo.address); + await hre.run('verify:verify', { + address: velo.address, + contract: 'contracts/Velo.sol:Velo', + constructorArguments: [] + }); + await velo.deployed(); + const name = await velo.name(); + console.log('dunksname: ', name); + const temp1 = { + [name]: velo.address + }; + const json1 = JSON.stringify(temp1); + console.log('result of json is ', json1); + fs.writeFileSync('contracts/deployments/veloAddress.json', json1, err => { + if (err) { + console.log('ERROR! while creating file: ', err); + } + else { + console.log('result is ', json1); + } + }); + // repeat for gauge factory + // update all the things... + const gaugeFactory = await GaugeFactory.deploy(); + await gaugeFactory.deployed(); + console.log('GaugeFactory deployed to: ', gaugeFactory.address); + // await hre.run('verify:verify', { + // address: gaugeFactory.address, + // contract: 'contracts/factories/GaugeFactory.sol:GaugeFactory', //Filename.sol:ClassName + // constructorArguments: [] + // }) + // await gaugeFactory.deployed() + // const name1 = await gaugeFactory.name() + // console.log('dunksname: ', name) + // const temp = { + // [name1]: gaugeFactory.address + // } + // const json = JSON.stringify(temp) + // console.log('result of json is ', json) + // fs.writeFileSync('contracts/deployments/veloAddress.json', json, err => { + // if (err) { + // console.log('ERROR! while creating file: ', err) + // } else { + // console.log('result is ', json) + // } + // }) + const bribeFactory = await BribeFactory.deploy(); + await bribeFactory.deployed(); + console.log('BribeFactory deployed to: ', bribeFactory.address); + const pairFactory = await PairFactory.deploy(); + await pairFactory.deployed(); + console.log('PairFactory deployed to: ', pairFactory.address); + const router = await Router.deploy(pairFactory.address, OP_CONFIG.WETH); + await router.deployed(); + console.log('Router deployed to: ', router.address); + console.log('Args: ', pairFactory.address, OP_CONFIG.WETH, '\n'); + const library = await Library.deploy(router.address); + await library.deployed(); + console.log('VelodromeLibrary deployed to: ', library.address); + console.log('Args: ', router.address, '\n'); + const artProxy = await VeArtProxy.deploy(); + await artProxy.deployed(); + console.log('VeArtProxy deployed to: ', artProxy.address); + const escrow = await VotingEscrow.deploy(velo.address, artProxy.address); + await escrow.deployed(); + console.log('VotingEscrow deployed to: ', escrow.address); + console.log('Args: ', velo.address, artProxy.address, '\n'); + const distributor = await RewardsDistributor.deploy(escrow.address); + await distributor.deployed(); + console.log('RewardsDistributor deployed to: ', distributor.address); + console.log('Args: ', escrow.address, '\n'); + const voter = await Voter.deploy(escrow.address, pairFactory.address, gaugeFactory.address, bribeFactory.address); + await voter.deployed(); + console.log('Voter deployed to: ', voter.address); + console.log('Args: ', escrow.address, pairFactory.address, gaugeFactory.address, bribeFactory.address, '\n'); + const minter = await Minter.deploy(voter.address, escrow.address, distributor.address); + await minter.deployed(); + console.log('Minter deployed to: ', minter.address); + console.log('Args: ', voter.address, escrow.address, distributor.address, '\n'); + const receiver = await RedemptionReceiver.deploy(OP_CONFIG.USDC, velo.address, FTM_CONFIG.lzChainId, OP_CONFIG.lzEndpoint); + await receiver.deployed(); + console.log('RedemptionReceiver deployed to: ', receiver.address); + console.log('Args: ', OP_CONFIG.USDC, velo.address, FTM_CONFIG.lzChainId, OP_CONFIG.lzEndpoint, '\n'); + const governor = await VeloGovernor.deploy(escrow.address); + await governor.deployed(); + console.log('VeloGovernor deployed to: ', governor.address); + console.log('Args: ', escrow.address, '\n'); + // Airdrop + // const claim = await MerkleClaim.deploy(velo.address, OP_CONFIG.merkleRoot) + // await claim.deployed() + // console.log('MerkleClaim deployed to: ', claim.address) + // console.log('Args: ', velo.address, OP_CONFIG.merkleRoot, '\n') + // Initialize + await velo.initialMint(OP_CONFIG.teamEOA); + console.log('Initial minted'); + await velo.setRedemptionReceiver(receiver.address); + console.log('RedemptionReceiver set'); + // await velo.setMerkleClaim(claim.address) + // console.log('MerkleClaim set') + await velo.setMinter(minter.address); + console.log('Minter set'); + await pairFactory.setPauser(OP_CONFIG.teamMultisig); + console.log('Pauser set'); + await escrow.setVoter(voter.address); + console.log('Voter set', 'voter address: ', voter.address, 'escrow address: ', escrow.address); + await escrow.setTeam(OP_CONFIG.teamMultisig); + console.log('Team set for escrow'); + await voter.setGovernor(OP_CONFIG.teamMultisig); + console.log('Governor set'); + await voter.setEmergencyCouncil(OP_CONFIG.teamMultisig); + console.log('Emergency Council set'); + await distributor.setDepositor(minter.address); + console.log('Depositor set'); + await receiver.setTeam(OP_CONFIG.teamMultisig); + console.log('Team set for receiver'); + await governor.setTeam(OP_CONFIG.teamMultisig); + console.log('Team set for governor'); + // Whitelist + const nativeToken = [velo.address]; + const tokenWhitelist = nativeToken.concat(OP_CONFIG.tokenWhitelist); + await voter.initialize(tokenWhitelist, minter.address); + console.log('Whitelist set'); + // Initial veVELO distro + await minter.initialize(OP_CONFIG.partnerAddrs, OP_CONFIG.partnerAmts, OP_CONFIG.partnerMax); + console.log('veVELO distributed'); + await minter.setTeam(OP_CONFIG.teamMultisig); + console.log('Team set for minter'); + console.log('Arbitrum Goerli Velocimeter Instruments deployed'); +}); diff --git a/dist/tasks/deploy/constants/arbConfig.d.ts b/dist/tasks/deploy/constants/arbConfig.d.ts new file mode 100644 index 00000000..232c2572 --- /dev/null +++ b/dist/tasks/deploy/constants/arbConfig.d.ts @@ -0,0 +1,16 @@ +import { ethers } from 'ethers'; +declare const arbConfig: { + lzChainId: number; + lzEndpoint: string; + WETH: string; + USDC: string; + teamEOA: string; + teamMultisig: string; + emergencyCouncil: string; + merkleRoot: string; + tokenWhitelist: string[]; + partnerAddrs: string[]; + partnerAmts: ethers.BigNumber[]; + partnerMax: ethers.BigNumber; +}; +export default arbConfig; diff --git a/dist/tasks/deploy/constants/arbConfig.js b/dist/tasks/deploy/constants/arbConfig.js new file mode 100644 index 00000000..9c2d36e9 --- /dev/null +++ b/dist/tasks/deploy/constants/arbConfig.js @@ -0,0 +1,82 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const ethers_1 = require("ethers"); +const TOKEN_DECIMALS = ethers_1.ethers.BigNumber.from('10').pow(ethers_1.ethers.BigNumber.from('18')); +const MILLION = ethers_1.ethers.BigNumber.from('10').pow(ethers_1.ethers.BigNumber.from('6')); +const FOUR_MILLION = ethers_1.ethers.BigNumber.from('4').mul(MILLION).mul(TOKEN_DECIMALS); +const TEN_MILLION = ethers_1.ethers.BigNumber.from('10').mul(MILLION).mul(TOKEN_DECIMALS); +const TWENTY_MILLION = ethers_1.ethers.BigNumber.from('20') + .mul(MILLION) + .mul(TOKEN_DECIMALS); +const PARTNER_MAX = ethers_1.ethers.BigNumber.from('78').mul(MILLION).mul(TOKEN_DECIMALS); +const TEAM_MULTISIG = '0x069e85D4F1010DD961897dC8C095FBB5FF297434'; +const TEAM_EOA = '0x069e85D4F1010DD961897dC8C095FBB5FF297434'; +const arbConfig = { + // Chain const + lzChainId: 110, + lzEndpoint: '0x3c2269811836af69497E5F486A85D7316753cf62', + // Tokens + WETH: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', + USDC: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', + // Addresses + teamEOA: TEAM_EOA, + teamMultisig: TEAM_MULTISIG, + emergencyCouncil: '0xcC2D01030eC2cd187346F70bFc483F24488C32E8', + merkleRoot: '0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f', + tokenWhitelist: [ + '0x4200000000000000000000000000000000000042', + '0x4200000000000000000000000000000000000006', + '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', + '0x2E3D870790dC77A83DD1d18184Acc7439A53f475', + '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', + '0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9', + '0x217D47011b23BB961eB6D93cA9945B7501a5BB11', + '0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb', + '0x67CCEA5bb16181E7b4109c9c2143c24a1c2205Be', + '0x9e1028F5F1D5eDE59748FFceE5532509976840E0', + '0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4', + '0xCB8FA9a76b8e203D8C3797bF438d8FB81Ea3326A', + '0x3E29D3A9316dAB217754d13b28646B76607c5f04', + '0x8aE125E8653821E851F12A49F7765db9a9ce7384', + '0x10010078a54396F62c96dF8532dc2B4847d47ED3', + // "", // BTRFLY -- N/A + // "", // pxVELO -- N/A + '0xc40F949F8a4e094D1b49a23ea9241D289B7b2819' // LUSD + // "", // wstETH -- N/A + // "", // HOP -- N/A + ], + partnerAddrs: [ + TEAM_EOA, + '0x4a84675512949f81EBFEAAcC6C00D03eDd329de5', + TEAM_EOA, + '0xa283139017a2f5BAdE8d8e25412C600055D318F8', + '0xDcf664d0f76E99eaA2DBD569474d0E75dC899FCD', + '0x489863b61C625a15C74FB4C21486baCb4A3937AB', + '0x641f26c67A5D0829Ae61019131093B6a7c7d18a3', + '0xC224bf25Dcc99236F00843c7D8C4194abE8AA94a', + '0xB6DACAE4eF97b4817d54df8e005269f509f803f9', + TEAM_EOA, + TEAM_EOA, + '0x0dF840dCbf1229262A4125C1fc559bd338eC9491', + '0x2E33A660742e813aD948fB9f7d682FE461E5fbf3', + '0xd2D4e9024D8C90aB52032a9F1e0d92D4cE20191B' // LUSD + ], + partnerAmts: [ + TEN_MILLION, + TWENTY_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION + ], + partnerMax: PARTNER_MAX +}; +exports.default = arbConfig; diff --git a/dist/tasks/deploy/constants/arbHardhatConfig.d.ts b/dist/tasks/deploy/constants/arbHardhatConfig.d.ts new file mode 100644 index 00000000..5d2c6776 --- /dev/null +++ b/dist/tasks/deploy/constants/arbHardhatConfig.d.ts @@ -0,0 +1,16 @@ +import { ethers } from 'ethers'; +declare const arbHardhatConfig: { + lzChainId: number; + lzEndpoint: string; + WETH: string; + USDC: string; + teamEOA: string; + teamMultisig: string; + emergencyCouncil: string; + merkleRoot: string; + tokenWhitelist: string[]; + partnerAddrs: string[]; + partnerAmts: ethers.BigNumber[]; + partnerMax: ethers.BigNumber; +}; +export default arbHardhatConfig; diff --git a/dist/tasks/deploy/constants/arbHardhatConfig.js b/dist/tasks/deploy/constants/arbHardhatConfig.js new file mode 100644 index 00000000..de543984 --- /dev/null +++ b/dist/tasks/deploy/constants/arbHardhatConfig.js @@ -0,0 +1,82 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const ethers_1 = require("ethers"); +const TOKEN_DECIMALS = ethers_1.ethers.BigNumber.from('10').pow(ethers_1.ethers.BigNumber.from('18')); +const MILLION = ethers_1.ethers.BigNumber.from('10').pow(ethers_1.ethers.BigNumber.from('6')); +const FOUR_MILLION = ethers_1.ethers.BigNumber.from('4').mul(MILLION).mul(TOKEN_DECIMALS); +const TEN_MILLION = ethers_1.ethers.BigNumber.from('10').mul(MILLION).mul(TOKEN_DECIMALS); +const TWENTY_MILLION = ethers_1.ethers.BigNumber.from('20') + .mul(MILLION) + .mul(TOKEN_DECIMALS); +const PARTNER_MAX = ethers_1.ethers.BigNumber.from('78').mul(MILLION).mul(TOKEN_DECIMALS); +const TEAM_MULTISIG = '0x069e85D4F1010DD961897dC8C095FBB5FF297434'; +const TEAM_EOA = '0x069e85D4F1010DD961897dC8C095FBB5FF297434'; +const arbHardhatConfig = { + // Chain const + lzChainId: 110, + lzEndpoint: '0x3c2269811836af69497E5F486A85D7316753cf62', + // Tokens + WETH: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', + USDC: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', + // Addresses + teamEOA: TEAM_EOA, + teamMultisig: TEAM_MULTISIG, + emergencyCouncil: '0xcC2D01030eC2cd187346F70bFc483F24488C32E8', + merkleRoot: '0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f', + tokenWhitelist: [ + '0x4200000000000000000000000000000000000042', + '0x4200000000000000000000000000000000000006', + '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', + '0x2E3D870790dC77A83DD1d18184Acc7439A53f475', + '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', + '0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9', + '0x217D47011b23BB961eB6D93cA9945B7501a5BB11', + '0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb', + '0x67CCEA5bb16181E7b4109c9c2143c24a1c2205Be', + '0x9e1028F5F1D5eDE59748FFceE5532509976840E0', + '0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4', + '0xCB8FA9a76b8e203D8C3797bF438d8FB81Ea3326A', + '0x3E29D3A9316dAB217754d13b28646B76607c5f04', + '0x8aE125E8653821E851F12A49F7765db9a9ce7384', + '0x10010078a54396F62c96dF8532dc2B4847d47ED3', + // "", // BTRFLY -- N/A + // "", // pxVELO -- N/A + '0xc40F949F8a4e094D1b49a23ea9241D289B7b2819' // LUSD + // "", // wstETH -- N/A + // "", // HOP -- N/A + ], + partnerAddrs: [ + TEAM_EOA, + '0x4a84675512949f81EBFEAAcC6C00D03eDd329de5', + TEAM_EOA, + '0xa283139017a2f5BAdE8d8e25412C600055D318F8', + '0xDcf664d0f76E99eaA2DBD569474d0E75dC899FCD', + '0x489863b61C625a15C74FB4C21486baCb4A3937AB', + '0x641f26c67A5D0829Ae61019131093B6a7c7d18a3', + '0xC224bf25Dcc99236F00843c7D8C4194abE8AA94a', + '0xB6DACAE4eF97b4817d54df8e005269f509f803f9', + TEAM_EOA, + TEAM_EOA, + '0x0dF840dCbf1229262A4125C1fc559bd338eC9491', + '0x2E33A660742e813aD948fB9f7d682FE461E5fbf3', + '0xd2D4e9024D8C90aB52032a9F1e0d92D4cE20191B' // LUSD + ], + partnerAmts: [ + TEN_MILLION, + TWENTY_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION + ], + partnerMax: PARTNER_MAX +}; +exports.default = arbHardhatConfig; diff --git a/dist/tasks/deploy/constants/arbTestnetConfig.d.ts b/dist/tasks/deploy/constants/arbTestnetConfig.d.ts new file mode 100644 index 00000000..0ef81208 --- /dev/null +++ b/dist/tasks/deploy/constants/arbTestnetConfig.d.ts @@ -0,0 +1,16 @@ +import { ethers } from 'ethers'; +declare const arbTestnetConfig: { + lzChainId: number; + lzEndpoint: string; + WETH: string; + USDC: string; + teamEOA: string; + teamMultisig: string; + emergencyCouncil: string; + merkleRoot: string; + tokenWhitelist: string[]; + partnerAddrs: string[]; + partnerAmts: ethers.BigNumber[]; + partnerMax: ethers.BigNumber; +}; +export default arbTestnetConfig; diff --git a/dist/tasks/deploy/constants/arbTestnetConfig.js b/dist/tasks/deploy/constants/arbTestnetConfig.js new file mode 100644 index 00000000..642db67b --- /dev/null +++ b/dist/tasks/deploy/constants/arbTestnetConfig.js @@ -0,0 +1,82 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const ethers_1 = require("ethers"); +const TOKEN_DECIMALS = ethers_1.ethers.BigNumber.from('10').pow(ethers_1.ethers.BigNumber.from('18')); +const MILLION = ethers_1.ethers.BigNumber.from('10').pow(ethers_1.ethers.BigNumber.from('6')); +const FOUR_MILLION = ethers_1.ethers.BigNumber.from('4').mul(MILLION).mul(TOKEN_DECIMALS); +const TEN_MILLION = ethers_1.ethers.BigNumber.from('10').mul(MILLION).mul(TOKEN_DECIMALS); +const TWENTY_MILLION = ethers_1.ethers.BigNumber.from('20') + .mul(MILLION) + .mul(TOKEN_DECIMALS); +const PARTNER_MAX = ethers_1.ethers.BigNumber.from('78').mul(MILLION).mul(TOKEN_DECIMALS); +const TEAM_MULTISIG = '0xb074ec6c37659525EEf2Fb44478077901F878012'; +const TEAM_EOA = '0xe247340f06FCB7eb904F16a48C548221375b5b96'; +const arbTestnetConfig = { + // Chain const + lzChainId: 11, + lzEndpoint: '0x3c2269811836af69497E5F486A85D7316753cf62', + // Tokens + WETH: '0x4200000000000000000000000000000000000006', + USDC: '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', + // Addresses + teamEOA: TEAM_EOA, + teamMultisig: TEAM_MULTISIG, + emergencyCouncil: '0xcC2D01030eC2cd187346F70bFc483F24488C32E8', + merkleRoot: '0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f', + tokenWhitelist: [ + '0x4200000000000000000000000000000000000042', + '0x4200000000000000000000000000000000000006', + '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', + '0x2E3D870790dC77A83DD1d18184Acc7439A53f475', + '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', + '0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9', + '0x217D47011b23BB961eB6D93cA9945B7501a5BB11', + '0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb', + '0x67CCEA5bb16181E7b4109c9c2143c24a1c2205Be', + '0x9e1028F5F1D5eDE59748FFceE5532509976840E0', + '0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4', + '0xCB8FA9a76b8e203D8C3797bF438d8FB81Ea3326A', + '0x3E29D3A9316dAB217754d13b28646B76607c5f04', + '0x8aE125E8653821E851F12A49F7765db9a9ce7384', + '0x10010078a54396F62c96dF8532dc2B4847d47ED3', + // "", // BTRFLY -- N/A + // "", // pxVELO -- N/A + '0xc40F949F8a4e094D1b49a23ea9241D289B7b2819' // LUSD + // "", // wstETH -- N/A + // "", // HOP -- N/A + ], + partnerAddrs: [ + TEAM_EOA, + '0x4a84675512949f81EBFEAAcC6C00D03eDd329de5', + TEAM_EOA, + '0xa283139017a2f5BAdE8d8e25412C600055D318F8', + '0xDcf664d0f76E99eaA2DBD569474d0E75dC899FCD', + '0x489863b61C625a15C74FB4C21486baCb4A3937AB', + '0x641f26c67A5D0829Ae61019131093B6a7c7d18a3', + '0xC224bf25Dcc99236F00843c7D8C4194abE8AA94a', + '0xB6DACAE4eF97b4817d54df8e005269f509f803f9', + TEAM_EOA, + TEAM_EOA, + '0x0dF840dCbf1229262A4125C1fc559bd338eC9491', + '0x2E33A660742e813aD948fB9f7d682FE461E5fbf3', + '0xd2D4e9024D8C90aB52032a9F1e0d92D4cE20191B' // LUSD + ], + partnerAmts: [ + TEN_MILLION, + TWENTY_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION + ], + partnerMax: PARTNER_MAX +}; +exports.default = arbTestnetConfig; diff --git a/dist/tasks/deploy/constants/deployed.d.ts b/dist/tasks/deploy/constants/deployed.d.ts new file mode 100644 index 00000000..4c9ac591 --- /dev/null +++ b/dist/tasks/deploy/constants/deployed.d.ts @@ -0,0 +1,5 @@ +declare const deployed: { + optimismReceiver: string; + fantomSender: string; +}; +export default deployed; diff --git a/dist/tasks/deploy/constants/deployed.js b/dist/tasks/deploy/constants/deployed.js new file mode 100644 index 00000000..8a6fadb4 --- /dev/null +++ b/dist/tasks/deploy/constants/deployed.js @@ -0,0 +1,7 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const deployed = { + optimismReceiver: "0x846e822e9a00669dcC647079d7d625d2cd25A951", + fantomSender: "", +}; +exports.default = deployed; diff --git a/dist/tasks/deploy/constants/fantomConfig.d.ts b/dist/tasks/deploy/constants/fantomConfig.d.ts new file mode 100644 index 00000000..e65dac76 --- /dev/null +++ b/dist/tasks/deploy/constants/fantomConfig.d.ts @@ -0,0 +1,6 @@ +declare const fantomConfig: { + lzChainId: number; + lzEndpoint: string; + WEVE: string; +}; +export default fantomConfig; diff --git a/dist/tasks/deploy/constants/fantomConfig.js b/dist/tasks/deploy/constants/fantomConfig.js new file mode 100644 index 00000000..f001c87b --- /dev/null +++ b/dist/tasks/deploy/constants/fantomConfig.js @@ -0,0 +1,8 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const fantomConfig = { + lzChainId: 12, + lzEndpoint: "0xb6319cC6c8c27A8F5dAF0dD3DF91EA35C4720dd7", + WEVE: "0x911da02C1232A3c3E1418B834A311921143B04d7", +}; +exports.default = fantomConfig; diff --git a/dist/tasks/deploy/constants/index.d.ts b/dist/tasks/deploy/constants/index.d.ts new file mode 100644 index 00000000..e69de29b diff --git a/dist/tasks/deploy/constants/index.js b/dist/tasks/deploy/constants/index.js new file mode 100644 index 00000000..3918c74e --- /dev/null +++ b/dist/tasks/deploy/constants/index.js @@ -0,0 +1 @@ +"use strict"; diff --git a/dist/tasks/deploy/constants/optimismConfig.d.ts b/dist/tasks/deploy/constants/optimismConfig.d.ts new file mode 100644 index 00000000..e42ce760 --- /dev/null +++ b/dist/tasks/deploy/constants/optimismConfig.d.ts @@ -0,0 +1,16 @@ +import { ethers } from "ethers"; +declare const optimismConfig: { + lzChainId: number; + lzEndpoint: string; + WETH: string; + USDC: string; + teamEOA: string; + teamMultisig: string; + emergencyCouncil: string; + merkleRoot: string; + tokenWhitelist: string[]; + partnerAddrs: string[]; + partnerAmts: ethers.BigNumber[]; + partnerMax: ethers.BigNumber; +}; +export default optimismConfig; diff --git a/dist/tasks/deploy/constants/optimismConfig.js b/dist/tasks/deploy/constants/optimismConfig.js new file mode 100644 index 00000000..51b329f5 --- /dev/null +++ b/dist/tasks/deploy/constants/optimismConfig.js @@ -0,0 +1,88 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const ethers_1 = require("ethers"); +const TOKEN_DECIMALS = ethers_1.ethers.BigNumber.from("10").pow(ethers_1.ethers.BigNumber.from("18")); +const MILLION = ethers_1.ethers.BigNumber.from("10").pow(ethers_1.ethers.BigNumber.from("6")); +const FOUR_MILLION = ethers_1.ethers.BigNumber.from("4") + .mul(MILLION) + .mul(TOKEN_DECIMALS); +const TEN_MILLION = ethers_1.ethers.BigNumber.from("10") + .mul(MILLION) + .mul(TOKEN_DECIMALS); +const TWENTY_MILLION = ethers_1.ethers.BigNumber.from("20") + .mul(MILLION) + .mul(TOKEN_DECIMALS); +const PARTNER_MAX = ethers_1.ethers.BigNumber.from("78") + .mul(MILLION) + .mul(TOKEN_DECIMALS); +const TEAM_MULTISIG = "0xb074ec6c37659525EEf2Fb44478077901F878012"; +const TEAM_EOA = "0xe247340f06FCB7eb904F16a48C548221375b5b96"; +const optimismConfig = { + // Chain const + lzChainId: 11, + lzEndpoint: "0x3c2269811836af69497E5F486A85D7316753cf62", + // Tokens + WETH: "0x4200000000000000000000000000000000000006", + USDC: "0x7F5c764cBc14f9669B88837ca1490cCa17c31607", + // Addresses + teamEOA: TEAM_EOA, + teamMultisig: TEAM_MULTISIG, + emergencyCouncil: "0xcC2D01030eC2cd187346F70bFc483F24488C32E8", + merkleRoot: "0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f", + tokenWhitelist: [ + "0x4200000000000000000000000000000000000042", + "0x4200000000000000000000000000000000000006", + "0x7F5c764cBc14f9669B88837ca1490cCa17c31607", + "0x2E3D870790dC77A83DD1d18184Acc7439A53f475", + "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1", + "0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9", + "0x217D47011b23BB961eB6D93cA9945B7501a5BB11", + "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb", + "0x67CCEA5bb16181E7b4109c9c2143c24a1c2205Be", + "0x9e1028F5F1D5eDE59748FFceE5532509976840E0", + "0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4", + "0xCB8FA9a76b8e203D8C3797bF438d8FB81Ea3326A", + "0x3E29D3A9316dAB217754d13b28646B76607c5f04", + "0x8aE125E8653821E851F12A49F7765db9a9ce7384", + "0x10010078a54396F62c96dF8532dc2B4847d47ED3", + // "", // BTRFLY -- N/A + // "", // pxVELO -- N/A + "0xc40F949F8a4e094D1b49a23ea9241D289B7b2819", // LUSD + // "", // wstETH -- N/A + // "", // HOP -- N/A + ], + partnerAddrs: [ + TEAM_EOA, + "0x4a84675512949f81EBFEAAcC6C00D03eDd329de5", + TEAM_EOA, + "0xa283139017a2f5BAdE8d8e25412C600055D318F8", + "0xDcf664d0f76E99eaA2DBD569474d0E75dC899FCD", + "0x489863b61C625a15C74FB4C21486baCb4A3937AB", + "0x641f26c67A5D0829Ae61019131093B6a7c7d18a3", + "0xC224bf25Dcc99236F00843c7D8C4194abE8AA94a", + "0xB6DACAE4eF97b4817d54df8e005269f509f803f9", + TEAM_EOA, + TEAM_EOA, + "0x0dF840dCbf1229262A4125C1fc559bd338eC9491", + "0x2E33A660742e813aD948fB9f7d682FE461E5fbf3", + "0xd2D4e9024D8C90aB52032a9F1e0d92D4cE20191B", // LUSD + ], + partnerAmts: [ + TEN_MILLION, + TWENTY_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + ], + partnerMax: PARTNER_MAX, +}; +exports.default = optimismConfig; diff --git a/dist/tasks/deploy/constants/testFantomConfig.d.ts b/dist/tasks/deploy/constants/testFantomConfig.d.ts new file mode 100644 index 00000000..402b558d --- /dev/null +++ b/dist/tasks/deploy/constants/testFantomConfig.d.ts @@ -0,0 +1,6 @@ +declare const testFantomConfig: { + lzChainId: number; + lzEndpoint: string; + WEVE: string; +}; +export default testFantomConfig; diff --git a/dist/tasks/deploy/constants/testFantomConfig.js b/dist/tasks/deploy/constants/testFantomConfig.js new file mode 100644 index 00000000..f6bfb370 --- /dev/null +++ b/dist/tasks/deploy/constants/testFantomConfig.js @@ -0,0 +1,8 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const testFantomConfig = { + lzChainId: 10012, + lzEndpoint: "0x7dcAD72640F835B0FA36EFD3D6d3ec902C7E5acf", + WEVE: "0xb824b106FC861860Fc2f2E9eE83f7616074f2Dca", +}; +exports.default = testFantomConfig; diff --git a/dist/tasks/deploy/constants/testOptimismConfig.d.ts b/dist/tasks/deploy/constants/testOptimismConfig.d.ts new file mode 100644 index 00000000..12d3000e --- /dev/null +++ b/dist/tasks/deploy/constants/testOptimismConfig.d.ts @@ -0,0 +1,16 @@ +import { ethers } from "ethers"; +declare const testOptimismArgs: { + lzChainId: number; + lzEndpoint: string; + WETH: string; + USDC: string; + teamEOA: string; + teamMultisig: string; + emergencyCouncil: string; + merkleRoot: string; + tokenWhitelist: string[]; + partnerAddrs: string[]; + partnerAmts: ethers.BigNumber[]; + partnerMax: ethers.BigNumber; +}; +export default testOptimismArgs; diff --git a/dist/tasks/deploy/constants/testOptimismConfig.js b/dist/tasks/deploy/constants/testOptimismConfig.js new file mode 100644 index 00000000..4f9afd96 --- /dev/null +++ b/dist/tasks/deploy/constants/testOptimismConfig.js @@ -0,0 +1,59 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const ethers_1 = require("ethers"); +const TOKEN_DECIMALS = ethers_1.ethers.BigNumber.from("10").pow(ethers_1.ethers.BigNumber.from("18")); +const MILLION = ethers_1.ethers.BigNumber.from("10").pow(ethers_1.ethers.BigNumber.from("6")); +const FOUR_MILLION = ethers_1.ethers.BigNumber.from("4") + .mul(MILLION) + .mul(TOKEN_DECIMALS); +const TWENTY_MILLION = ethers_1.ethers.BigNumber.from("20") + .mul(MILLION) + .mul(TOKEN_DECIMALS); +const PARTNER_MAX = ethers_1.ethers.BigNumber.from("78") + .mul(MILLION) + .mul(TOKEN_DECIMALS); +const TEAM_MULTISIG = "0x52f02a075191F69E30917effc66087ad981Db703"; +const TEAM_EOA = "0x52f02a075191F69E30917effc66087ad981Db703"; +const testOptimismArgs = { + // Chain const + lzChainId: 10011, + lzEndpoint: "0x72aB53a133b27Fa428ca7Dc263080807AfEc91b5", + // Tokens + WETH: "0x4200000000000000000000000000000000000006", + USDC: "0x3e22e37Cb472c872B5dE121134cFD1B57Ef06560", + // Addresses + teamEOA: TEAM_EOA, + teamMultisig: TEAM_MULTISIG, + emergencyCouncil: "0x52f02a075191F69E30917effc66087ad981Db703", + merkleRoot: "", + tokenWhitelist: [ + "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1", + "0xbC6F6b680bc61e30dB47721c6D1c5cde19C1300d", + "0x0064A673267696049938AA47595dD0B3C2e705A1", + "0x3e22e37Cb472c872B5dE121134cFD1B57Ef06560", + ], + partnerAddrs: [ + "0x52f02a075191F69E30917effc66087ad981Db703", + "0x82D54397B88CE80Ea2Df9aD049213ACb47dc2523", + "0x6122a6A39a6C3f2BCd96B929Fc2066204FDb125a", + "0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199", + "0xDEcc3156Bd9826a0034D829C35Dc3679Be5ac529", + "0x203693De100D1527637167d89dce39D876B7821B", + "0x4F7d04d96732515052751929362Ce6DA7622caCe", + "0x53e0B897EAE600B2F6855FCe4a42482E9229D2c2", + TEAM_EOA, // TEST + ], + partnerAmts: [ + TWENTY_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + ], + partnerMax: PARTNER_MAX, +}; +exports.default = testOptimismArgs; diff --git a/dist/tasks/deploy/ftm.d.ts b/dist/tasks/deploy/ftm.d.ts new file mode 100644 index 00000000..cb0ff5c3 --- /dev/null +++ b/dist/tasks/deploy/ftm.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/tasks/deploy/ftm.js b/dist/tasks/deploy/ftm.js new file mode 100644 index 00000000..5f6f1d98 --- /dev/null +++ b/dist/tasks/deploy/ftm.js @@ -0,0 +1,27 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const config_1 = require("hardhat/config"); +const optimismConfig_1 = __importDefault(require("./constants/optimismConfig")); +const testOptimismConfig_1 = __importDefault(require("./constants/testOptimismConfig")); +const fantomConfig_1 = __importDefault(require("./constants/fantomConfig")); +const testFantomConfig_1 = __importDefault(require("./constants/testFantomConfig")); +const deployed_1 = __importDefault(require("./constants/deployed")); +(0, config_1.task)("deploy:ftm", "Deploys Fantom contracts").setAction(async function (taskArguments, { ethers }) { + const mainnet = false; + const OP_CONFIG = mainnet ? optimismConfig_1.default : testOptimismConfig_1.default; + const FTM_CONFIG = mainnet ? fantomConfig_1.default : testFantomConfig_1.default; + // CHECK that optimismReceiver is not empty for network + if (deployed_1.default.optimismReceiver.length === 0) { + throw "receiver not set"; + } + // Load + const RedemptionSender = await ethers.getContractFactory("RedemptionSender"); + // Deploy + const sender = await RedemptionSender.deploy(FTM_CONFIG.WEVE, OP_CONFIG.lzChainId, FTM_CONFIG.lzEndpoint, deployed_1.default.optimismReceiver); + console.log("RedemptionSender deployed to: ", sender.address); + console.log("Args: ", FTM_CONFIG.WEVE, OP_CONFIG.lzChainId, FTM_CONFIG.lzEndpoint, deployed_1.default.optimismReceiver, "\n"); + console.log("Fantom contracts deployed"); +}); diff --git a/dist/tasks/deploy/index.d.ts b/dist/tasks/deploy/index.d.ts new file mode 100644 index 00000000..1c206590 --- /dev/null +++ b/dist/tasks/deploy/index.d.ts @@ -0,0 +1,6 @@ +import './op.ts'; +import './ftm.ts'; +import './init.ts'; +import './arb.ts'; +import './arbHardhat.ts'; +import './arbTest.ts'; diff --git a/dist/tasks/deploy/index.js b/dist/tasks/deploy/index.js new file mode 100644 index 00000000..bfdf784a --- /dev/null +++ b/dist/tasks/deploy/index.js @@ -0,0 +1,8 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("./op.ts"); +require("./ftm.ts"); +require("./init.ts"); +require("./arb.ts"); +require("./arbHardhat.ts"); +require("./arbTest.ts"); diff --git a/dist/tasks/deploy/init.d.ts b/dist/tasks/deploy/init.d.ts new file mode 100644 index 00000000..e69de29b diff --git a/dist/tasks/deploy/init.js b/dist/tasks/deploy/init.js new file mode 100644 index 00000000..e4ccaf8b --- /dev/null +++ b/dist/tasks/deploy/init.js @@ -0,0 +1,34 @@ +"use strict"; +// The tasks in this file should be called by the multisig +// CURRENTLY OUTDATED +// import { task } from "hardhat/config"; +// import deployed from "./constants/deployed"; +// task("deploy:init", "Initializes RedemptionSender on Optimism").setAction( +// async function (taskArguments, { ethers }) { +// // Define network +// const network = "optimism-kovan"; // "optimism" for mainnet deploy +// // PERFORM CHECKS ON ARGS +// // TODO move +// const TOKEN_DECIMALS = ethers.BigNumber.from("10").pow( +// ethers.BigNumber.from("18") +// ); +// const ELIGIBLE_WEVE = +// ethers.BigNumber.from("375112540").mul(TOKEN_DECIMALS); // TODO fix rounding +// const REDEEMABLE_USDC = ethers.BigNumber.from("0"); // TODO update +// const REDEEMABLE_VELO = +// ethers.BigNumber.from("108000000").mul(TOKEN_DECIMALS); // TODO fix rounding +// // Load +// const RedemptionReceiver = await ethers.getContractFactory( +// "RedemptionReceiver" +// ); +// const receiver = await RedemptionReceiver.attach(deployed.optimismReceiver); +// // Initialize +// await receiver.initializeReceiverWith( +// deployed.fantomSender, +// ELIGIBLE_WEVE, +// REDEEMABLE_USDC, +// REDEEMABLE_VELO +// ); +// console.log(`RedemptionSender at ${receiver.address} configured!`); +// } +// ); diff --git a/dist/tasks/deploy/op.d.ts b/dist/tasks/deploy/op.d.ts new file mode 100644 index 00000000..cb0ff5c3 --- /dev/null +++ b/dist/tasks/deploy/op.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/tasks/deploy/op.js b/dist/tasks/deploy/op.js new file mode 100644 index 00000000..a09e3e9d --- /dev/null +++ b/dist/tasks/deploy/op.js @@ -0,0 +1,120 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const config_1 = require("hardhat/config"); +const optimismConfig_1 = __importDefault(require("./constants/optimismConfig")); +const testOptimismConfig_1 = __importDefault(require("./constants/testOptimismConfig")); +const fantomConfig_1 = __importDefault(require("./constants/fantomConfig")); +const testFantomConfig_1 = __importDefault(require("./constants/testFantomConfig")); +(0, config_1.task)("deploy:op", "Deploys Optimism contracts").setAction(async function (taskArguments, { ethers }) { + const mainnet = false; + const OP_CONFIG = mainnet ? optimismConfig_1.default : testOptimismConfig_1.default; + const FTM_CONFIG = mainnet ? fantomConfig_1.default : testFantomConfig_1.default; + // Load + const [Velo, GaugeFactory, BribeFactory, PairFactory, Router, Library, VeArtProxy, VotingEscrow, RewardsDistributor, Voter, Minter, VeloGovernor, RedemptionReceiver, MerkleClaim,] = await Promise.all([ + ethers.getContractFactory("Velo"), + ethers.getContractFactory("GaugeFactory"), + ethers.getContractFactory("BribeFactory"), + ethers.getContractFactory("PairFactory"), + ethers.getContractFactory("Router"), + ethers.getContractFactory("VelodromeLibrary"), + ethers.getContractFactory("VeArtProxy"), + ethers.getContractFactory("VotingEscrow"), + ethers.getContractFactory("RewardsDistributor"), + ethers.getContractFactory("Voter"), + ethers.getContractFactory("Minter"), + ethers.getContractFactory("VeloGovernor"), + ethers.getContractFactory("RedemptionReceiver"), + ethers.getContractFactory("MerkleClaim"), + ]); + const velo = await Velo.deploy(); + await velo.deployed(); + console.log("Velo deployed to: ", velo.address); + const gaugeFactory = await GaugeFactory.deploy(); + await gaugeFactory.deployed(); + console.log("GaugeFactory deployed to: ", gaugeFactory.address); + const bribeFactory = await BribeFactory.deploy(); + await bribeFactory.deployed(); + console.log("BribeFactory deployed to: ", bribeFactory.address); + const pairFactory = await PairFactory.deploy(); + await pairFactory.deployed(); + console.log("PairFactory deployed to: ", pairFactory.address); + const router = await Router.deploy(pairFactory.address, OP_CONFIG.WETH); + await router.deployed(); + console.log("Router deployed to: ", router.address); + console.log("Args: ", pairFactory.address, OP_CONFIG.WETH, "\n"); + const library = await Library.deploy(router.address); + await library.deployed(); + console.log("VelodromeLibrary deployed to: ", library.address); + console.log("Args: ", router.address, "\n"); + const artProxy = await VeArtProxy.deploy(); + await artProxy.deployed(); + console.log("VeArtProxy deployed to: ", artProxy.address); + const escrow = await VotingEscrow.deploy(velo.address, artProxy.address); + await escrow.deployed(); + console.log("VotingEscrow deployed to: ", escrow.address); + console.log("Args: ", velo.address, artProxy.address, "\n"); + const distributor = await RewardsDistributor.deploy(escrow.address); + await distributor.deployed(); + console.log("RewardsDistributor deployed to: ", distributor.address); + console.log("Args: ", escrow.address, "\n"); + const voter = await Voter.deploy(escrow.address, pairFactory.address, gaugeFactory.address, bribeFactory.address); + await voter.deployed(); + console.log("Voter deployed to: ", voter.address); + console.log("Args: ", escrow.address, pairFactory.address, gaugeFactory.address, bribeFactory.address, "\n"); + const minter = await Minter.deploy(voter.address, escrow.address, distributor.address); + await minter.deployed(); + console.log("Minter deployed to: ", minter.address); + console.log("Args: ", voter.address, escrow.address, distributor.address, "\n"); + const receiver = await RedemptionReceiver.deploy(OP_CONFIG.USDC, velo.address, FTM_CONFIG.lzChainId, OP_CONFIG.lzEndpoint); + await receiver.deployed(); + console.log("RedemptionReceiver deployed to: ", receiver.address); + console.log("Args: ", OP_CONFIG.USDC, velo.address, FTM_CONFIG.lzChainId, OP_CONFIG.lzEndpoint, "\n"); + const governor = await VeloGovernor.deploy(escrow.address); + await governor.deployed(); + console.log("VeloGovernor deployed to: ", governor.address); + console.log("Args: ", escrow.address, "\n"); + // Airdrop + const claim = await MerkleClaim.deploy(velo.address, OP_CONFIG.merkleRoot); + await claim.deployed(); + console.log("MerkleClaim deployed to: ", claim.address); + console.log("Args: ", velo.address, OP_CONFIG.merkleRoot, "\n"); + // Initialize + await velo.initialMint(OP_CONFIG.teamEOA); + console.log("Initial minted"); + await velo.setRedemptionReceiver(receiver.address); + console.log("RedemptionReceiver set"); + await velo.setMerkleClaim(claim.address); + console.log("MerkleClaim set"); + await velo.setMinter(minter.address); + console.log("Minter set"); + await pairFactory.setPauser(OP_CONFIG.teamMultisig); + console.log("Pauser set"); + await escrow.setVoter(voter.address); + console.log("Voter set"); + await escrow.setTeam(OP_CONFIG.teamMultisig); + console.log("Team set for escrow"); + await voter.setGovernor(OP_CONFIG.teamMultisig); + console.log("Governor set"); + await voter.setEmergencyCouncil(OP_CONFIG.teamMultisig); + console.log("Emergency Council set"); + await distributor.setDepositor(minter.address); + console.log("Depositor set"); + await receiver.setTeam(OP_CONFIG.teamMultisig); + console.log("Team set for receiver"); + await governor.setTeam(OP_CONFIG.teamMultisig); + console.log("Team set for governor"); + // Whitelist + const nativeToken = [velo.address]; + const tokenWhitelist = nativeToken.concat(OP_CONFIG.tokenWhitelist); + await voter.initialize(tokenWhitelist, minter.address); + console.log("Whitelist set"); + // Initial veVELO distro + await minter.initialize(OP_CONFIG.partnerAddrs, OP_CONFIG.partnerAmts, OP_CONFIG.partnerMax); + console.log("veVELO distributed"); + await minter.setTeam(OP_CONFIG.teamMultisig); + console.log("Team set for minter"); + console.log("Optimism contracts deployed"); +}); diff --git a/jsonFromFile.js b/jsonFromFile.js new file mode 100644 index 00000000..43ad0d66 --- /dev/null +++ b/jsonFromFile.js @@ -0,0 +1,23 @@ +// get json from exported.json file and convert to object + +const fs = require('fs') + +const jsonFromFile = () => { + const data = fs.readFileSync('./exported.json') + return JSON.parse(data) +} + +// console.log(jsonFromFile()) + +// remove abi from the object + +const removeAbi = obj => { + const newObj = {} + Object.keys(obj.contracts).forEach(key => { + newObj[key] = obj.contracts[key].address + }) + return newObj +} + +const final = removeAbi(jsonFromFile()) +console.log(final) diff --git a/package.json b/package.json index 25f35b09..7c718fbe 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,9 @@ "directories": { "lib": "lib" }, + "scripts": { + "verify": "npx hardhat --network arbitrumGoerli etherscan-verify --solc-input --sleep" + }, "devDependencies": { "@nomiclabs/hardhat-ethers": "yarn:hardhat-deploy-ethers", "@nomiclabs/hardhat-etherscan": "^3.1.4", @@ -31,4 +34,4 @@ "dependencies": { "zod": "^3.20.2" } -} +} \ No newline at end of file diff --git a/readme.md b/readme.md index 3f7c5146..559d225d 100644 --- a/readme.md +++ b/readme.md @@ -6,37 +6,22 @@ https://github.com/Velocimeter/instruments/blob/master/gitsubmodules.sh -Goerli - - -Velo deployed to: 0x41754Fd93201B64Cd7633a8e8f861D47594b29A8 -GaugeFactory deployed to: 0x30Ba274c119865312c1417b6E1Be6C98DAceb6B2 -BribeFactory deployed to: 0x4871E36eDEB6750e47f616C57e70a978ac9a9003 -PairFactory deployed to: 0xB4AD2aAC39268687D62b36BD69fC532862CF6590 -Router deployed to: 0x1584d57c849797fb752d3dc5071F49B59D6C7416 -Args: 0xB4AD2aAC39268687D62b36BD69fC532862CF6590 0x4200000000000000000000000000000000000006 - -VelodromeLibrary deployed to: 0x83c08EE991D0010208a117b84F7ea412373AEB90 -Args: 0x1584d57c849797fb752d3dc5071F49B59D6C7416 - -VeArtProxy deployed to: 0x944AF7785d57bcfC00e95388453B93DAD373216e -VotingEscrow deployed to: 0x2B0BB6962e89bD5FE9510Ff09Af8D709be21AAD7 -Args: 0x41754Fd93201B64Cd7633a8e8f861D47594b29A8 0x944AF7785d57bcfC00e95388453B93DAD373216e - -RewardsDistributor deployed to: 0xf4F344Cfa1A82eDD37C96E879f01D9CA03f385b9 -Args: 0x2B0BB6962e89bD5FE9510Ff09Af8D709be21AAD7 - -Voter deployed to: 0x9f7fdaB9317f1442808B90B819Ed0a4eF4f74994 -Args: 0x2B0BB6962e89bD5FE9510Ff09Af8D709be21AAD7 0xB4AD2aAC39268687D62b36BD69fC532862CF6590 0x30Ba274c119865312c1417b6E1Be6C98DAceb6B2 0x4871E36eDEB6750e47f616C57e70a978ac9a9003 - -Minter deployed to: 0x52A18b2386D6221Cf9DbcD4790456a23249e5279 -Args: 0x9f7fdaB9317f1442808B90B819Ed0a4eF4f74994 0x2B0BB6962e89bD5FE9510Ff09Af8D709be21AAD7 0xf4F344Cfa1A82eDD37C96E879f01D9CA03f385b9 - -RedemptionReceiver deployed to: 0xfe873D4923b343F0D6BD98045a9C82D8dDEC511E -Args: 0x3e22e37Cb472c872B5dE121134cFD1B57Ef06560 0x41754Fd93201B64Cd7633a8e8f861D47594b29A8 10012 0x72aB53a133b27Fa428ca7Dc263080807AfEc91b5 - -VeloGovernor deployed to: 0x0bd9d21b40428a650DbFC0F7bd3F7B6FA321F915 -Args: 0x2B0BB6962e89bD5FE9510Ff09Af8D709be21AAD7 +{ + BribeFactory: '0x5542edb529F7c963583e9B8e5339121cFCf4B606', + GaugeFactory: '0x1Ac3032Dfd7e206BA6d08F453f38593b9A583052', + MerkleClaim: '0x0a68F78212D69EfC6346B5F9d72BC5A301779BE9', + Minter: '0xd2C3ebFB8e7e79CA84080a8551D86Df50B0F559d', + PairFactory: '0x7488AC81DC3908ff7141db4949e70D60A3Fd4DCc', + RedemptionReceiver: '0x08e352f2130d4b68d7B1264CD42191205B61b60f', + RewardsDistributor: '0xf6CdA702C6Bd15d5C0A325CE8f9f88219fE5F445', + Router: '0xCeaEA7A5cB3e7521DdE6717BCc99a4c8c60E07b6', + VeArtProxy: '0x5e7569D02214289490d16bCE4F96B38071db1aD8', + Velo: '0xe69b00A164047e7eB87B73971B0f340eEbFF9c81', + VeloGovernor: '0x588ADD83f24690BceEbaa4266cd8DC65709DDa4d', + VelodromeLibrary: '0x233ed5d7FAed19F7b8A28844E2845FBF0F145Be2', + Voter: '0x574607c69f369f0535E77C5F7C35767Aee04879A', + VotingEscrow: '0x6b938BA22FB5520fFB5D14c9C4Fef82a48761497' +} ## Testing From cc16c701ce02ea8fd553682de1e6db5b411e2421 Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Sun, 15 Jan 2023 13:10:15 +1100 Subject: [PATCH 10/43] added scripts / verify velo manually (not sure why that needed to happen??) --- deploy/05_router.ts | 30 +-- deploy/13_redemptionReceiver.ts | 36 +-- deploy/14_merkleClaim.ts | 31 +-- deploy/15_init.ts | 96 ++++---- deploy/16_whitelist.ts | 34 +-- deploy/17_dist.ts | 76 +++++-- deployments/arbitrumGoerli/.migrations.json | 6 +- deployments/arbitrumGoerli/BribeFactory.json | 28 +-- deployments/arbitrumGoerli/GaugeFactory.json | 28 +-- deployments/arbitrumGoerli/MerkleClaim.json | 30 +-- deployments/arbitrumGoerli/Minter.json | 34 +-- deployments/arbitrumGoerli/PairFactory.json | 28 +-- .../arbitrumGoerli/RedemptionReceiver.json | 32 +-- .../arbitrumGoerli/RewardsDistributor.json | 44 ++-- deployments/arbitrumGoerli/Router.json | 32 +-- deployments/arbitrumGoerli/VeArtProxy.json | 28 +-- deployments/arbitrumGoerli/Velo.json | 40 ++-- deployments/arbitrumGoerli/VeloGovernor.json | 40 ++-- .../arbitrumGoerli/VelodromeLibrary.json | 30 +-- deployments/arbitrumGoerli/Voter.json | 36 +-- deployments/arbitrumGoerli/VotingEscrow.json | 54 ++--- dist/deploy/15_init.js | 108 ++++----- dist/hardhat.config.js | 206 +++++++++--------- .../deploy/constants/arbTestnetConfig.d.ts | 16 -- .../deploy/constants/arbTestnetConfig.js | 173 ++++++++------- exported.json | 28 +-- hardhat.config.ts | 154 +++++++------ package.json | 3 +- readme.md | 35 +-- tasks/accounts.ts | 10 + tasks/deploy/constants/arbHardhatConfig.ts | 7 +- tasks/deploy/constants/arbTestnetConfig.ts | 17 +- 32 files changed, 810 insertions(+), 740 deletions(-) delete mode 100644 dist/tasks/deploy/constants/arbTestnetConfig.d.ts create mode 100644 tasks/accounts.ts diff --git a/deploy/05_router.ts b/deploy/05_router.ts index b04ecaaa..526dd34b 100644 --- a/deploy/05_router.ts +++ b/deploy/05_router.ts @@ -1,24 +1,24 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' -import arbTestnetConfig from "../tasks/deploy/constants/arbTestnetConfig"; -const ARB_TEST_CONFIG = arbTestnetConfig; +import arbTestnetConfig from '../tasks/deploy/constants/arbTestnetConfig' +const ARB_TEST_CONFIG = arbTestnetConfig const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments - const { deployer } = await getNamedAccounts(); + const { deployer } = await getNamedAccounts() - const pairFactory = await deployments.get("PairFactory"); + const pairFactory = await deployments.get('PairFactory') - await deploy("Router", { + await deploy('Router', { from: deployer, args: [pairFactory.address, ARB_TEST_CONFIG.WETH], log: true, - skipIfAlreadyDeployed: true, - }); -}; -export default func; -func.tags = ["Router"]; -func.id = "router"; \ No newline at end of file + skipIfAlreadyDeployed: true + }) +} +export default func +func.tags = ['Router'] +func.id = 'router' diff --git a/deploy/13_redemptionReceiver.ts b/deploy/13_redemptionReceiver.ts index 0ee096ae..14ad1a5f 100644 --- a/deploy/13_redemptionReceiver.ts +++ b/deploy/13_redemptionReceiver.ts @@ -1,32 +1,32 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' -import arbTestnetConfig from "../tasks/deploy/constants/arbTestnetConfig"; -import testFantomConfig from "../tasks/deploy/constants/testFantomConfig"; +import arbTestnetConfig from '../tasks/deploy/constants/arbTestnetConfig' +import testFantomConfig from '../tasks/deploy/constants/testFantomConfig' -const ARB_TEST_CONFIG = arbTestnetConfig; -const FTM_CONFIG = testFantomConfig; +const ARB_TEST_CONFIG = arbTestnetConfig +const FTM_CONFIG = testFantomConfig const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments - const { deployer } = await getNamedAccounts(); + const { deployer } = await getNamedAccounts() - const velo = await deployments.get("Velo"); + const velo = await deployments.get('Velo') - await deploy("RedemptionReceiver", { + await deploy('RedemptionReceiver', { from: deployer, args: [ ARB_TEST_CONFIG.USDC, velo.address, FTM_CONFIG.lzChainId, - ARB_TEST_CONFIG.lzEndpoint, + ARB_TEST_CONFIG.lzEndpoint ], log: true, - skipIfAlreadyDeployed: true, - }); -}; -export default func; -func.tags = ["RedemptionReceiver"]; -func.id = "redemptionReceiver"; \ No newline at end of file + skipIfAlreadyDeployed: true + }) +} +export default func +func.tags = ['RedemptionReceiver'] +func.id = 'redemptionReceiver' diff --git a/deploy/14_merkleClaim.ts b/deploy/14_merkleClaim.ts index 4b9fb709..b680ea2e 100644 --- a/deploy/14_merkleClaim.ts +++ b/deploy/14_merkleClaim.ts @@ -1,25 +1,26 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' -import arbTestnetConfig from "../tasks/deploy/constants/arbTestnetConfig"; +//import arbTestnetConfig from '../tasks/deploy/constants/arbTestnetConfig' +import arbHardhatConfig from '../tasks/deploy/constants/arbHardhatConfig' -const ARB_TEST_CONFIG = arbTestnetConfig; +const ARB_TEST_CONFIG = arbHardhatConfig const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments - const { deployer } = await getNamedAccounts(); + const { deployer } = await getNamedAccounts() - const velo = await deployments.get("Velo"); + const velo = await deployments.get('Velo') - await deploy("MerkleClaim", { + await deploy('MerkleClaim', { from: deployer, args: [velo.address, ARB_TEST_CONFIG.merkleRoot], log: true, - skipIfAlreadyDeployed: true, - }); -}; -export default func; -func.tags = ["MerkleClaim"]; -func.id = "merkleClaim"; + skipIfAlreadyDeployed: true + }) +} +export default func +func.tags = ['MerkleClaim'] +func.id = 'merkleClaim' diff --git a/deploy/15_init.ts b/deploy/15_init.ts index 315532dd..a275a5d4 100644 --- a/deploy/15_init.ts +++ b/deploy/15_init.ts @@ -1,72 +1,72 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' -import arbTestnetConfig from "../tasks/deploy/constants/arbTestnetConfig"; +import arbHardhatConfig from '../tasks/deploy/constants/arbHardhatConfig' -const ARB_TEST_CONFIG = arbTestnetConfig; +const ARB_TEST_CONFIG = arbHardhatConfig const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, ethers } = hre; + const { deployments, ethers } = hre - const velo = await ethers.getContract("Velo"); - const pairFactory = await ethers.getContract("PairFactory"); - const escrow = await ethers.getContract("VotingEscrow"); - const voter = await ethers.getContract("Voter"); - const distributor = await ethers.getContract("RewardsDistributor"); - const governor = await ethers.getContract("VeloGovernor"); - const minter = await ethers.getContract("Minter"); - const receiver = await ethers.getContract("RedemptionReceiver"); + const velo = await ethers.getContract('Velo') + const pairFactory = await ethers.getContract('PairFactory') + const escrow = await ethers.getContract('VotingEscrow') + const voter = await ethers.getContract('Voter') + const distributor = await ethers.getContract('RewardsDistributor') + const governor = await ethers.getContract('VeloGovernor') + const minter = await ethers.getContract('Minter') + const receiver = await ethers.getContract('RedemptionReceiver') - const claim = await deployments.get("MerkleClaim"); + const claim = await deployments.get('MerkleClaim') // Initialize - await velo.initialMint(ARB_TEST_CONFIG.teamEOA); - console.log("Initial minted"); + await velo.initialMint(ARB_TEST_CONFIG.teamEOA) + console.log('Initial minted') - await velo.setRedemptionReceiver(receiver.address); - console.log("RedemptionReceiver set"); + await velo.setRedemptionReceiver(receiver.address) + console.log('RedemptionReceiver set') - await velo.setMerkleClaim(claim.address); - console.log("MerkleClaim set"); + await velo.setMerkleClaim(claim.address) + console.log('MerkleClaim set') - await velo.setMinter(minter.address); - console.log("Minter set"); + await velo.setMinter(minter.address) + console.log('Minter set') - await pairFactory.setPauser(ARB_TEST_CONFIG.teamMultisig); - console.log("Pauser set"); + await pairFactory.setPauser(ARB_TEST_CONFIG.teamMultisig) + console.log('Pauser set') - await escrow.setVoter(voter.address); + await escrow.setVoter(voter.address) console.log( - "Voter set", - "voter address: ", + 'Voter set', + 'voter address: ', voter.address, - "escrow address: ", + 'escrow address: ', escrow.address - ); + ) - await escrow.setTeam(ARB_TEST_CONFIG.teamMultisig); - console.log("Team set for escrow"); + await escrow.setTeam(ARB_TEST_CONFIG.teamMultisig) + console.log('Team set for escrow') - await voter.setGovernor(ARB_TEST_CONFIG.teamMultisig); - console.log("Governor set"); + await voter.setGovernor(ARB_TEST_CONFIG.teamMultisig) + console.log('Governor set') - await voter.setEmergencyCouncil(ARB_TEST_CONFIG.teamMultisig); - console.log("Emergency Council set"); + await voter.setEmergencyCouncil(ARB_TEST_CONFIG.teamMultisig) + console.log('Emergency Council set') - await distributor.setDepositor(minter.address); - console.log("Depositor set"); + await distributor.setDepositor(minter.address) + console.log('Depositor set') - await receiver.setTeam(ARB_TEST_CONFIG.teamMultisig); - console.log("Team set for receiver"); + await receiver.setTeam(ARB_TEST_CONFIG.teamMultisig) + console.log('Team set for receiver') - await governor.setTeam(ARB_TEST_CONFIG.teamMultisig); - console.log("Team set for governor"); + await governor.setTeam(ARB_TEST_CONFIG.teamMultisig) + console.log('Team set for governor') - await minter.setTeam(ARB_TEST_CONFIG.teamMultisig); - console.log("Team set for minter"); + await minter.setTeam(ARB_TEST_CONFIG.teamMultisig) + console.log('Team set for minter') - return true; -}; -export default func; -func.tags = ["init_deploy"]; -func.id = "init_deploy"; + return true +} +export default func +func.tags = ['init_deploy'] +func.id = 'init_deploy' diff --git a/deploy/16_whitelist.ts b/deploy/16_whitelist.ts index 8431821a..b448047c 100644 --- a/deploy/16_whitelist.ts +++ b/deploy/16_whitelist.ts @@ -1,25 +1,25 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' -import arbTestnetConfig from "../tasks/deploy/constants/arbTestnetConfig"; +import arbTestnetConfig from '../tasks/deploy/constants/arbTestnetConfig' -const ARB_TEST_CONFIG = arbTestnetConfig; +const ARB_TEST_CONFIG = arbTestnetConfig const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { ethers } = hre; + const { ethers } = hre - const velo = await ethers.getContract("Velo"); - const voter = await ethers.getContract("Voter"); - const minter = await ethers.getContract("Minter"); + const velo = await ethers.getContract('Velo') + const voter = await ethers.getContract('Voter') + const minter = await ethers.getContract('Minter') // Whitelist - const nativeToken = [velo.address]; - const tokenWhitelist = nativeToken.concat(ARB_TEST_CONFIG.tokenWhitelist); - await voter.initialize(tokenWhitelist, minter.address); - console.log("Whitelist set"); + const nativeToken = [velo.address] + const tokenWhitelist = nativeToken.concat(ARB_TEST_CONFIG.tokenWhitelist) + await voter.initialize(tokenWhitelist, minter.address) + console.log('Whitelist set') - return true; -}; -export default func; -func.tags = ["whitelist"]; -func.id = "whitelist"; + return true +} +export default func +func.tags = ['whitelist'] +func.id = 'whitelist' diff --git a/deploy/17_dist.ts b/deploy/17_dist.ts index a4951acc..6b99bb91 100644 --- a/deploy/17_dist.ts +++ b/deploy/17_dist.ts @@ -1,26 +1,74 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' +// import * as tasks1 from 'tasks/deploy/arbHardhat' -import arbTestnetConfig from "../tasks/deploy/constants/arbTestnetConfig"; +import arbTestnetConfig from '../tasks/deploy/constants/arbTestnetConfig' +import arbHardhatConfig from '../tasks/deploy/constants/arbHardhatConfig' -const ARB_TEST_CONFIG = arbTestnetConfig; +const ARB_TEST_CONFIG = arbHardhatConfig const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { ethers } = hre; - const minter = await ethers.getContract("Minter"); + const { ethers } = hre + const minter = await ethers.getContract('Minter') + + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments + + const { deployer } = await getNamedAccounts() + + const velo = await deployments.get('Velo') // Initial veVELO distro await minter.initialize( ARB_TEST_CONFIG.partnerAddrs, ARB_TEST_CONFIG.partnerAmts, ARB_TEST_CONFIG.partnerMax - ); - console.log("veVELO distributed"); + ) + console.log('veVELO distributed') + // + console.log('Arbitrum Goerli Velocimeter Instruments deployed') + + return true + // Initialize + + console.log('deployer', deployer) + + // await velo.initialMint(ARB_CONFIG.teamEOA) + // console.log('Initial minted') + + // await velo.setRedemptionReceiver(receiver.address) + // console.log('RedemptionReceiver set') + + // await velo.setMerkleClaim(claim.address) + // console.log('MerkleClaim set') + + // await velo.setMinter(minter.address) + // console.log('Minter set') + + // await pairFactory.setPauser(ARB_CONFIG.teamMultisig) + // console.log('Pauser set') + + // await escrow.setVoter(voter.address) + // console.log('Voter set') + + // await escrow.setTeam(ARB_CONFIG.teamMultisig) + // console.log('Team set for escrow') + + // await voter.setGovernor(ARB_CONFIG.teamMultisig) + // console.log('Governor set') + + // await voter.setEmergencyCouncil(ARB_CONFIG.teamMultisig) + // console.log('Emergency Council set') + + // await distributor.setDepositor(minter.address) + // console.log('Depositor set') - console.log("Arbitrum Goerli Velocimeter Instruments deployed"); + // await receiver.setTeam(ARB_CONFIG.teamMultisig) + // console.log('Team set for receiver') - return true; -}; -export default func; -func.tags = ["initial_dist"]; -func.id = "initial_dist"; + // await governor.setTeam(ARB_CONFIG.teamMultisig) + // console.log('Team set for governor') +} +export default func +func.tags = ['initial_dist'] +func.id = 'initial_dist' diff --git a/deployments/arbitrumGoerli/.migrations.json b/deployments/arbitrumGoerli/.migrations.json index 298c850a..1049d810 100644 --- a/deployments/arbitrumGoerli/.migrations.json +++ b/deployments/arbitrumGoerli/.migrations.json @@ -1,5 +1,5 @@ { - "init_deploy": 1673436417, - "whitelist": 1673436420, - "initial_dist": 1673436425 + "init_deploy": 1673742596, + "whitelist": 1673742599, + "initial_dist": 1673742601 } \ No newline at end of file diff --git a/deployments/arbitrumGoerli/BribeFactory.json b/deployments/arbitrumGoerli/BribeFactory.json index 226f04d5..83ea468e 100644 --- a/deployments/arbitrumGoerli/BribeFactory.json +++ b/deployments/arbitrumGoerli/BribeFactory.json @@ -1,5 +1,5 @@ { - "address": "0x679e8fED0Cd87abAFB0BA481F32b7BDd8b272789", + "address": "0x560b401d9F28F80980451d8582DEe903dD5295c3", "abi": [ { "inputs": [ @@ -66,28 +66,28 @@ "type": "function" } ], - "transactionHash": "0xc2bdc206f40980ba9cd61c742a5305a90998aaad88bf3eb136b4324242635877", + "transactionHash": "0xd2bfb0f6387a38f7c85ef125fd2de4c612b006f39b3e581ebddeda5e2e285d08", "receipt": { "to": null, - "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0x679e8fED0Cd87abAFB0BA481F32b7BDd8b272789", + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x560b401d9F28F80980451d8582DEe903dD5295c3", "transactionIndex": 1, - "gasUsed": "68419398", + "gasUsed": "4416403", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x09b064f0ab04c22103e1cfb3be1200f24164a3182432f0953516dd81c27ff50a", - "transactionHash": "0xc2bdc206f40980ba9cd61c742a5305a90998aaad88bf3eb136b4324242635877", + "blockHash": "0x69af5ecd4fae07b0786e4a2336921c49af0545a2268d3bfc1ddcb4b9ae5fcd6d", + "transactionHash": "0xd2bfb0f6387a38f7c85ef125fd2de4c612b006f39b3e581ebddeda5e2e285d08", "logs": [], - "blockNumber": 4263671, - "cumulativeGasUsed": "68419398", + "blockNumber": 4455872, + "cumulativeGasUsed": "4416403", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 8, - "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createExternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createInternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_external_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_internal_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/BribeFactory.sol\":\"BribeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/ExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract ExternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve; // \\u5929\\u4f7f\\u306e\\u305f\\u307e\\u3054\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balanceOf;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n _prevSupply = supplyCheckpoints[\\n getPriorSupplyIndex(_nextEpochStart + DURATION)\\n ].supply;\\n prevRewards.balanceOf =\\n (cp0.balanceOf *\\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (block.timestamp > _lastEpochEnd) {\\n reward +=\\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\\n }\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0xfe1e53dea8a63ce448c5856a740ed73038ad29a9dcd0f2a2752049b146bb4eb0\",\"license\":\"MIT\"},\"contracts/InternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract InternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve;\\n\\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 public constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n mapping(address => mapping(uint256 => uint256))\\n public userRewardPerTokenStored;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (totalSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / totalSupply);\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\\n _startTimestamp = endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][tokenId],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][tokenId]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n require(isReward[token]);\\n\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2dc302de5dfd95018d1fba7a3a1916d2c1fcf32859d19d38648767f13422a694\",\"license\":\"MIT\"},\"contracts/factories/BribeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IBribeFactory.sol\\\";\\nimport 'contracts/InternalBribe.sol';\\nimport 'contracts/ExternalBribe.sol';\\n\\ncontract BribeFactory is IBribeFactory {\\n address public last_internal_bribe;\\n address public last_external_bribe;\\n\\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\\n return last_internal_bribe;\\n }\\n\\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\\n return last_external_bribe;\\n }\\n}\\n\",\"keccak256\":\"0x30d69b5733c01d1d27e8af06e6217200709721fb84ee8458ee50269bf2ce7ed8\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50614cca806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea26469706673582212205001d291b73df7800b68c90f6d4fa28c64f7e39d7715f0603d0486eddb6c899f64736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea2646970667358221220e0d92e5694609f891642dbb48443dd8f64c369879924189c1410511aecb25c1b64736f6c634300080d0033a2646970667358221220fb1c721954beea886e30347669fd9426afc113dc313de278d83530f66e146c4b64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea26469706673582212205001d291b73df7800b68c90f6d4fa28c64f7e39d7715f0603d0486eddb6c899f64736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea2646970667358221220e0d92e5694609f891642dbb48443dd8f64c369879924189c1410511aecb25c1b64736f6c634300080d0033a2646970667358221220fb1c721954beea886e30347669fd9426afc113dc313de278d83530f66e146c4b64736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createExternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createInternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_external_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_internal_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/BribeFactory.sol\":\"BribeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/ExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract ExternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve; // \\u5929\\u4f7f\\u306e\\u305f\\u307e\\u3054\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balanceOf;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n _prevSupply = supplyCheckpoints[\\n getPriorSupplyIndex(_nextEpochStart + DURATION)\\n ].supply;\\n prevRewards.balanceOf =\\n (cp0.balanceOf *\\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (block.timestamp > _lastEpochEnd) {\\n reward +=\\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\\n }\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0xfe1e53dea8a63ce448c5856a740ed73038ad29a9dcd0f2a2752049b146bb4eb0\",\"license\":\"MIT\"},\"contracts/InternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract InternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve;\\n\\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 public constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n mapping(address => mapping(uint256 => uint256))\\n public userRewardPerTokenStored;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (totalSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / totalSupply);\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\\n _startTimestamp = endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][tokenId],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][tokenId]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n require(isReward[token]);\\n\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2dc302de5dfd95018d1fba7a3a1916d2c1fcf32859d19d38648767f13422a694\",\"license\":\"MIT\"},\"contracts/factories/BribeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IBribeFactory.sol\\\";\\nimport 'contracts/InternalBribe.sol';\\nimport 'contracts/ExternalBribe.sol';\\n\\ncontract BribeFactory is IBribeFactory {\\n address public last_internal_bribe;\\n address public last_external_bribe;\\n\\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\\n return last_internal_bribe;\\n }\\n\\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\\n return last_external_bribe;\\n }\\n}\\n\",\"keccak256\":\"0x30d69b5733c01d1d27e8af06e6217200709721fb84ee8458ee50269bf2ce7ed8\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50614cca806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea2646970667358221220efd2286df364745c6a561267c0e080a96fe1607b9ca8c59dd88db8449c06e2f064736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea264697066735822122032807a5a4af2a7e09f287a189f7d41c0fe80bf7ded450a48d6c047e50d355fae64736f6c634300080d0033a2646970667358221220ddd5a8c80f6c4f13aaec10b17f47da405d95cf2e069d0b5875cb77c5276bb85064736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea2646970667358221220efd2286df364745c6a561267c0e080a96fe1607b9ca8c59dd88db8449c06e2f064736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea264697066735822122032807a5a4af2a7e09f287a189f7d41c0fe80bf7ded450a48d6c047e50d355fae64736f6c634300080d0033a2646970667358221220ddd5a8c80f6c4f13aaec10b17f47da405d95cf2e069d0b5875cb77c5276bb85064736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/GaugeFactory.json b/deployments/arbitrumGoerli/GaugeFactory.json index e7bfdcea..3d6d3445 100644 --- a/deployments/arbitrumGoerli/GaugeFactory.json +++ b/deployments/arbitrumGoerli/GaugeFactory.json @@ -1,5 +1,5 @@ { - "address": "0x9974354d3a16C4801cce829349Cf17663b2c58a5", + "address": "0xeAA8Ebb77A7e3b7AE2d8090E7A1c2F9B605dc919", "abi": [ { "inputs": [ @@ -59,28 +59,28 @@ "type": "function" } ], - "transactionHash": "0xb24aade33d333dcf09e7eecae811424186221368766fe3fe3cdcb842c0196519", + "transactionHash": "0x7f6f1ecc83b06c652e8bdf68f0802c149d6aadb43ac2bb12ef73f667f92d06ba", "receipt": { "to": null, - "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0x9974354d3a16C4801cce829349Cf17663b2c58a5", + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0xeAA8Ebb77A7e3b7AE2d8090E7A1c2F9B605dc919", "transactionIndex": 1, - "gasUsed": "59373355", + "gasUsed": "3419689", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x71a8a0c6335ff501c4e054413d7def1b5207fd96672cfc17af1b304c9eebdc89", - "transactionHash": "0xb24aade33d333dcf09e7eecae811424186221368766fe3fe3cdcb842c0196519", + "blockHash": "0xc356f50eca13e49b083bbae272055a0a02168086bb9188bb487bec9d9f2e1bef", + "transactionHash": "0x7f6f1ecc83b06c652e8bdf68f0802c149d6aadb43ac2bb12ef73f667f92d06ba", "logs": [], - "blockNumber": 4263669, - "cumulativeGasUsed": "59373355", + "blockNumber": 4455868, + "cumulativeGasUsed": "3419689", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 8, - "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_internal_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_external_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_ve\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isPair\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_gauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/GaugeFactory.sol\":\"GaugeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Gauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\\ncontract Gauge is IGauge {\\n address public immutable stake; // the LP token that needs to be staked for rewards\\n address public immutable _ve; // the ve token used for gauges\\n address public immutable internal_bribe;\\n address public immutable external_bribe;\\n address public immutable voter;\\n\\n uint256 public derivedSupply;\\n mapping(address => uint256) public derivedBalances;\\n\\n bool public isForPair;\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 internal constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(address => uint256)) public lastEarn;\\n mapping(address => mapping(address => uint256))\\n public userRewardPerTokenStored;\\n\\n mapping(address => uint256) public tokenIds;\\n\\n uint256 public totalSupply;\\n mapping(address => uint256) public balanceOf;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n uint256 public fees0;\\n uint256 public fees1;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(\\n address _stake,\\n address _internal_bribe,\\n address _external_bribe,\\n address __ve,\\n address _voter,\\n bool _forPair,\\n address[] memory _allowedRewardTokens\\n ) {\\n stake = _stake;\\n internal_bribe = _internal_bribe;\\n external_bribe = _external_bribe;\\n _ve = __ve;\\n voter = _voter;\\n isForPair = _forPair;\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function claimFees()\\n external\\n lock\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n return _claimFees();\\n }\\n\\n function _claimFees()\\n internal\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n if (!isForPair) {\\n return (0, 0);\\n }\\n (claimed0, claimed1) = IPair(stake).claimFees();\\n if (claimed0 > 0 || claimed1 > 0) {\\n uint256 _fees0 = fees0 + claimed0;\\n uint256 _fees1 = fees1 + claimed1;\\n (address _token0, address _token1) = IPair(stake).tokens();\\n if (\\n _fees0 > IBribe(internal_bribe).left(_token0) &&\\n _fees0 / DURATION > 0\\n ) {\\n fees0 = 0;\\n _safeApprove(_token0, internal_bribe, _fees0);\\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\\n } else {\\n fees0 = _fees0;\\n }\\n if (\\n _fees1 > IBribe(internal_bribe).left(_token1) &&\\n _fees1 / DURATION > 0\\n ) {\\n fees1 = 0;\\n _safeApprove(_token1, internal_bribe, _fees1);\\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\\n } else {\\n fees1 = _fees1;\\n }\\n\\n emit ClaimFees(msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(address account, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(address account, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[account][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[account] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n derivedSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n function getReward(address account, address[] memory tokens) external lock {\\n require(msg.sender == account || msg.sender == voter);\\n _unlocked = 1;\\n IVoter(voter).distribute(address(this));\\n _unlocked = 2;\\n\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], account);\\n lastEarn[tokens[i]][account] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n\\n uint256 _derivedBalance = derivedBalances[account];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(account);\\n derivedBalances[account] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(account, derivedBalances[account]);\\n _writeSupplyCheckpoint();\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (derivedSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / derivedSupply);\\n }\\n\\n function derivedBalance(address account) public view returns (uint256) {\\n return balanceOf[account];\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\\n function earned(address token, address account)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][account],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[account] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[account] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[account][i];\\n Checkpoint memory cp1 = checkpoints[account][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[account][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][account]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n function depositAll(uint256 tokenId) external {\\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\\n }\\n\\n function deposit(uint256 amount, uint256 tokenId) public lock {\\n require(amount > 0);\\n _updateRewardForAllTokens();\\n\\n _safeTransferFrom(stake, msg.sender, address(this), amount);\\n totalSupply += amount;\\n balanceOf[msg.sender] += amount;\\n\\n if (tokenId > 0) {\\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\\n if (tokenIds[msg.sender] == 0) {\\n tokenIds[msg.sender] = tokenId;\\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\\n }\\n require(tokenIds[msg.sender] == tokenId);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, _derivedBalance);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function withdrawAll() external {\\n withdraw(balanceOf[msg.sender]);\\n }\\n\\n function withdraw(uint256 amount) public {\\n uint256 tokenId = 0;\\n if (amount == balanceOf[msg.sender]) {\\n tokenId = tokenIds[msg.sender];\\n }\\n withdrawToken(amount, tokenId);\\n }\\n\\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[msg.sender] -= amount;\\n _safeTransfer(stake, msg.sender, amount);\\n\\n if (tokenId > 0) {\\n require(tokenId == tokenIds[msg.sender]);\\n tokenIds[msg.sender] = 0;\\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(token != stake);\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"rewards tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n _claimFees();\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeApprove(\\n address token,\\n address spender,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x38cc0284dd60d8a1418d9c34e6be84911ca4a1b479dc129f19b9027e4c670e1f\",\"license\":\"MIT\"},\"contracts/factories/GaugeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/Gauge.sol';\\n\\ncontract GaugeFactory is IGaugeFactory {\\n address public last_gauge;\\n\\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\\n return last_gauge;\\n }\\n}\\n\",\"keccak256\":\"0x34f6ac4bdace9ef01d8cffda9b45842efae88b519230c67759b9936aee6acc9b\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50613b19806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea2646970667358221220ba05c301c95734156492aaed84b555a4ea9973ba2bdccc78146b6a31bd27572764736f6c634300080d0033a2646970667358221220e87095b83f1200821a412716f12847ba4ce521aa0b052cb3523dc12e213f1e3564736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea2646970667358221220ba05c301c95734156492aaed84b555a4ea9973ba2bdccc78146b6a31bd27572764736f6c634300080d0033a2646970667358221220e87095b83f1200821a412716f12847ba4ce521aa0b052cb3523dc12e213f1e3564736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_internal_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_external_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_ve\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isPair\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_gauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/GaugeFactory.sol\":\"GaugeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Gauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\\ncontract Gauge is IGauge {\\n address public immutable stake; // the LP token that needs to be staked for rewards\\n address public immutable _ve; // the ve token used for gauges\\n address public immutable internal_bribe;\\n address public immutable external_bribe;\\n address public immutable voter;\\n\\n uint256 public derivedSupply;\\n mapping(address => uint256) public derivedBalances;\\n\\n bool public isForPair;\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 internal constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(address => uint256)) public lastEarn;\\n mapping(address => mapping(address => uint256))\\n public userRewardPerTokenStored;\\n\\n mapping(address => uint256) public tokenIds;\\n\\n uint256 public totalSupply;\\n mapping(address => uint256) public balanceOf;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n uint256 public fees0;\\n uint256 public fees1;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(\\n address _stake,\\n address _internal_bribe,\\n address _external_bribe,\\n address __ve,\\n address _voter,\\n bool _forPair,\\n address[] memory _allowedRewardTokens\\n ) {\\n stake = _stake;\\n internal_bribe = _internal_bribe;\\n external_bribe = _external_bribe;\\n _ve = __ve;\\n voter = _voter;\\n isForPair = _forPair;\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function claimFees()\\n external\\n lock\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n return _claimFees();\\n }\\n\\n function _claimFees()\\n internal\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n if (!isForPair) {\\n return (0, 0);\\n }\\n (claimed0, claimed1) = IPair(stake).claimFees();\\n if (claimed0 > 0 || claimed1 > 0) {\\n uint256 _fees0 = fees0 + claimed0;\\n uint256 _fees1 = fees1 + claimed1;\\n (address _token0, address _token1) = IPair(stake).tokens();\\n if (\\n _fees0 > IBribe(internal_bribe).left(_token0) &&\\n _fees0 / DURATION > 0\\n ) {\\n fees0 = 0;\\n _safeApprove(_token0, internal_bribe, _fees0);\\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\\n } else {\\n fees0 = _fees0;\\n }\\n if (\\n _fees1 > IBribe(internal_bribe).left(_token1) &&\\n _fees1 / DURATION > 0\\n ) {\\n fees1 = 0;\\n _safeApprove(_token1, internal_bribe, _fees1);\\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\\n } else {\\n fees1 = _fees1;\\n }\\n\\n emit ClaimFees(msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(address account, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(address account, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[account][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[account] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n derivedSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n function getReward(address account, address[] memory tokens) external lock {\\n require(msg.sender == account || msg.sender == voter);\\n _unlocked = 1;\\n IVoter(voter).distribute(address(this));\\n _unlocked = 2;\\n\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], account);\\n lastEarn[tokens[i]][account] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n\\n uint256 _derivedBalance = derivedBalances[account];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(account);\\n derivedBalances[account] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(account, derivedBalances[account]);\\n _writeSupplyCheckpoint();\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (derivedSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / derivedSupply);\\n }\\n\\n function derivedBalance(address account) public view returns (uint256) {\\n return balanceOf[account];\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\\n function earned(address token, address account)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][account],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[account] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[account] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[account][i];\\n Checkpoint memory cp1 = checkpoints[account][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[account][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][account]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n function depositAll(uint256 tokenId) external {\\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\\n }\\n\\n function deposit(uint256 amount, uint256 tokenId) public lock {\\n require(amount > 0);\\n _updateRewardForAllTokens();\\n\\n _safeTransferFrom(stake, msg.sender, address(this), amount);\\n totalSupply += amount;\\n balanceOf[msg.sender] += amount;\\n\\n if (tokenId > 0) {\\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\\n if (tokenIds[msg.sender] == 0) {\\n tokenIds[msg.sender] = tokenId;\\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\\n }\\n require(tokenIds[msg.sender] == tokenId);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, _derivedBalance);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function withdrawAll() external {\\n withdraw(balanceOf[msg.sender]);\\n }\\n\\n function withdraw(uint256 amount) public {\\n uint256 tokenId = 0;\\n if (amount == balanceOf[msg.sender]) {\\n tokenId = tokenIds[msg.sender];\\n }\\n withdrawToken(amount, tokenId);\\n }\\n\\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[msg.sender] -= amount;\\n _safeTransfer(stake, msg.sender, amount);\\n\\n if (tokenId > 0) {\\n require(tokenId == tokenIds[msg.sender]);\\n tokenIds[msg.sender] = 0;\\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(token != stake);\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"rewards tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n _claimFees();\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeApprove(\\n address token,\\n address spender,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x38cc0284dd60d8a1418d9c34e6be84911ca4a1b479dc129f19b9027e4c670e1f\",\"license\":\"MIT\"},\"contracts/factories/GaugeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/Gauge.sol';\\n\\ncontract GaugeFactory is IGaugeFactory {\\n address public last_gauge;\\n\\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\\n return last_gauge;\\n }\\n}\\n\",\"keccak256\":\"0x34f6ac4bdace9ef01d8cffda9b45842efae88b519230c67759b9936aee6acc9b\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50613b19806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea2646970667358221220c06381d31029b69e5bf80856b47bc2c6fb3bf68a222f6443485012f0d1a029f464736f6c634300080d0033a264697066735822122049fcf5d52ddf2c6e544d113d8ad438616e0a0479cc9116cd6e1d5d4f0ccb7b2364736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea2646970667358221220c06381d31029b69e5bf80856b47bc2c6fb3bf68a222f6443485012f0d1a029f464736f6c634300080d0033a264697066735822122049fcf5d52ddf2c6e544d113d8ad438616e0a0479cc9116cd6e1d5d4f0ccb7b2364736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/MerkleClaim.json b/deployments/arbitrumGoerli/MerkleClaim.json index cf87aa5c..c92eedd1 100644 --- a/deployments/arbitrumGoerli/MerkleClaim.json +++ b/deployments/arbitrumGoerli/MerkleClaim.json @@ -1,5 +1,5 @@ { - "address": "0x339E9F114af629cefF4f46965c9D58f54F1234AA", + "address": "0x92eB499DBC33446Ace4f84Fba84E3A230370858D", "abi": [ { "inputs": [ @@ -105,31 +105,31 @@ "type": "function" } ], - "transactionHash": "0x0c1fc738d08c98a218963f967a9fd62fa4bc9b8cd237f6ee527ba69fefba9cb2", + "transactionHash": "0xed2995ce6e0f251ecae7787f47c3e63c7e9c678465cac23506f04fdce77d5610", "receipt": { "to": null, - "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0x339E9F114af629cefF4f46965c9D58f54F1234AA", + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x92eB499DBC33446Ace4f84Fba84E3A230370858D", "transactionIndex": 1, - "gasUsed": "10171864", + "gasUsed": "376375", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x089722a4f031122e7ddcf39528775a3a16067e1557df0c15b531c734ef62fbc1", - "transactionHash": "0x0c1fc738d08c98a218963f967a9fd62fa4bc9b8cd237f6ee527ba69fefba9cb2", + "blockHash": "0xcaac342c509bedceb64053d523bc7af000a2ee9954e10f8a0e0d6f855186c0b1", + "transactionHash": "0xed2995ce6e0f251ecae7787f47c3e63c7e9c678465cac23506f04fdce77d5610", "logs": [], - "blockNumber": 4263707, - "cumulativeGasUsed": "10171864", + "blockNumber": 4455902, + "cumulativeGasUsed": "376375", "status": 1, "byzantium": true }, "args": [ - "0x162404E6Cd4633656925b90EF67237F29D5cc85c", + "0x84Ca387E7ede764A3284c67Ff8c68a305a9030a0", "0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f" ], - "numDeployments": 5, - "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_velo\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"_merkleRoot\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Claim\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"VELO\",\"outputs\":[{\"internalType\":\"contract IVelo\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"hasClaimed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\",\"events\":{\"Claim(address,uint256)\":{\"params\":{\"amount\":\"of tokens claimed\",\"to\":\"recipient of claim\"}}},\"kind\":\"dev\",\"methods\":{\"claim(address,uint256,bytes32[])\":{\"params\":{\"amount\":\"of tokens owed to claimee\",\"proof\":\"merkle proof to prove address and amount are in tree\",\"to\":\"address of claimee\"}},\"constructor\":{\"params\":{\"_merkleRoot\":\"of claimees\",\"_velo\":\"address\"}}},\"title\":\"MerkleClaim\",\"version\":1},\"userdoc\":{\"events\":{\"Claim(address,uint256)\":{\"notice\":\"Emitted after a successful token claim\"}},\"kind\":\"user\",\"methods\":{\"VELO()\":{\"notice\":\"VELO token to claim\"},\"claim(address,uint256,bytes32[])\":{\"notice\":\"Allows claiming tokens if address is part of merkle tree\"},\"constructor\":{\"notice\":\"Creates a new MerkleClaim contract\"},\"hasClaimed(address)\":{\"notice\":\"Mapping of addresses who have claimed tokens\"},\"merkleRoot()\":{\"notice\":\"ERC20-claimee inclusion root\"}},\"notice\":\"Claims VELO for members of a merkle tree\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/MerkleClaim.sol\":\"MerkleClaim\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"},\"contracts/redeem/MerkleClaim.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity 0.8.13;\\n\\n/// ============ Imports ============\\n\\nimport {IVelo} from \\\"contracts/interfaces/IVelo.sol\\\";\\nimport {MerkleProof} from \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\\\"; // OZ: MerkleProof\\n\\n/// @title MerkleClaim\\n/// @notice Claims VELO for members of a merkle tree\\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\\ncontract MerkleClaim {\\n /// ============ Immutable storage ============\\n\\n /// @notice VELO token to claim\\n IVelo public immutable VELO;\\n /// @notice ERC20-claimee inclusion root\\n bytes32 public immutable merkleRoot;\\n\\n /// ============ Mutable storage ============\\n\\n /// @notice Mapping of addresses who have claimed tokens\\n mapping(address => bool) public hasClaimed;\\n\\n /// ============ Constructor ============\\n\\n /// @notice Creates a new MerkleClaim contract\\n /// @param _velo address\\n /// @param _merkleRoot of claimees\\n constructor(address _velo, bytes32 _merkleRoot) {\\n VELO = IVelo(_velo);\\n merkleRoot = _merkleRoot;\\n }\\n\\n /// ============ Events ============\\n\\n /// @notice Emitted after a successful token claim\\n /// @param to recipient of claim\\n /// @param amount of tokens claimed\\n event Claim(address indexed to, uint256 amount);\\n\\n /// ============ Functions ============\\n\\n /// @notice Allows claiming tokens if address is part of merkle tree\\n /// @param to address of claimee\\n /// @param amount of tokens owed to claimee\\n /// @param proof merkle proof to prove address and amount are in tree\\n function claim(\\n address to,\\n uint256 amount,\\n bytes32[] calldata proof\\n ) external {\\n // Throw if address has already claimed tokens\\n require(!hasClaimed[to], \\\"ALREADY_CLAIMED\\\");\\n\\n // Verify merkle proof, or revert if not in tree\\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\\n require(isValidLeaf, \\\"NOT_IN_MERKLE\\\");\\n\\n // Set address to claimed\\n hasClaimed[to] = true;\\n\\n // Claim tokens for address\\n require(VELO.claim(to, amount), \\\"CLAIM_FAILED\\\");\\n\\n // Emit claim event\\n emit Claim(to, amount);\\n }\\n}\\n\",\"keccak256\":\"0xb4724b0f4bf1f8a9f5ef9147e834b2d85ae61005ffc1d6b261f911c093f38270\",\"license\":\"AGPL-3.0-only\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev These functions deal with verification of Merkle Tree proofs.\\n *\\n * The tree and the proofs can be generated using our\\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\\n * You will find a quickstart guide in the readme.\\n *\\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\\n * hashing, or use a hash function other than keccak256 for hashing leaves.\\n * This is because the concatenation of a sorted pair of internal nodes in\\n * the merkle tree could be reinterpreted as a leaf value.\\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\\n * against this attack out of the box.\\n */\\nlibrary MerkleProof {\\n /**\\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\\n * defined by `root`. For this, a `proof` must be provided, containing\\n * sibling hashes on the branch from the leaf to the root of the tree. Each\\n * pair of leaves and each pair of pre-images are assumed to be sorted.\\n */\\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProof(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {verify}\\n *\\n * _Available since v4.7._\\n */\\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProofCalldata(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\\n * hash matches the root of the tree. When processing the proof, the pairs\\n * of leafs & pre-images are assumed to be sorted.\\n *\\n * _Available since v4.4._\\n */\\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Calldata version of {processProof}\\n *\\n * _Available since v4.7._\\n */\\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerify(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProof(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {multiProofVerify}\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerifyCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\\n * respectively.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProof(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n /**\\n * @dev Calldata version of {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProofCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\\n }\\n\\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x00, a)\\n mstore(0x20, b)\\n value := keccak256(0x00, 0x40)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcc76dbe53154a5bbd12fdd1613a73f73f3dc7c63d813be36f7ee606f52d6a7b3\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60c060405234801561001057600080fd5b5060405161062638038061062683398101604081905261002f91610045565b6001600160a01b0390911660805260a05261007f565b6000806040838503121561005857600080fd5b82516001600160a01b038116811461006f57600080fd5b6020939093015192949293505050565b60805160a0516105766100b060003960008181605601526101ea01526000818160d8015261029601526105766000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633d13f8741461008b57806373b2e80e146100a0578063a0eeb39a146100d3575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61009e61009936600461043c565b610112565b005b6100c36100ae3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6100fa7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea26469706673582212207394f2666e3f24ba67c7077393298dc048c3e4507cbe99f1f31fc81a3d32dfc164736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633d13f8741461008b57806373b2e80e146100a0578063a0eeb39a146100d3575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61009e61009936600461043c565b610112565b005b6100c36100ae3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6100fa7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea26469706673582212207394f2666e3f24ba67c7077393298dc048c3e4507cbe99f1f31fc81a3d32dfc164736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_velo\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"_merkleRoot\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Claim\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"VELO\",\"outputs\":[{\"internalType\":\"contract IVelo\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"hasClaimed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\",\"events\":{\"Claim(address,uint256)\":{\"params\":{\"amount\":\"of tokens claimed\",\"to\":\"recipient of claim\"}}},\"kind\":\"dev\",\"methods\":{\"claim(address,uint256,bytes32[])\":{\"params\":{\"amount\":\"of tokens owed to claimee\",\"proof\":\"merkle proof to prove address and amount are in tree\",\"to\":\"address of claimee\"}},\"constructor\":{\"params\":{\"_merkleRoot\":\"of claimees\",\"_velo\":\"address\"}}},\"title\":\"MerkleClaim\",\"version\":1},\"userdoc\":{\"events\":{\"Claim(address,uint256)\":{\"notice\":\"Emitted after a successful token claim\"}},\"kind\":\"user\",\"methods\":{\"VELO()\":{\"notice\":\"VELO token to claim\"},\"claim(address,uint256,bytes32[])\":{\"notice\":\"Allows claiming tokens if address is part of merkle tree\"},\"constructor\":{\"notice\":\"Creates a new MerkleClaim contract\"},\"hasClaimed(address)\":{\"notice\":\"Mapping of addresses who have claimed tokens\"},\"merkleRoot()\":{\"notice\":\"ERC20-claimee inclusion root\"}},\"notice\":\"Claims VELO for members of a merkle tree\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/MerkleClaim.sol\":\"MerkleClaim\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"},\"contracts/redeem/MerkleClaim.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity 0.8.13;\\n\\n/// ============ Imports ============\\n\\nimport {IVelo} from \\\"contracts/interfaces/IVelo.sol\\\";\\nimport {MerkleProof} from \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\\\"; // OZ: MerkleProof\\n\\n/// @title MerkleClaim\\n/// @notice Claims VELO for members of a merkle tree\\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\\ncontract MerkleClaim {\\n /// ============ Immutable storage ============\\n\\n /// @notice VELO token to claim\\n IVelo public immutable VELO;\\n /// @notice ERC20-claimee inclusion root\\n bytes32 public immutable merkleRoot;\\n\\n /// ============ Mutable storage ============\\n\\n /// @notice Mapping of addresses who have claimed tokens\\n mapping(address => bool) public hasClaimed;\\n\\n /// ============ Constructor ============\\n\\n /// @notice Creates a new MerkleClaim contract\\n /// @param _velo address\\n /// @param _merkleRoot of claimees\\n constructor(address _velo, bytes32 _merkleRoot) {\\n VELO = IVelo(_velo);\\n merkleRoot = _merkleRoot;\\n }\\n\\n /// ============ Events ============\\n\\n /// @notice Emitted after a successful token claim\\n /// @param to recipient of claim\\n /// @param amount of tokens claimed\\n event Claim(address indexed to, uint256 amount);\\n\\n /// ============ Functions ============\\n\\n /// @notice Allows claiming tokens if address is part of merkle tree\\n /// @param to address of claimee\\n /// @param amount of tokens owed to claimee\\n /// @param proof merkle proof to prove address and amount are in tree\\n function claim(\\n address to,\\n uint256 amount,\\n bytes32[] calldata proof\\n ) external {\\n // Throw if address has already claimed tokens\\n require(!hasClaimed[to], \\\"ALREADY_CLAIMED\\\");\\n\\n // Verify merkle proof, or revert if not in tree\\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\\n require(isValidLeaf, \\\"NOT_IN_MERKLE\\\");\\n\\n // Set address to claimed\\n hasClaimed[to] = true;\\n\\n // Claim tokens for address\\n require(VELO.claim(to, amount), \\\"CLAIM_FAILED\\\");\\n\\n // Emit claim event\\n emit Claim(to, amount);\\n }\\n}\\n\",\"keccak256\":\"0xb4724b0f4bf1f8a9f5ef9147e834b2d85ae61005ffc1d6b261f911c093f38270\",\"license\":\"AGPL-3.0-only\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev These functions deal with verification of Merkle Tree proofs.\\n *\\n * The tree and the proofs can be generated using our\\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\\n * You will find a quickstart guide in the readme.\\n *\\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\\n * hashing, or use a hash function other than keccak256 for hashing leaves.\\n * This is because the concatenation of a sorted pair of internal nodes in\\n * the merkle tree could be reinterpreted as a leaf value.\\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\\n * against this attack out of the box.\\n */\\nlibrary MerkleProof {\\n /**\\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\\n * defined by `root`. For this, a `proof` must be provided, containing\\n * sibling hashes on the branch from the leaf to the root of the tree. Each\\n * pair of leaves and each pair of pre-images are assumed to be sorted.\\n */\\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProof(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {verify}\\n *\\n * _Available since v4.7._\\n */\\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProofCalldata(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\\n * hash matches the root of the tree. When processing the proof, the pairs\\n * of leafs & pre-images are assumed to be sorted.\\n *\\n * _Available since v4.4._\\n */\\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Calldata version of {processProof}\\n *\\n * _Available since v4.7._\\n */\\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerify(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProof(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {multiProofVerify}\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerifyCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\\n * respectively.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProof(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n /**\\n * @dev Calldata version of {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProofCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\\n }\\n\\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x00, a)\\n mstore(0x20, b)\\n value := keccak256(0x00, 0x40)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcc76dbe53154a5bbd12fdd1613a73f73f3dc7c63d813be36f7ee606f52d6a7b3\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c060405234801561001057600080fd5b5060405161062638038061062683398101604081905261002f91610045565b6001600160a01b0390911660805260a05261007f565b6000806040838503121561005857600080fd5b82516001600160a01b038116811461006f57600080fd5b6020939093015192949293505050565b60805160a0516105766100b060003960008181605601526101ea01526000818160d8015261029601526105766000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633d13f8741461008b57806373b2e80e146100a0578063a0eeb39a146100d3575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61009e61009936600461043c565b610112565b005b6100c36100ae3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6100fa7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220c4a1bab597730e466dcb169625a9837504c5e0af82acc632d411e8517a3ed02964736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633d13f8741461008b57806373b2e80e146100a0578063a0eeb39a146100d3575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61009e61009936600461043c565b610112565b005b6100c36100ae3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6100fa7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220c4a1bab597730e466dcb169625a9837504c5e0af82acc632d411e8517a3ed02964736f6c634300080d0033", "devdoc": { "author": "Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)", "events": { diff --git a/deployments/arbitrumGoerli/Minter.json b/deployments/arbitrumGoerli/Minter.json index a4303ac1..0c8d2150 100644 --- a/deployments/arbitrumGoerli/Minter.json +++ b/deployments/arbitrumGoerli/Minter.json @@ -1,5 +1,5 @@ { - "address": "0x2eE17Ac8031caea5f11F7685715BF375F4BaeF6f", + "address": "0x402f3c314149F252144EE4Ca8646b4a215ACD6aC", "abi": [ { "inputs": [ @@ -324,32 +324,32 @@ "type": "function" } ], - "transactionHash": "0xa9128e0e846d5ec961d24e5febe22b721bb1e0b185233e402f31fc1935a1b353", + "transactionHash": "0xb286b07d5b396515e46cc6a6b8babba627980fcd79ca741b914e28f95cc766ca", "receipt": { "to": null, - "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0x2eE17Ac8031caea5f11F7685715BF375F4BaeF6f", + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x402f3c314149F252144EE4Ca8646b4a215ACD6aC", "transactionIndex": 1, - "gasUsed": "22608178", + "gasUsed": "1240030", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x744e6f5be02b10f764ccb372ffdde4b4e4911ab5b75034cb84e9baee3598111d", - "transactionHash": "0xa9128e0e846d5ec961d24e5febe22b721bb1e0b185233e402f31fc1935a1b353", + "blockHash": "0x98ac4f1cbbf01c907d9eeee29aedb2ab604deaadef1812effe4eeb52f1aed6e4", + "transactionHash": "0xb286b07d5b396515e46cc6a6b8babba627980fcd79ca741b914e28f95cc766ca", "logs": [], - "blockNumber": 4263696, - "cumulativeGasUsed": "22608178", + "blockNumber": 4455893, + "cumulativeGasUsed": "1240030", "status": 1, "byzantium": true }, "args": [ - "0x19E081b804AB558cF6f7B629a2902F7c79ADa9cD", - "0xCDAF5f01849Fff0a9E36D768B2ae7354A98360c0", - "0x3B2233FA015D316fdf6e79373470AD59672Ed3BD" + "0x854086d39955d28317aE3856399312b8Edb1B473", + "0xBf05364D6cf1586852c18c6b1CbEe218E3e09885", + "0xc4b9295487B4C43C1929299076820D8f55BBf957" ], - "numDeployments": 5, - "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__voter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__rewards_distributor\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weekly\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_supply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_emission\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_TEAM_RATE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_rewards_distributor\",\"outputs\":[{\"internalType\":\"contract IRewardsDistributor\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"contract IVotingEscrow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_velo\",\"outputs\":[{\"internalType\":\"contract IVelo\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_voter\",\"outputs\":[{\"internalType\":\"contract IVoter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"active_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"calculate_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minted\",\"type\":\"uint256\"}],\"name\":\"calculate_growth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"claimants\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingTeam\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_teamRate\",\"type\":\"uint256\"}],\"name\":\"setTeamRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"teamRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"update_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Minter.sol\":\"Minter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Minter.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IMinter.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVelo.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\\n\\ncontract Minter is IMinter {\\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\\n uint256 internal constant EMISSION = 990;\\n uint256 internal constant TAIL_EMISSION = 2;\\n uint256 internal constant PRECISION = 1000;\\n IVelo public immutable _velo;\\n IVoter public immutable _voter;\\n IVotingEscrow public immutable _ve;\\n IRewardsDistributor public immutable _rewards_distributor;\\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\\n uint256 public active_period;\\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\\n\\n address internal initializer;\\n address public team;\\n address public pendingTeam;\\n uint256 public teamRate;\\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\\n\\n event Mint(\\n address indexed sender,\\n uint256 weekly,\\n uint256 circulating_supply,\\n uint256 circulating_emission\\n );\\n\\n constructor(\\n address __voter, // the voting & distribution system\\n address __ve, // the ve(3,3) system that will be locked into\\n address __rewards_distributor // the distribution system that ensures users aren't diluted\\n ) {\\n initializer = msg.sender;\\n team = msg.sender;\\n teamRate = 30; // 30 bps = 0.03%\\n _velo = IVelo(IVotingEscrow(__ve).token());\\n _voter = IVoter(__voter);\\n _ve = IVotingEscrow(__ve);\\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\\n }\\n\\n function initialize(\\n address[] memory claimants,\\n uint256[] memory amounts,\\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\\n ) external {\\n require(initializer == msg.sender);\\n _velo.mint(address(this), max);\\n _velo.approve(address(_ve), type(uint256).max);\\n for (uint256 i = 0; i < claimants.length; i++) {\\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\\n }\\n initializer = address(0);\\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\\n }\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team, \\\"not team\\\");\\n pendingTeam = _team;\\n }\\n\\n function acceptTeam() external {\\n require(msg.sender == pendingTeam, \\\"not pending team\\\");\\n team = pendingTeam;\\n }\\n\\n function setTeamRate(uint256 _teamRate) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(_teamRate <= MAX_TEAM_RATE, \\\"rate too high\\\");\\n teamRate = _teamRate;\\n }\\n\\n // calculate circulating supply as total token supply - locked supply\\n function circulating_supply() public view returns (uint256) {\\n return _velo.totalSupply() - _ve.totalSupply();\\n }\\n\\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\\n function calculate_emission() public view returns (uint256) {\\n return (weekly * EMISSION) / PRECISION;\\n }\\n\\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\\n function weekly_emission() public view returns (uint256) {\\n return MathDunks.max(calculate_emission(), circulating_emission());\\n }\\n\\n // calculates tail end (infinity) emissions as 0.2% of total supply\\n function circulating_emission() public view returns (uint256) {\\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\\n }\\n\\n // calculate inflation and adjust ve balances accordingly\\n function calculate_growth(uint256 _minted) public view returns (uint256) {\\n uint256 _veTotal = _ve.totalSupply();\\n uint256 _veloTotal = _velo.totalSupply();\\n return\\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\\n _veTotal) /\\n _veloTotal /\\n 2;\\n }\\n\\n // update period can only be called once per cycle (1 week)\\n function update_period() external returns (uint256) {\\n uint256 _period = active_period;\\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\\n // only trigger if new week\\n _period = (block.timestamp / WEEK) * WEEK;\\n active_period = _period;\\n weekly = weekly_emission();\\n\\n uint256 _growth = calculate_growth(weekly);\\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\\n (PRECISION - teamRate);\\n uint256 _required = _growth + weekly + _teamEmissions;\\n uint256 _balanceOf = _velo.balanceOf(address(this));\\n if (_balanceOf < _required) {\\n _velo.mint(address(this), _required - _balanceOf);\\n }\\n\\n require(_velo.transfer(team, _teamEmissions));\\n require(_velo.transfer(address(_rewards_distributor), _growth));\\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\\n\\n _velo.approve(address(_voter), weekly);\\n _voter.notifyRewardAmount(weekly);\\n\\n emit Mint(\\n msg.sender,\\n weekly,\\n circulating_supply(),\\n circulating_emission()\\n );\\n }\\n return _period;\\n }\\n}\\n\",\"keccak256\":\"0x8dce50c09815e53982006f9ddc46cd52cf7ac86b0c1b7bb15c817f86fb990580\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x6101006040526a0c685fa11e01ec6f0000006000553480156200002157600080fd5b506040516200158938038062001589833981016040819052620000449162000156565b60028054336001600160a01b03199182168117909255600380549091169091179055601e60055560408051637e062a3560e11b815290516001600160a01b0384169163fc0c546a9160048083019260209291908290030181865afa158015620000b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d79190620001a0565b6001600160a01b0390811660805283811660a05282811660c052811660e05262093a808062000108816002620001db565b620001149042620001fd565b62000120919062000218565b6200012c9190620001db565b600155506200023b915050565b80516001600160a01b03811681146200015157600080fd5b919050565b6000806000606084860312156200016c57600080fd5b620001778462000139565b9250620001876020850162000139565b9150620001976040850162000139565b90509250925092565b600060208284031215620001b357600080fd5b620001be8262000139565b9392505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620001f857620001f8620001c5565b500290565b60008219821115620002135762000213620001c5565b500190565b6000826200023657634e487b7160e01b600052601260045260246000fd5b500490565b60805160a05160c05160e051611296620002f3600039600081816101f801528181610c3701528181610cde0152610d51015260008181610261015281816104b30152818161055f0152818161068901526108750152600081816101d101528181610e090152610ea301526000818161015101528181610426015281816104e30152818161070f015281816108f701528181610a5f01528181610ade01528181610ba801528181610c660152610dda01526112966000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c806378ef7f02116100ad578063b5cc143a11610071578063b5cc143a14610296578063cfc6c8ff1461029e578063d1399608146102a6578063e038c75a146102af578063ed29fc11146102b757600080fd5b806378ef7f021461022d578063851708131461023657806385f2aef2146102495780638dd598fb1461025c5780638e01fbfa1461028357600080fd5b80632e8f7b1f116100f45780632e8f7b1f146101b157806336d96faf146101c45780633db9b42a146101cc5780634b1cd5da146101f357806359d46ffc1461021a57600080fd5b806301c8e6fd1461013157806308aa44581461014c578063095cf5c61461018b5780631eebae80146101a057806326cfc17b146101a8575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b61019e610199366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61019e6101bf366004610fb8565b610353565b6101396103de565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b600454610173906001600160a01b031681565b61013960055481565b61019e6102443660046110a7565b6103f3565b600354610173906001600160a01b031681565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b610139610291366004610fb8565b610684565b61019e6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea264697066735822122029438f922f44621ac4ad13f191e125db9a2cbc3825de07f3a7f336bcfd98402f64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c806378ef7f02116100ad578063b5cc143a11610071578063b5cc143a14610296578063cfc6c8ff1461029e578063d1399608146102a6578063e038c75a146102af578063ed29fc11146102b757600080fd5b806378ef7f021461022d578063851708131461023657806385f2aef2146102495780638dd598fb1461025c5780638e01fbfa1461028357600080fd5b80632e8f7b1f116100f45780632e8f7b1f146101b157806336d96faf146101c45780633db9b42a146101cc5780634b1cd5da146101f357806359d46ffc1461021a57600080fd5b806301c8e6fd1461013157806308aa44581461014c578063095cf5c61461018b5780631eebae80146101a057806326cfc17b146101a8575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b61019e610199366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61019e6101bf366004610fb8565b610353565b6101396103de565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b600454610173906001600160a01b031681565b61013960055481565b61019e6102443660046110a7565b6103f3565b600354610173906001600160a01b031681565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b610139610291366004610fb8565b610684565b61019e6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea264697066735822122029438f922f44621ac4ad13f191e125db9a2cbc3825de07f3a7f336bcfd98402f64736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__voter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__rewards_distributor\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weekly\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_supply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_emission\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_TEAM_RATE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_rewards_distributor\",\"outputs\":[{\"internalType\":\"contract IRewardsDistributor\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"contract IVotingEscrow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_velo\",\"outputs\":[{\"internalType\":\"contract IVelo\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_voter\",\"outputs\":[{\"internalType\":\"contract IVoter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"active_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"calculate_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minted\",\"type\":\"uint256\"}],\"name\":\"calculate_growth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"claimants\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingTeam\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_teamRate\",\"type\":\"uint256\"}],\"name\":\"setTeamRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"teamRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"update_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Minter.sol\":\"Minter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Minter.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IMinter.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVelo.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\\n\\ncontract Minter is IMinter {\\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\\n uint256 internal constant EMISSION = 990;\\n uint256 internal constant TAIL_EMISSION = 2;\\n uint256 internal constant PRECISION = 1000;\\n IVelo public immutable _velo;\\n IVoter public immutable _voter;\\n IVotingEscrow public immutable _ve;\\n IRewardsDistributor public immutable _rewards_distributor;\\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\\n uint256 public active_period;\\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\\n\\n address internal initializer;\\n address public team;\\n address public pendingTeam;\\n uint256 public teamRate;\\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\\n\\n event Mint(\\n address indexed sender,\\n uint256 weekly,\\n uint256 circulating_supply,\\n uint256 circulating_emission\\n );\\n\\n constructor(\\n address __voter, // the voting & distribution system\\n address __ve, // the ve(3,3) system that will be locked into\\n address __rewards_distributor // the distribution system that ensures users aren't diluted\\n ) {\\n initializer = msg.sender;\\n team = msg.sender;\\n teamRate = 30; // 30 bps = 0.03%\\n _velo = IVelo(IVotingEscrow(__ve).token());\\n _voter = IVoter(__voter);\\n _ve = IVotingEscrow(__ve);\\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\\n }\\n\\n function initialize(\\n address[] memory claimants,\\n uint256[] memory amounts,\\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\\n ) external {\\n require(initializer == msg.sender);\\n _velo.mint(address(this), max);\\n _velo.approve(address(_ve), type(uint256).max);\\n for (uint256 i = 0; i < claimants.length; i++) {\\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\\n }\\n initializer = address(0);\\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\\n }\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team, \\\"not team\\\");\\n pendingTeam = _team;\\n }\\n\\n function acceptTeam() external {\\n require(msg.sender == pendingTeam, \\\"not pending team\\\");\\n team = pendingTeam;\\n }\\n\\n function setTeamRate(uint256 _teamRate) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(_teamRate <= MAX_TEAM_RATE, \\\"rate too high\\\");\\n teamRate = _teamRate;\\n }\\n\\n // calculate circulating supply as total token supply - locked supply\\n function circulating_supply() public view returns (uint256) {\\n return _velo.totalSupply() - _ve.totalSupply();\\n }\\n\\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\\n function calculate_emission() public view returns (uint256) {\\n return (weekly * EMISSION) / PRECISION;\\n }\\n\\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\\n function weekly_emission() public view returns (uint256) {\\n return MathDunks.max(calculate_emission(), circulating_emission());\\n }\\n\\n // calculates tail end (infinity) emissions as 0.2% of total supply\\n function circulating_emission() public view returns (uint256) {\\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\\n }\\n\\n // calculate inflation and adjust ve balances accordingly\\n function calculate_growth(uint256 _minted) public view returns (uint256) {\\n uint256 _veTotal = _ve.totalSupply();\\n uint256 _veloTotal = _velo.totalSupply();\\n return\\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\\n _veTotal) /\\n _veloTotal /\\n 2;\\n }\\n\\n // update period can only be called once per cycle (1 week)\\n function update_period() external returns (uint256) {\\n uint256 _period = active_period;\\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\\n // only trigger if new week\\n _period = (block.timestamp / WEEK) * WEEK;\\n active_period = _period;\\n weekly = weekly_emission();\\n\\n uint256 _growth = calculate_growth(weekly);\\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\\n (PRECISION - teamRate);\\n uint256 _required = _growth + weekly + _teamEmissions;\\n uint256 _balanceOf = _velo.balanceOf(address(this));\\n if (_balanceOf < _required) {\\n _velo.mint(address(this), _required - _balanceOf);\\n }\\n\\n require(_velo.transfer(team, _teamEmissions));\\n require(_velo.transfer(address(_rewards_distributor), _growth));\\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\\n\\n _velo.approve(address(_voter), weekly);\\n _voter.notifyRewardAmount(weekly);\\n\\n emit Mint(\\n msg.sender,\\n weekly,\\n circulating_supply(),\\n circulating_emission()\\n );\\n }\\n return _period;\\n }\\n}\\n\",\"keccak256\":\"0x8dce50c09815e53982006f9ddc46cd52cf7ac86b0c1b7bb15c817f86fb990580\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x6101006040526a0c685fa11e01ec6f0000006000553480156200002157600080fd5b506040516200158938038062001589833981016040819052620000449162000156565b60028054336001600160a01b03199182168117909255600380549091169091179055601e60055560408051637e062a3560e11b815290516001600160a01b0384169163fc0c546a9160048083019260209291908290030181865afa158015620000b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d79190620001a0565b6001600160a01b0390811660805283811660a05282811660c052811660e05262093a808062000108816002620001db565b620001149042620001fd565b62000120919062000218565b6200012c9190620001db565b600155506200023b915050565b80516001600160a01b03811681146200015157600080fd5b919050565b6000806000606084860312156200016c57600080fd5b620001778462000139565b9250620001876020850162000139565b9150620001976040850162000139565b90509250925092565b600060208284031215620001b357600080fd5b620001be8262000139565b9392505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620001f857620001f8620001c5565b500290565b60008219821115620002135762000213620001c5565b500190565b6000826200023657634e487b7160e01b600052601260045260246000fd5b500490565b60805160a05160c05160e051611296620002f3600039600081816101f801528181610c3701528181610cde0152610d51015260008181610261015281816104b30152818161055f0152818161068901526108750152600081816101d101528181610e090152610ea301526000818161015101528181610426015281816104e30152818161070f015281816108f701528181610a5f01528181610ade01528181610ba801528181610c660152610dda01526112966000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c806378ef7f02116100ad578063b5cc143a11610071578063b5cc143a14610296578063cfc6c8ff1461029e578063d1399608146102a6578063e038c75a146102af578063ed29fc11146102b757600080fd5b806378ef7f021461022d578063851708131461023657806385f2aef2146102495780638dd598fb1461025c5780638e01fbfa1461028357600080fd5b80632e8f7b1f116100f45780632e8f7b1f146101b157806336d96faf146101c45780633db9b42a146101cc5780634b1cd5da146101f357806359d46ffc1461021a57600080fd5b806301c8e6fd1461013157806308aa44581461014c578063095cf5c61461018b5780631eebae80146101a057806326cfc17b146101a8575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b61019e610199366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61019e6101bf366004610fb8565b610353565b6101396103de565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b600454610173906001600160a01b031681565b61013960055481565b61019e6102443660046110a7565b6103f3565b600354610173906001600160a01b031681565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b610139610291366004610fb8565b610684565b61019e6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea26469706673582212206fa40733fc0460202dd7acad8836bc192a7e6f0195a1ba5004b64c08f206af0564736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c806378ef7f02116100ad578063b5cc143a11610071578063b5cc143a14610296578063cfc6c8ff1461029e578063d1399608146102a6578063e038c75a146102af578063ed29fc11146102b757600080fd5b806378ef7f021461022d578063851708131461023657806385f2aef2146102495780638dd598fb1461025c5780638e01fbfa1461028357600080fd5b80632e8f7b1f116100f45780632e8f7b1f146101b157806336d96faf146101c45780633db9b42a146101cc5780634b1cd5da146101f357806359d46ffc1461021a57600080fd5b806301c8e6fd1461013157806308aa44581461014c578063095cf5c61461018b5780631eebae80146101a057806326cfc17b146101a8575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b61019e610199366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61019e6101bf366004610fb8565b610353565b6101396103de565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b600454610173906001600160a01b031681565b61013960055481565b61019e6102443660046110a7565b6103f3565b600354610173906001600160a01b031681565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b610139610291366004610fb8565b610684565b61019e6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea26469706673582212206fa40733fc0460202dd7acad8836bc192a7e6f0195a1ba5004b64c08f206af0564736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/PairFactory.json b/deployments/arbitrumGoerli/PairFactory.json index 46c85196..c72dff2f 100644 --- a/deployments/arbitrumGoerli/PairFactory.json +++ b/deployments/arbitrumGoerli/PairFactory.json @@ -1,5 +1,5 @@ { - "address": "0xcA698eA7f3A74b7D3D4229765dcF47F7A224859F", + "address": "0x6389e934d35fC9e066FAb549C8DBc9FddaC10e0D", "abi": [ { "inputs": [], @@ -383,28 +383,28 @@ "type": "function" } ], - "transactionHash": "0x2af9c03ec273fa0fa064d96e928f6c4837da417a859f27ec469133350ba1160c", + "transactionHash": "0x6ed74c056b5b7bd5c74422c6a7f3bcdb0c8f660e5036b0e602ecad2bf3c7069b", "receipt": { "to": null, - "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0xcA698eA7f3A74b7D3D4229765dcF47F7A224859F", + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x6389e934d35fC9e066FAb549C8DBc9FddaC10e0D", "transactionIndex": 1, - "gasUsed": "79767077", + "gasUsed": "4777620", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xab8bc7d3d92f462a3d996a61e22d4a78007f9d4a54c922e675acd0c804ab4185", - "transactionHash": "0x2af9c03ec273fa0fa064d96e928f6c4837da417a859f27ec469133350ba1160c", + "blockHash": "0x15d0ab42df0563378e2406c0d098da299916fce4242aa1646a01591688fa367a", + "transactionHash": "0x6ed74c056b5b7bd5c74422c6a7f3bcdb0c8f660e5036b0e602ecad2bf3c7069b", "logs": [], - "blockNumber": 4263673, - "cumulativeGasUsed": "79767077", + "blockNumber": 4455874, + "cumulativeGasUsed": "4777620", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 8, - "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"PairCreated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_FEE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allPairs\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"allPairsLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"createPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getInitializable\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"name\":\"getPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pairCodeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingFeeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingPauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_feeManager\",\"type\":\"address\"}],\"name\":\"setFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_state\",\"type\":\"bool\"}],\"name\":\"setPause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pauser\",\"type\":\"address\"}],\"name\":\"setPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stableFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"volatileFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/PairFactory.sol\":\"PairFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Pair.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairCallee.sol\\\";\\nimport \\\"contracts/factories/PairFactory.sol\\\";\\nimport \\\"contracts/PairFees.sol\\\";\\n\\n// The base pair of pools, either stable or volatile\\ncontract Pair is IPair {\\n string public name;\\n string public symbol;\\n uint8 public constant decimals = 18;\\n\\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\\n bool public immutable stable;\\n\\n uint256 public totalSupply = 0;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n mapping(address => uint256) public balanceOf;\\n\\n bytes32 internal DOMAIN_SEPARATOR;\\n // keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 internal constant PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n mapping(address => uint256) public nonces;\\n\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n\\n address public immutable token0;\\n address public immutable token1;\\n address public immutable fees;\\n address immutable factory;\\n\\n // Structure to capture time period obervations every 30 minutes, used for local oracles\\n struct Observation {\\n uint256 timestamp;\\n uint256 reserve0Cumulative;\\n uint256 reserve1Cumulative;\\n }\\n\\n // Capture oracle reading every 30 minutes\\n uint256 constant periodSize = 1800;\\n\\n Observation[] public observations;\\n\\n uint256 internal immutable decimals0;\\n uint256 internal immutable decimals1;\\n\\n uint256 public reserve0;\\n uint256 public reserve1;\\n uint256 public blockTimestampLast;\\n\\n uint256 public reserve0CumulativeLast;\\n uint256 public reserve1CumulativeLast;\\n\\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \\\"clean\\\"\\n // this further allows LP holders to easily claim fees for tokens they have/staked\\n uint256 public index0 = 0;\\n uint256 public index1 = 0;\\n\\n // position assigned to each LP to track their current index0 & index1 vs the global position\\n mapping(address => uint256) public supplyIndex0;\\n mapping(address => uint256) public supplyIndex1;\\n\\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\\n mapping(address => uint256) public claimable0;\\n mapping(address => uint256) public claimable1;\\n\\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\\n event Burn(\\n address indexed sender,\\n uint256 amount0,\\n uint256 amount1,\\n address indexed to\\n );\\n event Swap(\\n address indexed sender,\\n uint256 amount0In,\\n uint256 amount1In,\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address indexed to\\n );\\n event Sync(uint256 reserve0, uint256 reserve1);\\n event Claim(\\n address indexed sender,\\n address indexed recipient,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 amount\\n );\\n\\n constructor() {\\n factory = msg.sender;\\n (address _token0, address _token1, bool _stable) = PairFactory(\\n msg.sender\\n ).getInitializable();\\n (token0, token1, stable) = (_token0, _token1, _stable);\\n fees = address(new PairFees(_token0, _token1));\\n if (_stable) {\\n name = string(\\n abi.encodePacked(\\n \\\"StableV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"sAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n } else {\\n name = string(\\n abi.encodePacked(\\n \\\"VolatileV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"vAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n }\\n\\n decimals0 = 10**IERC20(_token0).decimals();\\n decimals1 = 10**IERC20(_token1).decimals();\\n\\n observations.push(Observation(block.timestamp, 0, 0));\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function observationLength() external view returns (uint256) {\\n return observations.length;\\n }\\n\\n function lastObservation() public view returns (Observation memory) {\\n return observations[observations.length - 1];\\n }\\n\\n function metadata()\\n external\\n view\\n returns (\\n uint256 dec0,\\n uint256 dec1,\\n uint256 r0,\\n uint256 r1,\\n bool st,\\n address t0,\\n address t1\\n )\\n {\\n return (\\n decimals0,\\n decimals1,\\n reserve0,\\n reserve1,\\n stable,\\n token0,\\n token1\\n );\\n }\\n\\n function tokens() external view returns (address, address) {\\n return (token0, token1);\\n }\\n\\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\\n _updateFor(msg.sender);\\n\\n claimed0 = claimable0[msg.sender];\\n claimed1 = claimable1[msg.sender];\\n\\n if (claimed0 > 0 || claimed1 > 0) {\\n claimable0[msg.sender] = 0;\\n claimable1[msg.sender] = 0;\\n\\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\\n\\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n // Accrue fees on token0\\n function _update0(uint256 amount) internal {\\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index0 += _ratio;\\n }\\n emit Fees(msg.sender, amount, 0);\\n }\\n\\n // Accrue fees on token1\\n function _update1(uint256 amount) internal {\\n _safeTransfer(token1, fees, amount);\\n uint256 _ratio = (amount * 1e18) / totalSupply;\\n if (_ratio > 0) {\\n index1 += _ratio;\\n }\\n emit Fees(msg.sender, 0, amount);\\n }\\n\\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\\n // Fees are segregated from core funds, so fees can never put liquidity at risk\\n function _updateFor(address recipient) internal {\\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\\n if (_supplied > 0) {\\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\\n uint256 _supplyIndex1 = supplyIndex1[recipient];\\n uint256 _index0 = index0; // get global index0 for accumulated fees\\n uint256 _index1 = index1;\\n supplyIndex0[recipient] = _index0; // update user current position to global position\\n supplyIndex1[recipient] = _index1;\\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\\n uint256 _delta1 = _index1 - _supplyIndex1;\\n if (_delta0 > 0) {\\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\\n claimable0[recipient] += _share;\\n }\\n if (_delta1 > 0) {\\n uint256 _share = (_supplied * _delta1) / 1e18;\\n claimable1[recipient] += _share;\\n }\\n } else {\\n supplyIndex0[recipient] = index0; // new users are set to the default global state\\n supplyIndex1[recipient] = index1;\\n }\\n }\\n\\n function getReserves()\\n public\\n view\\n returns (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n )\\n {\\n _reserve0 = reserve0;\\n _reserve1 = reserve1;\\n _blockTimestampLast = blockTimestampLast;\\n }\\n\\n // update reserves and, on the first call per block, price accumulators\\n function _update(\\n uint256 balance0,\\n uint256 balance1,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal {\\n uint256 blockTimestamp = block.timestamp;\\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\\n reserve0CumulativeLast += _reserve0 * timeElapsed;\\n reserve1CumulativeLast += _reserve1 * timeElapsed;\\n }\\n\\n Observation memory _point = lastObservation();\\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\\n if (timeElapsed > periodSize) {\\n observations.push(\\n Observation(\\n blockTimestamp,\\n reserve0CumulativeLast,\\n reserve1CumulativeLast\\n )\\n );\\n }\\n reserve0 = balance0;\\n reserve1 = balance1;\\n blockTimestampLast = blockTimestamp;\\n emit Sync(reserve0, reserve1);\\n }\\n\\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\\n function currentCumulativePrices()\\n public\\n view\\n returns (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n uint256 blockTimestamp\\n )\\n {\\n blockTimestamp = block.timestamp;\\n reserve0Cumulative = reserve0CumulativeLast;\\n reserve1Cumulative = reserve1CumulativeLast;\\n\\n // if time has elapsed since the last update on the pair, mock the accumulated price values\\n (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n ) = getReserves();\\n if (_blockTimestampLast != blockTimestamp) {\\n // subtraction overflow is desired\\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\\n reserve0Cumulative += _reserve0 * timeElapsed;\\n reserve1Cumulative += _reserve1 * timeElapsed;\\n }\\n }\\n\\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\\n function current(address tokenIn, uint256 amountIn)\\n external\\n view\\n returns (uint256 amountOut)\\n {\\n Observation memory _observation = lastObservation();\\n (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n\\n ) = currentCumulativePrices();\\n if (block.timestamp == _observation.timestamp) {\\n _observation = observations[observations.length - 2];\\n }\\n\\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\\n uint256 _reserve0 = (reserve0Cumulative -\\n _observation.reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (reserve1Cumulative -\\n _observation.reserve1Cumulative) / timeElapsed;\\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n // as per `current`, however allows user configured granularity, up to the full window size\\n function quote(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 granularity\\n ) external view returns (uint256 amountOut) {\\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\\n uint256 priceAverageCumulative;\\n for (uint256 i = 0; i < _prices.length; i++) {\\n priceAverageCumulative += _prices[i];\\n }\\n return priceAverageCumulative / granularity;\\n }\\n\\n // returns a memory set of twap prices\\n function prices(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points\\n ) external view returns (uint256[] memory) {\\n return sample(tokenIn, amountIn, points, 1);\\n }\\n\\n function sample(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points,\\n uint256 window\\n ) public view returns (uint256[] memory) {\\n uint256[] memory _prices = new uint256[](points);\\n\\n uint256 length = observations.length - 1;\\n uint256 i = length - (points * window);\\n uint256 nextIndex = 0;\\n uint256 index = 0;\\n\\n for (; i < length; i += window) {\\n nextIndex = i + window;\\n uint256 timeElapsed = observations[nextIndex].timestamp -\\n observations[i].timestamp;\\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\\n observations[i].reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\\n observations[i].reserve1Cumulative) / timeElapsed;\\n _prices[index] = _getAmountOut(\\n amountIn,\\n tokenIn,\\n _reserve0,\\n _reserve1\\n );\\n // index < length; length cannot overflow\\n unchecked {\\n index = index + 1;\\n }\\n }\\n return _prices;\\n }\\n\\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\\n // standard uniswap v2 implementation\\n function mint(address to) external lock returns (uint256 liquidity) {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\\n uint256 _amount0 = _balance0 - _reserve0;\\n uint256 _amount1 = _balance1 - _reserve1;\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n if (_totalSupply == 0) {\\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\\n } else {\\n liquidity = MathDunks.min(\\n (_amount0 * _totalSupply) / _reserve0,\\n (_amount1 * _totalSupply) / _reserve1\\n );\\n }\\n require(liquidity > 0, \\\"ILM\\\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\\n _mint(to, liquidity);\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Mint(msg.sender, _amount0, _amount1);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n // standard uniswap v2 implementation\\n function burn(address to)\\n external\\n lock\\n returns (uint256 amount0, uint256 amount1)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n (address _token0, address _token1) = (token0, token1);\\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\\n uint256 _liquidity = balanceOf[address(this)];\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\\n require(amount0 > 0 && amount1 > 0, \\\"ILB\\\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\\n _burn(address(this), _liquidity);\\n _safeTransfer(_token0, to, amount0);\\n _safeTransfer(_token1, to, amount1);\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Burn(msg.sender, amount0, amount1, to);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n function swap(\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address to,\\n bytes calldata data\\n ) external lock {\\n require(!PairFactory(factory).isPaused());\\n require(amount0Out > 0 || amount1Out > 0, \\\"IOA\\\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \\\"IL\\\"); // Pair: INSUFFICIENT_LIQUIDITY\\n\\n uint256 _balance0;\\n uint256 _balance1;\\n {\\n // scope for _token{0,1}, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n require(to != _token0 && to != _token1, \\\"IT\\\"); // Pair: INVALID_TO\\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\\n if (data.length > 0)\\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n }\\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\\n ? _balance0 - (_reserve0 - amount0Out)\\n : 0;\\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\\n ? _balance1 - (_reserve1 - amount1Out)\\n : 0;\\n require(amount0In > 0 || amount1In > 0, \\\"IIA\\\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\\n {\\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n if (amount0In > 0)\\n _update0(\\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token0 and move them out of pool\\n if (amount1In > 0)\\n _update1(\\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token1 and move them out of pool\\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \\\"K\\\"); // Pair: K\\n }\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\\n }\\n\\n // force balances to match reserves\\n function skim(address to) external lock {\\n (address _token0, address _token1) = (token0, token1);\\n _safeTransfer(\\n _token0,\\n to,\\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\\n );\\n _safeTransfer(\\n _token1,\\n to,\\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\\n );\\n }\\n\\n // force reserves to match balances\\n function sync() external lock {\\n _update(\\n IERC20(token0).balanceOf(address(this)),\\n IERC20(token1).balanceOf(address(this)),\\n reserve0,\\n reserve1\\n );\\n }\\n\\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\\n 1e18 +\\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\\n 1e18;\\n }\\n\\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (3 * x0 * ((y * y) / 1e18)) /\\n 1e18 +\\n ((((x0 * x0) / 1e18) * x0) / 1e18);\\n }\\n\\n function _get_y(\\n uint256 x0,\\n uint256 xy,\\n uint256 y\\n ) internal pure returns (uint256) {\\n for (uint256 i = 0; i < 255; i++) {\\n uint256 y_prev = y;\\n uint256 k = _f(x0, y);\\n if (k < xy) {\\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\\n y = y + dy;\\n } else {\\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getAmountOut(uint256 amountIn, address tokenIn)\\n external\\n view\\n returns (uint256)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n function _getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal view returns (uint256) {\\n if (stable) {\\n uint256 xy = _k(_reserve0, _reserve1);\\n _reserve0 = (_reserve0 * 1e18) / decimals0;\\n _reserve1 = (_reserve1 * 1e18) / decimals1;\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0\\n ? (amountIn * 1e18) / decimals0\\n : (amountIn * 1e18) / decimals1;\\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\\n } else {\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n return (amountIn * reserveB) / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\\n if (stable) {\\n uint256 _x = (x * 1e18) / decimals0;\\n uint256 _y = (y * 1e18) / decimals1;\\n uint256 _a = (_x * _y) / 1e18;\\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return (_a * _b) / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n\\n function _mint(address dst, uint256 amount) internal {\\n _updateFor(dst); // balances must be updated on mint/burn/transfer\\n totalSupply += amount;\\n balanceOf[dst] += amount;\\n emit Transfer(address(0), dst, amount);\\n }\\n\\n function _burn(address dst, uint256 amount) internal {\\n _updateFor(dst);\\n totalSupply -= amount;\\n balanceOf[dst] -= amount;\\n emit Transfer(dst, address(0), amount);\\n }\\n\\n function approve(address spender, uint256 amount) external returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external {\\n require(deadline >= block.timestamp, \\\"Pair: EXPIRED\\\");\\n DOMAIN_SEPARATOR = keccak256(\\n abi.encode(\\n keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n ),\\n keccak256(bytes(name)),\\n keccak256(bytes(\\\"1\\\")),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR,\\n keccak256(\\n abi.encode(\\n PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n );\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n require(\\n recoveredAddress != address(0) && recoveredAddress == owner,\\n \\\"Pair: INVALID_SIGNATURE\\\"\\n );\\n allowance[owner][spender] = value;\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function transfer(address dst, uint256 amount) external returns (bool) {\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 amount\\n ) external returns (bool) {\\n address spender = msg.sender;\\n uint256 spenderAllowance = allowance[src][spender];\\n\\n if (spender != src && spenderAllowance != type(uint256).max) {\\n uint256 newAllowance = spenderAllowance - amount;\\n allowance[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n function _transferTokens(\\n address src,\\n address dst,\\n uint256 amount\\n ) internal {\\n _updateFor(src); // update fee position for src\\n _updateFor(dst); // update fee position for dst\\n\\n balanceOf[src] -= amount;\\n balanceOf[dst] += amount;\\n\\n emit Transfer(src, dst, amount);\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x4f508747645f4480e0b0f23d952fa9b82af1d9bc60b15b8cd1f542ee136043d1\",\"license\":\"MIT\"},\"contracts/PairFees.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IERC20.sol';\\n\\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\\ncontract PairFees {\\n\\n address internal immutable pair; // The pair it is bonded to\\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\\n\\n constructor(address _token0, address _token1) {\\n pair = msg.sender;\\n token0 = _token0;\\n token1 = _token1;\\n }\\n\\n function _safeTransfer(address token,address to,uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n // Allow the pair to transfer fees to users\\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\\n require(msg.sender == pair);\\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\\n }\\n\\n}\\n\",\"keccak256\":\"0xb772e192bab353f8642e89a95ef4ef0255d1caef08444101d7fe34469c1000ca\",\"license\":\"MIT\"},\"contracts/factories/PairFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/Pair.sol';\\n\\ncontract PairFactory is IPairFactory {\\n\\n bool public isPaused;\\n address public pauser;\\n address public pendingPauser;\\n\\n uint256 public stableFee;\\n uint256 public volatileFee;\\n uint256 public constant MAX_FEE = 5; // 0.05%\\n address public feeManager;\\n address public pendingFeeManager;\\n\\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\\n address[] public allPairs;\\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\\n\\n address internal _temp0;\\n address internal _temp1;\\n bool internal _temp;\\n\\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\\n\\n constructor() {\\n pauser = msg.sender;\\n isPaused = false;\\n feeManager = msg.sender;\\n stableFee = 2; // 0.02%\\n volatileFee = 2;\\n }\\n\\n function allPairsLength() external view returns (uint) {\\n return allPairs.length;\\n }\\n\\n function setPauser(address _pauser) external {\\n require(msg.sender == pauser);\\n pendingPauser = _pauser;\\n }\\n\\n function acceptPauser() external {\\n require(msg.sender == pendingPauser);\\n pauser = pendingPauser;\\n }\\n\\n function setPause(bool _state) external {\\n require(msg.sender == pauser);\\n isPaused = _state;\\n }\\n\\n function setFeeManager(address _feeManager) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n pendingFeeManager = _feeManager;\\n }\\n\\n function acceptFeeManager() external {\\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\\n feeManager = pendingFeeManager;\\n }\\n\\n function setFee(bool _stable, uint256 _fee) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n require(_fee <= MAX_FEE, 'fee too high');\\n require(_fee != 0, 'fee must be nonzero');\\n if (_stable) {\\n stableFee = _fee;\\n } else {\\n volatileFee = _fee;\\n }\\n }\\n\\n function getFee(bool _stable) public view returns(uint256) {\\n return _stable ? stableFee : volatileFee;\\n }\\n\\n function pairCodeHash() external pure returns (bytes32) {\\n return keccak256(type(Pair).creationCode);\\n }\\n\\n function getInitializable() external view returns (address, address, bool) {\\n return (_temp0, _temp1, _temp);\\n }\\n\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\\n (_temp0, _temp1, _temp) = (token0, token1, stable);\\n pair = address(new Pair{salt:salt}());\\n getPair[token0][token1][stable] = pair;\\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\\n allPairs.push(pair);\\n isPair[pair] = true;\\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\\n }\\n}\\n\",\"keccak256\":\"0x9b7984117a5a32188aa9ddf42b6cff024240579ab30f3776f7a201285d813e4f\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairCallee.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairCallee {\\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x3ac2de2c7a08bf59fd1006e4d108b247916369de15fbd048b72ca2b7814023ca\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50600080546001600160a81b03191633610100810260ff1916919091178255600480546001600160a01b0319169091179055600280805560035561519190819061005a90396000f3fe60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea26469706673582212209a81b6080f92b4404ef96a6f4be1eb720d086813c51978fa69228aa4a9475a0a64736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea264697066735822122001f7e6ebdc7c73c8cd4fc265ddf1f20b20d92174d591661f841bc8ad24c91c5364736f6c634300080d0033a2646970667358221220c135354976b334eda32c0379e423d9e6fc425df0ae93f17748c33d480901ab2764736f6c634300080d0033", - "deployedBytecode": "0x60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea26469706673582212209a81b6080f92b4404ef96a6f4be1eb720d086813c51978fa69228aa4a9475a0a64736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea264697066735822122001f7e6ebdc7c73c8cd4fc265ddf1f20b20d92174d591661f841bc8ad24c91c5364736f6c634300080d0033a2646970667358221220c135354976b334eda32c0379e423d9e6fc425df0ae93f17748c33d480901ab2764736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"PairCreated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_FEE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allPairs\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"allPairsLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"createPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getInitializable\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"name\":\"getPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pairCodeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingFeeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingPauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_feeManager\",\"type\":\"address\"}],\"name\":\"setFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_state\",\"type\":\"bool\"}],\"name\":\"setPause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pauser\",\"type\":\"address\"}],\"name\":\"setPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stableFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"volatileFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/PairFactory.sol\":\"PairFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Pair.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairCallee.sol\\\";\\nimport \\\"contracts/factories/PairFactory.sol\\\";\\nimport \\\"contracts/PairFees.sol\\\";\\n\\n// The base pair of pools, either stable or volatile\\ncontract Pair is IPair {\\n string public name;\\n string public symbol;\\n uint8 public constant decimals = 18;\\n\\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\\n bool public immutable stable;\\n\\n uint256 public totalSupply = 0;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n mapping(address => uint256) public balanceOf;\\n\\n bytes32 internal DOMAIN_SEPARATOR;\\n // keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 internal constant PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n mapping(address => uint256) public nonces;\\n\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n\\n address public immutable token0;\\n address public immutable token1;\\n address public immutable fees;\\n address immutable factory;\\n\\n // Structure to capture time period obervations every 30 minutes, used for local oracles\\n struct Observation {\\n uint256 timestamp;\\n uint256 reserve0Cumulative;\\n uint256 reserve1Cumulative;\\n }\\n\\n // Capture oracle reading every 30 minutes\\n uint256 constant periodSize = 1800;\\n\\n Observation[] public observations;\\n\\n uint256 internal immutable decimals0;\\n uint256 internal immutable decimals1;\\n\\n uint256 public reserve0;\\n uint256 public reserve1;\\n uint256 public blockTimestampLast;\\n\\n uint256 public reserve0CumulativeLast;\\n uint256 public reserve1CumulativeLast;\\n\\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \\\"clean\\\"\\n // this further allows LP holders to easily claim fees for tokens they have/staked\\n uint256 public index0 = 0;\\n uint256 public index1 = 0;\\n\\n // position assigned to each LP to track their current index0 & index1 vs the global position\\n mapping(address => uint256) public supplyIndex0;\\n mapping(address => uint256) public supplyIndex1;\\n\\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\\n mapping(address => uint256) public claimable0;\\n mapping(address => uint256) public claimable1;\\n\\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\\n event Burn(\\n address indexed sender,\\n uint256 amount0,\\n uint256 amount1,\\n address indexed to\\n );\\n event Swap(\\n address indexed sender,\\n uint256 amount0In,\\n uint256 amount1In,\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address indexed to\\n );\\n event Sync(uint256 reserve0, uint256 reserve1);\\n event Claim(\\n address indexed sender,\\n address indexed recipient,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 amount\\n );\\n\\n constructor() {\\n factory = msg.sender;\\n (address _token0, address _token1, bool _stable) = PairFactory(\\n msg.sender\\n ).getInitializable();\\n (token0, token1, stable) = (_token0, _token1, _stable);\\n fees = address(new PairFees(_token0, _token1));\\n if (_stable) {\\n name = string(\\n abi.encodePacked(\\n \\\"StableV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"sAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n } else {\\n name = string(\\n abi.encodePacked(\\n \\\"VolatileV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"vAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n }\\n\\n decimals0 = 10**IERC20(_token0).decimals();\\n decimals1 = 10**IERC20(_token1).decimals();\\n\\n observations.push(Observation(block.timestamp, 0, 0));\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function observationLength() external view returns (uint256) {\\n return observations.length;\\n }\\n\\n function lastObservation() public view returns (Observation memory) {\\n return observations[observations.length - 1];\\n }\\n\\n function metadata()\\n external\\n view\\n returns (\\n uint256 dec0,\\n uint256 dec1,\\n uint256 r0,\\n uint256 r1,\\n bool st,\\n address t0,\\n address t1\\n )\\n {\\n return (\\n decimals0,\\n decimals1,\\n reserve0,\\n reserve1,\\n stable,\\n token0,\\n token1\\n );\\n }\\n\\n function tokens() external view returns (address, address) {\\n return (token0, token1);\\n }\\n\\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\\n _updateFor(msg.sender);\\n\\n claimed0 = claimable0[msg.sender];\\n claimed1 = claimable1[msg.sender];\\n\\n if (claimed0 > 0 || claimed1 > 0) {\\n claimable0[msg.sender] = 0;\\n claimable1[msg.sender] = 0;\\n\\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\\n\\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n // Accrue fees on token0\\n function _update0(uint256 amount) internal {\\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index0 += _ratio;\\n }\\n emit Fees(msg.sender, amount, 0);\\n }\\n\\n // Accrue fees on token1\\n function _update1(uint256 amount) internal {\\n _safeTransfer(token1, fees, amount);\\n uint256 _ratio = (amount * 1e18) / totalSupply;\\n if (_ratio > 0) {\\n index1 += _ratio;\\n }\\n emit Fees(msg.sender, 0, amount);\\n }\\n\\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\\n // Fees are segregated from core funds, so fees can never put liquidity at risk\\n function _updateFor(address recipient) internal {\\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\\n if (_supplied > 0) {\\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\\n uint256 _supplyIndex1 = supplyIndex1[recipient];\\n uint256 _index0 = index0; // get global index0 for accumulated fees\\n uint256 _index1 = index1;\\n supplyIndex0[recipient] = _index0; // update user current position to global position\\n supplyIndex1[recipient] = _index1;\\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\\n uint256 _delta1 = _index1 - _supplyIndex1;\\n if (_delta0 > 0) {\\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\\n claimable0[recipient] += _share;\\n }\\n if (_delta1 > 0) {\\n uint256 _share = (_supplied * _delta1) / 1e18;\\n claimable1[recipient] += _share;\\n }\\n } else {\\n supplyIndex0[recipient] = index0; // new users are set to the default global state\\n supplyIndex1[recipient] = index1;\\n }\\n }\\n\\n function getReserves()\\n public\\n view\\n returns (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n )\\n {\\n _reserve0 = reserve0;\\n _reserve1 = reserve1;\\n _blockTimestampLast = blockTimestampLast;\\n }\\n\\n // update reserves and, on the first call per block, price accumulators\\n function _update(\\n uint256 balance0,\\n uint256 balance1,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal {\\n uint256 blockTimestamp = block.timestamp;\\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\\n reserve0CumulativeLast += _reserve0 * timeElapsed;\\n reserve1CumulativeLast += _reserve1 * timeElapsed;\\n }\\n\\n Observation memory _point = lastObservation();\\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\\n if (timeElapsed > periodSize) {\\n observations.push(\\n Observation(\\n blockTimestamp,\\n reserve0CumulativeLast,\\n reserve1CumulativeLast\\n )\\n );\\n }\\n reserve0 = balance0;\\n reserve1 = balance1;\\n blockTimestampLast = blockTimestamp;\\n emit Sync(reserve0, reserve1);\\n }\\n\\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\\n function currentCumulativePrices()\\n public\\n view\\n returns (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n uint256 blockTimestamp\\n )\\n {\\n blockTimestamp = block.timestamp;\\n reserve0Cumulative = reserve0CumulativeLast;\\n reserve1Cumulative = reserve1CumulativeLast;\\n\\n // if time has elapsed since the last update on the pair, mock the accumulated price values\\n (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n ) = getReserves();\\n if (_blockTimestampLast != blockTimestamp) {\\n // subtraction overflow is desired\\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\\n reserve0Cumulative += _reserve0 * timeElapsed;\\n reserve1Cumulative += _reserve1 * timeElapsed;\\n }\\n }\\n\\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\\n function current(address tokenIn, uint256 amountIn)\\n external\\n view\\n returns (uint256 amountOut)\\n {\\n Observation memory _observation = lastObservation();\\n (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n\\n ) = currentCumulativePrices();\\n if (block.timestamp == _observation.timestamp) {\\n _observation = observations[observations.length - 2];\\n }\\n\\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\\n uint256 _reserve0 = (reserve0Cumulative -\\n _observation.reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (reserve1Cumulative -\\n _observation.reserve1Cumulative) / timeElapsed;\\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n // as per `current`, however allows user configured granularity, up to the full window size\\n function quote(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 granularity\\n ) external view returns (uint256 amountOut) {\\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\\n uint256 priceAverageCumulative;\\n for (uint256 i = 0; i < _prices.length; i++) {\\n priceAverageCumulative += _prices[i];\\n }\\n return priceAverageCumulative / granularity;\\n }\\n\\n // returns a memory set of twap prices\\n function prices(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points\\n ) external view returns (uint256[] memory) {\\n return sample(tokenIn, amountIn, points, 1);\\n }\\n\\n function sample(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points,\\n uint256 window\\n ) public view returns (uint256[] memory) {\\n uint256[] memory _prices = new uint256[](points);\\n\\n uint256 length = observations.length - 1;\\n uint256 i = length - (points * window);\\n uint256 nextIndex = 0;\\n uint256 index = 0;\\n\\n for (; i < length; i += window) {\\n nextIndex = i + window;\\n uint256 timeElapsed = observations[nextIndex].timestamp -\\n observations[i].timestamp;\\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\\n observations[i].reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\\n observations[i].reserve1Cumulative) / timeElapsed;\\n _prices[index] = _getAmountOut(\\n amountIn,\\n tokenIn,\\n _reserve0,\\n _reserve1\\n );\\n // index < length; length cannot overflow\\n unchecked {\\n index = index + 1;\\n }\\n }\\n return _prices;\\n }\\n\\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\\n // standard uniswap v2 implementation\\n function mint(address to) external lock returns (uint256 liquidity) {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\\n uint256 _amount0 = _balance0 - _reserve0;\\n uint256 _amount1 = _balance1 - _reserve1;\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n if (_totalSupply == 0) {\\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\\n } else {\\n liquidity = MathDunks.min(\\n (_amount0 * _totalSupply) / _reserve0,\\n (_amount1 * _totalSupply) / _reserve1\\n );\\n }\\n require(liquidity > 0, \\\"ILM\\\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\\n _mint(to, liquidity);\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Mint(msg.sender, _amount0, _amount1);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n // standard uniswap v2 implementation\\n function burn(address to)\\n external\\n lock\\n returns (uint256 amount0, uint256 amount1)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n (address _token0, address _token1) = (token0, token1);\\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\\n uint256 _liquidity = balanceOf[address(this)];\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\\n require(amount0 > 0 && amount1 > 0, \\\"ILB\\\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\\n _burn(address(this), _liquidity);\\n _safeTransfer(_token0, to, amount0);\\n _safeTransfer(_token1, to, amount1);\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Burn(msg.sender, amount0, amount1, to);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n function swap(\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address to,\\n bytes calldata data\\n ) external lock {\\n require(!PairFactory(factory).isPaused());\\n require(amount0Out > 0 || amount1Out > 0, \\\"IOA\\\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \\\"IL\\\"); // Pair: INSUFFICIENT_LIQUIDITY\\n\\n uint256 _balance0;\\n uint256 _balance1;\\n {\\n // scope for _token{0,1}, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n require(to != _token0 && to != _token1, \\\"IT\\\"); // Pair: INVALID_TO\\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\\n if (data.length > 0)\\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n }\\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\\n ? _balance0 - (_reserve0 - amount0Out)\\n : 0;\\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\\n ? _balance1 - (_reserve1 - amount1Out)\\n : 0;\\n require(amount0In > 0 || amount1In > 0, \\\"IIA\\\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\\n {\\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n if (amount0In > 0)\\n _update0(\\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token0 and move them out of pool\\n if (amount1In > 0)\\n _update1(\\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token1 and move them out of pool\\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \\\"K\\\"); // Pair: K\\n }\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\\n }\\n\\n // force balances to match reserves\\n function skim(address to) external lock {\\n (address _token0, address _token1) = (token0, token1);\\n _safeTransfer(\\n _token0,\\n to,\\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\\n );\\n _safeTransfer(\\n _token1,\\n to,\\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\\n );\\n }\\n\\n // force reserves to match balances\\n function sync() external lock {\\n _update(\\n IERC20(token0).balanceOf(address(this)),\\n IERC20(token1).balanceOf(address(this)),\\n reserve0,\\n reserve1\\n );\\n }\\n\\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\\n 1e18 +\\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\\n 1e18;\\n }\\n\\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (3 * x0 * ((y * y) / 1e18)) /\\n 1e18 +\\n ((((x0 * x0) / 1e18) * x0) / 1e18);\\n }\\n\\n function _get_y(\\n uint256 x0,\\n uint256 xy,\\n uint256 y\\n ) internal pure returns (uint256) {\\n for (uint256 i = 0; i < 255; i++) {\\n uint256 y_prev = y;\\n uint256 k = _f(x0, y);\\n if (k < xy) {\\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\\n y = y + dy;\\n } else {\\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getAmountOut(uint256 amountIn, address tokenIn)\\n external\\n view\\n returns (uint256)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n function _getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal view returns (uint256) {\\n if (stable) {\\n uint256 xy = _k(_reserve0, _reserve1);\\n _reserve0 = (_reserve0 * 1e18) / decimals0;\\n _reserve1 = (_reserve1 * 1e18) / decimals1;\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0\\n ? (amountIn * 1e18) / decimals0\\n : (amountIn * 1e18) / decimals1;\\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\\n } else {\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n return (amountIn * reserveB) / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\\n if (stable) {\\n uint256 _x = (x * 1e18) / decimals0;\\n uint256 _y = (y * 1e18) / decimals1;\\n uint256 _a = (_x * _y) / 1e18;\\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return (_a * _b) / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n\\n function _mint(address dst, uint256 amount) internal {\\n _updateFor(dst); // balances must be updated on mint/burn/transfer\\n totalSupply += amount;\\n balanceOf[dst] += amount;\\n emit Transfer(address(0), dst, amount);\\n }\\n\\n function _burn(address dst, uint256 amount) internal {\\n _updateFor(dst);\\n totalSupply -= amount;\\n balanceOf[dst] -= amount;\\n emit Transfer(dst, address(0), amount);\\n }\\n\\n function approve(address spender, uint256 amount) external returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external {\\n require(deadline >= block.timestamp, \\\"Pair: EXPIRED\\\");\\n DOMAIN_SEPARATOR = keccak256(\\n abi.encode(\\n keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n ),\\n keccak256(bytes(name)),\\n keccak256(bytes(\\\"1\\\")),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR,\\n keccak256(\\n abi.encode(\\n PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n );\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n require(\\n recoveredAddress != address(0) && recoveredAddress == owner,\\n \\\"Pair: INVALID_SIGNATURE\\\"\\n );\\n allowance[owner][spender] = value;\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function transfer(address dst, uint256 amount) external returns (bool) {\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 amount\\n ) external returns (bool) {\\n address spender = msg.sender;\\n uint256 spenderAllowance = allowance[src][spender];\\n\\n if (spender != src && spenderAllowance != type(uint256).max) {\\n uint256 newAllowance = spenderAllowance - amount;\\n allowance[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n function _transferTokens(\\n address src,\\n address dst,\\n uint256 amount\\n ) internal {\\n _updateFor(src); // update fee position for src\\n _updateFor(dst); // update fee position for dst\\n\\n balanceOf[src] -= amount;\\n balanceOf[dst] += amount;\\n\\n emit Transfer(src, dst, amount);\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x4f508747645f4480e0b0f23d952fa9b82af1d9bc60b15b8cd1f542ee136043d1\",\"license\":\"MIT\"},\"contracts/PairFees.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IERC20.sol';\\n\\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\\ncontract PairFees {\\n\\n address internal immutable pair; // The pair it is bonded to\\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\\n\\n constructor(address _token0, address _token1) {\\n pair = msg.sender;\\n token0 = _token0;\\n token1 = _token1;\\n }\\n\\n function _safeTransfer(address token,address to,uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n // Allow the pair to transfer fees to users\\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\\n require(msg.sender == pair);\\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\\n }\\n\\n}\\n\",\"keccak256\":\"0xb772e192bab353f8642e89a95ef4ef0255d1caef08444101d7fe34469c1000ca\",\"license\":\"MIT\"},\"contracts/factories/PairFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/Pair.sol';\\n\\ncontract PairFactory is IPairFactory {\\n\\n bool public isPaused;\\n address public pauser;\\n address public pendingPauser;\\n\\n uint256 public stableFee;\\n uint256 public volatileFee;\\n uint256 public constant MAX_FEE = 5; // 0.05%\\n address public feeManager;\\n address public pendingFeeManager;\\n\\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\\n address[] public allPairs;\\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\\n\\n address internal _temp0;\\n address internal _temp1;\\n bool internal _temp;\\n\\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\\n\\n constructor() {\\n pauser = msg.sender;\\n isPaused = false;\\n feeManager = msg.sender;\\n stableFee = 2; // 0.02%\\n volatileFee = 2;\\n }\\n\\n function allPairsLength() external view returns (uint) {\\n return allPairs.length;\\n }\\n\\n function setPauser(address _pauser) external {\\n require(msg.sender == pauser);\\n pendingPauser = _pauser;\\n }\\n\\n function acceptPauser() external {\\n require(msg.sender == pendingPauser);\\n pauser = pendingPauser;\\n }\\n\\n function setPause(bool _state) external {\\n require(msg.sender == pauser);\\n isPaused = _state;\\n }\\n\\n function setFeeManager(address _feeManager) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n pendingFeeManager = _feeManager;\\n }\\n\\n function acceptFeeManager() external {\\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\\n feeManager = pendingFeeManager;\\n }\\n\\n function setFee(bool _stable, uint256 _fee) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n require(_fee <= MAX_FEE, 'fee too high');\\n require(_fee != 0, 'fee must be nonzero');\\n if (_stable) {\\n stableFee = _fee;\\n } else {\\n volatileFee = _fee;\\n }\\n }\\n\\n function getFee(bool _stable) public view returns(uint256) {\\n return _stable ? stableFee : volatileFee;\\n }\\n\\n function pairCodeHash() external pure returns (bytes32) {\\n return keccak256(type(Pair).creationCode);\\n }\\n\\n function getInitializable() external view returns (address, address, bool) {\\n return (_temp0, _temp1, _temp);\\n }\\n\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\\n (_temp0, _temp1, _temp) = (token0, token1, stable);\\n pair = address(new Pair{salt:salt}());\\n getPair[token0][token1][stable] = pair;\\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\\n allPairs.push(pair);\\n isPair[pair] = true;\\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\\n }\\n}\\n\",\"keccak256\":\"0x9b7984117a5a32188aa9ddf42b6cff024240579ab30f3776f7a201285d813e4f\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairCallee.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairCallee {\\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x3ac2de2c7a08bf59fd1006e4d108b247916369de15fbd048b72ca2b7814023ca\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50600080546001600160a81b03191633610100810260ff1916919091178255600480546001600160a01b0319169091179055600280805560035561519190819061005a90396000f3fe60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea2646970667358221220a6c1c49d2a02bc4a24e84a9e991bd58346313938bf594eb65d535709e7b46ac764736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea264697066735822122087f6444299d02580bffcb97ca1adfcbaae5d5dcd5007567b6722534a74b6bd3f64736f6c634300080d0033a2646970667358221220f93a0275ff0f5bd6a16554956d45f62614b3d89703e3c9d92f48df4c3d70a4b964736f6c634300080d0033", + "deployedBytecode": "0x60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea2646970667358221220a6c1c49d2a02bc4a24e84a9e991bd58346313938bf594eb65d535709e7b46ac764736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea264697066735822122087f6444299d02580bffcb97ca1adfcbaae5d5dcd5007567b6722534a74b6bd3f64736f6c634300080d0033a2646970667358221220f93a0275ff0f5bd6a16554956d45f62614b3d89703e3c9d92f48df4c3d70a4b964736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/RedemptionReceiver.json b/deployments/arbitrumGoerli/RedemptionReceiver.json index 4ca87de2..da744b76 100644 --- a/deployments/arbitrumGoerli/RedemptionReceiver.json +++ b/deployments/arbitrumGoerli/RedemptionReceiver.json @@ -1,5 +1,5 @@ { - "address": "0x7eEE2ED1bD98dd7e103518405933D56Dac2bC9Df", + "address": "0x52018E83E84ebe30ac6923F3747c7aE503923aaB", "abi": [ { "inputs": [ @@ -323,33 +323,33 @@ "type": "function" } ], - "transactionHash": "0x5b13661a7eabb59a780cf3f170d0dc5df51bcbb00337ea5d5992e1b34f7eb04c", + "transactionHash": "0xb92890feb62248533088d4adc0e25235f6ff55e33118157ec87b5f5273eaec09", "receipt": { "to": null, - "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0x7eEE2ED1bD98dd7e103518405933D56Dac2bC9Df", + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x52018E83E84ebe30ac6923F3747c7aE503923aaB", "transactionIndex": 1, - "gasUsed": "19122626", + "gasUsed": "878312", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xa5d1535c5893b986eeff581358eeb5a846f43dbf1ebd4f344b90d3327c83f1b2", - "transactionHash": "0x5b13661a7eabb59a780cf3f170d0dc5df51bcbb00337ea5d5992e1b34f7eb04c", + "blockHash": "0x3e266eb2e4f8dffba63778f5c9dd4db42d5da8660e567116b6ed09c3fa43333c", + "transactionHash": "0xb92890feb62248533088d4adc0e25235f6ff55e33118157ec87b5f5273eaec09", "logs": [], - "blockNumber": 4263703, - "cumulativeGasUsed": "19122626", + "blockNumber": 4455899, + "cumulativeGasUsed": "878312", "status": 1, "byzantium": true }, "args": [ - "0x7F5c764cBc14f9669B88837ca1490cCa17c31607", - "0x162404E6Cd4633656925b90EF67237F29D5cc85c", + "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8", + "0x84Ca387E7ede764A3284c67Ff8c68a305a9030a0", 10012, "0x3c2269811836af69497E5F486A85D7316753cf62" ], - "numDeployments": 5, - "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_usdc\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_velo\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"_fantomChainId\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"_endpoint\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fantomSender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableUSDC\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableVELO\",\"type\":\"uint256\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ELIGIBLE_WEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"USDC\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VELO\",\"outputs\":[{\"internalType\":\"contract IVelo\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"toAddressBytes\",\"type\":\"bytes\"}],\"name\":\"addressFromPackedBytes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimLeftovers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endpoint\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomChainId\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_fantomSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableVELO\",\"type\":\"uint256\"}],\"name\":\"initializeReceiverWith\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"leftoverVELO\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"srcChainId\",\"type\":\"uint16\"},{\"internalType\":\"bytes\",\"name\":\"srcAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"lzReceive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountWEVE\",\"type\":\"uint256\"}],\"name\":\"previewRedeem\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"shareOfUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shareOfVELO\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableUSDC\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableVELO\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemedWEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process This contract is responsible for receiving the LZ message and distributing USDC + VELO\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/RedemptionReceiver.sol\":\"RedemptionReceiver\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"},\"contracts/redeem/RedemptionReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\\\";\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IVelo.sol\\\";\\n\\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\\ncontract RedemptionReceiver is ILayerZeroReceiver {\\n IERC20 public immutable USDC;\\n IVelo public immutable VELO;\\n\\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\\n address public immutable endpoint;\\n\\n address public team;\\n uint256 public immutable deployed;\\n\\n address public fantomSender;\\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\\n uint256 public redeemedWEVE;\\n uint256 public redeemableUSDC;\\n uint256 public redeemableVELO;\\n uint256 public leftoverVELO;\\n\\n constructor(\\n address _usdc,\\n address _velo,\\n uint16 _fantomChainId,\\n address _endpoint\\n ) {\\n require(_fantomChainId == 12 || _fantomChainId == 10012, \\\"CHAIN_ID_NOT_FTM\\\");\\n\\n USDC = IERC20(_usdc);\\n VELO = IVelo(_velo);\\n\\n fantomChainId = _fantomChainId;\\n endpoint = _endpoint;\\n\\n team = msg.sender;\\n deployed = block.timestamp;\\n }\\n\\n modifier onlyTeam() {\\n require(msg.sender == team, \\\"ONLY_TEAM\\\");\\n _;\\n }\\n\\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\\n\\n function initializeReceiverWith(\\n address _fantomSender,\\n uint256 _redeemableUSDC,\\n uint256 _redeemableVELO\\n ) external onlyTeam {\\n require(fantomSender == address(0), \\\"ALREADY_INITIALIZED\\\");\\n require(\\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n fantomSender = _fantomSender;\\n redeemableUSDC = _redeemableUSDC;\\n redeemableVELO = _redeemableVELO;\\n leftoverVELO = _redeemableVELO;\\n\\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\\n }\\n\\n function setTeam(address _team) external onlyTeam {\\n team = _team;\\n }\\n\\n function previewRedeem(uint256 amountWEVE)\\n public\\n view\\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\\n {\\n // pro rata USDC\\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\\n // pro rata VELO\\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\\n }\\n\\n function lzReceive(\\n uint16 srcChainId,\\n bytes memory srcAddress,\\n uint64,\\n bytes memory payload\\n ) external override {\\n require(fantomSender != address(0), \\\"NOT_INITIALIZED\\\");\\n require(\\n msg.sender == endpoint &&\\n srcChainId == fantomChainId &&\\n addressFromPackedBytes(srcAddress) == fantomSender,\\n \\\"UNAUTHORIZED_CALLER\\\"\\n );\\n\\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\\n payload,\\n (address, uint256)\\n );\\n\\n require(\\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\\n \\\"cannot redeem more than eligible\\\"\\n );\\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\\n\\n require(\\n USDC.transfer(redemptionAddress, shareOfUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n leftoverVELO -= shareOfVELO; // this will revert if underflows\\n require(\\n VELO.claim(redemptionAddress, shareOfVELO),\\n \\\"CLAIM_FAILED\\\"\\n );\\n }\\n\\n function addressFromPackedBytes(bytes memory toAddressBytes)\\n public\\n pure\\n returns (address toAddress)\\n {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n toAddress := mload(add(toAddressBytes, 20))\\n }\\n }\\n\\n function claimLeftovers() external onlyTeam {\\n require(block.timestamp >= deployed + 30 days, \\\"LEFTOVERS_NOT_CLAIMABLE\\\");\\n require(\\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n }\\n}\\n\",\"keccak256\":\"0xb5c76f083e5076206e2713b64eed8bfc782715c19f6993ac8e97b1db898ae304\",\"license\":\"MIT\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\nimport \\\"./ILayerZeroUserApplicationConfig.sol\\\";\\n\\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\\n // @param _dstChainId - the destination chain identifier\\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\\n // @param _payload - a custom bytes payload to send to the destination contract\\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\\n\\n // @notice used by the messaging library to publish verified payload\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source contract (as bytes) at the source chain\\n // @param _dstAddress - the address on destination chain\\n // @param _nonce - the unbound message ordering nonce\\n // @param _gasLimit - the gas limit for external contract execution\\n // @param _payload - verified payload to send to the destination contract\\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\\n\\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\\n\\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\\n // @param _srcAddress - the source chain contract address\\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\\n\\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\\n // @param _dstChainId - the destination chain identifier\\n // @param _userApplication - the user app address on this EVM chain\\n // @param _payload - the custom message to send over LayerZero\\n // @param _payInZRO - if false, user app pays the protocol fee in native token\\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\\n\\n // @notice get this Endpoint's immutable source identifier\\n function getChainId() external view returns (uint16);\\n\\n // @notice the interface to retry failed message on this Endpoint destination\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n // @param _payload - the payload to be retried\\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\\n\\n // @notice query if any STORED payload (message blocking) at the endpoint.\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\\n\\n // @notice query if the _libraryAddress is valid for sending msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getSendLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the _libraryAddress is valid for receiving msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the non-reentrancy guard for send() is on\\n // @return true if the guard is on. false otherwise\\n function isSendingPayload() external view returns (bool);\\n\\n // @notice query if the non-reentrancy guard for receive() is on\\n // @return true if the guard is on. false otherwise\\n function isReceivingPayload() external view returns (bool);\\n\\n // @notice get the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _userApplication - the contract address of the user application\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\\n\\n // @notice get the send() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getSendVersion(address _userApplication) external view returns (uint16);\\n\\n // @notice get the lzReceive() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getReceiveVersion(address _userApplication) external view returns (uint16);\\n}\\n\",\"keccak256\":\"0xbc2e0022d4d53d136830aa90037be2ed7a0966f5fd1b409bf5986185984c495f\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroReceiver {\\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\\n // @param _srcChainId - the source endpoint identifier\\n // @param _srcAddress - the source sending contract address from the source chain\\n // @param _nonce - the ordered message nonce\\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\\n}\\n\",\"keccak256\":\"0xd1617e455d90d41556bba636bc440627d301ec481de16ff04fbd520333c3c6f3\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroUserApplicationConfig {\\n // @notice set the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n // @param _config - configuration in the bytes. can encode arbitrary content.\\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\\n\\n // @notice set the send() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setSendVersion(uint16 _version) external;\\n\\n // @notice set the lzReceive() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setReceiveVersion(uint16 _version) external;\\n\\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\\n // @param _srcChainId - the chainId of the source chain\\n // @param _srcAddress - the contract address of the source contract at the source chain\\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\\n}\\n\",\"keccak256\":\"0xdc7e072cf3064081a8edf4a286ca43ddecc24330f2923d96f416f9d3f6538447\",\"license\":\"BUSL-1.1\"}},\"version\":1}", - "bytecode": "0x61012060405234801561001157600080fd5b50604051610f81380380610f81833981016040819052610030916100e2565b8161ffff16600c148061004857508161ffff1661271c145b61008b5760405162461bcd60e51b815260206004820152601060248201526f434841494e5f49445f4e4f545f46544d60801b604482015260640160405180910390fd5b6001600160a01b0393841660805291831660a05261ffff1660c0521660e052600080546001600160a01b03191633179055426101005261013f565b80516001600160a01b03811681146100dd57600080fd5b919050565b600080600080608085870312156100f857600080fd5b610101856100c6565b935061010f602086016100c6565b9250604085015161ffff8116811461012657600080fd5b9150610134606086016100c6565b905092959194509250565b60805160a05160c05160e05161010051610dcd6101b4600039600081816102d601526108c00152600081816101940152610352015260008181610245015261037c01526000818161027f015261059f01526000818161021e015281816104d70152818161078e015261094c0152610dcd6000f3fe608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a0eeb39a11610071578063a0eeb39a1461027a578063a408bb4c146102a1578063aaa8f2ef146102a9578063b8ea6281146102bc578063f905c15a146102d157600080fd5b80636bfd23a7146101fd57806385f2aef21461020657806389a3027114610219578063997a03b71461024057600080fd5b80634cdad506116100e95780634cdad506146101675780635e280f111461018f57806363b4eb8d146101ce57806368ecc6bc146101e15780636ac55083146101f457600080fd5b80621d35671461011a578063095cf5c61461012f578063221798ad1461014257806347db1a6a1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60045481565b6040519081526020015b60405180910390f35b61014b60035481565b61017a610175366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b6001546101b6906001600160a01b031681565b61012d6101ef366004610be5565b6106f3565b61014b60055481565b61014b60025481565b6000546101b6906001600160a01b031681565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6102677f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101b66102ca366004610c1a565b6014015190565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea2646970667358221220fcc08a51d0a33b24a91a401bba0a9c91bdb72b806b020a47a1060a734e9c381764736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a0eeb39a11610071578063a0eeb39a1461027a578063a408bb4c146102a1578063aaa8f2ef146102a9578063b8ea6281146102bc578063f905c15a146102d157600080fd5b80636bfd23a7146101fd57806385f2aef21461020657806389a3027114610219578063997a03b71461024057600080fd5b80634cdad506116100e95780634cdad506146101675780635e280f111461018f57806363b4eb8d146101ce57806368ecc6bc146101e15780636ac55083146101f457600080fd5b80621d35671461011a578063095cf5c61461012f578063221798ad1461014257806347db1a6a1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60045481565b6040519081526020015b60405180910390f35b61014b60035481565b61017a610175366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b6001546101b6906001600160a01b031681565b61012d6101ef366004610be5565b6106f3565b61014b60055481565b61014b60025481565b6000546101b6906001600160a01b031681565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6102677f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101b66102ca366004610c1a565b6014015190565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea2646970667358221220fcc08a51d0a33b24a91a401bba0a9c91bdb72b806b020a47a1060a734e9c381764736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_usdc\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_velo\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"_fantomChainId\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"_endpoint\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fantomSender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableUSDC\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableVELO\",\"type\":\"uint256\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ELIGIBLE_WEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"USDC\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VELO\",\"outputs\":[{\"internalType\":\"contract IVelo\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"toAddressBytes\",\"type\":\"bytes\"}],\"name\":\"addressFromPackedBytes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimLeftovers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endpoint\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomChainId\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_fantomSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableVELO\",\"type\":\"uint256\"}],\"name\":\"initializeReceiverWith\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"leftoverVELO\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"srcChainId\",\"type\":\"uint16\"},{\"internalType\":\"bytes\",\"name\":\"srcAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"lzReceive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountWEVE\",\"type\":\"uint256\"}],\"name\":\"previewRedeem\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"shareOfUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shareOfVELO\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableUSDC\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableVELO\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemedWEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process This contract is responsible for receiving the LZ message and distributing USDC + VELO\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/RedemptionReceiver.sol\":\"RedemptionReceiver\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"},\"contracts/redeem/RedemptionReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\\\";\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IVelo.sol\\\";\\n\\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\\ncontract RedemptionReceiver is ILayerZeroReceiver {\\n IERC20 public immutable USDC;\\n IVelo public immutable VELO;\\n\\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\\n address public immutable endpoint;\\n\\n address public team;\\n uint256 public immutable deployed;\\n\\n address public fantomSender;\\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\\n uint256 public redeemedWEVE;\\n uint256 public redeemableUSDC;\\n uint256 public redeemableVELO;\\n uint256 public leftoverVELO;\\n\\n constructor(\\n address _usdc,\\n address _velo,\\n uint16 _fantomChainId,\\n address _endpoint\\n ) {\\n require(_fantomChainId == 12 || _fantomChainId == 10012, \\\"CHAIN_ID_NOT_FTM\\\");\\n\\n USDC = IERC20(_usdc);\\n VELO = IVelo(_velo);\\n\\n fantomChainId = _fantomChainId;\\n endpoint = _endpoint;\\n\\n team = msg.sender;\\n deployed = block.timestamp;\\n }\\n\\n modifier onlyTeam() {\\n require(msg.sender == team, \\\"ONLY_TEAM\\\");\\n _;\\n }\\n\\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\\n\\n function initializeReceiverWith(\\n address _fantomSender,\\n uint256 _redeemableUSDC,\\n uint256 _redeemableVELO\\n ) external onlyTeam {\\n require(fantomSender == address(0), \\\"ALREADY_INITIALIZED\\\");\\n require(\\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n fantomSender = _fantomSender;\\n redeemableUSDC = _redeemableUSDC;\\n redeemableVELO = _redeemableVELO;\\n leftoverVELO = _redeemableVELO;\\n\\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\\n }\\n\\n function setTeam(address _team) external onlyTeam {\\n team = _team;\\n }\\n\\n function previewRedeem(uint256 amountWEVE)\\n public\\n view\\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\\n {\\n // pro rata USDC\\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\\n // pro rata VELO\\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\\n }\\n\\n function lzReceive(\\n uint16 srcChainId,\\n bytes memory srcAddress,\\n uint64,\\n bytes memory payload\\n ) external override {\\n require(fantomSender != address(0), \\\"NOT_INITIALIZED\\\");\\n require(\\n msg.sender == endpoint &&\\n srcChainId == fantomChainId &&\\n addressFromPackedBytes(srcAddress) == fantomSender,\\n \\\"UNAUTHORIZED_CALLER\\\"\\n );\\n\\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\\n payload,\\n (address, uint256)\\n );\\n\\n require(\\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\\n \\\"cannot redeem more than eligible\\\"\\n );\\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\\n\\n require(\\n USDC.transfer(redemptionAddress, shareOfUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n leftoverVELO -= shareOfVELO; // this will revert if underflows\\n require(\\n VELO.claim(redemptionAddress, shareOfVELO),\\n \\\"CLAIM_FAILED\\\"\\n );\\n }\\n\\n function addressFromPackedBytes(bytes memory toAddressBytes)\\n public\\n pure\\n returns (address toAddress)\\n {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n toAddress := mload(add(toAddressBytes, 20))\\n }\\n }\\n\\n function claimLeftovers() external onlyTeam {\\n require(block.timestamp >= deployed + 30 days, \\\"LEFTOVERS_NOT_CLAIMABLE\\\");\\n require(\\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n }\\n}\\n\",\"keccak256\":\"0xb5c76f083e5076206e2713b64eed8bfc782715c19f6993ac8e97b1db898ae304\",\"license\":\"MIT\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\nimport \\\"./ILayerZeroUserApplicationConfig.sol\\\";\\n\\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\\n // @param _dstChainId - the destination chain identifier\\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\\n // @param _payload - a custom bytes payload to send to the destination contract\\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\\n\\n // @notice used by the messaging library to publish verified payload\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source contract (as bytes) at the source chain\\n // @param _dstAddress - the address on destination chain\\n // @param _nonce - the unbound message ordering nonce\\n // @param _gasLimit - the gas limit for external contract execution\\n // @param _payload - verified payload to send to the destination contract\\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\\n\\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\\n\\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\\n // @param _srcAddress - the source chain contract address\\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\\n\\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\\n // @param _dstChainId - the destination chain identifier\\n // @param _userApplication - the user app address on this EVM chain\\n // @param _payload - the custom message to send over LayerZero\\n // @param _payInZRO - if false, user app pays the protocol fee in native token\\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\\n\\n // @notice get this Endpoint's immutable source identifier\\n function getChainId() external view returns (uint16);\\n\\n // @notice the interface to retry failed message on this Endpoint destination\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n // @param _payload - the payload to be retried\\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\\n\\n // @notice query if any STORED payload (message blocking) at the endpoint.\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\\n\\n // @notice query if the _libraryAddress is valid for sending msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getSendLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the _libraryAddress is valid for receiving msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the non-reentrancy guard for send() is on\\n // @return true if the guard is on. false otherwise\\n function isSendingPayload() external view returns (bool);\\n\\n // @notice query if the non-reentrancy guard for receive() is on\\n // @return true if the guard is on. false otherwise\\n function isReceivingPayload() external view returns (bool);\\n\\n // @notice get the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _userApplication - the contract address of the user application\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\\n\\n // @notice get the send() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getSendVersion(address _userApplication) external view returns (uint16);\\n\\n // @notice get the lzReceive() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getReceiveVersion(address _userApplication) external view returns (uint16);\\n}\\n\",\"keccak256\":\"0xbc2e0022d4d53d136830aa90037be2ed7a0966f5fd1b409bf5986185984c495f\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroReceiver {\\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\\n // @param _srcChainId - the source endpoint identifier\\n // @param _srcAddress - the source sending contract address from the source chain\\n // @param _nonce - the ordered message nonce\\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\\n}\\n\",\"keccak256\":\"0xd1617e455d90d41556bba636bc440627d301ec481de16ff04fbd520333c3c6f3\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroUserApplicationConfig {\\n // @notice set the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n // @param _config - configuration in the bytes. can encode arbitrary content.\\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\\n\\n // @notice set the send() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setSendVersion(uint16 _version) external;\\n\\n // @notice set the lzReceive() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setReceiveVersion(uint16 _version) external;\\n\\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\\n // @param _srcChainId - the chainId of the source chain\\n // @param _srcAddress - the contract address of the source contract at the source chain\\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\\n}\\n\",\"keccak256\":\"0xdc7e072cf3064081a8edf4a286ca43ddecc24330f2923d96f416f9d3f6538447\",\"license\":\"BUSL-1.1\"}},\"version\":1}", + "bytecode": "0x61012060405234801561001157600080fd5b50604051610f81380380610f81833981016040819052610030916100e2565b8161ffff16600c148061004857508161ffff1661271c145b61008b5760405162461bcd60e51b815260206004820152601060248201526f434841494e5f49445f4e4f545f46544d60801b604482015260640160405180910390fd5b6001600160a01b0393841660805291831660a05261ffff1660c0521660e052600080546001600160a01b03191633179055426101005261013f565b80516001600160a01b03811681146100dd57600080fd5b919050565b600080600080608085870312156100f857600080fd5b610101856100c6565b935061010f602086016100c6565b9250604085015161ffff8116811461012657600080fd5b9150610134606086016100c6565b905092959194509250565b60805160a05160c05160e05161010051610dcd6101b4600039600081816102d601526108c00152600081816101940152610352015260008181610245015261037c01526000818161027f015261059f01526000818161021e015281816104d70152818161078e015261094c0152610dcd6000f3fe608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a0eeb39a11610071578063a0eeb39a1461027a578063a408bb4c146102a1578063aaa8f2ef146102a9578063b8ea6281146102bc578063f905c15a146102d157600080fd5b80636bfd23a7146101fd57806385f2aef21461020657806389a3027114610219578063997a03b71461024057600080fd5b80634cdad506116100e95780634cdad506146101675780635e280f111461018f57806363b4eb8d146101ce57806368ecc6bc146101e15780636ac55083146101f457600080fd5b80621d35671461011a578063095cf5c61461012f578063221798ad1461014257806347db1a6a1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60045481565b6040519081526020015b60405180910390f35b61014b60035481565b61017a610175366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b6001546101b6906001600160a01b031681565b61012d6101ef366004610be5565b6106f3565b61014b60055481565b61014b60025481565b6000546101b6906001600160a01b031681565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6102677f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101b66102ca366004610c1a565b6014015190565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea2646970667358221220b598fc2bd4de791cc9775861ae06595f700bc013f87600fbf2bdb67f21fed1a764736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a0eeb39a11610071578063a0eeb39a1461027a578063a408bb4c146102a1578063aaa8f2ef146102a9578063b8ea6281146102bc578063f905c15a146102d157600080fd5b80636bfd23a7146101fd57806385f2aef21461020657806389a3027114610219578063997a03b71461024057600080fd5b80634cdad506116100e95780634cdad506146101675780635e280f111461018f57806363b4eb8d146101ce57806368ecc6bc146101e15780636ac55083146101f457600080fd5b80621d35671461011a578063095cf5c61461012f578063221798ad1461014257806347db1a6a1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60045481565b6040519081526020015b60405180910390f35b61014b60035481565b61017a610175366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b6001546101b6906001600160a01b031681565b61012d6101ef366004610be5565b6106f3565b61014b60055481565b61014b60025481565b6000546101b6906001600160a01b031681565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6102677f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101b66102ca366004610c1a565b6014015190565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea2646970667358221220b598fc2bd4de791cc9775861ae06595f700bc013f87600fbf2bdb67f21fed1a764736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/RewardsDistributor.json b/deployments/arbitrumGoerli/RewardsDistributor.json index 89708c15..b4112b3c 100644 --- a/deployments/arbitrumGoerli/RewardsDistributor.json +++ b/deployments/arbitrumGoerli/RewardsDistributor.json @@ -1,5 +1,5 @@ { - "address": "0x3B2233FA015D316fdf6e79373470AD59672Ed3BD", + "address": "0xc4b9295487B4C43C1929299076820D8f55BBf957", "abi": [ { "inputs": [ @@ -351,45 +351,45 @@ "type": "function" } ], - "transactionHash": "0x9d4fd2cfacaeb19936c3000747a9d30a0be6a6b1764d1262f3c38cca4cc0cde6", + "transactionHash": "0x3da7f01a909390d938a1b55c6711edc4e51b5b5d3759e23a79db10a86ccc298f", "receipt": { "to": null, - "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0x3B2233FA015D316fdf6e79373470AD59672Ed3BD", + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0xc4b9295487B4C43C1929299076820D8f55BBf957", "transactionIndex": 1, - "gasUsed": "29355647", - "logsBloom": "0x00000000000000000000000000000000000000000000100800000000000000000000000000000000000000000000000000000000000000000000000000200000001000000000500000000000000000000000000000200000000000000000000000000000008000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x5b24f00319d65e48ac2a06fac0b683d601d48c7d933fcd1eb3577bbe08bcd62f", - "transactionHash": "0x9d4fd2cfacaeb19936c3000747a9d30a0be6a6b1764d1262f3c38cca4cc0cde6", + "gasUsed": "1676854", + "logsBloom": "0x00000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000002000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020001000000008000000000000000000008000000000000000000000200000000000000000000000000000000000000000002000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x533fb1fbc52cac7b9ef364882a21aacb70fa93316760ea3f3c347796628e89e5", + "transactionHash": "0x3da7f01a909390d938a1b55c6711edc4e51b5b5d3759e23a79db10a86ccc298f", "logs": [ { "transactionIndex": 1, - "blockNumber": 4263691, - "transactionHash": "0x9d4fd2cfacaeb19936c3000747a9d30a0be6a6b1764d1262f3c38cca4cc0cde6", - "address": "0x162404E6Cd4633656925b90EF67237F29D5cc85c", + "blockNumber": 4455886, + "transactionHash": "0x3da7f01a909390d938a1b55c6711edc4e51b5b5d3759e23a79db10a86ccc298f", + "address": "0x84Ca387E7ede764A3284c67Ff8c68a305a9030a0", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x0000000000000000000000003b2233fa015d316fdf6e79373470ad59672ed3bd", - "0x000000000000000000000000cdaf5f01849fff0a9e36d768b2ae7354a98360c0" + "0x000000000000000000000000c4b9295487b4c43c1929299076820d8f55bbf957", + "0x000000000000000000000000bf05364d6cf1586852c18c6b1cbee218e3e09885" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "logIndex": 0, - "blockHash": "0x5b24f00319d65e48ac2a06fac0b683d601d48c7d933fcd1eb3577bbe08bcd62f" + "blockHash": "0x533fb1fbc52cac7b9ef364882a21aacb70fa93316760ea3f3c347796628e89e5" } ], - "blockNumber": 4263691, - "cumulativeGasUsed": "29355647", + "blockNumber": 4455886, + "cumulativeGasUsed": "1676854", "status": 1, "byzantium": true }, "args": [ - "0xCDAF5f01849Fff0a9E36D768B2ae7354A98360c0" + "0xBf05364D6cf1586852c18c6b1CbEe218E3e09885" ], - "numDeployments": 7, - "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voting_escrow\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"time\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"CheckpointToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"claim_epoch\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"max_epoch\",\"type\":\"uint256\"}],\"name\":\"Claimed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"checkpoint_token\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint_total_supply\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"_tokenIds\",\"type\":\"uint256[]\"}],\"name\":\"claim_many\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_token_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"}],\"name\":\"setDepositor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"start_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"time_cursor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"time_cursor_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token_last_balance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"tokens_per_week\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_epoch_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"ve_for_at\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ve_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voting_escrow\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RewardsDistributor.sol\":\"RewardsDistributor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/*\\n\\n@title Curve Fee Distribution modified for ve(3,3) emissions\\n@author Curve Finance, andrecronje\\n@license MIT\\n\\n*/\\n\\ncontract RewardsDistributor is IRewardsDistributor {\\n event CheckpointToken(uint256 time, uint256 tokens);\\n\\n event Claimed(\\n uint256 tokenId,\\n uint256 amount,\\n uint256 claim_epoch,\\n uint256 max_epoch\\n );\\n\\n uint256 constant WEEK = 7 * 86400;\\n\\n uint256 public start_time;\\n uint256 public time_cursor;\\n mapping(uint256 => uint256) public time_cursor_of;\\n mapping(uint256 => uint256) public user_epoch_of;\\n\\n uint256 public last_token_time;\\n uint256[1000000000000000] public tokens_per_week;\\n\\n address public voting_escrow;\\n address public token;\\n uint256 public token_last_balance;\\n\\n uint256[1000000000000000] public ve_supply;\\n\\n address public depositor;\\n\\n constructor(address _voting_escrow) {\\n uint256 _t = (block.timestamp / WEEK) * WEEK;\\n start_time = _t;\\n last_token_time = _t;\\n time_cursor = _t;\\n address _token = IVotingEscrow(_voting_escrow).token();\\n token = _token;\\n voting_escrow = _voting_escrow;\\n depositor = msg.sender;\\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\\n }\\n\\n function timestamp() external view returns (uint256) {\\n return (block.timestamp / WEEK) * WEEK;\\n }\\n\\n function _checkpoint_token() internal {\\n uint256 token_balance = IERC20(token).balanceOf(address(this));\\n uint256 to_distribute = token_balance - token_last_balance;\\n token_last_balance = token_balance;\\n\\n uint256 t = last_token_time;\\n uint256 since_last = block.timestamp - t;\\n last_token_time = block.timestamp;\\n uint256 this_week = (t / WEEK) * WEEK;\\n uint256 next_week = 0;\\n\\n for (uint256 i = 0; i < 20; i++) {\\n next_week = this_week + WEEK;\\n if (block.timestamp < next_week) {\\n if (since_last == 0 && block.timestamp == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (block.timestamp - t)) /\\n since_last;\\n }\\n break;\\n } else {\\n if (since_last == 0 && next_week == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (next_week - t)) /\\n since_last;\\n }\\n }\\n t = next_week;\\n this_week = next_week;\\n }\\n emit CheckpointToken(block.timestamp, to_distribute);\\n }\\n\\n function checkpoint_token() external {\\n assert(msg.sender == depositor);\\n _checkpoint_token();\\n }\\n\\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\\n internal\\n view\\n returns (uint256)\\n {\\n uint256 _min = 0;\\n uint256 _max = IVotingEscrow(ve).epoch();\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n _mid\\n );\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function _find_timestamp_user_epoch(\\n address ve,\\n uint256 tokenId,\\n uint256 _timestamp,\\n uint256 max_user_epoch\\n ) internal view returns (uint256) {\\n uint256 _min = 0;\\n uint256 _max = max_user_epoch;\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\\n .user_point_history(tokenId, _mid);\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\\n external\\n view\\n returns (uint256)\\n {\\n address ve = voting_escrow;\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _timestamp,\\n max_user_epoch\\n );\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n epoch\\n );\\n return\\n MathDunks.max(\\n uint256(\\n int256(\\n pt.bias -\\n pt.slope *\\n (int128(int256(_timestamp - pt.ts)))\\n )\\n ),\\n 0\\n );\\n }\\n\\n function _checkpoint_total_supply() internal {\\n address ve = voting_escrow;\\n uint256 t = time_cursor;\\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\\n IVotingEscrow(ve).checkpoint();\\n\\n for (uint256 i = 0; i < 20; i++) {\\n if (t > rounded_timestamp) {\\n break;\\n } else {\\n uint256 epoch = _find_timestamp_epoch(ve, t);\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n epoch\\n );\\n int128 dt = 0;\\n if (t > pt.ts) {\\n dt = int128(int256(t - pt.ts));\\n }\\n ve_supply[t] = MathDunks.max(\\n uint256(int256(pt.bias - pt.slope * dt)),\\n 0\\n );\\n }\\n t += WEEK;\\n }\\n time_cursor = t;\\n }\\n\\n function checkpoint_total_supply() external {\\n _checkpoint_total_supply();\\n }\\n\\n function _claim(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\\n user_epoch_of[_tokenId] = user_epoch;\\n time_cursor_of[_tokenId] = week_cursor;\\n\\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\\n\\n return to_distribute;\\n }\\n\\n function _claimable(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal view returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n return to_distribute;\\n }\\n\\n function claimable(uint256 _tokenId) external view returns (uint256) {\\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\\n return _claimable(_tokenId, voting_escrow, _last_token_time);\\n }\\n\\n function claim(uint256 _tokenId) external returns (uint256) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\\n token_last_balance -= amount;\\n }\\n return amount;\\n }\\n\\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n address _voting_escrow = voting_escrow;\\n uint256 total = 0;\\n\\n for (uint256 i = 0; i < _tokenIds.length; i++) {\\n uint256 _tokenId = _tokenIds[i];\\n if (_tokenId == 0) break;\\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\\n total += amount;\\n }\\n }\\n if (total != 0) {\\n token_last_balance -= total;\\n }\\n\\n return true;\\n }\\n\\n // Once off event on contract initialize\\n function setDepositor(address _depositor) external {\\n require(msg.sender == depositor);\\n depositor = _depositor;\\n }\\n}\\n\",\"keccak256\":\"0xdbcfb11d65c6ca7d63baba42fb2f1222478c6ca78d8e81970032eff5e034e09b\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b5060405162001b9f38038062001b9f83398101604081905262000034916200019f565b600062093a80620000468142620001d1565b620000529190620001f4565b90508060008190555080600481905550806001819055506000826001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000aa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d091906200019f565b66038d7ea4c6800680546001600160a01b038381166001600160a01b0319928316811790935566038d7ea4c6800580549188169183168217905566071afd498d00088054909216331790915560405163095ea7b360e01b8152600481019190915260001960248201529192509063095ea7b3906044016020604051808303816000875af115801562000166573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200018c919062000222565b6200019657600080fd5b50505062000246565b600060208284031215620001b257600080fd5b81516001600160a01b0381168114620001ca57600080fd5b9392505050565b600082620001ef57634e487b7160e01b600052601260045260246000fd5b500490565b60008160001904831182151516156200021d57634e487b7160e01b600052601160045260246000fd5b500290565b6000602082840312156200023557600080fd5b81518015158114620001ca57600080fd5b61194980620002566000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea264697066735822122038f298ff421ca186346ca5ae24b719017aa28e10f5dd8ef97c7002e71e0bf94464736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea264697066735822122038f298ff421ca186346ca5ae24b719017aa28e10f5dd8ef97c7002e71e0bf94464736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voting_escrow\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"time\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"CheckpointToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"claim_epoch\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"max_epoch\",\"type\":\"uint256\"}],\"name\":\"Claimed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"checkpoint_token\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint_total_supply\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"_tokenIds\",\"type\":\"uint256[]\"}],\"name\":\"claim_many\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_token_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"}],\"name\":\"setDepositor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"start_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"time_cursor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"time_cursor_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token_last_balance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"tokens_per_week\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_epoch_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"ve_for_at\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ve_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voting_escrow\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RewardsDistributor.sol\":\"RewardsDistributor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/*\\n\\n@title Curve Fee Distribution modified for ve(3,3) emissions\\n@author Curve Finance, andrecronje\\n@license MIT\\n\\n*/\\n\\ncontract RewardsDistributor is IRewardsDistributor {\\n event CheckpointToken(uint256 time, uint256 tokens);\\n\\n event Claimed(\\n uint256 tokenId,\\n uint256 amount,\\n uint256 claim_epoch,\\n uint256 max_epoch\\n );\\n\\n uint256 constant WEEK = 7 * 86400;\\n\\n uint256 public start_time;\\n uint256 public time_cursor;\\n mapping(uint256 => uint256) public time_cursor_of;\\n mapping(uint256 => uint256) public user_epoch_of;\\n\\n uint256 public last_token_time;\\n uint256[1000000000000000] public tokens_per_week;\\n\\n address public voting_escrow;\\n address public token;\\n uint256 public token_last_balance;\\n\\n uint256[1000000000000000] public ve_supply;\\n\\n address public depositor;\\n\\n constructor(address _voting_escrow) {\\n uint256 _t = (block.timestamp / WEEK) * WEEK;\\n start_time = _t;\\n last_token_time = _t;\\n time_cursor = _t;\\n address _token = IVotingEscrow(_voting_escrow).token();\\n token = _token;\\n voting_escrow = _voting_escrow;\\n depositor = msg.sender;\\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\\n }\\n\\n function timestamp() external view returns (uint256) {\\n return (block.timestamp / WEEK) * WEEK;\\n }\\n\\n function _checkpoint_token() internal {\\n uint256 token_balance = IERC20(token).balanceOf(address(this));\\n uint256 to_distribute = token_balance - token_last_balance;\\n token_last_balance = token_balance;\\n\\n uint256 t = last_token_time;\\n uint256 since_last = block.timestamp - t;\\n last_token_time = block.timestamp;\\n uint256 this_week = (t / WEEK) * WEEK;\\n uint256 next_week = 0;\\n\\n for (uint256 i = 0; i < 20; i++) {\\n next_week = this_week + WEEK;\\n if (block.timestamp < next_week) {\\n if (since_last == 0 && block.timestamp == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (block.timestamp - t)) /\\n since_last;\\n }\\n break;\\n } else {\\n if (since_last == 0 && next_week == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (next_week - t)) /\\n since_last;\\n }\\n }\\n t = next_week;\\n this_week = next_week;\\n }\\n emit CheckpointToken(block.timestamp, to_distribute);\\n }\\n\\n function checkpoint_token() external {\\n assert(msg.sender == depositor);\\n _checkpoint_token();\\n }\\n\\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\\n internal\\n view\\n returns (uint256)\\n {\\n uint256 _min = 0;\\n uint256 _max = IVotingEscrow(ve).epoch();\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n _mid\\n );\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function _find_timestamp_user_epoch(\\n address ve,\\n uint256 tokenId,\\n uint256 _timestamp,\\n uint256 max_user_epoch\\n ) internal view returns (uint256) {\\n uint256 _min = 0;\\n uint256 _max = max_user_epoch;\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\\n .user_point_history(tokenId, _mid);\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\\n external\\n view\\n returns (uint256)\\n {\\n address ve = voting_escrow;\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _timestamp,\\n max_user_epoch\\n );\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n epoch\\n );\\n return\\n MathDunks.max(\\n uint256(\\n int256(\\n pt.bias -\\n pt.slope *\\n (int128(int256(_timestamp - pt.ts)))\\n )\\n ),\\n 0\\n );\\n }\\n\\n function _checkpoint_total_supply() internal {\\n address ve = voting_escrow;\\n uint256 t = time_cursor;\\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\\n IVotingEscrow(ve).checkpoint();\\n\\n for (uint256 i = 0; i < 20; i++) {\\n if (t > rounded_timestamp) {\\n break;\\n } else {\\n uint256 epoch = _find_timestamp_epoch(ve, t);\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n epoch\\n );\\n int128 dt = 0;\\n if (t > pt.ts) {\\n dt = int128(int256(t - pt.ts));\\n }\\n ve_supply[t] = MathDunks.max(\\n uint256(int256(pt.bias - pt.slope * dt)),\\n 0\\n );\\n }\\n t += WEEK;\\n }\\n time_cursor = t;\\n }\\n\\n function checkpoint_total_supply() external {\\n _checkpoint_total_supply();\\n }\\n\\n function _claim(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\\n user_epoch_of[_tokenId] = user_epoch;\\n time_cursor_of[_tokenId] = week_cursor;\\n\\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\\n\\n return to_distribute;\\n }\\n\\n function _claimable(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal view returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n return to_distribute;\\n }\\n\\n function claimable(uint256 _tokenId) external view returns (uint256) {\\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\\n return _claimable(_tokenId, voting_escrow, _last_token_time);\\n }\\n\\n function claim(uint256 _tokenId) external returns (uint256) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\\n token_last_balance -= amount;\\n }\\n return amount;\\n }\\n\\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n address _voting_escrow = voting_escrow;\\n uint256 total = 0;\\n\\n for (uint256 i = 0; i < _tokenIds.length; i++) {\\n uint256 _tokenId = _tokenIds[i];\\n if (_tokenId == 0) break;\\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\\n total += amount;\\n }\\n }\\n if (total != 0) {\\n token_last_balance -= total;\\n }\\n\\n return true;\\n }\\n\\n // Once off event on contract initialize\\n function setDepositor(address _depositor) external {\\n require(msg.sender == depositor);\\n depositor = _depositor;\\n }\\n}\\n\",\"keccak256\":\"0xdbcfb11d65c6ca7d63baba42fb2f1222478c6ca78d8e81970032eff5e034e09b\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b5060405162001b9f38038062001b9f83398101604081905262000034916200019f565b600062093a80620000468142620001d1565b620000529190620001f4565b90508060008190555080600481905550806001819055506000826001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000aa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d091906200019f565b66038d7ea4c6800680546001600160a01b038381166001600160a01b0319928316811790935566038d7ea4c6800580549188169183168217905566071afd498d00088054909216331790915560405163095ea7b360e01b8152600481019190915260001960248201529192509063095ea7b3906044016020604051808303816000875af115801562000166573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200018c919062000222565b6200019657600080fd5b50505062000246565b600060208284031215620001b257600080fd5b81516001600160a01b0381168114620001ca57600080fd5b9392505050565b600082620001ef57634e487b7160e01b600052601260045260246000fd5b500490565b60008160001904831182151516156200021d57634e487b7160e01b600052601160045260246000fd5b500290565b6000602082840312156200023557600080fd5b81518015158114620001ca57600080fd5b61194980620002566000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea26469706673582212203106563b3fbc12e10f6737c5ef908828c2a3f356862c6c472cb078657f47140b64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea26469706673582212203106563b3fbc12e10f6737c5ef908828c2a3f356862c6c472cb078657f47140b64736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/Router.json b/deployments/arbitrumGoerli/Router.json index b7247e2d..f3f674c3 100644 --- a/deployments/arbitrumGoerli/Router.json +++ b/deployments/arbitrumGoerli/Router.json @@ -1,5 +1,5 @@ { - "address": "0x8562618F69ED7F313Ca699556Eb18A36FB2dB1e3", + "address": "0x1B0aC6bf6f35E638f6cce8D69C6074561273dc52", "abi": [ { "inputs": [ @@ -979,31 +979,31 @@ "type": "receive" } ], - "transactionHash": "0x99fe8d1feb56c855fa474add22bb418a6d8d7921518c6536f4fbfee11a598e94", + "transactionHash": "0x95ae820faec784f4c39345361659f4d3f37f6a02c6e723fa105c1e985e303832", "receipt": { "to": null, - "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0x8562618F69ED7F313Ca699556Eb18A36FB2dB1e3", + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x1B0aC6bf6f35E638f6cce8D69C6074561273dc52", "transactionIndex": 1, - "gasUsed": "55608083", + "gasUsed": "3250410", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x49db2baff4b4114a9831368f9e4da8c4e602cb8c45a27cab2bacae0f6ec03d79", - "transactionHash": "0x99fe8d1feb56c855fa474add22bb418a6d8d7921518c6536f4fbfee11a598e94", + "blockHash": "0x6b332b331cd45f4e5ea7479d9ec5e8eab1dc518626ee7ca06fcb07ca0742c4f6", + "transactionHash": "0x95ae820faec784f4c39345361659f4d3f37f6a02c6e723fa105c1e985e303832", "logs": [], - "blockNumber": 4263676, - "cumulativeGasUsed": "55608083", + "blockNumber": 4455877, + "cumulativeGasUsed": "3250410", "status": 1, "byzantium": true }, "args": [ - "0xcA698eA7f3A74b7D3D4229765dcF47F7A224859F", - "0x4200000000000000000000000000000000000006" + "0x6389e934d35fC9e066FAb549C8DBc9FddaC10e0D", + "0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83" ], - "numDeployments": 8, - "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_weth\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"UNSAFE_swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"}],\"name\":\"getAmountsOut\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reserveA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"pairFor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"}],\"name\":\"quoteAddLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"name\":\"quoteRemoveLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityETHWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"}],\"name\":\"sortTokens\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactETHForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForETH\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenFrom\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenTo\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokensSimple\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weth\",\"outputs\":[{\"internalType\":\"contract IWETH\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Router.sol\":\"Router\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Router.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairFactory.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\nimport \\\"contracts/interfaces/IWETH.sol\\\";\\n\\ncontract Router is IRouter {\\n struct route {\\n address from;\\n address to;\\n bool stable;\\n }\\n\\n address public immutable factory;\\n IWETH public immutable weth;\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n bytes32 immutable pairCodeHash;\\n\\n modifier ensure(uint256 deadline) {\\n require(deadline >= block.timestamp, \\\"Router: EXPIRED\\\");\\n _;\\n }\\n\\n constructor(address _factory, address _weth) {\\n factory = _factory;\\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\\n weth = IWETH(_weth);\\n }\\n\\n receive() external payable {\\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\\n }\\n\\n function sortTokens(address tokenA, address tokenB)\\n public\\n pure\\n returns (address token0, address token1)\\n {\\n require(tokenA != tokenB, \\\"Router: IDENTICAL_ADDRESSES\\\");\\n (token0, token1) = tokenA < tokenB\\n ? (tokenA, tokenB)\\n : (tokenB, tokenA);\\n require(token0 != address(0), \\\"Router: ZERO_ADDRESS\\\");\\n }\\n\\n // calculates the CREATE2 address for a pair without making any external calls\\n function pairFor(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (address pair) {\\n (address token0, address token1) = sortTokens(tokenA, tokenB);\\n pair = address(\\n uint160(\\n uint256(\\n keccak256(\\n abi.encodePacked(\\n hex\\\"ff\\\",\\n factory,\\n keccak256(abi.encodePacked(token0, token1, stable)),\\n pairCodeHash // init code hash\\n )\\n )\\n )\\n )\\n );\\n }\\n\\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\\n function quoteLiquidity(\\n uint256 amountA,\\n uint256 reserveA,\\n uint256 reserveB\\n ) internal pure returns (uint256 amountB) {\\n require(amountA > 0, \\\"Router: INSUFFICIENT_AMOUNT\\\");\\n require(reserveA > 0 && reserveB > 0, \\\"Router: INSUFFICIENT_LIQUIDITY\\\");\\n amountB = (amountA * reserveB) / reserveA;\\n }\\n\\n // fetches and sorts the reserves for a pair\\n function getReserves(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (uint256 reserveA, uint256 reserveB) {\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (uint256 reserve0, uint256 reserve1, ) = IPair(\\n pairFor(tokenA, tokenB, stable)\\n ).getReserves();\\n (reserveA, reserveB) = tokenA == token0\\n ? (reserve0, reserve1)\\n : (reserve1, reserve0);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n address tokenOut\\n ) external view returns (uint256 amount, bool stable) {\\n address pair = pairFor(tokenIn, tokenOut, true);\\n uint256 amountStable;\\n uint256 amountVolatile;\\n if (IPairFactory(factory).isPair(pair)) {\\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n pair = pairFor(tokenIn, tokenOut, false);\\n if (IPairFactory(factory).isPair(pair)) {\\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n return\\n amountStable > amountVolatile\\n ? (amountStable, true)\\n : (amountVolatile, false);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountsOut(uint256 amountIn, route[] memory routes)\\n public\\n view\\n returns (uint256[] memory amounts)\\n {\\n require(routes.length >= 1, \\\"Router: INVALID_PATH\\\");\\n amounts = new uint256[](routes.length + 1);\\n amounts[0] = amountIn;\\n for (uint256 i = 0; i < routes.length; i++) {\\n address pair = pairFor(\\n routes[i].from,\\n routes[i].to,\\n routes[i].stable\\n );\\n if (IPairFactory(factory).isPair(pair)) {\\n amounts[i + 1] = IPair(pair).getAmountOut(\\n amounts[i],\\n routes[i].from\\n );\\n }\\n }\\n }\\n\\n function isPair(address pair) external view returns (bool) {\\n return IPairFactory(factory).isPair(pair);\\n }\\n\\n function quoteAddLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired\\n )\\n external\\n view\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n (uint256 reserveA, uint256 reserveB) = (0, 0);\\n uint256 _totalSupply = 0;\\n if (_pair != address(0)) {\\n _totalSupply = IERC20(_pair).totalSupply();\\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\\n }\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n }\\n }\\n }\\n\\n function quoteRemoveLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity\\n ) external view returns (uint256 amountA, uint256 amountB) {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n\\n if (_pair == address(0)) {\\n return (0, 0);\\n }\\n\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n uint256 _totalSupply = IERC20(_pair).totalSupply();\\n\\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\\n }\\n\\n function _addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin\\n ) internal returns (uint256 amountA, uint256 amountB) {\\n require(amountADesired >= amountAMin);\\n require(amountBDesired >= amountBMin);\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n if (_pair == address(0)) {\\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\\n }\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n require(\\n amountBOptimal >= amountBMin,\\n \\\"Router: INSUFFICIENT_B_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n assert(amountAOptimal <= amountADesired);\\n require(\\n amountAOptimal >= amountAMin,\\n \\\"Router: INSUFFICIENT_A_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n }\\n }\\n }\\n\\n function addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n ensure(deadline)\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n (amountA, amountB) = _addLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n amountADesired,\\n amountBDesired,\\n amountAMin,\\n amountBMin\\n );\\n address pair = pairFor(tokenA, tokenB, stable);\\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\\n liquidity = IPair(pair).mint(to);\\n }\\n\\n function addLiquidityETH(\\n address token,\\n bool stable,\\n uint256 amountTokenDesired,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n payable\\n ensure(deadline)\\n returns (\\n uint256 amountToken,\\n uint256 amountETH,\\n uint256 liquidity\\n )\\n {\\n (amountToken, amountETH) = _addLiquidity(\\n token,\\n address(weth),\\n stable,\\n amountTokenDesired,\\n msg.value,\\n amountTokenMin,\\n amountETHMin\\n );\\n address pair = pairFor(token, address(weth), stable);\\n _safeTransferFrom(token, msg.sender, pair, amountToken);\\n weth.deposit{value: amountETH}();\\n assert(weth.transfer(pair, amountETH));\\n liquidity = IPair(pair).mint(to);\\n // refund dust eth, if any\\n if (msg.value > amountETH)\\n _safeTransferETH(msg.sender, msg.value - amountETH);\\n }\\n\\n // **** REMOVE LIQUIDITY ****\\n function removeLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (amountA, amountB) = tokenA == token0\\n ? (amount0, amount1)\\n : (amount1, amount0);\\n require(amountA >= amountAMin, \\\"Router: INSUFFICIENT_A_AMOUNT\\\");\\n require(amountB >= amountBMin, \\\"Router: INSUFFICIENT_B_AMOUNT\\\");\\n }\\n\\n function removeLiquidityETH(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\\n (amountToken, amountETH) = removeLiquidity(\\n token,\\n address(weth),\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n address(this),\\n deadline\\n );\\n _safeTransfer(token, to, amountToken);\\n weth.withdraw(amountETH);\\n _safeTransferETH(to, amountETH);\\n }\\n\\n function removeLiquidityWithPermit(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n {\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(\\n msg.sender,\\n address(this),\\n value,\\n deadline,\\n v,\\n r,\\n s\\n );\\n }\\n\\n (amountA, amountB) = removeLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n liquidity,\\n amountAMin,\\n amountBMin,\\n to,\\n deadline\\n );\\n }\\n\\n function removeLiquidityETHWithPermit(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountToken, uint256 amountETH) {\\n address pair = pairFor(token, address(weth), stable);\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\\n (amountToken, amountETH) = removeLiquidityETH(\\n token,\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n to,\\n deadline\\n );\\n }\\n\\n // **** SWAP ****\\n // requires the initial amount to have already been sent to the first pair\\n function _swap(\\n uint256[] memory amounts,\\n route[] memory routes,\\n address _to\\n ) internal virtual {\\n for (uint256 i = 0; i < routes.length; i++) {\\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\\n uint256 amountOut = amounts[i + 1];\\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\\n ? (uint256(0), amountOut)\\n : (amountOut, uint256(0));\\n address to = i < routes.length - 1\\n ? pairFor(\\n routes[i + 1].from,\\n routes[i + 1].to,\\n routes[i + 1].stable\\n )\\n : _to;\\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\\n amount0Out,\\n amount1Out,\\n to,\\n new bytes(0)\\n );\\n }\\n }\\n\\n function swapExactTokensForTokensSimple(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n address tokenFrom,\\n address tokenTo,\\n bool stable,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n route[] memory routes = new route[](1);\\n routes[0].from = tokenFrom;\\n routes[0].to = tokenTo;\\n routes[0].stable = stable;\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForTokens(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactETHForTokens(\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\\n require(routes[0].from == address(weth), \\\"Router: INVALID_PATH\\\");\\n amounts = getAmountsOut(msg.value, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n weth.deposit{value: amounts[0]}();\\n assert(\\n weth.transfer(\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n )\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForETH(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n require(\\n routes[routes.length - 1].to == address(weth),\\n \\\"Router: INVALID_PATH\\\"\\n );\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, address(this));\\n weth.withdraw(amounts[amounts.length - 1]);\\n _safeTransferETH(to, amounts[amounts.length - 1]);\\n }\\n\\n function UNSAFE_swapExactTokensForTokens(\\n uint256[] memory amounts,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory) {\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n return amounts;\\n }\\n\\n function _safeTransferETH(address to, uint256 value) internal {\\n (bool success, ) = to.call{value: value}(new bytes(0));\\n require(success, \\\"TransferHelper: ETH_TRANSFER_FAILED\\\");\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x3d84c846129d645eec66c37a493bb7fb401a2524497f450eaced155088305ead\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"},\"contracts/interfaces/IWETH.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n function transfer(address to, uint256 value) external returns (bool);\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0x20ad0b3a319a36e3430f0d8512ee3755de8f85a80effe78d06f333f5326ee3d7\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x60e06040523480156200001157600080fd5b50604051620039bc380380620039bc8339810160408190526200003491620000d8565b6001600160a01b038216608081905260408051631355724960e31b81529051639aab9248916004808201926020929091908290030181865afa1580156200007f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000a5919062000110565b60c0526001600160a01b031660a052506200012a565b80516001600160a01b0381168114620000d357600080fd5b919050565b60008060408385031215620000ec57600080fd5b620000f783620000bb565b91506200010760208401620000bb565b90509250929050565b6000602082840312156200012357600080fd5b5051919050565b60805160a05160c0516137c8620001f46000396000610ef901526000818161013e0152818161020b0152818161091901528181610b5801528181610da901528181611470015281816115830152818161161101528181611de901528181611e1f01528181611e5401528181611ee901528181612028015261207801526000818161042d01528181610c3e01528181610ebe015281816111770152818161128b0152818161199601528181611b0a01528181612115015281816126ff01526127a001526137c86000f3fe60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea26469706673582212201f35e2970aea09da0502317678d6baed4a758797d319082c046f53f0070c23e364736f6c634300080d0033", - "deployedBytecode": "0x60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea26469706673582212201f35e2970aea09da0502317678d6baed4a758797d319082c046f53f0070c23e364736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_weth\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"UNSAFE_swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"}],\"name\":\"getAmountsOut\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reserveA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"pairFor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"}],\"name\":\"quoteAddLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"name\":\"quoteRemoveLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityETHWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"}],\"name\":\"sortTokens\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactETHForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForETH\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenFrom\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenTo\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokensSimple\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weth\",\"outputs\":[{\"internalType\":\"contract IWETH\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Router.sol\":\"Router\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Router.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairFactory.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\nimport \\\"contracts/interfaces/IWETH.sol\\\";\\n\\ncontract Router is IRouter {\\n struct route {\\n address from;\\n address to;\\n bool stable;\\n }\\n\\n address public immutable factory;\\n IWETH public immutable weth;\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n bytes32 immutable pairCodeHash;\\n\\n modifier ensure(uint256 deadline) {\\n require(deadline >= block.timestamp, \\\"Router: EXPIRED\\\");\\n _;\\n }\\n\\n constructor(address _factory, address _weth) {\\n factory = _factory;\\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\\n weth = IWETH(_weth);\\n }\\n\\n receive() external payable {\\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\\n }\\n\\n function sortTokens(address tokenA, address tokenB)\\n public\\n pure\\n returns (address token0, address token1)\\n {\\n require(tokenA != tokenB, \\\"Router: IDENTICAL_ADDRESSES\\\");\\n (token0, token1) = tokenA < tokenB\\n ? (tokenA, tokenB)\\n : (tokenB, tokenA);\\n require(token0 != address(0), \\\"Router: ZERO_ADDRESS\\\");\\n }\\n\\n // calculates the CREATE2 address for a pair without making any external calls\\n function pairFor(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (address pair) {\\n (address token0, address token1) = sortTokens(tokenA, tokenB);\\n pair = address(\\n uint160(\\n uint256(\\n keccak256(\\n abi.encodePacked(\\n hex\\\"ff\\\",\\n factory,\\n keccak256(abi.encodePacked(token0, token1, stable)),\\n pairCodeHash // init code hash\\n )\\n )\\n )\\n )\\n );\\n }\\n\\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\\n function quoteLiquidity(\\n uint256 amountA,\\n uint256 reserveA,\\n uint256 reserveB\\n ) internal pure returns (uint256 amountB) {\\n require(amountA > 0, \\\"Router: INSUFFICIENT_AMOUNT\\\");\\n require(reserveA > 0 && reserveB > 0, \\\"Router: INSUFFICIENT_LIQUIDITY\\\");\\n amountB = (amountA * reserveB) / reserveA;\\n }\\n\\n // fetches and sorts the reserves for a pair\\n function getReserves(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (uint256 reserveA, uint256 reserveB) {\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (uint256 reserve0, uint256 reserve1, ) = IPair(\\n pairFor(tokenA, tokenB, stable)\\n ).getReserves();\\n (reserveA, reserveB) = tokenA == token0\\n ? (reserve0, reserve1)\\n : (reserve1, reserve0);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n address tokenOut\\n ) external view returns (uint256 amount, bool stable) {\\n address pair = pairFor(tokenIn, tokenOut, true);\\n uint256 amountStable;\\n uint256 amountVolatile;\\n if (IPairFactory(factory).isPair(pair)) {\\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n pair = pairFor(tokenIn, tokenOut, false);\\n if (IPairFactory(factory).isPair(pair)) {\\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n return\\n amountStable > amountVolatile\\n ? (amountStable, true)\\n : (amountVolatile, false);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountsOut(uint256 amountIn, route[] memory routes)\\n public\\n view\\n returns (uint256[] memory amounts)\\n {\\n require(routes.length >= 1, \\\"Router: INVALID_PATH\\\");\\n amounts = new uint256[](routes.length + 1);\\n amounts[0] = amountIn;\\n for (uint256 i = 0; i < routes.length; i++) {\\n address pair = pairFor(\\n routes[i].from,\\n routes[i].to,\\n routes[i].stable\\n );\\n if (IPairFactory(factory).isPair(pair)) {\\n amounts[i + 1] = IPair(pair).getAmountOut(\\n amounts[i],\\n routes[i].from\\n );\\n }\\n }\\n }\\n\\n function isPair(address pair) external view returns (bool) {\\n return IPairFactory(factory).isPair(pair);\\n }\\n\\n function quoteAddLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired\\n )\\n external\\n view\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n (uint256 reserveA, uint256 reserveB) = (0, 0);\\n uint256 _totalSupply = 0;\\n if (_pair != address(0)) {\\n _totalSupply = IERC20(_pair).totalSupply();\\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\\n }\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n }\\n }\\n }\\n\\n function quoteRemoveLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity\\n ) external view returns (uint256 amountA, uint256 amountB) {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n\\n if (_pair == address(0)) {\\n return (0, 0);\\n }\\n\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n uint256 _totalSupply = IERC20(_pair).totalSupply();\\n\\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\\n }\\n\\n function _addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin\\n ) internal returns (uint256 amountA, uint256 amountB) {\\n require(amountADesired >= amountAMin);\\n require(amountBDesired >= amountBMin);\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n if (_pair == address(0)) {\\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\\n }\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n require(\\n amountBOptimal >= amountBMin,\\n \\\"Router: INSUFFICIENT_B_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n assert(amountAOptimal <= amountADesired);\\n require(\\n amountAOptimal >= amountAMin,\\n \\\"Router: INSUFFICIENT_A_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n }\\n }\\n }\\n\\n function addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n ensure(deadline)\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n (amountA, amountB) = _addLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n amountADesired,\\n amountBDesired,\\n amountAMin,\\n amountBMin\\n );\\n address pair = pairFor(tokenA, tokenB, stable);\\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\\n liquidity = IPair(pair).mint(to);\\n }\\n\\n function addLiquidityETH(\\n address token,\\n bool stable,\\n uint256 amountTokenDesired,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n payable\\n ensure(deadline)\\n returns (\\n uint256 amountToken,\\n uint256 amountETH,\\n uint256 liquidity\\n )\\n {\\n (amountToken, amountETH) = _addLiquidity(\\n token,\\n address(weth),\\n stable,\\n amountTokenDesired,\\n msg.value,\\n amountTokenMin,\\n amountETHMin\\n );\\n address pair = pairFor(token, address(weth), stable);\\n _safeTransferFrom(token, msg.sender, pair, amountToken);\\n weth.deposit{value: amountETH}();\\n assert(weth.transfer(pair, amountETH));\\n liquidity = IPair(pair).mint(to);\\n // refund dust eth, if any\\n if (msg.value > amountETH)\\n _safeTransferETH(msg.sender, msg.value - amountETH);\\n }\\n\\n // **** REMOVE LIQUIDITY ****\\n function removeLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (amountA, amountB) = tokenA == token0\\n ? (amount0, amount1)\\n : (amount1, amount0);\\n require(amountA >= amountAMin, \\\"Router: INSUFFICIENT_A_AMOUNT\\\");\\n require(amountB >= amountBMin, \\\"Router: INSUFFICIENT_B_AMOUNT\\\");\\n }\\n\\n function removeLiquidityETH(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\\n (amountToken, amountETH) = removeLiquidity(\\n token,\\n address(weth),\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n address(this),\\n deadline\\n );\\n _safeTransfer(token, to, amountToken);\\n weth.withdraw(amountETH);\\n _safeTransferETH(to, amountETH);\\n }\\n\\n function removeLiquidityWithPermit(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n {\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(\\n msg.sender,\\n address(this),\\n value,\\n deadline,\\n v,\\n r,\\n s\\n );\\n }\\n\\n (amountA, amountB) = removeLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n liquidity,\\n amountAMin,\\n amountBMin,\\n to,\\n deadline\\n );\\n }\\n\\n function removeLiquidityETHWithPermit(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountToken, uint256 amountETH) {\\n address pair = pairFor(token, address(weth), stable);\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\\n (amountToken, amountETH) = removeLiquidityETH(\\n token,\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n to,\\n deadline\\n );\\n }\\n\\n // **** SWAP ****\\n // requires the initial amount to have already been sent to the first pair\\n function _swap(\\n uint256[] memory amounts,\\n route[] memory routes,\\n address _to\\n ) internal virtual {\\n for (uint256 i = 0; i < routes.length; i++) {\\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\\n uint256 amountOut = amounts[i + 1];\\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\\n ? (uint256(0), amountOut)\\n : (amountOut, uint256(0));\\n address to = i < routes.length - 1\\n ? pairFor(\\n routes[i + 1].from,\\n routes[i + 1].to,\\n routes[i + 1].stable\\n )\\n : _to;\\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\\n amount0Out,\\n amount1Out,\\n to,\\n new bytes(0)\\n );\\n }\\n }\\n\\n function swapExactTokensForTokensSimple(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n address tokenFrom,\\n address tokenTo,\\n bool stable,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n route[] memory routes = new route[](1);\\n routes[0].from = tokenFrom;\\n routes[0].to = tokenTo;\\n routes[0].stable = stable;\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForTokens(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactETHForTokens(\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\\n require(routes[0].from == address(weth), \\\"Router: INVALID_PATH\\\");\\n amounts = getAmountsOut(msg.value, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n weth.deposit{value: amounts[0]}();\\n assert(\\n weth.transfer(\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n )\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForETH(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n require(\\n routes[routes.length - 1].to == address(weth),\\n \\\"Router: INVALID_PATH\\\"\\n );\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, address(this));\\n weth.withdraw(amounts[amounts.length - 1]);\\n _safeTransferETH(to, amounts[amounts.length - 1]);\\n }\\n\\n function UNSAFE_swapExactTokensForTokens(\\n uint256[] memory amounts,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory) {\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n return amounts;\\n }\\n\\n function _safeTransferETH(address to, uint256 value) internal {\\n (bool success, ) = to.call{value: value}(new bytes(0));\\n require(success, \\\"TransferHelper: ETH_TRANSFER_FAILED\\\");\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x3d84c846129d645eec66c37a493bb7fb401a2524497f450eaced155088305ead\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"},\"contracts/interfaces/IWETH.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n function transfer(address to, uint256 value) external returns (bool);\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0x20ad0b3a319a36e3430f0d8512ee3755de8f85a80effe78d06f333f5326ee3d7\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x60e06040523480156200001157600080fd5b50604051620039bc380380620039bc8339810160408190526200003491620000d8565b6001600160a01b038216608081905260408051631355724960e31b81529051639aab9248916004808201926020929091908290030181865afa1580156200007f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000a5919062000110565b60c0526001600160a01b031660a052506200012a565b80516001600160a01b0381168114620000d357600080fd5b919050565b60008060408385031215620000ec57600080fd5b620000f783620000bb565b91506200010760208401620000bb565b90509250929050565b6000602082840312156200012357600080fd5b5051919050565b60805160a05160c0516137c8620001f46000396000610ef901526000818161013e0152818161020b0152818161091901528181610b5801528181610da901528181611470015281816115830152818161161101528181611de901528181611e1f01528181611e5401528181611ee901528181612028015261207801526000818161042d01528181610c3e01528181610ebe015281816111770152818161128b0152818161199601528181611b0a01528181612115015281816126ff01526127a001526137c86000f3fe60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea2646970667358221220f2ee1975729b6186adceb8b9288ee74fe51d172125a95d24ef2076061558626e64736f6c634300080d0033", + "deployedBytecode": "0x60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea2646970667358221220f2ee1975729b6186adceb8b9288ee74fe51d172125a95d24ef2076061558626e64736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/VeArtProxy.json b/deployments/arbitrumGoerli/VeArtProxy.json index 5e031367..93a3c3be 100644 --- a/deployments/arbitrumGoerli/VeArtProxy.json +++ b/deployments/arbitrumGoerli/VeArtProxy.json @@ -1,5 +1,5 @@ { - "address": "0xB143E062f93E7d4F9f7B2b7127861c72Fb2ADF82", + "address": "0x821B98D42D3AB509AF4F54205f0c52B019b9E2D5", "abi": [ { "inputs": [ @@ -36,28 +36,28 @@ "type": "function" } ], - "transactionHash": "0xcf453a376d54dcf123c4b44a29b8dae43b316dc7862d73fe10dc42322937d6dd", + "transactionHash": "0x54e3314db01e3cabc091054c4928e7e5ddc5bc219384cdbc0bb493b8009cf015", "receipt": { "to": null, - "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0xB143E062f93E7d4F9f7B2b7127861c72Fb2ADF82", + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x821B98D42D3AB509AF4F54205f0c52B019b9E2D5", "transactionIndex": 1, - "gasUsed": "15137628", + "gasUsed": "644260", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x56b817b010cc0513d7646de82ba80ad09b54d0577b89aca1a9158ea606f948df", - "transactionHash": "0xcf453a376d54dcf123c4b44a29b8dae43b316dc7862d73fe10dc42322937d6dd", + "blockHash": "0x4f111813d8e4e78801f82168c4bec40866a898791e08a4fd8d4984f5f60e200b", + "transactionHash": "0x54e3314db01e3cabc091054c4928e7e5ddc5bc219384cdbc0bb493b8009cf015", "logs": [], - "blockNumber": 4263688, - "cumulativeGasUsed": "15137628", + "blockNumber": 4455883, + "cumulativeGasUsed": "644260", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 7, - "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_locked_end\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"_tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"output\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VeArtProxy.sol\":\"VeArtProxy\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\nimport {Base64} from \\\"contracts/libraries/Base64.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\n\\ncontract VeArtProxy is IVeArtProxy {\\n function toString(uint value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT license\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint temp = value;\\n uint digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\\n output = '';\\n output = string(abi.encodePacked(output, \\\"token \\\", toString(_tokenId), ''));\\n output = string(abi.encodePacked(output, \\\"balanceOf \\\", toString(_balanceOf), ''));\\n output = string(abi.encodePacked(output, \\\"locked_end \\\", toString(_locked_end), ''));\\n output = string(abi.encodePacked(output, \\\"value \\\", toString(_value), ''));\\n\\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\\\"name\\\": \\\"lock #', toString(_tokenId), '\\\", \\\"description\\\": \\\"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\\\", \\\"image\\\": \\\"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\\\"}'))));\\n output = string(abi.encodePacked('data:application/json;base64,', json));\\n }\\n}\\n\",\"keccak256\":\"0x8757d8095922dcad7af8c6820415049fd7d5af61a5580719210e5e91a31d80b1\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/libraries/Base64.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n/// [MIT License]\\n/// @title Base64\\n/// @notice Provides a function for encoding some bytes in base64\\n/// @author Brecht Devos \\nlibrary Base64 {\\n bytes internal constant TABLE = \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\";\\n\\n /// @notice Encodes some bytes to the base64 representation\\n function encode(bytes memory data) internal pure returns (string memory) {\\n uint len = data.length;\\n if (len == 0) return \\\"\\\";\\n\\n // multiply by 4/3 rounded up\\n uint encodedLen = 4 * ((len + 2) / 3);\\n\\n // Add some extra buffer at the end\\n bytes memory result = new bytes(encodedLen + 32);\\n\\n bytes memory table = TABLE;\\n\\n assembly {\\n let tablePtr := add(table, 1)\\n let resultPtr := add(result, 32)\\n\\n for {\\n let i := 0\\n } lt(i, len) {\\n\\n } {\\n i := add(i, 3)\\n let input := and(mload(add(data, i)), 0xffffff)\\n\\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\\n out := shl(224, out)\\n\\n mstore(resultPtr, out)\\n\\n resultPtr := add(resultPtr, 4)\\n }\\n\\n switch mod(len, 3)\\n case 1 {\\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\\n }\\n case 2 {\\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\\n }\\n\\n mstore(result, encodedLen)\\n }\\n\\n return string(result);\\n }\\n}\\n\",\"keccak256\":\"0x55535e1e0a14bbac370fe5f25df23aa88c678b915af53517672130f9a54f7e3e\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50610a2b806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f64726f6d65206c6f636010918401918201527f6b732c2063616e206265207573656420746f20626f6f7374206761756765207960308201527f69656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c206160508201527f6e64207265636569766520627269626573222c2022696d616765223a2022646160708201527f74613a696d6167652f7376672b786d6c3b6261736536342c0000000000000000609082015283516107718160a8840160208801610435565b61227d60f01b60a8929091019182015260aa01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212201586b6c87e32cb6d7584ee4fc014e36ccdf48dd4c8e3b693a3631810e74f917364736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f64726f6d65206c6f636010918401918201527f6b732c2063616e206265207573656420746f20626f6f7374206761756765207960308201527f69656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c206160508201527f6e64207265636569766520627269626573222c2022696d616765223a2022646160708201527f74613a696d6167652f7376672b786d6c3b6261736536342c0000000000000000609082015283516107718160a8840160208801610435565b61227d60f01b60a8929091019182015260aa01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212201586b6c87e32cb6d7584ee4fc014e36ccdf48dd4c8e3b693a3631810e74f917364736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_locked_end\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"_tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"output\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VeArtProxy.sol\":\"VeArtProxy\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\nimport {Base64} from \\\"contracts/libraries/Base64.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\n\\ncontract VeArtProxy is IVeArtProxy {\\n function toString(uint value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT license\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint temp = value;\\n uint digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\\n output = '';\\n output = string(abi.encodePacked(output, \\\"token \\\", toString(_tokenId), ''));\\n output = string(abi.encodePacked(output, \\\"balanceOf \\\", toString(_balanceOf), ''));\\n output = string(abi.encodePacked(output, \\\"locked_end \\\", toString(_locked_end), ''));\\n output = string(abi.encodePacked(output, \\\"value \\\", toString(_value), ''));\\n\\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\\\"name\\\": \\\"lock #', toString(_tokenId), '\\\", \\\"description\\\": \\\"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\\\", \\\"image\\\": \\\"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\\\"}'))));\\n output = string(abi.encodePacked('data:application/json;base64,', json));\\n }\\n}\\n\",\"keccak256\":\"0x8757d8095922dcad7af8c6820415049fd7d5af61a5580719210e5e91a31d80b1\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/libraries/Base64.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n/// [MIT License]\\n/// @title Base64\\n/// @notice Provides a function for encoding some bytes in base64\\n/// @author Brecht Devos \\nlibrary Base64 {\\n bytes internal constant TABLE = \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\";\\n\\n /// @notice Encodes some bytes to the base64 representation\\n function encode(bytes memory data) internal pure returns (string memory) {\\n uint len = data.length;\\n if (len == 0) return \\\"\\\";\\n\\n // multiply by 4/3 rounded up\\n uint encodedLen = 4 * ((len + 2) / 3);\\n\\n // Add some extra buffer at the end\\n bytes memory result = new bytes(encodedLen + 32);\\n\\n bytes memory table = TABLE;\\n\\n assembly {\\n let tablePtr := add(table, 1)\\n let resultPtr := add(result, 32)\\n\\n for {\\n let i := 0\\n } lt(i, len) {\\n\\n } {\\n i := add(i, 3)\\n let input := and(mload(add(data, i)), 0xffffff)\\n\\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\\n out := shl(224, out)\\n\\n mstore(resultPtr, out)\\n\\n resultPtr := add(resultPtr, 4)\\n }\\n\\n switch mod(len, 3)\\n case 1 {\\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\\n }\\n case 2 {\\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\\n }\\n\\n mstore(result, encodedLen)\\n }\\n\\n return string(result);\\n }\\n}\\n\",\"keccak256\":\"0x55535e1e0a14bbac370fe5f25df23aa88c678b915af53517672130f9a54f7e3e\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610a2b806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f64726f6d65206c6f636010918401918201527f6b732c2063616e206265207573656420746f20626f6f7374206761756765207960308201527f69656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c206160508201527f6e64207265636569766520627269626573222c2022696d616765223a2022646160708201527f74613a696d6167652f7376672b786d6c3b6261736536342c0000000000000000609082015283516107718160a8840160208801610435565b61227d60f01b60a8929091019182015260aa01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220af1f8cc7181d18ce7e9f4d26a0b55e87cfad516b6b2bf21dc6cebe86c06fb7bf64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f64726f6d65206c6f636010918401918201527f6b732c2063616e206265207573656420746f20626f6f7374206761756765207960308201527f69656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c206160508201527f6e64207265636569766520627269626573222c2022696d616765223a2022646160708201527f74613a696d6167652f7376672b786d6c3b6261736536342c0000000000000000609082015283516107718160a8840160208801610435565b61227d60f01b60a8929091019182015260aa01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220af1f8cc7181d18ce7e9f4d26a0b55e87cfad516b6b2bf21dc6cebe86c06fb7bf64736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/Velo.json b/deployments/arbitrumGoerli/Velo.json index c40f44af..2efd133c 100644 --- a/deployments/arbitrumGoerli/Velo.json +++ b/deployments/arbitrumGoerli/Velo.json @@ -1,5 +1,5 @@ { - "address": "0x162404E6Cd4633656925b90EF67237F29D5cc85c", + "address": "0x84Ca387E7ede764A3284c67Ff8c68a305a9030a0", "abi": [ { "inputs": [], @@ -381,43 +381,43 @@ "type": "function" } ], - "transactionHash": "0xc4fe1ef3bd2c9531ba9f3fe41ca788f79076df1241d1838f586067f566752ef6", + "transactionHash": "0xbbd7f88f2b70de030ef83ee08f21e48441fa45a4d6417cfd4572bb922dac2c90", "receipt": { "to": null, - "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0x162404E6Cd4633656925b90EF67237F29D5cc85c", + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x84Ca387E7ede764A3284c67Ff8c68a305a9030a0", "transactionIndex": 1, - "gasUsed": "12494147", - "logsBloom": "0x00000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000400000000008000000000000000000000000000040000000000000000000020000000000000000000800000000000000000000000010000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000400000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x030240c8f3f6499c33f4c32c669372151316fddca42d0d9f7abdf5567802923d", - "transactionHash": "0xc4fe1ef3bd2c9531ba9f3fe41ca788f79076df1241d1838f586067f566752ef6", + "gasUsed": "560637", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000008000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000010000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000008000000000000000000004200000000000002000000000000000000000000000000000000000000000000000020000000000000000000000000080000000000000000000000000000000000000000", + "blockHash": "0x002c02bea3e5ceb325db6c195e62ae108d8a7f5b97f991cffb6d72be896c5aa7", + "transactionHash": "0xbbd7f88f2b70de030ef83ee08f21e48441fa45a4d6417cfd4572bb922dac2c90", "logs": [ { "transactionIndex": 1, - "blockNumber": 4263666, - "transactionHash": "0xc4fe1ef3bd2c9531ba9f3fe41ca788f79076df1241d1838f586067f566752ef6", - "address": "0x162404E6Cd4633656925b90EF67237F29D5cc85c", + "blockNumber": 4455863, + "transactionHash": "0xbbd7f88f2b70de030ef83ee08f21e48441fa45a4d6417cfd4572bb922dac2c90", + "address": "0x84Ca387E7ede764A3284c67Ff8c68a305a9030a0", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000003406eda8850592ea85886d854edbd55042cb7805" + "0x00000000000000000000000053f3b51fd7f327e1ec4e6eaa3a049149cb2acad2" ], "data": "0x0000000000000000000000000000000000000000000000000000000000000000", "logIndex": 0, - "blockHash": "0x030240c8f3f6499c33f4c32c669372151316fddca42d0d9f7abdf5567802923d" + "blockHash": "0x002c02bea3e5ceb325db6c195e62ae108d8a7f5b97f991cffb6d72be896c5aa7" } ], - "blockNumber": 4263666, - "cumulativeGasUsed": "12494147", + "blockNumber": 4455863, + "cumulativeGasUsed": "560637", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 8, - "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"initialMint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialMinted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleClaim\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redemptionReceiver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_merkleClaim\",\"type\":\"address\"}],\"name\":\"setMerkleClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"setMinter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_receiver\",\"type\":\"address\"}],\"name\":\"setRedemptionReceiver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Velo.sol\":\"Velo\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Velo.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IVelo.sol\\\";\\n\\ncontract Velo is IVelo {\\n\\n string public constant name = \\\"Velodrome\\\";\\n string public constant symbol = \\\"VELO\\\";\\n uint8 public constant decimals = 18;\\n uint public totalSupply = 0;\\n\\n mapping(address => uint) public balanceOf;\\n mapping(address => mapping(address => uint)) public allowance;\\n\\n bool public initialMinted;\\n address public minter;\\n address public redemptionReceiver;\\n address public merkleClaim;\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n\\n constructor() {\\n minter = msg.sender;\\n _mint(msg.sender, 0);\\n }\\n\\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\\n function setMinter(address _minter) external {\\n require(msg.sender == minter);\\n minter = _minter;\\n }\\n\\n function setRedemptionReceiver(address _receiver) external {\\n require(msg.sender == minter);\\n redemptionReceiver = _receiver;\\n }\\n\\n function setMerkleClaim(address _merkleClaim) external {\\n require(msg.sender == minter);\\n merkleClaim = _merkleClaim;\\n }\\n\\n // Initial mint: total 82M\\n // 4M for \\\"Genesis\\\" pools\\n // 30M for liquid team allocation (40M excl init veNFT)\\n // 48M for future partners\\n function initialMint(address _recipient) external {\\n require(msg.sender == minter && !initialMinted);\\n initialMinted = true;\\n _mint(_recipient, 82 * 1e6 * 1e18);\\n }\\n\\n function approve(address _spender, uint _value) external returns (bool) {\\n allowance[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n function _mint(address _to, uint _amount) internal returns (bool) {\\n totalSupply += _amount;\\n unchecked {\\n balanceOf[_to] += _amount;\\n }\\n emit Transfer(address(0x0), _to, _amount);\\n return true;\\n }\\n\\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\\n balanceOf[_from] -= _value;\\n unchecked {\\n balanceOf[_to] += _value;\\n }\\n emit Transfer(_from, _to, _value);\\n return true;\\n }\\n\\n function transfer(address _to, uint _value) external returns (bool) {\\n return _transfer(msg.sender, _to, _value);\\n }\\n\\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\\n uint allowed_from = allowance[_from][msg.sender];\\n if (allowed_from != type(uint).max) {\\n allowance[_from][msg.sender] -= _value;\\n }\\n return _transfer(_from, _to, _value);\\n }\\n\\n function mint(address account, uint amount) external returns (bool) {\\n require(msg.sender == minter);\\n _mint(account, amount);\\n return true;\\n }\\n\\n function claim(address account, uint amount) external returns (bool) {\\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\\n _mint(account, amount);\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xb5231de79b43d576febc9d6a0ebee8c4f251ec109869ce7a3e0afc2a185d0246\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"}},\"version\":1}", - "bytecode": "0x60806040526000805534801561001457600080fd5b5060038054610100600160a81b0319163361010081029190911790915561003c906000610042565b506100d9565b60008160008082825461005591906100b3565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a350600192915050565b600082198211156100d457634e487b7160e01b600052601160045260246000fd5b500190565b61082c806100e86000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ac578063dd62ed3e146102bf578063e752c44a146102ea578063ec676a25146102fd578063fca3b5aa1461031057600080fd5b806395d89b4114610241578063a9059cbb14610264578063aad3ec9614610277578063c268f9ba1461028a578063ca1c4de91461029f57600080fd5b806323b872dd116100f457806323b872dd146101ce578063313ce567146101e157806340c10f19146101fb5780635e05fe501461020e57806370a082311461022157600080fd5b806306fdde03146101265780630754617214610164578063095ea7b31461019457806318160ddd146101b7575b600080fd5b61014e6040518060400160405280600981526020016856656c6f64726f6d6560b81b81525081565b60405161015b919061068c565b60405180910390f35b60035461017c9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015b565b6101a76101a23660046106fd565b610323565b604051901515815260200161015b565b6101c060005481565b60405190815260200161015b565b6101a76101dc366004610727565b61038f565b6101e9601281565b60405160ff909116815260200161015b565b6101a76102093660046106fd565b610409565b60045461017c906001600160a01b031681565b6101c061022f366004610763565b60016020526000908152604090205481565b61014e6040518060400160405280600481526020016356454c4f60e01b81525081565b6101a76102723660046106fd565b61043c565b6101a76102853660046106fd565b610450565b61029d610298366004610763565b61047f565b005b6003546101a79060ff1681565b61029d6102ba366004610763565b6104d0565b6101c06102cd36600461077e565b600260209081526000928352604080842090915290825290205481565b60055461017c906001600160a01b031681565b61029d61030b366004610763565b61050e565b61029d61031e366004610763565b61054c565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259061037e9086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f5576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103ef9084906107c7565b90915550505b610400858585610590565b95945050505050565b60035460009061010090046001600160a01b0316331461042857600080fd5b6104328383610627565b5060019392505050565b6000610449338484610590565b9392505050565b6004546000906001600160a01b031633148061047657506005546001600160a01b031633145b61042857600080fd5b60035461010090046001600160a01b0316331480156104a1575060035460ff16155b6104aa57600080fd5b6003805460ff191660011790556104cc816a43d42ce83da41d92000000610627565b5050565b60035461010090046001600160a01b031633146104ec57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052a57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056857600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105ba9084906107c7565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106159086815260200190565b60405180910390a35060019392505050565b60008160008082825461063a91906107de565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910161037e565b600060208083528351808285015260005b818110156106b95785810183015185820160400152820161069d565b818111156106cb576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106f857600080fd5b919050565b6000806040838503121561071057600080fd5b610719836106e1565b946020939093013593505050565b60008060006060848603121561073c57600080fd5b610745846106e1565b9250610753602085016106e1565b9150604084013590509250925092565b60006020828403121561077557600080fd5b610449826106e1565b6000806040838503121561079157600080fd5b61079a836106e1565b91506107a8602084016106e1565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107d9576107d96107b1565b500390565b600082198211156107f1576107f16107b1565b50019056fea26469706673582212200ee48cb937aa2a18763edead8de90507d9439e6b529b100360b93838fc56165d64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ac578063dd62ed3e146102bf578063e752c44a146102ea578063ec676a25146102fd578063fca3b5aa1461031057600080fd5b806395d89b4114610241578063a9059cbb14610264578063aad3ec9614610277578063c268f9ba1461028a578063ca1c4de91461029f57600080fd5b806323b872dd116100f457806323b872dd146101ce578063313ce567146101e157806340c10f19146101fb5780635e05fe501461020e57806370a082311461022157600080fd5b806306fdde03146101265780630754617214610164578063095ea7b31461019457806318160ddd146101b7575b600080fd5b61014e6040518060400160405280600981526020016856656c6f64726f6d6560b81b81525081565b60405161015b919061068c565b60405180910390f35b60035461017c9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015b565b6101a76101a23660046106fd565b610323565b604051901515815260200161015b565b6101c060005481565b60405190815260200161015b565b6101a76101dc366004610727565b61038f565b6101e9601281565b60405160ff909116815260200161015b565b6101a76102093660046106fd565b610409565b60045461017c906001600160a01b031681565b6101c061022f366004610763565b60016020526000908152604090205481565b61014e6040518060400160405280600481526020016356454c4f60e01b81525081565b6101a76102723660046106fd565b61043c565b6101a76102853660046106fd565b610450565b61029d610298366004610763565b61047f565b005b6003546101a79060ff1681565b61029d6102ba366004610763565b6104d0565b6101c06102cd36600461077e565b600260209081526000928352604080842090915290825290205481565b60055461017c906001600160a01b031681565b61029d61030b366004610763565b61050e565b61029d61031e366004610763565b61054c565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259061037e9086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f5576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103ef9084906107c7565b90915550505b610400858585610590565b95945050505050565b60035460009061010090046001600160a01b0316331461042857600080fd5b6104328383610627565b5060019392505050565b6000610449338484610590565b9392505050565b6004546000906001600160a01b031633148061047657506005546001600160a01b031633145b61042857600080fd5b60035461010090046001600160a01b0316331480156104a1575060035460ff16155b6104aa57600080fd5b6003805460ff191660011790556104cc816a43d42ce83da41d92000000610627565b5050565b60035461010090046001600160a01b031633146104ec57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052a57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056857600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105ba9084906107c7565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106159086815260200190565b60405180910390a35060019392505050565b60008160008082825461063a91906107de565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910161037e565b600060208083528351808285015260005b818110156106b95785810183015185820160400152820161069d565b818111156106cb576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106f857600080fd5b919050565b6000806040838503121561071057600080fd5b610719836106e1565b946020939093013593505050565b60008060006060848603121561073c57600080fd5b610745846106e1565b9250610753602085016106e1565b9150604084013590509250925092565b60006020828403121561077557600080fd5b610449826106e1565b6000806040838503121561079157600080fd5b61079a836106e1565b91506107a8602084016106e1565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107d9576107d96107b1565b500390565b600082198211156107f1576107f16107b1565b50019056fea26469706673582212200ee48cb937aa2a18763edead8de90507d9439e6b529b100360b93838fc56165d64736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"initialMint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialMinted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleClaim\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redemptionReceiver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_merkleClaim\",\"type\":\"address\"}],\"name\":\"setMerkleClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"setMinter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_receiver\",\"type\":\"address\"}],\"name\":\"setRedemptionReceiver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Velo.sol\":\"Velo\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Velo.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IVelo.sol\\\";\\n\\ncontract Velo is IVelo {\\n\\n string public constant name = \\\"Velodrome\\\";\\n string public constant symbol = \\\"VELO\\\";\\n uint8 public constant decimals = 18;\\n uint public totalSupply = 0;\\n\\n mapping(address => uint) public balanceOf;\\n mapping(address => mapping(address => uint)) public allowance;\\n\\n bool public initialMinted;\\n address public minter;\\n address public redemptionReceiver;\\n address public merkleClaim;\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n\\n constructor() {\\n minter = msg.sender;\\n _mint(msg.sender, 0);\\n }\\n\\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\\n function setMinter(address _minter) external {\\n require(msg.sender == minter);\\n minter = _minter;\\n }\\n\\n function setRedemptionReceiver(address _receiver) external {\\n require(msg.sender == minter);\\n redemptionReceiver = _receiver;\\n }\\n\\n function setMerkleClaim(address _merkleClaim) external {\\n require(msg.sender == minter);\\n merkleClaim = _merkleClaim;\\n }\\n\\n // Initial mint: total 82M\\n // 4M for \\\"Genesis\\\" pools\\n // 30M for liquid team allocation (40M excl init veNFT)\\n // 48M for future partners\\n function initialMint(address _recipient) external {\\n require(msg.sender == minter && !initialMinted);\\n initialMinted = true;\\n _mint(_recipient, 82 * 1e6 * 1e18);\\n }\\n\\n function approve(address _spender, uint _value) external returns (bool) {\\n allowance[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n function _mint(address _to, uint _amount) internal returns (bool) {\\n totalSupply += _amount;\\n unchecked {\\n balanceOf[_to] += _amount;\\n }\\n emit Transfer(address(0x0), _to, _amount);\\n return true;\\n }\\n\\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\\n balanceOf[_from] -= _value;\\n unchecked {\\n balanceOf[_to] += _value;\\n }\\n emit Transfer(_from, _to, _value);\\n return true;\\n }\\n\\n function transfer(address _to, uint _value) external returns (bool) {\\n return _transfer(msg.sender, _to, _value);\\n }\\n\\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\\n uint allowed_from = allowance[_from][msg.sender];\\n if (allowed_from != type(uint).max) {\\n allowance[_from][msg.sender] -= _value;\\n }\\n return _transfer(_from, _to, _value);\\n }\\n\\n function mint(address account, uint amount) external returns (bool) {\\n require(msg.sender == minter);\\n _mint(account, amount);\\n return true;\\n }\\n\\n function claim(address account, uint amount) external returns (bool) {\\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\\n _mint(account, amount);\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xb5231de79b43d576febc9d6a0ebee8c4f251ec109869ce7a3e0afc2a185d0246\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"}},\"version\":1}", + "bytecode": "0x60806040526000805534801561001457600080fd5b5060038054610100600160a81b0319163361010081029190911790915561003c906000610042565b506100d9565b60008160008082825461005591906100b3565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a350600192915050565b600082198211156100d457634e487b7160e01b600052601160045260246000fd5b500190565b61082c806100e86000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ac578063dd62ed3e146102bf578063e752c44a146102ea578063ec676a25146102fd578063fca3b5aa1461031057600080fd5b806395d89b4114610241578063a9059cbb14610264578063aad3ec9614610277578063c268f9ba1461028a578063ca1c4de91461029f57600080fd5b806323b872dd116100f457806323b872dd146101ce578063313ce567146101e157806340c10f19146101fb5780635e05fe501461020e57806370a082311461022157600080fd5b806306fdde03146101265780630754617214610164578063095ea7b31461019457806318160ddd146101b7575b600080fd5b61014e6040518060400160405280600981526020016856656c6f64726f6d6560b81b81525081565b60405161015b919061068c565b60405180910390f35b60035461017c9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015b565b6101a76101a23660046106fd565b610323565b604051901515815260200161015b565b6101c060005481565b60405190815260200161015b565b6101a76101dc366004610727565b61038f565b6101e9601281565b60405160ff909116815260200161015b565b6101a76102093660046106fd565b610409565b60045461017c906001600160a01b031681565b6101c061022f366004610763565b60016020526000908152604090205481565b61014e6040518060400160405280600481526020016356454c4f60e01b81525081565b6101a76102723660046106fd565b61043c565b6101a76102853660046106fd565b610450565b61029d610298366004610763565b61047f565b005b6003546101a79060ff1681565b61029d6102ba366004610763565b6104d0565b6101c06102cd36600461077e565b600260209081526000928352604080842090915290825290205481565b60055461017c906001600160a01b031681565b61029d61030b366004610763565b61050e565b61029d61031e366004610763565b61054c565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259061037e9086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f5576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103ef9084906107c7565b90915550505b610400858585610590565b95945050505050565b60035460009061010090046001600160a01b0316331461042857600080fd5b6104328383610627565b5060019392505050565b6000610449338484610590565b9392505050565b6004546000906001600160a01b031633148061047657506005546001600160a01b031633145b61042857600080fd5b60035461010090046001600160a01b0316331480156104a1575060035460ff16155b6104aa57600080fd5b6003805460ff191660011790556104cc816a43d42ce83da41d92000000610627565b5050565b60035461010090046001600160a01b031633146104ec57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052a57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056857600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105ba9084906107c7565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106159086815260200190565b60405180910390a35060019392505050565b60008160008082825461063a91906107de565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910161037e565b600060208083528351808285015260005b818110156106b95785810183015185820160400152820161069d565b818111156106cb576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106f857600080fd5b919050565b6000806040838503121561071057600080fd5b610719836106e1565b946020939093013593505050565b60008060006060848603121561073c57600080fd5b610745846106e1565b9250610753602085016106e1565b9150604084013590509250925092565b60006020828403121561077557600080fd5b610449826106e1565b6000806040838503121561079157600080fd5b61079a836106e1565b91506107a8602084016106e1565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107d9576107d96107b1565b500390565b600082198211156107f1576107f16107b1565b50019056fea26469706673582212205c10bf292220f7b70a6a720da510bc53600c2c817ee2a5030f9ab74b3a2a711364736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ac578063dd62ed3e146102bf578063e752c44a146102ea578063ec676a25146102fd578063fca3b5aa1461031057600080fd5b806395d89b4114610241578063a9059cbb14610264578063aad3ec9614610277578063c268f9ba1461028a578063ca1c4de91461029f57600080fd5b806323b872dd116100f457806323b872dd146101ce578063313ce567146101e157806340c10f19146101fb5780635e05fe501461020e57806370a082311461022157600080fd5b806306fdde03146101265780630754617214610164578063095ea7b31461019457806318160ddd146101b7575b600080fd5b61014e6040518060400160405280600981526020016856656c6f64726f6d6560b81b81525081565b60405161015b919061068c565b60405180910390f35b60035461017c9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015b565b6101a76101a23660046106fd565b610323565b604051901515815260200161015b565b6101c060005481565b60405190815260200161015b565b6101a76101dc366004610727565b61038f565b6101e9601281565b60405160ff909116815260200161015b565b6101a76102093660046106fd565b610409565b60045461017c906001600160a01b031681565b6101c061022f366004610763565b60016020526000908152604090205481565b61014e6040518060400160405280600481526020016356454c4f60e01b81525081565b6101a76102723660046106fd565b61043c565b6101a76102853660046106fd565b610450565b61029d610298366004610763565b61047f565b005b6003546101a79060ff1681565b61029d6102ba366004610763565b6104d0565b6101c06102cd36600461077e565b600260209081526000928352604080842090915290825290205481565b60055461017c906001600160a01b031681565b61029d61030b366004610763565b61050e565b61029d61031e366004610763565b61054c565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259061037e9086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f5576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103ef9084906107c7565b90915550505b610400858585610590565b95945050505050565b60035460009061010090046001600160a01b0316331461042857600080fd5b6104328383610627565b5060019392505050565b6000610449338484610590565b9392505050565b6004546000906001600160a01b031633148061047657506005546001600160a01b031633145b61042857600080fd5b60035461010090046001600160a01b0316331480156104a1575060035460ff16155b6104aa57600080fd5b6003805460ff191660011790556104cc816a43d42ce83da41d92000000610627565b5050565b60035461010090046001600160a01b031633146104ec57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052a57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056857600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105ba9084906107c7565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106159086815260200190565b60405180910390a35060019392505050565b60008160008082825461063a91906107de565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910161037e565b600060208083528351808285015260005b818110156106b95785810183015185820160400152820161069d565b818111156106cb576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106f857600080fd5b919050565b6000806040838503121561071057600080fd5b610719836106e1565b946020939093013593505050565b60008060006060848603121561073c57600080fd5b610745846106e1565b9250610753602085016106e1565b9150604084013590509250925092565b60006020828403121561077557600080fd5b610449826106e1565b6000806040838503121561079157600080fd5b61079a836106e1565b91506107a8602084016106e1565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107d9576107d96107b1565b500390565b600082198211156107f1576107f16107b1565b50019056fea26469706673582212205c10bf292220f7b70a6a720da510bc53600c2c817ee2a5030f9ab74b3a2a711364736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/VeloGovernor.json b/deployments/arbitrumGoerli/VeloGovernor.json index c5cc4e9f..063cc4b2 100644 --- a/deployments/arbitrumGoerli/VeloGovernor.json +++ b/deployments/arbitrumGoerli/VeloGovernor.json @@ -1,5 +1,5 @@ { - "address": "0xF2bf0557E4b13bFA4c256F59a026A2F95b238479", + "address": "0x1a79b9daa3E741774bf67732F8a8B5820De8A53a", "abi": [ { "inputs": [ @@ -1055,43 +1055,43 @@ "type": "receive" } ], - "transactionHash": "0xbea3b33607b7287abef3796a8010ceca6d11f688a78720b3c9f1cf8810ffc12d", + "transactionHash": "0x4a643f6407d24899d49ae4c8f4f8af6c638991636267c8c19c51db19d58c16f1", "receipt": { "to": null, - "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0xF2bf0557E4b13bFA4c256F59a026A2F95b238479", + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x1a79b9daa3E741774bf67732F8a8B5820De8A53a", "transactionIndex": 1, - "gasUsed": "57985095", - "logsBloom": "0x00000000000000000100000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x452398a6f23bab1a7b573f24801f0eac7b46f85af713e67de63e16fc3fdfe64f", - "transactionHash": "0xbea3b33607b7287abef3796a8010ceca6d11f688a78720b3c9f1cf8810ffc12d", + "gasUsed": "2851602", + "logsBloom": "0x00000000000000000100000000001000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xa613ccf9c1c4459e5c227f665c806c3d46ea612c1a333a7f75a76f498e952898", + "transactionHash": "0x4a643f6407d24899d49ae4c8f4f8af6c638991636267c8c19c51db19d58c16f1", "logs": [ { "transactionIndex": 1, - "blockNumber": 4263700, - "transactionHash": "0xbea3b33607b7287abef3796a8010ceca6d11f688a78720b3c9f1cf8810ffc12d", - "address": "0xF2bf0557E4b13bFA4c256F59a026A2F95b238479", + "blockNumber": 4455895, + "transactionHash": "0x4a643f6407d24899d49ae4c8f4f8af6c638991636267c8c19c51db19d58c16f1", + "address": "0x1a79b9daa3E741774bf67732F8a8B5820De8A53a", "topics": [ "0x0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997" ], "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004", "logIndex": 0, - "blockHash": "0x452398a6f23bab1a7b573f24801f0eac7b46f85af713e67de63e16fc3fdfe64f" + "blockHash": "0xa613ccf9c1c4459e5c227f665c806c3d46ea612c1a333a7f75a76f498e952898" } ], - "blockNumber": 4263700, - "cumulativeGasUsed": "57985095", + "blockNumber": 4455895, + "cumulativeGasUsed": "2851602", "status": 1, "byzantium": true }, "args": [ - "0xCDAF5f01849Fff0a9E36D768B2ae7354A98360c0" + "0xBf05364D6cf1586852c18c6b1CbEe218E3e09885" ], - "numDeployments": 5, - "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"_ve\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"Empty\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"proposer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"string[]\",\"name\":\"signatures\",\"type\":\"string[]\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"ProposalCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldQuorumNumerator\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"QuorumNumeratorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"VoteCast\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"VoteCastWithParams\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"COUNTING_MODE\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EXTENDED_BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_PROPOSAL_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROPOSAL_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"}],\"name\":\"castVote\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"castVoteWithReason\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"castVoteWithReasonAndParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteWithReasonAndParamsBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"execute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"getVotesWithParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasVoted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"hashProposal\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalDeadline\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalSnapshot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"againstVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"forVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"abstainVotes\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"propose\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"quorum\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumDenominator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"}],\"name\":\"setProposalNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTeam\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"state\",\"outputs\":[{\"internalType\":\"enum IGovernor.ProposalState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"updateQuorumNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"Empty()\":[{\"details\":\"An operation (e.g. {front}) couldn't be completed due to the queue being empty.\"}]},\"kind\":\"dev\",\"methods\":{\"COUNTING_MODE()\":{\"details\":\"See {IGovernor-COUNTING_MODE}.\"},\"castVote(uint256,uint8)\":{\"details\":\"See {IGovernor-castVote}.\"},\"castVoteBySig(uint256,uint8,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteBySig}.\"},\"castVoteWithReason(uint256,uint8,string)\":{\"details\":\"See {IGovernor-castVoteWithReason}.\"},\"castVoteWithReasonAndParams(uint256,uint8,string,bytes)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParams}.\"},\"castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParamsBySig}.\"},\"execute(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-execute}.\"},\"getVotes(address,uint256)\":{\"details\":\"See {IGovernor-getVotes}.\"},\"getVotesWithParams(address,uint256,bytes)\":{\"details\":\"See {IGovernor-getVotesWithParams}.\"},\"hasVoted(uint256,address)\":{\"details\":\"See {IGovernor-hasVoted}.\"},\"hashProposal(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-hashProposal}. The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in advance, before the proposal is submitted. Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the same proposal (with same operation and same description) will have the same id if submitted on multiple governors across multiple networks. This also means that in order to execute the same operation twice (on the same governor) the proposer will have to change the description in order to avoid proposal id conflicts.\"},\"name()\":{\"details\":\"See {IGovernor-name}.\"},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155BatchReceived}.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155Received}.\"},\"onERC721Received(address,address,uint256,bytes)\":{\"details\":\"See {IERC721Receiver-onERC721Received}.\"},\"proposalDeadline(uint256)\":{\"details\":\"See {IGovernor-proposalDeadline}.\"},\"proposalSnapshot(uint256)\":{\"details\":\"See {IGovernor-proposalSnapshot}.\"},\"proposalThreshold()\":{\"details\":\"Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\"},\"proposalVotes(uint256)\":{\"details\":\"Accessor to the internal vote counts.\"},\"propose(address[],uint256[],bytes[],string)\":{\"details\":\"See {IGovernor-propose}.\"},\"quorum(uint256)\":{\"details\":\"Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\"},\"quorumDenominator()\":{\"details\":\"Returns the quorum denominator. Defaults to 100, but may be overridden.\"},\"quorumNumerator()\":{\"details\":\"Returns the current quorum numerator. See {quorumDenominator}.\"},\"relay(address,uint256,bytes)\":{\"details\":\"Relays a transaction or function call to an arbitrary target. In cases where the governance executor is some contract other than the governor itself, like when using a timelock, this function can be invoked in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake. Note that if the executor is simply the governor itself, use of `relay` is redundant.\"},\"state(uint256)\":{\"details\":\"See {IGovernor-state}.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"updateQuorumNumerator(uint256)\":{\"details\":\"Changes the quorum numerator. Emits a {QuorumNumeratorUpdated} event. Requirements: - Must be called through a governance proposal. - New numerator must be smaller or equal to the denominator.\"},\"version()\":{\"details\":\"See {IGovernor-version}.\"},\"votingDelay()\":{\"details\":\"Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\"},\"votingPeriod()\":{\"details\":\"Delay, in number of blocks, between the vote start and vote ends. NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting duration compared to the voting delay.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"votingDelay()\":{\"notice\":\"module:user-config\"},\"votingPeriod()\":{\"notice\":\"module:user-config\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VeloGovernor.sol\":\"VeloGovernor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VeloGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IGovernor} from \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\nimport {L2GovernorCountingSimple} from \\\"contracts/governance/L2GovernorCountingSimple.sol\\\";\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\nimport {L2GovernorVotesQuorumFraction} from \\\"contracts/governance/L2GovernorVotesQuorumFraction.sol\\\";\\n\\ncontract VeloGovernor is\\n L2Governor,\\n L2GovernorCountingSimple,\\n L2GovernorVotes,\\n L2GovernorVotesQuorumFraction\\n{\\n address public team;\\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\\n uint256 public proposalNumerator = 2; // start at 0.02%\\n\\n constructor(IVotes _ve)\\n L2Governor(\\\"Velodrome Governor\\\")\\n L2GovernorVotes(_ve)\\n L2GovernorVotesQuorumFraction(4) // 4%\\n {\\n team = msg.sender;\\n }\\n\\n function votingDelay() public pure override(IGovernor) returns (uint256) {\\n return 15 minutes; // 1 block\\n }\\n\\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\\n return 1 weeks;\\n }\\n\\n function setTeam(address newTeam) external {\\n require(msg.sender == team, \\\"not team\\\");\\n team = newTeam;\\n }\\n\\n function setProposalNumerator(uint256 numerator) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \\\"numerator too high\\\");\\n proposalNumerator = numerator;\\n }\\n\\n function proposalThreshold()\\n public\\n view\\n override(L2Governor)\\n returns (uint256)\\n {\\n return\\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\\n PROPOSAL_DENOMINATOR;\\n }\\n}\\n\",\"keccak256\":\"0xbdbc34fd1c78fdffb528f7a2f450e75457cb089369204f4671ec241aa0eb3a7e\",\"license\":\"MIT\"},\"contracts/governance/L2Governor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Address.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Context.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\\n *\\n * @dev Core of the governance system, designed to be extended though various modules.\\n *\\n * This contract is abstract and requires several function to be implemented in various modules:\\n *\\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\\n * - A voting module must implement {_getVotes}\\n * - Additionanly, the {votingPeriod} must also be implemented\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\\n using SafeCast for uint256;\\n using Timers for Timers.Timestamp;\\n\\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\\\"Ballot(uint256 proposalId,uint8 support)\\\");\\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\\n keccak256(\\\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\\\");\\n\\n struct ProposalCore {\\n Timers.Timestamp voteStart;\\n Timers.Timestamp voteEnd;\\n bool executed;\\n bool canceled;\\n }\\n\\n string private _name;\\n\\n mapping(uint256 => ProposalCore) private _proposals;\\n\\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\\n\\n /**\\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\\n * parameter setters in {GovernorSettings} are protected using this modifier.\\n *\\n * The governance executing address may be different from the Governor's own address, for example it could be a\\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\\n * for example, additional timelock proposers are not able to change governance parameters without going through the\\n * governance protocol (since v4.6).\\n */\\n modifier onlyGovernance() {\\n require(_msgSender() == _executor(), \\\"Governor: onlyGovernance\\\");\\n if (_executor() != address(this)) {\\n bytes32 msgDataHash = keccak256(_msgData());\\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\\n while (_governanceCall.popFront() != msgDataHash) {}\\n }\\n _;\\n }\\n\\n /**\\n * @dev Sets the value for {name} and {version}\\n */\\n constructor(string memory name_) EIP712(name_, version()) {\\n _name = name_;\\n }\\n\\n /**\\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\\n */\\n receive() external payable virtual {\\n require(_executor() == address(this));\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\\n // include the castVoteWithReasonAndParams() function as standard\\n return\\n interfaceId ==\\n (type(IGovernor).interfaceId ^\\n this.castVoteWithReasonAndParams.selector ^\\n this.castVoteWithReasonAndParamsBySig.selector ^\\n this.getVotesWithParams.selector) ||\\n interfaceId == type(IGovernor).interfaceId ||\\n interfaceId == type(IERC1155Receiver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IGovernor-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IGovernor-version}.\\n */\\n function version() public view virtual override returns (string memory) {\\n return \\\"1\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hashProposal}.\\n *\\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\\n * advance, before the proposal is submitted.\\n *\\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual override returns (uint256) {\\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\\n }\\n\\n /**\\n * @dev See {IGovernor-state}.\\n */\\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n\\n if (proposal.executed) {\\n return ProposalState.Executed;\\n }\\n\\n if (proposal.canceled) {\\n return ProposalState.Canceled;\\n }\\n\\n uint256 start = proposalSnapshot(proposalId);\\n\\n if (start == 0) {\\n revert(\\\"Governor: unknown proposal id\\\");\\n }\\n\\n if (start >= block.timestamp) {\\n return ProposalState.Pending;\\n }\\n\\n uint256 deadline = proposalDeadline(proposalId);\\n\\n if (deadline >= block.timestamp) {\\n return ProposalState.Active;\\n }\\n\\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\\n return ProposalState.Succeeded;\\n } else {\\n return ProposalState.Defeated;\\n }\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalSnapshot}.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteStart.getDeadline();\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalDeadline}.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteEnd.getDeadline();\\n }\\n\\n /**\\n * @dev Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\\n */\\n function proposalThreshold() public view virtual returns (uint256) {\\n return 0;\\n }\\n\\n /**\\n * @dev Amount of votes already cast passes the threshold limit.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Is the proposal successful or not.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) internal view virtual returns (uint256);\\n\\n /**\\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\\n *\\n * Note: Support is generic and can represent various things depending on the voting system used.\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory params\\n ) internal virtual;\\n\\n /**\\n * @dev Default additional encoded parameters used by castVote methods that don't include them\\n *\\n * Note: Should be overridden by specific implementations to use an appropriate value, the\\n * meaning of the additional params, in the context of that implementation\\n */\\n function _defaultParams() internal view virtual returns (bytes memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-propose}.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual override returns (uint256) {\\n require(\\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\\n \\\"Governor: proposer votes below proposal threshold\\\"\\n );\\n\\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\\n\\n require(targets.length == values.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length == calldatas.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length > 0, \\\"Governor: empty proposal\\\");\\n\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(proposal.voteStart.isUnset(), \\\"Governor: proposal already exists\\\");\\n\\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\\n uint64 deadline = start + votingPeriod().toUint64();\\n\\n proposal.voteStart.setDeadline(start);\\n proposal.voteEnd.setDeadline(deadline);\\n\\n emit ProposalCreated(\\n proposalId,\\n _msgSender(),\\n targets,\\n values,\\n new string[](targets.length),\\n calldatas,\\n start,\\n deadline,\\n description\\n );\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-execute}.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual override returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n\\n ProposalState status = state(proposalId);\\n require(\\n status == ProposalState.Succeeded || status == ProposalState.Queued,\\n \\\"Governor: proposal not successful\\\"\\n );\\n _proposals[proposalId].executed = true;\\n\\n emit ProposalExecuted(proposalId);\\n\\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\\n _execute(proposalId, targets, values, calldatas, descriptionHash);\\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\\n */\\n function _execute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n string memory errorMessage = \\\"Governor: call reverted without message\\\";\\n for (uint256 i = 0; i < targets.length; ++i) {\\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\\n Address.verifyCallResult(success, returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Hook before execution is triggered.\\n */\\n function _beforeExecute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory, /* values */\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n for (uint256 i = 0; i < targets.length; ++i) {\\n if (targets[i] == address(this)) {\\n _governanceCall.pushBack(keccak256(calldatas[i]));\\n }\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook after execution is triggered.\\n */\\n function _afterExecute(\\n uint256, /* proposalId */\\n address[] memory, /* targets */\\n uint256[] memory, /* values */\\n bytes[] memory, /* calldatas */\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n if (!_governanceCall.empty()) {\\n _governanceCall.clear();\\n }\\n }\\n }\\n\\n /**\\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\\n * canceled to allow distinguishing it from executed proposals.\\n *\\n * Emits a {IGovernor-ProposalCanceled} event.\\n */\\n function _cancel(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) internal virtual returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n ProposalState status = state(proposalId);\\n\\n require(\\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\\n \\\"Governor: proposal not active\\\"\\n );\\n _proposals[proposalId].canceled = true;\\n\\n emit ProposalCanceled(proposalId);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotes}.\\n */\\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, _defaultParams());\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotesWithParams}.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVote}.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReason}.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteBySig}.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\\n v,\\n r,\\n s\\n );\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(\\n keccak256(\\n abi.encode(\\n EXTENDED_BALLOT_TYPEHASH,\\n proposalId,\\n support,\\n keccak256(bytes(reason)),\\n keccak256(params)\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason\\n ) internal virtual returns (uint256) {\\n return _castVote(proposalId, account, support, reason, _defaultParams());\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason,\\n bytes memory params\\n ) internal virtual returns (uint256) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(state(proposalId) == ProposalState.Active, \\\"Governor: vote not currently active\\\");\\n\\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\\n _countVote(proposalId, account, support, weight, params);\\n\\n if (params.length == 0) {\\n emit VoteCast(account, proposalId, support, weight, reason);\\n } else {\\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\\n }\\n\\n return weight;\\n }\\n\\n /**\\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\\n */\\n function relay(\\n address target,\\n uint256 value,\\n bytes calldata data\\n ) external virtual onlyGovernance {\\n Address.functionCallWithValue(target, data, value);\\n }\\n\\n /**\\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\\n * through another contract such as a timelock.\\n */\\n function _executor() internal view virtual returns (address) {\\n return address(this);\\n }\\n\\n /**\\n * @dev See {IERC721Receiver-onERC721Received}.\\n */\\n function onERC721Received(\\n address,\\n address,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155Received}.\\n */\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\\n */\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] memory,\\n uint256[] memory,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155BatchReceived.selector;\\n }\\n}\\n\",\"keccak256\":\"0xa2846313b89a871807cdebd0225b0bf8f23b17505ab8b3288549ec54a5a4a71b\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorCountingSimple.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\\n *\\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorCountingSimple is L2Governor {\\n /**\\n * @dev Supported vote types. Matches Governor Bravo ordering.\\n */\\n enum VoteType {\\n Against,\\n For,\\n Abstain\\n }\\n\\n struct ProposalVote {\\n uint256 againstVotes;\\n uint256 forVotes;\\n uint256 abstainVotes;\\n mapping(address => bool) hasVoted;\\n }\\n\\n mapping(uint256 => ProposalVote) private _proposalVotes;\\n\\n /**\\n * @dev See {IGovernor-COUNTING_MODE}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual override returns (string memory) {\\n return \\\"support=bravo&quorum=for,abstain\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hasVoted}.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\\n return _proposalVotes[proposalId].hasVoted[account];\\n }\\n\\n /**\\n * @dev Accessor to the internal vote counts.\\n */\\n function proposalVotes(uint256 proposalId)\\n public\\n view\\n virtual\\n returns (\\n uint256 againstVotes,\\n uint256 forVotes,\\n uint256 abstainVotes\\n )\\n {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\\n }\\n\\n /**\\n * @dev See {Governor-_quorumReached}.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return proposalvote.forVotes > proposalvote.againstVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory // params\\n ) internal virtual override {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n require(!proposalvote.hasVoted[account], \\\"GovernorVotingSimple: vote already cast\\\");\\n proposalvote.hasVoted[account] = true;\\n\\n if (support == uint8(VoteType.Against)) {\\n proposalvote.againstVotes += weight;\\n } else if (support == uint8(VoteType.For)) {\\n proposalvote.forVotes += weight;\\n } else if (support == uint8(VoteType.Abstain)) {\\n proposalvote.abstainVotes += weight;\\n } else {\\n revert(\\\"GovernorVotingSimple: invalid value for enum VoteType\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xdc37daa24118a6e6ba5208b4abefa1632af2ff340135ca6c6d7237f70102d5db\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotes is L2Governor {\\n IVotes public immutable token;\\n\\n constructor(IVotes tokenAddress) {\\n token = tokenAddress;\\n }\\n\\n /**\\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory /*params*/\\n ) internal view virtual override returns (uint256) {\\n return token.getPastVotes(account, blockTimestamp);\\n }\\n}\\n\",\"keccak256\":\"0x605a7de71228dda3cb8fd878cac313a86bc5841fd34d7344214346ba46e63af1\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotesQuorumFraction.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\\n * fraction of the total supply.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\\n uint256 private _quorumNumerator;\\n\\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\\n\\n /**\\n * @dev Initialize quorum as a fraction of the token's total supply.\\n *\\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\\n * customized by overriding {quorumDenominator}.\\n */\\n constructor(uint256 quorumNumeratorValue) {\\n _updateQuorumNumerator(quorumNumeratorValue);\\n }\\n\\n /**\\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\\n */\\n function quorumNumerator() public view virtual returns (uint256) {\\n return _quorumNumerator;\\n }\\n\\n /**\\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\\n */\\n function quorumDenominator() public view virtual returns (uint256) {\\n return 100;\\n }\\n\\n /**\\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\\n */\\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - Must be called through a governance proposal.\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\\n _updateQuorumNumerator(newQuorumNumerator);\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\\n require(\\n newQuorumNumerator <= quorumDenominator(),\\n \\\"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\\\"\\n );\\n\\n uint256 oldQuorumNumerator = _quorumNumerator;\\n _quorumNumerator = newQuorumNumerator;\\n\\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\\n }\\n}\\n\",\"keccak256\":\"0xe66d29c0ffd2274de933d80e11d68891f3acc3f078be4560a2b493b7d88dcb7f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Interface of the {Governor} core.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract IGovernor is IERC165 {\\n enum ProposalState {\\n Pending,\\n Active,\\n Canceled,\\n Defeated,\\n Succeeded,\\n Queued,\\n Expired,\\n Executed\\n }\\n\\n /**\\n * @dev Emitted when a proposal is created.\\n */\\n event ProposalCreated(\\n uint256 proposalId,\\n address proposer,\\n address[] targets,\\n uint256[] values,\\n string[] signatures,\\n bytes[] calldatas,\\n uint256 startBlock,\\n uint256 endBlock,\\n string description\\n );\\n\\n /**\\n * @dev Emitted when a proposal is canceled.\\n */\\n event ProposalCanceled(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a proposal is executed.\\n */\\n event ProposalExecuted(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a vote is cast without params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n */\\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\\n\\n /**\\n * @dev Emitted when a vote is cast with params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\\n */\\n event VoteCastWithParams(\\n address indexed voter,\\n uint256 proposalId,\\n uint8 support,\\n uint256 weight,\\n string reason,\\n bytes params\\n );\\n\\n /**\\n * @notice module:core\\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\\n */\\n function name() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \\\"1\\\"\\n */\\n function version() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:voting\\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\\n *\\n * There are 2 standard keys: `support` and `quorum`.\\n *\\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\\n * - `quorum=bravo` means that only For votes are counted towards quorum.\\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\\n *\\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\\n * name that describes the behavior. For example:\\n *\\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\\n *\\n * NOTE: The string can be decoded by the standard\\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\\n * JavaScript class.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Current state of a proposal, following Compound's convention\\n */\\n function state(uint256 proposalId) public view virtual returns (ProposalState);\\n\\n /**\\n * @notice module:core\\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\\n * beginning of the following block.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\\n * during this block.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\\n */\\n function votingDelay() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of blocks, between the vote start and vote ends.\\n *\\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\\n * duration compared to the voting delay.\\n */\\n function votingPeriod() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Minimum number of cast voted required for a proposal to be successful.\\n *\\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\\n */\\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber`.\\n *\\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\\n * multiple), {ERC20Votes} tokens.\\n */\\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockNumber,\\n bytes memory params\\n ) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:voting\\n * @dev Returns whether `account` has cast a vote on `proposalId`.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\\n\\n /**\\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\\n * {IGovernor-votingPeriod} blocks after the voting starts.\\n *\\n * Emits a {ProposalCreated} event.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\\n * deadline to be reached.\\n *\\n * Emits a {ProposalExecuted} event.\\n *\\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Cast a vote\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xa52d593ff06a2353f78fa149da31f2ca94f03d1eff99bde41977fa2fe985a92f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2e53602b96c1bf97c731ed3e2a981b4f85e23a9410a5ebd36e549a4cc93340dc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x2626d8ab3dfdad0fad630c212ad146d59473d0f48b771784c61a7c1dbbea1f3f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Tooling for timepoints, timers and delays\\n */\\nlibrary Timers {\\n struct Timestamp {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(Timestamp storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(Timestamp memory timer) internal view returns (bool) {\\n return timer._deadline > block.timestamp;\\n }\\n\\n function isExpired(Timestamp memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.timestamp;\\n }\\n\\n struct BlockNumber {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(BlockNumber storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(BlockNumber memory timer) internal view returns (bool) {\\n return timer._deadline > block.number;\\n }\\n\\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.number;\\n }\\n}\\n\",\"keccak256\":\"0x29791a62950a7983e02a673639c1a781d1e448691800456c2ce4b99715391b14\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS,\\n InvalidSignatureV // Deprecated in v4.8\\n }\\n\\n function _throwError(RecoverError error) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert(\\\"ECDSA: invalid signature\\\");\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert(\\\"ECDSA: invalid signature 's' value\\\");\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature` or error string. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\\n if (signature.length == 65) {\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n /// @solidity memory-safe-assembly\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n return tryRecover(hash, v, r, s);\\n } else {\\n return (address(0), RecoverError.InvalidSignatureLength);\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, signature);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n *\\n * _Available since v4.2._\\n */\\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature);\\n }\\n\\n return (signer, RecoverError.NoError);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from `s`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", Strings.toString(s.length), s));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Typed Data, created from a\\n * `domainSeparator` and a `structHash`. This produces hash corresponding\\n * to the one signed with the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\\n * JSON-RPC method as part of EIP-712.\\n *\\n * See {recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n }\\n}\\n\",\"keccak256\":\"0x54ee424bfc83ce63b2a918b9a1efb5090a0fb68dbd1de3b10bc667776885dd4f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ECDSA.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n /* solhint-disable var-name-mixedcase */\\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n // invalidate the cached domain separator if the chain id changes.\\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n uint256 private immutable _CACHED_CHAIN_ID;\\n address private immutable _CACHED_THIS;\\n\\n bytes32 private immutable _HASHED_NAME;\\n bytes32 private immutable _HASHED_VERSION;\\n bytes32 private immutable _TYPE_HASH;\\n\\n /* solhint-enable var-name-mixedcase */\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n constructor(string memory name, string memory version) {\\n bytes32 hashedName = keccak256(bytes(name));\\n bytes32 hashedVersion = keccak256(bytes(version));\\n bytes32 typeHash = keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n );\\n _HASHED_NAME = hashedName;\\n _HASHED_VERSION = hashedVersion;\\n _CACHED_CHAIN_ID = block.chainid;\\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n _CACHED_THIS = address(this);\\n _TYPE_HASH = typeHash;\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\\n return _CACHED_DOMAIN_SEPARATOR;\\n } else {\\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n }\\n }\\n\\n function _buildDomainSeparator(\\n bytes32 typeHash,\\n bytes32 nameHash,\\n bytes32 versionHash\\n ) private view returns (bytes32) {\\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\\n }\\n}\\n\",\"keccak256\":\"0x948d8b2d18f38141ec78c5229d770d950ebc781ed3f44cc9e3ccbb9fded5846a\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\\n\\nimport \\\"./EIP712.sol\\\";\\n\",\"keccak256\":\"0xea30c402170bc240354b74e6c6f6a8e5bdb1935d90d168cc58c0654461c6a72b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3546b156d97633f7f8cad536d5454c81d1d604687c02b2eb105fdc33cb962b41\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\\npragma solidity ^0.8.4;\\n\\nimport \\\"../math/SafeCast.sol\\\";\\n\\n/**\\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\\n * the existing queue contents are left in storage.\\n *\\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\\n * used in storage, and not in memory.\\n * ```\\n * DoubleEndedQueue.Bytes32Deque queue;\\n * ```\\n *\\n * _Available since v4.6._\\n */\\nlibrary DoubleEndedQueue {\\n /**\\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\\n */\\n error Empty();\\n\\n /**\\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\\n */\\n error OutOfBounds();\\n\\n /**\\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\\n *\\n * Struct members have an underscore prefix indicating that they are \\\"private\\\" and should not be read or written to\\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\\n * lead to unexpected behavior.\\n *\\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\\n * data[end - 1].\\n */\\n struct Bytes32Deque {\\n int128 _begin;\\n int128 _end;\\n mapping(int128 => bytes32) _data;\\n }\\n\\n /**\\n * @dev Inserts an item at the end of the queue.\\n */\\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 backIndex = deque._end;\\n deque._data[backIndex] = value;\\n unchecked {\\n deque._end = backIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Removes the item at the end of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n value = deque._data[backIndex];\\n delete deque._data[backIndex];\\n deque._end = backIndex;\\n }\\n\\n /**\\n * @dev Inserts an item at the beginning of the queue.\\n */\\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 frontIndex;\\n unchecked {\\n frontIndex = deque._begin - 1;\\n }\\n deque._data[frontIndex] = value;\\n deque._begin = frontIndex;\\n }\\n\\n /**\\n * @dev Removes the item at the beginning of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n value = deque._data[frontIndex];\\n delete deque._data[frontIndex];\\n unchecked {\\n deque._begin = frontIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Returns the item at the beginning of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n return deque._data[frontIndex];\\n }\\n\\n /**\\n * @dev Returns the item at the end of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n return deque._data[backIndex];\\n }\\n\\n /**\\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\\n * `length(deque) - 1`.\\n *\\n * Reverts with `OutOfBounds` if the index is out of bounds.\\n */\\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\\n // int256(deque._begin) is a safe upcast\\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\\n if (idx >= deque._end) revert OutOfBounds();\\n return deque._data[idx];\\n }\\n\\n /**\\n * @dev Resets the queue back to being empty.\\n *\\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\\n * out on potential gas refunds.\\n */\\n function clear(Bytes32Deque storage deque) internal {\\n deque._begin = 0;\\n deque._end = 0;\\n }\\n\\n /**\\n * @dev Returns the number of items in the queue.\\n */\\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\\n // We also assume there are at most int256.max items in the queue.\\n unchecked {\\n return uint256(int256(deque._end) - int256(deque._begin));\\n }\\n }\\n\\n /**\\n * @dev Returns true if the queue is empty.\\n */\\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\\n return deque._end <= deque._begin;\\n }\\n}\\n\",\"keccak256\":\"0x4859ffd6dd69382a1462930c00b6e394007da80e78e510f56930271034737bf2\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x61016060405260026007553480156200001757600080fd5b506040516200328f3803806200328f8339810160408190526200003a91620002e1565b600481604051806040016040528060128152602001712b32b637b23937b6b29023b7bb32b93737b960711b81525080620000796200015360201b60201c565b815160208084019190912082518383012060e08290526101008190524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81880181905281830187905260608201869052608082019490945230818401528151808203909301835260c00190528051940193909320919290916080523060c05261012052505082516200011f92506000915060208401906200023b565b50506001600160a01b03166101405262000139816200016e565b5050600680546001600160a01b031916331790556200034f565b6040805180820190915260018152603160f81b602082015290565b6064811115620001f65760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a40160405180910390fd5b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b828054620002499062000313565b90600052602060002090601f0160209004810192826200026d5760008555620002b8565b82601f106200028857805160ff1916838001178555620002b8565b82800160010185558215620002b8579182015b82811115620002b85782518255916020019190600101906200029b565b50620002c6929150620002ca565b5090565b5b80821115620002c65760008155600101620002cb565b600060208284031215620002f457600080fd5b81516001600160a01b03811681146200030c57600080fd5b9392505050565b600181811c908216806200032857607f821691505b6020821081036200034957634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e051610100516101205161014051612ed0620003bf600039600081816107df0152818161120f015281816113e40152611a0601526000611b2301526000611b7201526000611b4d01526000611aa601526000611ad001526000611afa0152612ed06000f3fe6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220da19b0886c70f281039e6002f39d70a76440f06ae01c8b38d718c3ab4457695f64736f6c634300080d0033", - "deployedBytecode": "0x6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220da19b0886c70f281039e6002f39d70a76440f06ae01c8b38d718c3ab4457695f64736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"_ve\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"Empty\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"proposer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"string[]\",\"name\":\"signatures\",\"type\":\"string[]\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"ProposalCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldQuorumNumerator\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"QuorumNumeratorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"VoteCast\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"VoteCastWithParams\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"COUNTING_MODE\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EXTENDED_BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_PROPOSAL_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROPOSAL_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"}],\"name\":\"castVote\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"castVoteWithReason\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"castVoteWithReasonAndParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteWithReasonAndParamsBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"execute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"getVotesWithParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasVoted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"hashProposal\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalDeadline\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalSnapshot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"againstVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"forVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"abstainVotes\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"propose\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"quorum\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumDenominator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"}],\"name\":\"setProposalNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTeam\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"state\",\"outputs\":[{\"internalType\":\"enum IGovernor.ProposalState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"updateQuorumNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"Empty()\":[{\"details\":\"An operation (e.g. {front}) couldn't be completed due to the queue being empty.\"}]},\"kind\":\"dev\",\"methods\":{\"COUNTING_MODE()\":{\"details\":\"See {IGovernor-COUNTING_MODE}.\"},\"castVote(uint256,uint8)\":{\"details\":\"See {IGovernor-castVote}.\"},\"castVoteBySig(uint256,uint8,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteBySig}.\"},\"castVoteWithReason(uint256,uint8,string)\":{\"details\":\"See {IGovernor-castVoteWithReason}.\"},\"castVoteWithReasonAndParams(uint256,uint8,string,bytes)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParams}.\"},\"castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParamsBySig}.\"},\"execute(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-execute}.\"},\"getVotes(address,uint256)\":{\"details\":\"See {IGovernor-getVotes}.\"},\"getVotesWithParams(address,uint256,bytes)\":{\"details\":\"See {IGovernor-getVotesWithParams}.\"},\"hasVoted(uint256,address)\":{\"details\":\"See {IGovernor-hasVoted}.\"},\"hashProposal(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-hashProposal}. The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in advance, before the proposal is submitted. Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the same proposal (with same operation and same description) will have the same id if submitted on multiple governors across multiple networks. This also means that in order to execute the same operation twice (on the same governor) the proposer will have to change the description in order to avoid proposal id conflicts.\"},\"name()\":{\"details\":\"See {IGovernor-name}.\"},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155BatchReceived}.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155Received}.\"},\"onERC721Received(address,address,uint256,bytes)\":{\"details\":\"See {IERC721Receiver-onERC721Received}.\"},\"proposalDeadline(uint256)\":{\"details\":\"See {IGovernor-proposalDeadline}.\"},\"proposalSnapshot(uint256)\":{\"details\":\"See {IGovernor-proposalSnapshot}.\"},\"proposalThreshold()\":{\"details\":\"Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\"},\"proposalVotes(uint256)\":{\"details\":\"Accessor to the internal vote counts.\"},\"propose(address[],uint256[],bytes[],string)\":{\"details\":\"See {IGovernor-propose}.\"},\"quorum(uint256)\":{\"details\":\"Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\"},\"quorumDenominator()\":{\"details\":\"Returns the quorum denominator. Defaults to 100, but may be overridden.\"},\"quorumNumerator()\":{\"details\":\"Returns the current quorum numerator. See {quorumDenominator}.\"},\"relay(address,uint256,bytes)\":{\"details\":\"Relays a transaction or function call to an arbitrary target. In cases where the governance executor is some contract other than the governor itself, like when using a timelock, this function can be invoked in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake. Note that if the executor is simply the governor itself, use of `relay` is redundant.\"},\"state(uint256)\":{\"details\":\"See {IGovernor-state}.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"updateQuorumNumerator(uint256)\":{\"details\":\"Changes the quorum numerator. Emits a {QuorumNumeratorUpdated} event. Requirements: - Must be called through a governance proposal. - New numerator must be smaller or equal to the denominator.\"},\"version()\":{\"details\":\"See {IGovernor-version}.\"},\"votingDelay()\":{\"details\":\"Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\"},\"votingPeriod()\":{\"details\":\"Delay, in number of blocks, between the vote start and vote ends. NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting duration compared to the voting delay.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"votingDelay()\":{\"notice\":\"module:user-config\"},\"votingPeriod()\":{\"notice\":\"module:user-config\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VeloGovernor.sol\":\"VeloGovernor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VeloGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IGovernor} from \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\nimport {L2GovernorCountingSimple} from \\\"contracts/governance/L2GovernorCountingSimple.sol\\\";\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\nimport {L2GovernorVotesQuorumFraction} from \\\"contracts/governance/L2GovernorVotesQuorumFraction.sol\\\";\\n\\ncontract VeloGovernor is\\n L2Governor,\\n L2GovernorCountingSimple,\\n L2GovernorVotes,\\n L2GovernorVotesQuorumFraction\\n{\\n address public team;\\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\\n uint256 public proposalNumerator = 2; // start at 0.02%\\n\\n constructor(IVotes _ve)\\n L2Governor(\\\"Velodrome Governor\\\")\\n L2GovernorVotes(_ve)\\n L2GovernorVotesQuorumFraction(4) // 4%\\n {\\n team = msg.sender;\\n }\\n\\n function votingDelay() public pure override(IGovernor) returns (uint256) {\\n return 15 minutes; // 1 block\\n }\\n\\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\\n return 1 weeks;\\n }\\n\\n function setTeam(address newTeam) external {\\n require(msg.sender == team, \\\"not team\\\");\\n team = newTeam;\\n }\\n\\n function setProposalNumerator(uint256 numerator) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \\\"numerator too high\\\");\\n proposalNumerator = numerator;\\n }\\n\\n function proposalThreshold()\\n public\\n view\\n override(L2Governor)\\n returns (uint256)\\n {\\n return\\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\\n PROPOSAL_DENOMINATOR;\\n }\\n}\\n\",\"keccak256\":\"0xbdbc34fd1c78fdffb528f7a2f450e75457cb089369204f4671ec241aa0eb3a7e\",\"license\":\"MIT\"},\"contracts/governance/L2Governor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Address.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Context.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\\n *\\n * @dev Core of the governance system, designed to be extended though various modules.\\n *\\n * This contract is abstract and requires several function to be implemented in various modules:\\n *\\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\\n * - A voting module must implement {_getVotes}\\n * - Additionanly, the {votingPeriod} must also be implemented\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\\n using SafeCast for uint256;\\n using Timers for Timers.Timestamp;\\n\\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\\\"Ballot(uint256 proposalId,uint8 support)\\\");\\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\\n keccak256(\\\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\\\");\\n\\n struct ProposalCore {\\n Timers.Timestamp voteStart;\\n Timers.Timestamp voteEnd;\\n bool executed;\\n bool canceled;\\n }\\n\\n string private _name;\\n\\n mapping(uint256 => ProposalCore) private _proposals;\\n\\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\\n\\n /**\\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\\n * parameter setters in {GovernorSettings} are protected using this modifier.\\n *\\n * The governance executing address may be different from the Governor's own address, for example it could be a\\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\\n * for example, additional timelock proposers are not able to change governance parameters without going through the\\n * governance protocol (since v4.6).\\n */\\n modifier onlyGovernance() {\\n require(_msgSender() == _executor(), \\\"Governor: onlyGovernance\\\");\\n if (_executor() != address(this)) {\\n bytes32 msgDataHash = keccak256(_msgData());\\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\\n while (_governanceCall.popFront() != msgDataHash) {}\\n }\\n _;\\n }\\n\\n /**\\n * @dev Sets the value for {name} and {version}\\n */\\n constructor(string memory name_) EIP712(name_, version()) {\\n _name = name_;\\n }\\n\\n /**\\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\\n */\\n receive() external payable virtual {\\n require(_executor() == address(this));\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\\n // include the castVoteWithReasonAndParams() function as standard\\n return\\n interfaceId ==\\n (type(IGovernor).interfaceId ^\\n this.castVoteWithReasonAndParams.selector ^\\n this.castVoteWithReasonAndParamsBySig.selector ^\\n this.getVotesWithParams.selector) ||\\n interfaceId == type(IGovernor).interfaceId ||\\n interfaceId == type(IERC1155Receiver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IGovernor-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IGovernor-version}.\\n */\\n function version() public view virtual override returns (string memory) {\\n return \\\"1\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hashProposal}.\\n *\\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\\n * advance, before the proposal is submitted.\\n *\\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual override returns (uint256) {\\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\\n }\\n\\n /**\\n * @dev See {IGovernor-state}.\\n */\\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n\\n if (proposal.executed) {\\n return ProposalState.Executed;\\n }\\n\\n if (proposal.canceled) {\\n return ProposalState.Canceled;\\n }\\n\\n uint256 start = proposalSnapshot(proposalId);\\n\\n if (start == 0) {\\n revert(\\\"Governor: unknown proposal id\\\");\\n }\\n\\n if (start >= block.timestamp) {\\n return ProposalState.Pending;\\n }\\n\\n uint256 deadline = proposalDeadline(proposalId);\\n\\n if (deadline >= block.timestamp) {\\n return ProposalState.Active;\\n }\\n\\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\\n return ProposalState.Succeeded;\\n } else {\\n return ProposalState.Defeated;\\n }\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalSnapshot}.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteStart.getDeadline();\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalDeadline}.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteEnd.getDeadline();\\n }\\n\\n /**\\n * @dev Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\\n */\\n function proposalThreshold() public view virtual returns (uint256) {\\n return 0;\\n }\\n\\n /**\\n * @dev Amount of votes already cast passes the threshold limit.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Is the proposal successful or not.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) internal view virtual returns (uint256);\\n\\n /**\\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\\n *\\n * Note: Support is generic and can represent various things depending on the voting system used.\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory params\\n ) internal virtual;\\n\\n /**\\n * @dev Default additional encoded parameters used by castVote methods that don't include them\\n *\\n * Note: Should be overridden by specific implementations to use an appropriate value, the\\n * meaning of the additional params, in the context of that implementation\\n */\\n function _defaultParams() internal view virtual returns (bytes memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-propose}.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual override returns (uint256) {\\n require(\\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\\n \\\"Governor: proposer votes below proposal threshold\\\"\\n );\\n\\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\\n\\n require(targets.length == values.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length == calldatas.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length > 0, \\\"Governor: empty proposal\\\");\\n\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(proposal.voteStart.isUnset(), \\\"Governor: proposal already exists\\\");\\n\\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\\n uint64 deadline = start + votingPeriod().toUint64();\\n\\n proposal.voteStart.setDeadline(start);\\n proposal.voteEnd.setDeadline(deadline);\\n\\n emit ProposalCreated(\\n proposalId,\\n _msgSender(),\\n targets,\\n values,\\n new string[](targets.length),\\n calldatas,\\n start,\\n deadline,\\n description\\n );\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-execute}.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual override returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n\\n ProposalState status = state(proposalId);\\n require(\\n status == ProposalState.Succeeded || status == ProposalState.Queued,\\n \\\"Governor: proposal not successful\\\"\\n );\\n _proposals[proposalId].executed = true;\\n\\n emit ProposalExecuted(proposalId);\\n\\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\\n _execute(proposalId, targets, values, calldatas, descriptionHash);\\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\\n */\\n function _execute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n string memory errorMessage = \\\"Governor: call reverted without message\\\";\\n for (uint256 i = 0; i < targets.length; ++i) {\\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\\n Address.verifyCallResult(success, returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Hook before execution is triggered.\\n */\\n function _beforeExecute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory, /* values */\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n for (uint256 i = 0; i < targets.length; ++i) {\\n if (targets[i] == address(this)) {\\n _governanceCall.pushBack(keccak256(calldatas[i]));\\n }\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook after execution is triggered.\\n */\\n function _afterExecute(\\n uint256, /* proposalId */\\n address[] memory, /* targets */\\n uint256[] memory, /* values */\\n bytes[] memory, /* calldatas */\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n if (!_governanceCall.empty()) {\\n _governanceCall.clear();\\n }\\n }\\n }\\n\\n /**\\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\\n * canceled to allow distinguishing it from executed proposals.\\n *\\n * Emits a {IGovernor-ProposalCanceled} event.\\n */\\n function _cancel(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) internal virtual returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n ProposalState status = state(proposalId);\\n\\n require(\\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\\n \\\"Governor: proposal not active\\\"\\n );\\n _proposals[proposalId].canceled = true;\\n\\n emit ProposalCanceled(proposalId);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotes}.\\n */\\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, _defaultParams());\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotesWithParams}.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVote}.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReason}.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteBySig}.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\\n v,\\n r,\\n s\\n );\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(\\n keccak256(\\n abi.encode(\\n EXTENDED_BALLOT_TYPEHASH,\\n proposalId,\\n support,\\n keccak256(bytes(reason)),\\n keccak256(params)\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason\\n ) internal virtual returns (uint256) {\\n return _castVote(proposalId, account, support, reason, _defaultParams());\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason,\\n bytes memory params\\n ) internal virtual returns (uint256) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(state(proposalId) == ProposalState.Active, \\\"Governor: vote not currently active\\\");\\n\\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\\n _countVote(proposalId, account, support, weight, params);\\n\\n if (params.length == 0) {\\n emit VoteCast(account, proposalId, support, weight, reason);\\n } else {\\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\\n }\\n\\n return weight;\\n }\\n\\n /**\\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\\n */\\n function relay(\\n address target,\\n uint256 value,\\n bytes calldata data\\n ) external virtual onlyGovernance {\\n Address.functionCallWithValue(target, data, value);\\n }\\n\\n /**\\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\\n * through another contract such as a timelock.\\n */\\n function _executor() internal view virtual returns (address) {\\n return address(this);\\n }\\n\\n /**\\n * @dev See {IERC721Receiver-onERC721Received}.\\n */\\n function onERC721Received(\\n address,\\n address,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155Received}.\\n */\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\\n */\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] memory,\\n uint256[] memory,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155BatchReceived.selector;\\n }\\n}\\n\",\"keccak256\":\"0xa2846313b89a871807cdebd0225b0bf8f23b17505ab8b3288549ec54a5a4a71b\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorCountingSimple.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\\n *\\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorCountingSimple is L2Governor {\\n /**\\n * @dev Supported vote types. Matches Governor Bravo ordering.\\n */\\n enum VoteType {\\n Against,\\n For,\\n Abstain\\n }\\n\\n struct ProposalVote {\\n uint256 againstVotes;\\n uint256 forVotes;\\n uint256 abstainVotes;\\n mapping(address => bool) hasVoted;\\n }\\n\\n mapping(uint256 => ProposalVote) private _proposalVotes;\\n\\n /**\\n * @dev See {IGovernor-COUNTING_MODE}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual override returns (string memory) {\\n return \\\"support=bravo&quorum=for,abstain\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hasVoted}.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\\n return _proposalVotes[proposalId].hasVoted[account];\\n }\\n\\n /**\\n * @dev Accessor to the internal vote counts.\\n */\\n function proposalVotes(uint256 proposalId)\\n public\\n view\\n virtual\\n returns (\\n uint256 againstVotes,\\n uint256 forVotes,\\n uint256 abstainVotes\\n )\\n {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\\n }\\n\\n /**\\n * @dev See {Governor-_quorumReached}.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return proposalvote.forVotes > proposalvote.againstVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory // params\\n ) internal virtual override {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n require(!proposalvote.hasVoted[account], \\\"GovernorVotingSimple: vote already cast\\\");\\n proposalvote.hasVoted[account] = true;\\n\\n if (support == uint8(VoteType.Against)) {\\n proposalvote.againstVotes += weight;\\n } else if (support == uint8(VoteType.For)) {\\n proposalvote.forVotes += weight;\\n } else if (support == uint8(VoteType.Abstain)) {\\n proposalvote.abstainVotes += weight;\\n } else {\\n revert(\\\"GovernorVotingSimple: invalid value for enum VoteType\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xdc37daa24118a6e6ba5208b4abefa1632af2ff340135ca6c6d7237f70102d5db\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotes is L2Governor {\\n IVotes public immutable token;\\n\\n constructor(IVotes tokenAddress) {\\n token = tokenAddress;\\n }\\n\\n /**\\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory /*params*/\\n ) internal view virtual override returns (uint256) {\\n return token.getPastVotes(account, blockTimestamp);\\n }\\n}\\n\",\"keccak256\":\"0x605a7de71228dda3cb8fd878cac313a86bc5841fd34d7344214346ba46e63af1\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotesQuorumFraction.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\\n * fraction of the total supply.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\\n uint256 private _quorumNumerator;\\n\\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\\n\\n /**\\n * @dev Initialize quorum as a fraction of the token's total supply.\\n *\\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\\n * customized by overriding {quorumDenominator}.\\n */\\n constructor(uint256 quorumNumeratorValue) {\\n _updateQuorumNumerator(quorumNumeratorValue);\\n }\\n\\n /**\\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\\n */\\n function quorumNumerator() public view virtual returns (uint256) {\\n return _quorumNumerator;\\n }\\n\\n /**\\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\\n */\\n function quorumDenominator() public view virtual returns (uint256) {\\n return 100;\\n }\\n\\n /**\\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\\n */\\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - Must be called through a governance proposal.\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\\n _updateQuorumNumerator(newQuorumNumerator);\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\\n require(\\n newQuorumNumerator <= quorumDenominator(),\\n \\\"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\\\"\\n );\\n\\n uint256 oldQuorumNumerator = _quorumNumerator;\\n _quorumNumerator = newQuorumNumerator;\\n\\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\\n }\\n}\\n\",\"keccak256\":\"0xe66d29c0ffd2274de933d80e11d68891f3acc3f078be4560a2b493b7d88dcb7f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Interface of the {Governor} core.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract IGovernor is IERC165 {\\n enum ProposalState {\\n Pending,\\n Active,\\n Canceled,\\n Defeated,\\n Succeeded,\\n Queued,\\n Expired,\\n Executed\\n }\\n\\n /**\\n * @dev Emitted when a proposal is created.\\n */\\n event ProposalCreated(\\n uint256 proposalId,\\n address proposer,\\n address[] targets,\\n uint256[] values,\\n string[] signatures,\\n bytes[] calldatas,\\n uint256 startBlock,\\n uint256 endBlock,\\n string description\\n );\\n\\n /**\\n * @dev Emitted when a proposal is canceled.\\n */\\n event ProposalCanceled(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a proposal is executed.\\n */\\n event ProposalExecuted(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a vote is cast without params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n */\\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\\n\\n /**\\n * @dev Emitted when a vote is cast with params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\\n */\\n event VoteCastWithParams(\\n address indexed voter,\\n uint256 proposalId,\\n uint8 support,\\n uint256 weight,\\n string reason,\\n bytes params\\n );\\n\\n /**\\n * @notice module:core\\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\\n */\\n function name() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \\\"1\\\"\\n */\\n function version() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:voting\\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\\n *\\n * There are 2 standard keys: `support` and `quorum`.\\n *\\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\\n * - `quorum=bravo` means that only For votes are counted towards quorum.\\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\\n *\\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\\n * name that describes the behavior. For example:\\n *\\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\\n *\\n * NOTE: The string can be decoded by the standard\\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\\n * JavaScript class.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Current state of a proposal, following Compound's convention\\n */\\n function state(uint256 proposalId) public view virtual returns (ProposalState);\\n\\n /**\\n * @notice module:core\\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\\n * beginning of the following block.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\\n * during this block.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\\n */\\n function votingDelay() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of blocks, between the vote start and vote ends.\\n *\\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\\n * duration compared to the voting delay.\\n */\\n function votingPeriod() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Minimum number of cast voted required for a proposal to be successful.\\n *\\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\\n */\\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber`.\\n *\\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\\n * multiple), {ERC20Votes} tokens.\\n */\\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockNumber,\\n bytes memory params\\n ) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:voting\\n * @dev Returns whether `account` has cast a vote on `proposalId`.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\\n\\n /**\\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\\n * {IGovernor-votingPeriod} blocks after the voting starts.\\n *\\n * Emits a {ProposalCreated} event.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\\n * deadline to be reached.\\n *\\n * Emits a {ProposalExecuted} event.\\n *\\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Cast a vote\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xa52d593ff06a2353f78fa149da31f2ca94f03d1eff99bde41977fa2fe985a92f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2e53602b96c1bf97c731ed3e2a981b4f85e23a9410a5ebd36e549a4cc93340dc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x2626d8ab3dfdad0fad630c212ad146d59473d0f48b771784c61a7c1dbbea1f3f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Tooling for timepoints, timers and delays\\n */\\nlibrary Timers {\\n struct Timestamp {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(Timestamp storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(Timestamp memory timer) internal view returns (bool) {\\n return timer._deadline > block.timestamp;\\n }\\n\\n function isExpired(Timestamp memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.timestamp;\\n }\\n\\n struct BlockNumber {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(BlockNumber storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(BlockNumber memory timer) internal view returns (bool) {\\n return timer._deadline > block.number;\\n }\\n\\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.number;\\n }\\n}\\n\",\"keccak256\":\"0x29791a62950a7983e02a673639c1a781d1e448691800456c2ce4b99715391b14\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS,\\n InvalidSignatureV // Deprecated in v4.8\\n }\\n\\n function _throwError(RecoverError error) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert(\\\"ECDSA: invalid signature\\\");\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert(\\\"ECDSA: invalid signature 's' value\\\");\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature` or error string. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\\n if (signature.length == 65) {\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n /// @solidity memory-safe-assembly\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n return tryRecover(hash, v, r, s);\\n } else {\\n return (address(0), RecoverError.InvalidSignatureLength);\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, signature);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n *\\n * _Available since v4.2._\\n */\\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature);\\n }\\n\\n return (signer, RecoverError.NoError);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from `s`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", Strings.toString(s.length), s));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Typed Data, created from a\\n * `domainSeparator` and a `structHash`. This produces hash corresponding\\n * to the one signed with the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\\n * JSON-RPC method as part of EIP-712.\\n *\\n * See {recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n }\\n}\\n\",\"keccak256\":\"0x54ee424bfc83ce63b2a918b9a1efb5090a0fb68dbd1de3b10bc667776885dd4f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ECDSA.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n /* solhint-disable var-name-mixedcase */\\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n // invalidate the cached domain separator if the chain id changes.\\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n uint256 private immutable _CACHED_CHAIN_ID;\\n address private immutable _CACHED_THIS;\\n\\n bytes32 private immutable _HASHED_NAME;\\n bytes32 private immutable _HASHED_VERSION;\\n bytes32 private immutable _TYPE_HASH;\\n\\n /* solhint-enable var-name-mixedcase */\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n constructor(string memory name, string memory version) {\\n bytes32 hashedName = keccak256(bytes(name));\\n bytes32 hashedVersion = keccak256(bytes(version));\\n bytes32 typeHash = keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n );\\n _HASHED_NAME = hashedName;\\n _HASHED_VERSION = hashedVersion;\\n _CACHED_CHAIN_ID = block.chainid;\\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n _CACHED_THIS = address(this);\\n _TYPE_HASH = typeHash;\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\\n return _CACHED_DOMAIN_SEPARATOR;\\n } else {\\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n }\\n }\\n\\n function _buildDomainSeparator(\\n bytes32 typeHash,\\n bytes32 nameHash,\\n bytes32 versionHash\\n ) private view returns (bytes32) {\\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\\n }\\n}\\n\",\"keccak256\":\"0x948d8b2d18f38141ec78c5229d770d950ebc781ed3f44cc9e3ccbb9fded5846a\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\\n\\nimport \\\"./EIP712.sol\\\";\\n\",\"keccak256\":\"0xea30c402170bc240354b74e6c6f6a8e5bdb1935d90d168cc58c0654461c6a72b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3546b156d97633f7f8cad536d5454c81d1d604687c02b2eb105fdc33cb962b41\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\\npragma solidity ^0.8.4;\\n\\nimport \\\"../math/SafeCast.sol\\\";\\n\\n/**\\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\\n * the existing queue contents are left in storage.\\n *\\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\\n * used in storage, and not in memory.\\n * ```\\n * DoubleEndedQueue.Bytes32Deque queue;\\n * ```\\n *\\n * _Available since v4.6._\\n */\\nlibrary DoubleEndedQueue {\\n /**\\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\\n */\\n error Empty();\\n\\n /**\\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\\n */\\n error OutOfBounds();\\n\\n /**\\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\\n *\\n * Struct members have an underscore prefix indicating that they are \\\"private\\\" and should not be read or written to\\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\\n * lead to unexpected behavior.\\n *\\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\\n * data[end - 1].\\n */\\n struct Bytes32Deque {\\n int128 _begin;\\n int128 _end;\\n mapping(int128 => bytes32) _data;\\n }\\n\\n /**\\n * @dev Inserts an item at the end of the queue.\\n */\\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 backIndex = deque._end;\\n deque._data[backIndex] = value;\\n unchecked {\\n deque._end = backIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Removes the item at the end of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n value = deque._data[backIndex];\\n delete deque._data[backIndex];\\n deque._end = backIndex;\\n }\\n\\n /**\\n * @dev Inserts an item at the beginning of the queue.\\n */\\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 frontIndex;\\n unchecked {\\n frontIndex = deque._begin - 1;\\n }\\n deque._data[frontIndex] = value;\\n deque._begin = frontIndex;\\n }\\n\\n /**\\n * @dev Removes the item at the beginning of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n value = deque._data[frontIndex];\\n delete deque._data[frontIndex];\\n unchecked {\\n deque._begin = frontIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Returns the item at the beginning of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n return deque._data[frontIndex];\\n }\\n\\n /**\\n * @dev Returns the item at the end of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n return deque._data[backIndex];\\n }\\n\\n /**\\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\\n * `length(deque) - 1`.\\n *\\n * Reverts with `OutOfBounds` if the index is out of bounds.\\n */\\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\\n // int256(deque._begin) is a safe upcast\\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\\n if (idx >= deque._end) revert OutOfBounds();\\n return deque._data[idx];\\n }\\n\\n /**\\n * @dev Resets the queue back to being empty.\\n *\\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\\n * out on potential gas refunds.\\n */\\n function clear(Bytes32Deque storage deque) internal {\\n deque._begin = 0;\\n deque._end = 0;\\n }\\n\\n /**\\n * @dev Returns the number of items in the queue.\\n */\\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\\n // We also assume there are at most int256.max items in the queue.\\n unchecked {\\n return uint256(int256(deque._end) - int256(deque._begin));\\n }\\n }\\n\\n /**\\n * @dev Returns true if the queue is empty.\\n */\\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\\n return deque._end <= deque._begin;\\n }\\n}\\n\",\"keccak256\":\"0x4859ffd6dd69382a1462930c00b6e394007da80e78e510f56930271034737bf2\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x61016060405260026007553480156200001757600080fd5b506040516200328f3803806200328f8339810160408190526200003a91620002e1565b600481604051806040016040528060128152602001712b32b637b23937b6b29023b7bb32b93737b960711b81525080620000796200015360201b60201c565b815160208084019190912082518383012060e08290526101008190524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81880181905281830187905260608201869052608082019490945230818401528151808203909301835260c00190528051940193909320919290916080523060c05261012052505082516200011f92506000915060208401906200023b565b50506001600160a01b03166101405262000139816200016e565b5050600680546001600160a01b031916331790556200034f565b6040805180820190915260018152603160f81b602082015290565b6064811115620001f65760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a40160405180910390fd5b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b828054620002499062000313565b90600052602060002090601f0160209004810192826200026d5760008555620002b8565b82601f106200028857805160ff1916838001178555620002b8565b82800160010185558215620002b8579182015b82811115620002b85782518255916020019190600101906200029b565b50620002c6929150620002ca565b5090565b5b80821115620002c65760008155600101620002cb565b600060208284031215620002f457600080fd5b81516001600160a01b03811681146200030c57600080fd5b9392505050565b600181811c908216806200032857607f821691505b6020821081036200034957634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e051610100516101205161014051612ed0620003bf600039600081816107df0152818161120f015281816113e40152611a0601526000611b2301526000611b7201526000611b4d01526000611aa601526000611ad001526000611afa0152612ed06000f3fe6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220119f957513c875b695417363f9b7062f502d1257a648dd454afcc82247be7f3f64736f6c634300080d0033", + "deployedBytecode": "0x6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220119f957513c875b695417363f9b7062f502d1257a648dd454afcc82247be7f3f64736f6c634300080d0033", "devdoc": { "errors": { "Empty()": [ diff --git a/deployments/arbitrumGoerli/VelodromeLibrary.json b/deployments/arbitrumGoerli/VelodromeLibrary.json index e5c49fce..6610b2af 100644 --- a/deployments/arbitrumGoerli/VelodromeLibrary.json +++ b/deployments/arbitrumGoerli/VelodromeLibrary.json @@ -1,5 +1,5 @@ { - "address": "0x0B2D0b9983dc6Ecd01c3CbE836FBb642B75Ae752", + "address": "0xcbE4714A95f866EB9C2eB50856F431f9E7353Ab6", "abi": [ { "inputs": [ @@ -188,30 +188,30 @@ "type": "function" } ], - "transactionHash": "0xf0fc854d9afb44f3aa07d62b17de20ac841406cde1ca20e20dd4eb71b983c9ea", + "transactionHash": "0x508b39bf1e550abd528db525f3d3904ddb006efa56ccb949a2a66b36ce016c3c", "receipt": { "to": null, - "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0x0B2D0b9983dc6Ecd01c3CbE836FBb642B75Ae752", + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0xcbE4714A95f866EB9C2eB50856F431f9E7353Ab6", "transactionIndex": 1, - "gasUsed": "16464071", + "gasUsed": "934860", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x690098e045fde1edf9947aa388198ceed3a14abf5430ed26c8d4eb788be509d3", - "transactionHash": "0xf0fc854d9afb44f3aa07d62b17de20ac841406cde1ca20e20dd4eb71b983c9ea", + "blockHash": "0xb00a1be00151b9c41209b0d01f7af864660fc687f8d2abfe8d555309b5fdb98b", + "transactionHash": "0x508b39bf1e550abd528db525f3d3904ddb006efa56ccb949a2a66b36ce016c3c", "logs": [], - "blockNumber": 4263683, - "cumulativeGasUsed": "16464071", + "blockNumber": 4455881, + "cumulativeGasUsed": "934860", "status": 1, "byzantium": true }, "args": [ - "0x8562618F69ED7F313Ca699556Eb18A36FB2dB1e3" + "0x1B0aC6bf6f35E638f6cce8D69C6074561273dc52" ], - "numDeployments": 7, - "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getMinimumValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getSample\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VelodromeLibrary.sol\":\"VelodromeLibrary\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VelodromeLibrary.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\n\\ncontract VelodromeLibrary {\\n IRouter internal immutable router;\\n\\n constructor(address _router) {\\n router = IRouter(_router);\\n }\\n\\n function _f(uint x0, uint y) internal pure returns (uint) {\\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\\n }\\n\\n function _d(uint x0, uint y) internal pure returns (uint) {\\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\\n }\\n\\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\\n for (uint i = 0; i < 255; i++) {\\n uint y_prev = y;\\n uint k = _f(x0, y);\\n if (k < xy) {\\n uint dy = (xy - k)*1e18/_d(x0, y);\\n y = y + dy;\\n } else {\\n uint dy = (k - xy)*1e18/_d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n }\\n\\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return (sample, r0, r1);\\n }\\n\\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\\n if (stable) {\\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\\n _reserve0 = _reserve0 * 1e18 / decimals0;\\n _reserve1 = _reserve1 * 1e18 / decimals1;\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\\n } else {\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n return amountIn * reserveB / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\\n if (stable) {\\n uint _x = x * 1e18 / decimals0;\\n uint _y = y * 1e18 / decimals1;\\n uint _a = (_x * _y) / 1e18;\\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return _a * _b / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n \\n}\\n\",\"keccak256\":\"0x01df9d4f97d905560776a0b2d29e6dc1337dc952fdc3d8bfbfde99a510a62c1c\",\"license\":\"MIT\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"}},\"version\":1}", - "bytecode": "0x60a060405234801561001057600080fd5b5060405161100238038061100283398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051610f626100a06000396000818161010c015281816102730152818161043701526105cb0152610f626000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea2646970667358221220c9f5e9283840569934e74e4aad058121f7875c44a1155be3299fa9c2ea9c6b6c64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea2646970667358221220c9f5e9283840569934e74e4aad058121f7875c44a1155be3299fa9c2ea9c6b6c64736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getMinimumValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getSample\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VelodromeLibrary.sol\":\"VelodromeLibrary\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VelodromeLibrary.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\n\\ncontract VelodromeLibrary {\\n IRouter internal immutable router;\\n\\n constructor(address _router) {\\n router = IRouter(_router);\\n }\\n\\n function _f(uint x0, uint y) internal pure returns (uint) {\\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\\n }\\n\\n function _d(uint x0, uint y) internal pure returns (uint) {\\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\\n }\\n\\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\\n for (uint i = 0; i < 255; i++) {\\n uint y_prev = y;\\n uint k = _f(x0, y);\\n if (k < xy) {\\n uint dy = (xy - k)*1e18/_d(x0, y);\\n y = y + dy;\\n } else {\\n uint dy = (k - xy)*1e18/_d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n }\\n\\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return (sample, r0, r1);\\n }\\n\\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\\n if (stable) {\\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\\n _reserve0 = _reserve0 * 1e18 / decimals0;\\n _reserve1 = _reserve1 * 1e18 / decimals1;\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\\n } else {\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n return amountIn * reserveB / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\\n if (stable) {\\n uint _x = x * 1e18 / decimals0;\\n uint _y = y * 1e18 / decimals1;\\n uint _a = (_x * _y) / 1e18;\\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return _a * _b / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n \\n}\\n\",\"keccak256\":\"0x01df9d4f97d905560776a0b2d29e6dc1337dc952fdc3d8bfbfde99a510a62c1c\",\"license\":\"MIT\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"}},\"version\":1}", + "bytecode": "0x60a060405234801561001057600080fd5b5060405161100238038061100283398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051610f626100a06000396000818161010c015281816102730152818161043701526105cb0152610f626000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea2646970667358221220093d2ed1e54290287c6817778d55455c8a9d3c98dd723f7a03a8f09fc41e3d3364736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea2646970667358221220093d2ed1e54290287c6817778d55455c8a9d3c98dd723f7a03a8f09fc41e3d3364736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/Voter.json b/deployments/arbitrumGoerli/Voter.json index d166e0e4..f8e4b35c 100644 --- a/deployments/arbitrumGoerli/Voter.json +++ b/deployments/arbitrumGoerli/Voter.json @@ -1,5 +1,5 @@ { - "address": "0x19E081b804AB558cF6f7B629a2902F7c79ADa9cD", + "address": "0x854086d39955d28317aE3856399312b8Edb1B473", "abi": [ { "inputs": [ @@ -1141,33 +1141,33 @@ "type": "function" } ], - "transactionHash": "0x31badff59af423d1e93363365c69c1a4256ede69af484077bc8544ff287bbfa7", + "transactionHash": "0x6ab790bf44fd3a54927607a33f2b5a57ea2fbafe2190b94ee74e56c31d08e70a", "receipt": { "to": null, - "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0x19E081b804AB558cF6f7B629a2902F7c79ADa9cD", + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x854086d39955d28317aE3856399312b8Edb1B473", "transactionIndex": 1, - "gasUsed": "55972824", + "gasUsed": "3116558", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x3fade8135639bde4350276fb8772a6ff288e712661a99c085431928da4457a49", - "transactionHash": "0x31badff59af423d1e93363365c69c1a4256ede69af484077bc8544ff287bbfa7", + "blockHash": "0xd0e0eb7a2933832bbcb8e6990ff623f0fb228c4b67ebeedf90cf4bfcb44b99c7", + "transactionHash": "0x6ab790bf44fd3a54927607a33f2b5a57ea2fbafe2190b94ee74e56c31d08e70a", "logs": [], - "blockNumber": 4263692, - "cumulativeGasUsed": "55972824", + "blockNumber": 4455890, + "cumulativeGasUsed": "3116558", "status": 1, "byzantium": true }, "args": [ - "0xCDAF5f01849Fff0a9E36D768B2ae7354A98360c0", - "0xcA698eA7f3A74b7D3D4229765dcF47F7A224859F", - "0x9974354d3a16C4801cce829349Cf17663b2c58a5", - "0x679e8fED0Cd87abAFB0BA481F32b7BDd8b272789" + "0xBf05364D6cf1586852c18c6b1CbEe218E3e09885", + "0x6389e934d35fC9e066FAb549C8DBc9FddaC10e0D", + "0xeAA8Ebb77A7e3b7AE2d8090E7A1c2F9B605dc919", + "0x560b401d9F28F80980451d8582DEe903dD5295c3" ], - "numDeployments": 5, - "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_gauges\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_bribes\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Abstained\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Attach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Detach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributeReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"internal_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"external_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"name\":\"GaugeCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeKilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeRevived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"reward\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NotifyReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Voted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"whitelister\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"Whitelisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"attachTokenToGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bribefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_bribes\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimBribes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_fees\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"}],\"name\":\"claimRewards\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"detachTokenFromGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"finish\",\"type\":\"uint256\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distributeFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distro\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"emergencyCouncil\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"external_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gaugefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"gauges\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_tokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"internal_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isAlive\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isGauge\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isWhitelisted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"killGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"lastVoted\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"length\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"notifyRewardAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"poke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolForGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"poolVote\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"reset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"reviveGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_council\",\"type\":\"address\"}],\"name\":\"setEmergencyCouncil\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"setGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalWeight\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"updateFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"name\":\"updateForRange\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"updateGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedWeights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"_poolVote\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_weights\",\"type\":\"uint256[]\"}],\"name\":\"vote\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"votes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"weights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"whitelist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Voter.sol\":\"Voter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Voter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/libraries/Math.sol';\\nimport 'contracts/interfaces/IBribe.sol';\\nimport 'contracts/interfaces/IBribeFactory.sol';\\nimport 'contracts/interfaces/IGauge.sol';\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/interfaces/IERC20.sol';\\nimport 'contracts/interfaces/IMinter.sol';\\nimport 'contracts/interfaces/IPair.sol';\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/interfaces/IVoter.sol';\\nimport 'contracts/interfaces/IVotingEscrow.sol';\\n\\ncontract Voter is IVoter {\\n\\n address public immutable _ve; // the ve token that governs these contracts\\n address public immutable factory; // the PairFactory\\n address internal immutable base;\\n address public immutable gaugefactory;\\n address public immutable bribefactory;\\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\\n address public minter;\\n address public governor; // should be set to an IGovernor\\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\\n\\n uint public totalWeight; // total voting weight\\n\\n address[] public pools; // all pools viable for incentives\\n mapping(address => address) public gauges; // pool => gauge\\n mapping(address => address) public poolForGauge; // gauge => pool\\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\\n mapping(address => uint256) public weights; // pool => weight\\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\\n mapping(uint => address[]) public poolVote; // nft => pools\\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\\n mapping(address => bool) public isGauge;\\n mapping(address => bool) public isWhitelisted;\\n mapping(address => bool) public isAlive;\\n\\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\\n event GaugeKilled(address indexed gauge);\\n event GaugeRevived(address indexed gauge);\\n event Voted(address indexed voter, uint tokenId, uint256 weight);\\n event Abstained(uint tokenId, uint256 weight);\\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\\n event Whitelisted(address indexed whitelister, address indexed token);\\n\\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\\n _ve = __ve;\\n factory = _factory;\\n base = IVotingEscrow(__ve).token();\\n gaugefactory = _gauges;\\n bribefactory = _bribes;\\n minter = msg.sender;\\n governor = msg.sender;\\n emergencyCouncil = msg.sender;\\n }\\n\\n // simple re-entrancy check\\n uint internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n modifier onlyNewEpoch(uint _tokenId) {\\n // ensure new epoch since last vote \\n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \\\"TOKEN_ALREADY_VOTED_THIS_EPOCH\\\");\\n _;\\n }\\n\\n function initialize(address[] memory _tokens, address _minter) external {\\n require(msg.sender == minter);\\n for (uint i = 0; i < _tokens.length; i++) {\\n _whitelist(_tokens[i]);\\n }\\n minter = _minter;\\n }\\n\\n function setGovernor(address _governor) public {\\n require(msg.sender == governor);\\n governor = _governor;\\n }\\n\\n function setEmergencyCouncil(address _council) public {\\n require(msg.sender == emergencyCouncil);\\n emergencyCouncil = _council;\\n }\\n\\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n lastVoted[_tokenId] = block.timestamp;\\n _reset(_tokenId);\\n IVotingEscrow(_ve).abstain(_tokenId);\\n }\\n\\n function _reset(uint _tokenId) internal {\\n address[] storage _poolVote = poolVote[_tokenId];\\n uint _poolVoteCnt = _poolVote.length;\\n uint256 _totalWeight = 0;\\n\\n for (uint i = 0; i < _poolVoteCnt; i ++) {\\n address _pool = _poolVote[i];\\n uint256 _votes = votes[_tokenId][_pool];\\n\\n if (_votes != 0) {\\n _updateFor(gauges[_pool]);\\n weights[_pool] -= _votes;\\n votes[_tokenId][_pool] -= _votes;\\n if (_votes > 0) {\\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n _totalWeight += _votes;\\n } else {\\n _totalWeight -= _votes;\\n }\\n emit Abstained(_tokenId, _votes);\\n }\\n }\\n totalWeight -= uint256(_totalWeight);\\n usedWeights[_tokenId] = 0;\\n delete poolVote[_tokenId];\\n }\\n\\n function poke(uint _tokenId) external {\\n address[] memory _poolVote = poolVote[_tokenId];\\n uint _poolCnt = _poolVote.length;\\n uint256[] memory _weights = new uint256[](_poolCnt);\\n\\n for (uint i = 0; i < _poolCnt; i ++) {\\n _weights[i] = votes[_tokenId][_poolVote[i]];\\n }\\n\\n _vote(_tokenId, _poolVote, _weights);\\n }\\n\\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\\n _reset(_tokenId);\\n uint _poolCnt = _poolVote.length;\\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\\n uint256 _totalVoteWeight = 0;\\n uint256 _totalWeight = 0;\\n uint256 _usedWeight = 0;\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n _totalVoteWeight += _weights[i];\\n }\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n address _pool = _poolVote[i];\\n address _gauge = gauges[_pool];\\n\\n if (isGauge[_gauge]) {\\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\\n require(votes[_tokenId][_pool] == 0);\\n require(_poolWeight != 0);\\n _updateFor(_gauge);\\n\\n poolVote[_tokenId].push(_pool);\\n\\n weights[_pool] += _poolWeight;\\n votes[_tokenId][_pool] += _poolWeight;\\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n _usedWeight += _poolWeight;\\n _totalWeight += _poolWeight;\\n emit Voted(msg.sender, _tokenId, _poolWeight);\\n }\\n }\\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\\n totalWeight += uint256(_totalWeight);\\n usedWeights[_tokenId] = uint256(_usedWeight);\\n }\\n\\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n require(_poolVote.length == _weights.length);\\n lastVoted[tokenId] = block.timestamp;\\n _vote(tokenId, _poolVote, _weights);\\n }\\n\\n function whitelist(address _token) public {\\n require(msg.sender == governor);\\n _whitelist(_token);\\n }\\n\\n function _whitelist(address _token) internal {\\n require(!isWhitelisted[_token]);\\n isWhitelisted[_token] = true;\\n emit Whitelisted(msg.sender, _token);\\n }\\n\\n function createGauge(address _pool) external returns (address) {\\n require(gauges[_pool] == address(0x0), \\\"exists\\\");\\n address[] memory allowedRewards = new address[](3);\\n address[] memory internalRewards = new address[](2);\\n bool isPair = IPairFactory(factory).isPair(_pool);\\n address tokenA;\\n address tokenB;\\n\\n if (isPair) {\\n (tokenA, tokenB) = IPair(_pool).tokens();\\n allowedRewards[0] = tokenA;\\n allowedRewards[1] = tokenB;\\n internalRewards[0] = tokenA;\\n internalRewards[1] = tokenB;\\n\\n if (base != tokenA && base != tokenB) {\\n allowedRewards[2] = base;\\n }\\n }\\n\\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\\n require(isPair, \\\"!_pool\\\");\\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \\\"!whitelisted\\\");\\n }\\n\\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\\n\\n IERC20(base).approve(_gauge, type(uint).max);\\n internal_bribes[_gauge] = _internal_bribe;\\n external_bribes[_gauge] = _external_bribe;\\n gauges[_pool] = _gauge;\\n poolForGauge[_gauge] = _pool;\\n isGauge[_gauge] = true;\\n isAlive[_gauge] = true;\\n _updateFor(_gauge);\\n pools.push(_pool);\\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\\n return _gauge;\\n }\\n\\n function killGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(isAlive[_gauge], \\\"gauge already dead\\\");\\n isAlive[_gauge] = false;\\n claimable[_gauge] = 0;\\n emit GaugeKilled(_gauge);\\n }\\n\\n function reviveGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(!isAlive[_gauge], \\\"gauge already alive\\\");\\n isAlive[_gauge] = true;\\n emit GaugeRevived(_gauge);\\n }\\n\\n function attachTokenToGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\\n emit Attach(account, msg.sender, tokenId);\\n }\\n\\n function emitDeposit(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]);\\n emit Deposit(account, msg.sender, tokenId, amount);\\n }\\n\\n function detachTokenFromGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\\n emit Detach(account, msg.sender, tokenId);\\n }\\n\\n function emitWithdraw(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n emit Withdraw(account, msg.sender, tokenId, amount);\\n }\\n\\n function length() external view returns (uint) {\\n return pools.length;\\n }\\n\\n uint internal index;\\n mapping(address => uint) internal supplyIndex;\\n mapping(address => uint) public claimable;\\n\\n function notifyRewardAmount(uint amount) external {\\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index += _ratio;\\n }\\n emit NotifyReward(msg.sender, base, amount);\\n }\\n\\n function updateFor(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n _updateFor(_gauges[i]);\\n }\\n }\\n\\n function updateForRange(uint start, uint end) public {\\n for (uint i = start; i < end; i++) {\\n _updateFor(gauges[pools[i]]);\\n }\\n }\\n\\n function updateAll() external {\\n updateForRange(0, pools.length);\\n }\\n\\n function updateGauge(address _gauge) external {\\n _updateFor(_gauge);\\n }\\n\\n function _updateFor(address _gauge) internal {\\n address _pool = poolForGauge[_gauge];\\n uint256 _supplied = weights[_pool];\\n if (_supplied > 0) {\\n uint _supplyIndex = supplyIndex[_gauge];\\n uint _index = index; // get global index0 for accumulated distro\\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\\n if (_delta > 0) {\\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\\n if (isAlive[_gauge]) {\\n claimable[_gauge] += _share;\\n }\\n }\\n } else {\\n supplyIndex[_gauge] = index; // new users are set to the default global state\\n }\\n }\\n\\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\\n }\\n }\\n\\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _bribes.length; i++) {\\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _fees.length; i++) {\\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function distributeFees(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n if (IGauge(_gauges[i]).isForPair()){\\n IGauge(_gauges[i]).claimFees();\\n }\\n }\\n }\\n\\n function distribute(address _gauge) public lock {\\n IMinter(minter).update_period();\\n _updateFor(_gauge); // should set claimable to 0 if killed\\n uint _claimable = claimable[_gauge];\\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\\n claimable[_gauge] = 0;\\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\\n emit DistributeReward(msg.sender, _gauge, _claimable);\\n }\\n }\\n\\n function distro() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute(uint start, uint finish) public {\\n for (uint x = start; x < finish; x++) {\\n distribute(gauges[pools[x]]);\\n }\\n }\\n\\n function distribute(address[] memory _gauges) external {\\n for (uint x = 0; x < _gauges.length; x++) {\\n distribute(_gauges[x]);\\n }\\n }\\n\\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2ff3fc2765dfa0c54870e428d3a2c625f413fb6e10ed7742e786ab4404aae6dc\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x61012060405260016011553480156200001757600080fd5b5060405162003656380380620036568339810160408190526200003a916200011c565b6001600160a01b03808516608081905290841660a05260408051637e062a3560e11b8152905163fc0c546a916004808201926020929091908290030181865afa1580156200008c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b2919062000179565b6001600160a01b0390811660c05291821660e0521661010052505060008054336001600160a01b03199182168117909255600180548216831790556002805490911690911790556200019e565b80516001600160a01b03811681146200011757600080fd5b919050565b600080600080608085870312156200013357600080fd5b6200013e85620000ff565b93506200014e60208601620000ff565b92506200015e60408601620000ff565b91506200016e60608601620000ff565b905092959194509250565b6000602082840312156200018c57600080fd5b6200019782620000ff565b9392505050565b60805160a05160c05160e051610100516133e062000276600039600081816103e701528181611c680152611ce60152600081816104d30152611d79015260008181610b9401528181610c0d01528181610edd01528181610f9901528181611acd01528181611b0601528181611b380152611e5a0152600081816106fc015261192401526000818161058c0152818161092b015281816109d701528181610c9a01528181611069015281816111ea0152818161131a015281816114d901528181611dab015281816125e501526129a801526133e06000f3fe608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea2646970667358221220efdf32d446dea7220cae45ea22975b1081b44ec8e633c8802ff0585e94e083c564736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea2646970667358221220efdf32d446dea7220cae45ea22975b1081b44ec8e633c8802ff0585e94e083c564736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_gauges\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_bribes\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Abstained\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Attach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Detach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributeReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"internal_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"external_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"name\":\"GaugeCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeKilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeRevived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"reward\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NotifyReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Voted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"whitelister\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"Whitelisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"attachTokenToGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bribefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_bribes\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimBribes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_fees\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"}],\"name\":\"claimRewards\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"detachTokenFromGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"finish\",\"type\":\"uint256\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distributeFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distro\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"emergencyCouncil\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"external_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gaugefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"gauges\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_tokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"internal_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isAlive\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isGauge\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isWhitelisted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"killGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"lastVoted\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"length\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"notifyRewardAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"poke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolForGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"poolVote\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"reset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"reviveGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_council\",\"type\":\"address\"}],\"name\":\"setEmergencyCouncil\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"setGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalWeight\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"updateFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"name\":\"updateForRange\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"updateGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedWeights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"_poolVote\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_weights\",\"type\":\"uint256[]\"}],\"name\":\"vote\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"votes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"weights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"whitelist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Voter.sol\":\"Voter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Voter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/libraries/Math.sol';\\nimport 'contracts/interfaces/IBribe.sol';\\nimport 'contracts/interfaces/IBribeFactory.sol';\\nimport 'contracts/interfaces/IGauge.sol';\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/interfaces/IERC20.sol';\\nimport 'contracts/interfaces/IMinter.sol';\\nimport 'contracts/interfaces/IPair.sol';\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/interfaces/IVoter.sol';\\nimport 'contracts/interfaces/IVotingEscrow.sol';\\n\\ncontract Voter is IVoter {\\n\\n address public immutable _ve; // the ve token that governs these contracts\\n address public immutable factory; // the PairFactory\\n address internal immutable base;\\n address public immutable gaugefactory;\\n address public immutable bribefactory;\\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\\n address public minter;\\n address public governor; // should be set to an IGovernor\\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\\n\\n uint public totalWeight; // total voting weight\\n\\n address[] public pools; // all pools viable for incentives\\n mapping(address => address) public gauges; // pool => gauge\\n mapping(address => address) public poolForGauge; // gauge => pool\\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\\n mapping(address => uint256) public weights; // pool => weight\\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\\n mapping(uint => address[]) public poolVote; // nft => pools\\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\\n mapping(address => bool) public isGauge;\\n mapping(address => bool) public isWhitelisted;\\n mapping(address => bool) public isAlive;\\n\\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\\n event GaugeKilled(address indexed gauge);\\n event GaugeRevived(address indexed gauge);\\n event Voted(address indexed voter, uint tokenId, uint256 weight);\\n event Abstained(uint tokenId, uint256 weight);\\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\\n event Whitelisted(address indexed whitelister, address indexed token);\\n\\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\\n _ve = __ve;\\n factory = _factory;\\n base = IVotingEscrow(__ve).token();\\n gaugefactory = _gauges;\\n bribefactory = _bribes;\\n minter = msg.sender;\\n governor = msg.sender;\\n emergencyCouncil = msg.sender;\\n }\\n\\n // simple re-entrancy check\\n uint internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n modifier onlyNewEpoch(uint _tokenId) {\\n // ensure new epoch since last vote \\n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \\\"TOKEN_ALREADY_VOTED_THIS_EPOCH\\\");\\n _;\\n }\\n\\n function initialize(address[] memory _tokens, address _minter) external {\\n require(msg.sender == minter);\\n for (uint i = 0; i < _tokens.length; i++) {\\n _whitelist(_tokens[i]);\\n }\\n minter = _minter;\\n }\\n\\n function setGovernor(address _governor) public {\\n require(msg.sender == governor);\\n governor = _governor;\\n }\\n\\n function setEmergencyCouncil(address _council) public {\\n require(msg.sender == emergencyCouncil);\\n emergencyCouncil = _council;\\n }\\n\\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n lastVoted[_tokenId] = block.timestamp;\\n _reset(_tokenId);\\n IVotingEscrow(_ve).abstain(_tokenId);\\n }\\n\\n function _reset(uint _tokenId) internal {\\n address[] storage _poolVote = poolVote[_tokenId];\\n uint _poolVoteCnt = _poolVote.length;\\n uint256 _totalWeight = 0;\\n\\n for (uint i = 0; i < _poolVoteCnt; i ++) {\\n address _pool = _poolVote[i];\\n uint256 _votes = votes[_tokenId][_pool];\\n\\n if (_votes != 0) {\\n _updateFor(gauges[_pool]);\\n weights[_pool] -= _votes;\\n votes[_tokenId][_pool] -= _votes;\\n if (_votes > 0) {\\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n _totalWeight += _votes;\\n } else {\\n _totalWeight -= _votes;\\n }\\n emit Abstained(_tokenId, _votes);\\n }\\n }\\n totalWeight -= uint256(_totalWeight);\\n usedWeights[_tokenId] = 0;\\n delete poolVote[_tokenId];\\n }\\n\\n function poke(uint _tokenId) external {\\n address[] memory _poolVote = poolVote[_tokenId];\\n uint _poolCnt = _poolVote.length;\\n uint256[] memory _weights = new uint256[](_poolCnt);\\n\\n for (uint i = 0; i < _poolCnt; i ++) {\\n _weights[i] = votes[_tokenId][_poolVote[i]];\\n }\\n\\n _vote(_tokenId, _poolVote, _weights);\\n }\\n\\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\\n _reset(_tokenId);\\n uint _poolCnt = _poolVote.length;\\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\\n uint256 _totalVoteWeight = 0;\\n uint256 _totalWeight = 0;\\n uint256 _usedWeight = 0;\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n _totalVoteWeight += _weights[i];\\n }\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n address _pool = _poolVote[i];\\n address _gauge = gauges[_pool];\\n\\n if (isGauge[_gauge]) {\\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\\n require(votes[_tokenId][_pool] == 0);\\n require(_poolWeight != 0);\\n _updateFor(_gauge);\\n\\n poolVote[_tokenId].push(_pool);\\n\\n weights[_pool] += _poolWeight;\\n votes[_tokenId][_pool] += _poolWeight;\\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n _usedWeight += _poolWeight;\\n _totalWeight += _poolWeight;\\n emit Voted(msg.sender, _tokenId, _poolWeight);\\n }\\n }\\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\\n totalWeight += uint256(_totalWeight);\\n usedWeights[_tokenId] = uint256(_usedWeight);\\n }\\n\\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n require(_poolVote.length == _weights.length);\\n lastVoted[tokenId] = block.timestamp;\\n _vote(tokenId, _poolVote, _weights);\\n }\\n\\n function whitelist(address _token) public {\\n require(msg.sender == governor);\\n _whitelist(_token);\\n }\\n\\n function _whitelist(address _token) internal {\\n require(!isWhitelisted[_token]);\\n isWhitelisted[_token] = true;\\n emit Whitelisted(msg.sender, _token);\\n }\\n\\n function createGauge(address _pool) external returns (address) {\\n require(gauges[_pool] == address(0x0), \\\"exists\\\");\\n address[] memory allowedRewards = new address[](3);\\n address[] memory internalRewards = new address[](2);\\n bool isPair = IPairFactory(factory).isPair(_pool);\\n address tokenA;\\n address tokenB;\\n\\n if (isPair) {\\n (tokenA, tokenB) = IPair(_pool).tokens();\\n allowedRewards[0] = tokenA;\\n allowedRewards[1] = tokenB;\\n internalRewards[0] = tokenA;\\n internalRewards[1] = tokenB;\\n\\n if (base != tokenA && base != tokenB) {\\n allowedRewards[2] = base;\\n }\\n }\\n\\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\\n require(isPair, \\\"!_pool\\\");\\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \\\"!whitelisted\\\");\\n }\\n\\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\\n\\n IERC20(base).approve(_gauge, type(uint).max);\\n internal_bribes[_gauge] = _internal_bribe;\\n external_bribes[_gauge] = _external_bribe;\\n gauges[_pool] = _gauge;\\n poolForGauge[_gauge] = _pool;\\n isGauge[_gauge] = true;\\n isAlive[_gauge] = true;\\n _updateFor(_gauge);\\n pools.push(_pool);\\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\\n return _gauge;\\n }\\n\\n function killGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(isAlive[_gauge], \\\"gauge already dead\\\");\\n isAlive[_gauge] = false;\\n claimable[_gauge] = 0;\\n emit GaugeKilled(_gauge);\\n }\\n\\n function reviveGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(!isAlive[_gauge], \\\"gauge already alive\\\");\\n isAlive[_gauge] = true;\\n emit GaugeRevived(_gauge);\\n }\\n\\n function attachTokenToGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\\n emit Attach(account, msg.sender, tokenId);\\n }\\n\\n function emitDeposit(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]);\\n emit Deposit(account, msg.sender, tokenId, amount);\\n }\\n\\n function detachTokenFromGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\\n emit Detach(account, msg.sender, tokenId);\\n }\\n\\n function emitWithdraw(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n emit Withdraw(account, msg.sender, tokenId, amount);\\n }\\n\\n function length() external view returns (uint) {\\n return pools.length;\\n }\\n\\n uint internal index;\\n mapping(address => uint) internal supplyIndex;\\n mapping(address => uint) public claimable;\\n\\n function notifyRewardAmount(uint amount) external {\\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index += _ratio;\\n }\\n emit NotifyReward(msg.sender, base, amount);\\n }\\n\\n function updateFor(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n _updateFor(_gauges[i]);\\n }\\n }\\n\\n function updateForRange(uint start, uint end) public {\\n for (uint i = start; i < end; i++) {\\n _updateFor(gauges[pools[i]]);\\n }\\n }\\n\\n function updateAll() external {\\n updateForRange(0, pools.length);\\n }\\n\\n function updateGauge(address _gauge) external {\\n _updateFor(_gauge);\\n }\\n\\n function _updateFor(address _gauge) internal {\\n address _pool = poolForGauge[_gauge];\\n uint256 _supplied = weights[_pool];\\n if (_supplied > 0) {\\n uint _supplyIndex = supplyIndex[_gauge];\\n uint _index = index; // get global index0 for accumulated distro\\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\\n if (_delta > 0) {\\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\\n if (isAlive[_gauge]) {\\n claimable[_gauge] += _share;\\n }\\n }\\n } else {\\n supplyIndex[_gauge] = index; // new users are set to the default global state\\n }\\n }\\n\\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\\n }\\n }\\n\\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _bribes.length; i++) {\\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _fees.length; i++) {\\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function distributeFees(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n if (IGauge(_gauges[i]).isForPair()){\\n IGauge(_gauges[i]).claimFees();\\n }\\n }\\n }\\n\\n function distribute(address _gauge) public lock {\\n IMinter(minter).update_period();\\n _updateFor(_gauge); // should set claimable to 0 if killed\\n uint _claimable = claimable[_gauge];\\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\\n claimable[_gauge] = 0;\\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\\n emit DistributeReward(msg.sender, _gauge, _claimable);\\n }\\n }\\n\\n function distro() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute(uint start, uint finish) public {\\n for (uint x = start; x < finish; x++) {\\n distribute(gauges[pools[x]]);\\n }\\n }\\n\\n function distribute(address[] memory _gauges) external {\\n for (uint x = 0; x < _gauges.length; x++) {\\n distribute(_gauges[x]);\\n }\\n }\\n\\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2ff3fc2765dfa0c54870e428d3a2c625f413fb6e10ed7742e786ab4404aae6dc\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x61012060405260016011553480156200001757600080fd5b5060405162003656380380620036568339810160408190526200003a916200011c565b6001600160a01b03808516608081905290841660a05260408051637e062a3560e11b8152905163fc0c546a916004808201926020929091908290030181865afa1580156200008c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b2919062000179565b6001600160a01b0390811660c05291821660e0521661010052505060008054336001600160a01b03199182168117909255600180548216831790556002805490911690911790556200019e565b80516001600160a01b03811681146200011757600080fd5b919050565b600080600080608085870312156200013357600080fd5b6200013e85620000ff565b93506200014e60208601620000ff565b92506200015e60408601620000ff565b91506200016e60608601620000ff565b905092959194509250565b6000602082840312156200018c57600080fd5b6200019782620000ff565b9392505050565b60805160a05160c05160e051610100516133e062000276600039600081816103e701528181611c680152611ce60152600081816104d30152611d79015260008181610b9401528181610c0d01528181610edd01528181610f9901528181611acd01528181611b0601528181611b380152611e5a0152600081816106fc015261192401526000818161058c0152818161092b015281816109d701528181610c9a01528181611069015281816111ea0152818161131a015281816114d901528181611dab015281816125e501526129a801526133e06000f3fe608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea26469706673582212206417f3b87d56b8cad3ead79123e880da3688f5c8a600bd4d6bc932d9f942976264736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea26469706673582212206417f3b87d56b8cad3ead79123e880da3688f5c8a600bd4d6bc932d9f942976264736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/VotingEscrow.json b/deployments/arbitrumGoerli/VotingEscrow.json index e9e3d429..695b796f 100644 --- a/deployments/arbitrumGoerli/VotingEscrow.json +++ b/deployments/arbitrumGoerli/VotingEscrow.json @@ -1,5 +1,5 @@ { - "address": "0xCDAF5f01849Fff0a9E36D768B2ae7354A98360c0", + "address": "0xBf05364D6cf1586852c18c6b1CbEe218E3e09885", "abi": [ { "inputs": [ @@ -1521,62 +1521,62 @@ "type": "function" } ], - "transactionHash": "0x514a01a37dfc40d4174ba7a26e0059366c7412e6fd3390ccdd879b0dce4c5422", + "transactionHash": "0x2a4f550ce7f771e6c1174ee30ef320f5f4c5ff7e16cdcf1b8e96862fc0bf6b44", "receipt": { "to": null, - "from": "0x3406eDA8850592Ea85886d854EDBD55042CB7805", - "contractAddress": "0xCDAF5f01849Fff0a9E36D768B2ae7354A98360c0", + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0xBf05364D6cf1586852c18c6b1CbEe218E3e09885", "transactionIndex": 1, - "gasUsed": "81633251", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000008000000000000000000200000000000000000000000000000028000000000000000000800000000000000000000000010000000000000000000800000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000400", - "blockHash": "0x3ec3c1b2a1ad06a8f20452cab4fa8be7b5f90e901a92921de7e4c6878f75fea5", - "transactionHash": "0x514a01a37dfc40d4174ba7a26e0059366c7412e6fd3390ccdd879b0dce4c5422", + "gasUsed": "4394475", + "logsBloom": "0x00000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000020000000000000000000800000401000000000000000010000000000000000000000000000000000000000000000000000000000000000004000000000001000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000400000000000000000", + "blockHash": "0x8900ffab23000b0b19a48cbfe5540b30cc7088ef54c85315850b24e4b6ff5ce9", + "transactionHash": "0x2a4f550ce7f771e6c1174ee30ef320f5f4c5ff7e16cdcf1b8e96862fc0bf6b44", "logs": [ { "transactionIndex": 1, - "blockNumber": 4263689, - "transactionHash": "0x514a01a37dfc40d4174ba7a26e0059366c7412e6fd3390ccdd879b0dce4c5422", - "address": "0xCDAF5f01849Fff0a9E36D768B2ae7354A98360c0", + "blockNumber": 4455885, + "transactionHash": "0x2a4f550ce7f771e6c1174ee30ef320f5f4c5ff7e16cdcf1b8e96862fc0bf6b44", + "address": "0xBf05364D6cf1586852c18c6b1CbEe218E3e09885", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000cdaf5f01849fff0a9e36d768b2ae7354a98360c0", + "0x000000000000000000000000bf05364d6cf1586852c18c6b1cbee218e3e09885", "0x0000000000000000000000000000000000000000000000000000000000000000" ], "data": "0x", "logIndex": 0, - "blockHash": "0x3ec3c1b2a1ad06a8f20452cab4fa8be7b5f90e901a92921de7e4c6878f75fea5" + "blockHash": "0x8900ffab23000b0b19a48cbfe5540b30cc7088ef54c85315850b24e4b6ff5ce9" }, { "transactionIndex": 1, - "blockNumber": 4263689, - "transactionHash": "0x514a01a37dfc40d4174ba7a26e0059366c7412e6fd3390ccdd879b0dce4c5422", - "address": "0xCDAF5f01849Fff0a9E36D768B2ae7354A98360c0", + "blockNumber": 4455885, + "transactionHash": "0x2a4f550ce7f771e6c1174ee30ef320f5f4c5ff7e16cdcf1b8e96862fc0bf6b44", + "address": "0xBf05364D6cf1586852c18c6b1CbEe218E3e09885", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x000000000000000000000000cdaf5f01849fff0a9e36d768b2ae7354a98360c0", + "0x000000000000000000000000bf05364d6cf1586852c18c6b1cbee218e3e09885", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000" ], "data": "0x", "logIndex": 1, - "blockHash": "0x3ec3c1b2a1ad06a8f20452cab4fa8be7b5f90e901a92921de7e4c6878f75fea5" + "blockHash": "0x8900ffab23000b0b19a48cbfe5540b30cc7088ef54c85315850b24e4b6ff5ce9" } ], - "blockNumber": 4263689, - "cumulativeGasUsed": "81633251", + "blockNumber": 4455885, + "cumulativeGasUsed": "4394475", "status": 1, "byzantium": true }, "args": [ - "0x162404E6Cd4633656925b90EF67237F29D5cc85c", - "0xB143E062f93E7d4F9f7B2b7127861c72Fb2ADF82" + "0x84Ca387E7ede764A3284c67Ff8c68a305a9030a0", + "0x821B98D42D3AB509AF4F54205f0c52B019b9E2D5" ], - "numDeployments": 7, - "solcInputHash": "7fabbf584e02c1cd20d7799a434dc4a7", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token_addr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"art_proxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromDelegate\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toDelegate\",\"type\":\"address\"}],\"name\":\"DelegateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"DelegateVotesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"locktime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum VotingEscrow.DepositType\",\"name\":\"deposit_type\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"prevSupply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"supply\",\"type\":\"uint256\"}],\"name\":\"Supply\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DELEGATION_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_DELEGATES\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"abstain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_approved\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"artProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"attach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"attachments\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"balanceOfAtNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_t\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFTAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"block_number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"checkpoints\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"create_lock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"create_lock_for\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"}],\"name\":\"delegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"delegateBySig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"}],\"name\":\"delegates\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"deposit_for\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"detach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastTotalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotesIndex\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"get_last_user_slope\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"increase_amount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"increase_unlock_time\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"isApprovedOrOwner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"locked\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"amount\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"locked__end\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_from\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_to\",\"type\":\"uint256\"}],\"name\":\"merge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"numCheckpoints\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ownership_change\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_proxy\",\"type\":\"address\"}],\"name\":\"setArtProxy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voter\",\"type\":\"address\"}],\"name\":\"setVoter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"slope_changes\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenIndex\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"t\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAtT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_idx\",\"type\":\"uint256\"}],\"name\":\"user_point_history__ts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"voted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"voting\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\",\"details\":\"Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\",\"kind\":\"dev\",\"methods\":{\"approve(address,uint256)\":{\"details\":\"Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address. Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner. Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP) Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"Address to be approved for the given NFT ID.\",\"_tokenId\":\"ID of the token to be approved.\"}},\"balanceOf(address)\":{\"details\":\"Returns the number of NFTs owned by `_owner`. Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\",\"params\":{\"_owner\":\"Address for whom to query the balance.\"}},\"constructor\":{\"params\":{\"token_addr\":\"`VELO` token address\"}},\"create_lock(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_value\":\"Amount to deposit\"}},\"create_lock_for(uint256,uint256,address)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_to\":\"Address to deposit\",\"_value\":\"Amount to deposit\"}},\"delegate(address)\":{\"params\":{\"delegatee\":\"The address to delegate votes to\"}},\"delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Delegates votes from signer to `delegatee`.\"},\"deposit_for(uint256,uint256)\":{\"details\":\"Anyone (even a smart contract) can deposit for someone else, but cannot extend their locktime and deposit for a brand new user\",\"params\":{\"_tokenId\":\"lock NFT\",\"_value\":\"Amount to add to user's lock\"}},\"getApproved(uint256)\":{\"details\":\"Get the approved address for a single NFT.\",\"params\":{\"_tokenId\":\"ID of the NFT to query the approval of.\"}},\"getVotes(address)\":{\"params\":{\"account\":\"The address to get votes balance\"},\"returns\":{\"_0\":\"The number of current votes for `account`\"}},\"get_last_user_slope(uint256)\":{\"params\":{\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Value of the slope\"}},\"increase_amount(uint256,uint256)\":{\"params\":{\"_value\":\"Amount of tokens to deposit and add to the lock\"}},\"increase_unlock_time(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"New number of seconds until tokens unlock\"}},\"isApprovedForAll(address,address)\":{\"details\":\"Checks if `_operator` is an approved operator for `_owner`.\",\"params\":{\"_operator\":\"The address that acts on behalf of the owner.\",\"_owner\":\"The address that owns the NFTs.\"}},\"locked__end(uint256)\":{\"params\":{\"_tokenId\":\"User NFT\"},\"returns\":{\"_0\":\"Epoch time of the lock end\"}},\"ownerOf(uint256)\":{\"details\":\"Returns the address of the owner of the NFT.\",\"params\":{\"_tokenId\":\"The identifier for an NFT.\"}},\"safeTransferFrom(address,address,uint256)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"safeTransferFrom(address,address,uint256,bytes)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_data\":\"Additional data with no specified format, sent in call to `_to`.\",\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"details\":\"Enables or disables approval for a third party (\\\"operator\\\") to manage all of `msg.sender`'s assets. It also emits the ApprovalForAll event. Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"True if the operators is approved, false to revoke approval.\",\"_operator\":\"Address to add to the set of authorized operators.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Interface identification is specified in ERC-165.\",\"params\":{\"_interfaceID\":\"Id of the interface\"}},\"tokenOfOwnerByIndex(address,uint256)\":{\"details\":\"Get token by index\"},\"tokenURI(uint256)\":{\"details\":\"Returns current token URI metadata\",\"params\":{\"_tokenId\":\"Token ID to fetch URI for.\"}},\"totalSupplyAt(uint256)\":{\"params\":{\"_block\":\"Block to calculate the total voting power at\"},\"returns\":{\"_0\":\"Total voting power at `_block`\"}},\"totalSupplyAtT(uint256)\":{\"details\":\"Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\",\"returns\":{\"_0\":\"Total voting power\"}},\"transferFrom(address,address,uint256)\":{\"details\":\"Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"user_point_history__ts(uint256,uint256)\":{\"params\":{\"_idx\":\"User epoch number\",\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Epoch time of the checkpoint\"}},\"withdraw(uint256)\":{\"details\":\"Only possible if the lock has expired\"}},\"stateVariables\":{\"ERC165_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC165\"},\"ERC721_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721\"},\"ERC721_METADATA_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721Metadata\"},\"_not_entered\":{\"details\":\"reentrancy guard\"},\"idToApprovals\":{\"details\":\"Mapping from NFT ID to approved address.\"},\"idToOwner\":{\"details\":\"Mapping from NFT ID to the address that owns it.\"},\"name\":{\"details\":\"Returns the token collection name.\"},\"ownerToNFTokenCount\":{\"details\":\"Mapping from owner address to count of his tokens.\"},\"ownerToNFTokenIdList\":{\"details\":\"Mapping from owner address to mapping of index to tokenIds\"},\"ownerToOperators\":{\"details\":\"Mapping from owner address to mapping of operator addresses.\"},\"supportedInterfaces\":{\"details\":\"Mapping of interface id to bool about whether or not it's supported\"},\"symbol\":{\"details\":\"Returns the token collection symbol.\"},\"tokenId\":{\"details\":\"Current count of token\"},\"tokenToOwnerIndex\":{\"details\":\"Mapping from NFT ID to index of owner\"}},\"title\":\"Voting Escrow\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DELEGATION_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the delegation struct used by the contract\"},\"DOMAIN_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the contract's domain\"},\"checkpoint()\":{\"notice\":\"Record global data to checkpoint\"},\"checkpoints(address,uint32)\":{\"notice\":\"A record of delegated token checkpoints for each account, by index\"},\"constructor\":{\"notice\":\"Contract constructor\"},\"create_lock(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\"},\"create_lock_for(uint256,uint256,address)\":{\"notice\":\"Deposit `_value` tokens for `_to` and lock for `_lock_duration`\"},\"delegate(address)\":{\"notice\":\"Delegate votes from `msg.sender` to `delegatee`\"},\"delegates(address)\":{\"notice\":\"Overrides the standard `Comp.sol` delegates mapping to return the delegator's own address if they haven't delegated. This avoids having to delegate to oneself.\"},\"deposit_for(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `_tokenId` and add to the lock\"},\"getVotes(address)\":{\"notice\":\"Gets the current votes balance for `account`\"},\"get_last_user_slope(uint256)\":{\"notice\":\"Get the most recently recorded rate of voting power decrease for `_tokenId`\"},\"increase_amount(uint256,uint256)\":{\"notice\":\"Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\"},\"increase_unlock_time(uint256,uint256)\":{\"notice\":\"Extend the unlock time for `_tokenId`\"},\"locked__end(uint256)\":{\"notice\":\"Get timestamp when `_tokenId`'s lock finishes\"},\"nonces(address)\":{\"notice\":\"A record of states for signing / validating signatures\"},\"numCheckpoints(address)\":{\"notice\":\"The number of checkpoints for each account\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"This works even if sender doesn't own any tokens at the time.\"},\"totalSupplyAt(uint256)\":{\"notice\":\"Calculate total voting power at some point in the past\"},\"totalSupplyAtT(uint256)\":{\"notice\":\"Calculate total voting power\"},\"transferFrom(address,address,uint256)\":{\"notice\":\"The caller is responsible to confirm that `_to` is capable of receiving NFTs or else they maybe be permanently lost.\"},\"user_point_history__ts(uint256,uint256)\":{\"notice\":\"Get the timestamp for checkpoint `_idx` for `_tokenId`\"},\"withdraw(uint256)\":{\"notice\":\"Withdraw all tokens for `_tokenId`\"}},\"notice\":\"veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFTVotes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VotingEscrow.sol\":\"VotingEscrow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733343336363832383931\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VotingEscrow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IERC721, IERC721Metadata} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {IERC721Receiver} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {IERC20} from \\\"contracts/interfaces/IERC20.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\nimport {IVotingEscrow} from \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/// @title Voting Escrow\\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\\n enum DepositType {\\n DEPOSIT_FOR_TYPE,\\n CREATE_LOCK_TYPE,\\n INCREASE_LOCK_AMOUNT,\\n INCREASE_UNLOCK_TIME,\\n MERGE_TYPE\\n }\\n\\n struct LockedBalance {\\n int128 amount;\\n uint end;\\n }\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint ts;\\n uint blk; // block\\n }\\n /* We cannot really do block numbers per se b/c slope is per time, not per block\\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\\n * What we can do is to extrapolate ***At functions */\\n\\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\\n struct Checkpoint {\\n uint timestamp;\\n uint[] tokenIds;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Deposit(\\n address indexed provider,\\n uint tokenId,\\n uint value,\\n uint indexed locktime,\\n DepositType deposit_type,\\n uint ts\\n );\\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\\n event Supply(uint prevSupply, uint supply);\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n address public immutable token;\\n address public voter;\\n address public team;\\n address public artProxy;\\n\\n mapping(uint => Point) public point_history; // epoch -> unsigned point\\n\\n /// @dev Mapping of interface id to bool about whether or not it's supported\\n mapping(bytes4 => bool) internal supportedInterfaces;\\n\\n /// @dev ERC165 interface ID of ERC165\\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\\n\\n /// @dev ERC165 interface ID of ERC721\\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\\n\\n /// @dev ERC165 interface ID of ERC721Metadata\\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\\n\\n /// @dev Current count of token\\n uint internal tokenId;\\n\\n /// @notice Contract constructor\\n /// @param token_addr `VELO` token address\\n constructor(address token_addr, address art_proxy) {\\n token = token_addr;\\n voter = msg.sender;\\n team = msg.sender;\\n artProxy = art_proxy;\\n\\n point_history[0].blk = block.number;\\n point_history[0].ts = block.timestamp;\\n\\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\\n\\n // mint-ish\\n emit Transfer(address(0), address(this), tokenId);\\n // burn-ish\\n emit Transfer(address(this), address(0), tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n MODIFIERS\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev reentrancy guard\\n uint8 internal constant _not_entered = 1;\\n uint8 internal constant _entered = 2;\\n uint8 internal _entered_state = 1;\\n modifier nonreentrant() {\\n require(_entered_state == _not_entered);\\n _entered_state = _entered;\\n _;\\n _entered_state = _not_entered;\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string constant public name = \\\"veNFT\\\";\\n string constant public symbol = \\\"veNFT\\\";\\n string constant public version = \\\"1.0.0\\\";\\n uint8 constant public decimals = 18;\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team);\\n team = _team;\\n }\\n\\n function setArtProxy(address _proxy) external {\\n require(msg.sender == team);\\n artProxy = _proxy;\\n }\\n\\n /// @dev Returns current token URI metadata\\n /// @param _tokenId Token ID to fetch URI for.\\n function tokenURI(uint _tokenId) external view returns (string memory) {\\n require(idToOwner[_tokenId] != address(0), \\\"Query for nonexistent token\\\");\\n LockedBalance memory _locked = locked[_tokenId];\\n return IVeArtProxy(artProxy)._tokenURI(\\n _tokenId,\\n _balanceOfNFT(_tokenId, block.timestamp),\\n _locked.end,\\n uint(int256(_locked.amount))\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 BALANCE/OWNER STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to the address that owns it.\\n mapping(uint => address) internal idToOwner;\\n\\n /// @dev Mapping from owner address to count of his tokens.\\n mapping(address => uint) internal ownerToNFTokenCount;\\n\\n /// @dev Returns the address of the owner of the NFT.\\n /// @param _tokenId The identifier for an NFT.\\n function ownerOf(uint _tokenId) public view returns (address) {\\n return idToOwner[_tokenId];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function _balance(address _owner) internal view returns (uint) {\\n return ownerToNFTokenCount[_owner];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function balanceOf(address _owner) external view returns (uint) {\\n return _balance(_owner);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 APPROVAL STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to approved address.\\n mapping(uint => address) internal idToApprovals;\\n\\n /// @dev Mapping from owner address to mapping of operator addresses.\\n mapping(address => mapping(address => bool)) internal ownerToOperators;\\n\\n mapping(uint => uint) public ownership_change;\\n\\n /// @dev Get the approved address for a single NFT.\\n /// @param _tokenId ID of the NFT to query the approval of.\\n function getApproved(uint _tokenId) external view returns (address) {\\n return idToApprovals[_tokenId];\\n }\\n\\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\\n /// @param _owner The address that owns the NFTs.\\n /// @param _operator The address that acts on behalf of the owner.\\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\\n return (ownerToOperators[_owner])[_operator];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\\n /// @param _approved Address to be approved for the given NFT ID.\\n /// @param _tokenId ID of the token to be approved.\\n function approve(address _approved, uint _tokenId) public {\\n address owner = idToOwner[_tokenId];\\n // Throws if `_tokenId` is not a valid NFT\\n require(owner != address(0));\\n // Throws if `_approved` is the current owner\\n require(_approved != owner);\\n // Check requirements\\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\\n require(senderIsOwner || senderIsApprovedForAll);\\n // Set the approval\\n idToApprovals[_tokenId] = _approved;\\n emit Approval(owner, _approved, _tokenId);\\n }\\n\\n /// @dev Enables or disables approval for a third party (\\\"operator\\\") to manage all of\\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\\n /// @notice This works even if sender doesn't own any tokens at the time.\\n /// @param _operator Address to add to the set of authorized operators.\\n /// @param _approved True if the operators is approved, false to revoke approval.\\n function setApprovalForAll(address _operator, bool _approved) external {\\n // Throws if `_operator` is the `msg.sender`\\n assert(_operator != msg.sender);\\n ownerToOperators[msg.sender][_operator] = _approved;\\n emit ApprovalForAll(msg.sender, _operator, _approved);\\n }\\n\\n /* TRANSFER FUNCTIONS */\\n /// @dev Clear an approval of a given address\\n /// Throws if `_owner` is not the current owner.\\n function _clearApproval(address _owner, uint _tokenId) internal {\\n // Throws if `_owner` is not the current owner\\n assert(idToOwner[_tokenId] == _owner);\\n if (idToApprovals[_tokenId] != address(0)) {\\n // Reset approvals\\n idToApprovals[_tokenId] = address(0);\\n }\\n }\\n\\n /// @dev Returns whether the given spender can transfer a given token ID\\n /// @param _spender address of the spender to query\\n /// @param _tokenId uint ID of the token to be transferred\\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\\n address owner = idToOwner[_tokenId];\\n bool spenderIsOwner = owner == _spender;\\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\\n }\\n\\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\\n return _isApprovedOrOwner(_spender, _tokenId);\\n }\\n\\n /// @dev Exeute transfer of a NFT.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_tokenId` is not a valid NFT.\\n function _transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n address _sender\\n ) internal {\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n // Check requirements\\n require(_isApprovedOrOwner(_sender, _tokenId));\\n // Clear approval. Throws if `_from` is not the current owner\\n _clearApproval(_from, _tokenId);\\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\\n _removeTokenFrom(_from, _tokenId);\\n // auto re-delegate\\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\\n // Add NFT\\n _addTokenTo(_to, _tokenId);\\n // Set the block of ownership transfer (for Flash NFT protection)\\n ownership_change[_tokenId] = block.number;\\n // Log the transfer\\n emit Transfer(_from, _to, _tokenId);\\n }\\n\\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\\n /// they maybe be permanently lost.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n safeTransferFrom(_from, _to, _tokenId, \\\"\\\");\\n }\\n\\n function _isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n uint size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n /// @param _data Additional data with no specified format, sent in call to `_to`.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n bytes memory _data\\n ) public {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n\\n if (_isContract(_to)) {\\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\\n revert(\\\"ERC721: ERC721Receiver rejected tokens\\\");\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert('ERC721: transfer to non ERC721Receiver implementer');\\n } else {\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC165 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Interface identification is specified in ERC-165.\\n /// @param _interfaceID Id of the interface\\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\\n return supportedInterfaces[_interfaceID];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from owner address to mapping of index to tokenIds\\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\\n\\n /// @dev Mapping from NFT ID to index of owner\\n mapping(uint => uint) internal tokenToOwnerIndex;\\n\\n /// @dev Get token by index\\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\\n return ownerToNFTokenIdList[_owner][_tokenIndex];\\n }\\n\\n /// @dev Add a NFT to an index mapping to a given address\\n /// @param _to address of the receiver\\n /// @param _tokenId uint ID Of the token to be added\\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\\n uint current_count = _balance(_to);\\n\\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\\n tokenToOwnerIndex[_tokenId] = current_count;\\n }\\n\\n /// @dev Add a NFT to a given address\\n /// Throws if `_tokenId` is owned by someone.\\n function _addTokenTo(address _to, uint _tokenId) internal {\\n // Throws if `_tokenId` is owned by someone\\n assert(idToOwner[_tokenId] == address(0));\\n // Change the owner\\n idToOwner[_tokenId] = _to;\\n // Update owner token index tracking\\n _addTokenToOwnerList(_to, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_to] += 1;\\n }\\n\\n /// @dev Function to mint tokens\\n /// Throws if `_to` is zero address.\\n /// Throws if `_tokenId` is owned by someone.\\n /// @param _to The address that will receive the minted tokens.\\n /// @param _tokenId The token id to mint.\\n /// @return A boolean that indicates if the operation was successful.\\n function _mint(address _to, uint _tokenId) internal returns (bool) {\\n // Throws if `_to` is zero address\\n assert(_to != address(0));\\n // checkpoint for gov\\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\\n // Add NFT. Throws if `_tokenId` is owned by someone\\n _addTokenTo(_to, _tokenId);\\n emit Transfer(address(0), _to, _tokenId);\\n return true;\\n }\\n\\n /// @dev Remove a NFT from an index mapping to a given address\\n /// @param _from address of the sender\\n /// @param _tokenId uint ID Of the token to be removed\\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\\n // Delete\\n uint current_count = _balance(_from) - 1;\\n uint current_index = tokenToOwnerIndex[_tokenId];\\n\\n if (current_count == current_index) {\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n } else {\\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\\n\\n // Add\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[lastTokenId] = current_index;\\n\\n // Delete\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n }\\n }\\n\\n /// @dev Remove a NFT from a given address\\n /// Throws if `_from` is not the current owner.\\n function _removeTokenFrom(address _from, uint _tokenId) internal {\\n // Throws if `_from` is not the current owner\\n assert(idToOwner[_tokenId] == _from);\\n // Change the owner\\n idToOwner[_tokenId] = address(0);\\n // Update owner token index tracking\\n _removeTokenFromOwnerList(_from, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_from] -= 1;\\n }\\n\\n function _burn(uint _tokenId) internal {\\n require(_isApprovedOrOwner(msg.sender, _tokenId), \\\"caller is not owner nor approved\\\");\\n\\n address owner = ownerOf(_tokenId);\\n\\n // Clear approval\\n approve(address(0), _tokenId);\\n // checkpoint for gov\\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\\n // Remove token\\n _removeTokenFrom(msg.sender, _tokenId);\\n emit Transfer(owner, address(0), _tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public user_point_epoch;\\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\\n mapping(uint => LockedBalance) public locked;\\n uint public epoch;\\n mapping(uint => int128) public slope_changes; // time -> signed slope change\\n uint public supply;\\n\\n uint internal constant WEEK = 1 weeks;\\n uint internal constant MAXTIME = 4 * 365 * 86400;\\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\\n uint internal constant MULTIPLIER = 1 ether;\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @return Value of the slope\\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\\n uint uepoch = user_point_epoch[_tokenId];\\n return user_point_history[_tokenId][uepoch].slope;\\n }\\n\\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @param _idx User epoch number\\n /// @return Epoch time of the checkpoint\\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\\n return user_point_history[_tokenId][_idx].ts;\\n }\\n\\n /// @notice Get timestamp when `_tokenId`'s lock finishes\\n /// @param _tokenId User NFT\\n /// @return Epoch time of the lock end\\n function locked__end(uint _tokenId) external view returns (uint) {\\n return locked[_tokenId].end;\\n }\\n\\n /// @notice Record global and per-user data to checkpoint\\n /// @param _tokenId NFT token ID. No user checkpoint if 0\\n /// @param old_locked Pevious locked amount / end lock time for the user\\n /// @param new_locked New locked amount / end lock time for the user\\n function _checkpoint(\\n uint _tokenId,\\n LockedBalance memory old_locked,\\n LockedBalance memory new_locked\\n ) internal {\\n Point memory u_old;\\n Point memory u_new;\\n int128 old_dslope = 0;\\n int128 new_dslope = 0;\\n uint _epoch = epoch;\\n\\n if (_tokenId != 0) {\\n // Calculate slopes and biases\\n // Kept at zero when they have to\\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\\n u_old.slope = old_locked.amount / iMAXTIME;\\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\\n }\\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\\n u_new.slope = new_locked.amount / iMAXTIME;\\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\\n }\\n\\n // Read values of scheduled changes in the slope\\n // old_locked.end can be in the past and in the future\\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\\n old_dslope = slope_changes[old_locked.end];\\n if (new_locked.end != 0) {\\n if (new_locked.end == old_locked.end) {\\n new_dslope = old_dslope;\\n } else {\\n new_dslope = slope_changes[new_locked.end];\\n }\\n }\\n }\\n\\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\\n if (_epoch > 0) {\\n last_point = point_history[_epoch];\\n }\\n uint last_checkpoint = last_point.ts;\\n // initial_last_point is used for extrapolation to calculate block number\\n // (approximately, for *At methods) and save them\\n // as we cannot figure that out exactly from inside the contract\\n Point memory initial_last_point = last_point;\\n uint block_slope = 0; // dblock/dt\\n if (block.timestamp > last_point.ts) {\\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\\n }\\n // If last point is already recorded in this block, slope=0\\n // But that's ok b/c we know the block in such case\\n\\n // Go over weeks to fill history and calculate what the current point is\\n {\\n uint t_i = (last_checkpoint / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n // Hopefully it won't happen that this won't get used in 5 years!\\n // If it does, users will be able to withdraw but vote weight will be broken\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > block.timestamp) {\\n t_i = block.timestamp;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\\n last_point.slope += d_slope;\\n if (last_point.bias < 0) {\\n // This can happen\\n last_point.bias = 0;\\n }\\n if (last_point.slope < 0) {\\n // This cannot happen - just in case\\n last_point.slope = 0;\\n }\\n last_checkpoint = t_i;\\n last_point.ts = t_i;\\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\\n _epoch += 1;\\n if (t_i == block.timestamp) {\\n last_point.blk = block.number;\\n break;\\n } else {\\n point_history[_epoch] = last_point;\\n }\\n }\\n }\\n\\n epoch = _epoch;\\n // Now point_history is filled until t=now\\n\\n if (_tokenId != 0) {\\n // If last point was in this block, the slope change has been applied already\\n // But in such case we have 0 slope(s)\\n last_point.slope += (u_new.slope - u_old.slope);\\n last_point.bias += (u_new.bias - u_old.bias);\\n if (last_point.slope < 0) {\\n last_point.slope = 0;\\n }\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n }\\n\\n // Record the changed point into history\\n point_history[_epoch] = last_point;\\n\\n if (_tokenId != 0) {\\n // Schedule the slope changes (slope is going down)\\n // We subtract new_user_slope from [new_locked.end]\\n // and add old_user_slope to [old_locked.end]\\n if (old_locked.end > block.timestamp) {\\n // old_dslope was - u_old.slope, so we cancel that\\n old_dslope += u_old.slope;\\n if (new_locked.end == old_locked.end) {\\n old_dslope -= u_new.slope; // It was a new deposit, not extension\\n }\\n slope_changes[old_locked.end] = old_dslope;\\n }\\n\\n if (new_locked.end > block.timestamp) {\\n if (new_locked.end > old_locked.end) {\\n new_dslope -= u_new.slope; // old slope disappeared at this point\\n slope_changes[new_locked.end] = new_dslope;\\n }\\n // else: we recorded it already in old_dslope\\n }\\n // Now handle user history\\n uint user_epoch = user_point_epoch[_tokenId] + 1;\\n\\n user_point_epoch[_tokenId] = user_epoch;\\n u_new.ts = block.timestamp;\\n u_new.blk = block.number;\\n user_point_history[_tokenId][user_epoch] = u_new;\\n }\\n }\\n\\n /// @notice Deposit and lock tokens for a user\\n /// @param _tokenId NFT that holds lock\\n /// @param _value Amount to deposit\\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\\n /// @param locked_balance Previous locked amount / timestamp\\n /// @param deposit_type The type of deposit\\n function _deposit_for(\\n uint _tokenId,\\n uint _value,\\n uint unlock_time,\\n LockedBalance memory locked_balance,\\n DepositType deposit_type\\n ) internal {\\n LockedBalance memory _locked = locked_balance;\\n uint supply_before = supply;\\n\\n supply = supply_before + _value;\\n LockedBalance memory old_locked;\\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\\n // Adding to existing lock, or if a lock is expired - creating a new one\\n _locked.amount += int128(int256(_value));\\n if (unlock_time != 0) {\\n _locked.end = unlock_time;\\n }\\n locked[_tokenId] = _locked;\\n\\n // Possibilities:\\n // Both old_locked.end could be current or expired (>/< block.timestamp)\\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\\n // _locked.end > block.timestamp (always)\\n _checkpoint(_tokenId, old_locked, _locked);\\n\\n address from = msg.sender;\\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\\n assert(IERC20(token).transferFrom(from, address(this), _value));\\n }\\n\\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\\n emit Supply(supply_before, supply_before + _value);\\n }\\n\\n function block_number() external view returns (uint) {\\n return block.number;\\n }\\n\\n /// @notice Record global data to checkpoint\\n function checkpoint() external {\\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\\n }\\n\\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\\n /// cannot extend their locktime and deposit for a brand new user\\n /// @param _tokenId lock NFT\\n /// @param _value Amount to add to user's lock\\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n require(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_value > 0); // dev: need non-zero value\\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n ++tokenId;\\n uint _tokenId = tokenId;\\n _mint(_to, _tokenId);\\n\\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\\n return _tokenId;\\n }\\n\\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, msg.sender);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, _to);\\n }\\n\\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\\n /// @param _value Amount of tokens to deposit and add to the lock\\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n assert(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\\n }\\n\\n /// @notice Extend the unlock time for `_tokenId`\\n /// @param _lock_duration New number of seconds until tokens unlock\\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_locked.end > block.timestamp, 'Lock expired');\\n require(_locked.amount > 0, 'Nothing is locked');\\n require(unlock_time > _locked.end, 'Can only increase lock duration');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\\n }\\n\\n /// @notice Withdraw all tokens for `_tokenId`\\n /// @dev Only possible if the lock has expired\\n function withdraw(uint _tokenId) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n require(block.timestamp >= _locked.end, \\\"The lock didn't expire\\\");\\n uint value = uint(int256(_locked.amount));\\n\\n locked[_tokenId] = LockedBalance(0,0);\\n uint supply_before = supply;\\n supply = supply_before - value;\\n\\n // old_locked can have either expired <= timestamp or zero end\\n // _locked has only 0 end\\n // Both can have >= 0 amount\\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\\n\\n assert(IERC20(token).transfer(msg.sender, value));\\n\\n // Burn the NFT\\n _burn(_tokenId);\\n\\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\\n emit Supply(supply_before, supply_before - value);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\\n // They measure the weights for the purpose of voting, so they don't represent\\n // real coins.\\n\\n /// @notice Binary search to estimate timestamp for block number\\n /// @param _block Block to find\\n /// @param max_epoch Don't go beyond this epoch\\n /// @return Approximate timestamp for block\\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\\n // Binary search\\n uint _min = 0;\\n uint _max = max_epoch;\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (point_history[_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n /// @notice Get the current voting power for `_tokenId`\\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\\n /// @param _tokenId NFT for lock\\n /// @param _t Epoch time to return voting power at\\n /// @return User voting power\\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\\n uint _epoch = user_point_epoch[_tokenId];\\n if (_epoch == 0) {\\n return 0;\\n } else {\\n Point memory last_point = user_point_history[_tokenId][_epoch];\\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(int256(last_point.bias));\\n }\\n }\\n\\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\\n if (ownership_change[_tokenId] == block.number) return 0;\\n return _balanceOfNFT(_tokenId, block.timestamp);\\n }\\n\\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\\n return _balanceOfNFT(_tokenId, _t);\\n }\\n\\n /// @notice Measure voting power of `_tokenId` at block height `_block`\\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\\n /// @param _tokenId User's wallet NFT\\n /// @param _block Block to calculate the voting power at\\n /// @return Voting power\\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\\n // Copying and pasting totalSupply code because Vyper cannot pass by\\n // reference yet\\n assert(_block <= block.number);\\n\\n // Binary search\\n uint _min = 0;\\n uint _max = user_point_epoch[_tokenId];\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (user_point_history[_tokenId][_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n\\n Point memory upoint = user_point_history[_tokenId][_min];\\n\\n uint max_epoch = epoch;\\n uint _epoch = _find_block_epoch(_block, max_epoch);\\n Point memory point_0 = point_history[_epoch];\\n uint d_block = 0;\\n uint d_t = 0;\\n if (_epoch < max_epoch) {\\n Point memory point_1 = point_history[_epoch + 1];\\n d_block = point_1.blk - point_0.blk;\\n d_t = point_1.ts - point_0.ts;\\n } else {\\n d_block = block.number - point_0.blk;\\n d_t = block.timestamp - point_0.ts;\\n }\\n uint block_time = point_0.ts;\\n if (d_block != 0) {\\n block_time += (d_t * (_block - point_0.blk)) / d_block;\\n }\\n\\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\\n if (upoint.bias >= 0) {\\n return uint(uint128(upoint.bias));\\n } else {\\n return 0;\\n }\\n }\\n\\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\\n return _balanceOfAtNFT(_tokenId, _block);\\n }\\n\\n /// @notice Calculate total voting power at some point in the past\\n /// @param _block Block to calculate the total voting power at\\n /// @return Total voting power at `_block`\\n function totalSupplyAt(uint _block) external view returns (uint) {\\n assert(_block <= block.number);\\n uint _epoch = epoch;\\n uint target_epoch = _find_block_epoch(_block, _epoch);\\n\\n Point memory point = point_history[target_epoch];\\n uint dt = 0;\\n if (target_epoch < _epoch) {\\n Point memory point_next = point_history[target_epoch + 1];\\n if (point.blk != point_next.blk) {\\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\\n }\\n } else {\\n if (point.blk != block.number) {\\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\\n }\\n }\\n // Now dt contains info on how far are we beyond point\\n return _supply_at(point, point.ts + dt);\\n }\\n /// @notice Calculate total voting power at some point in the past\\n /// @param point The point (bias/slope) to start search from\\n /// @param t Time to calculate the total voting power at\\n /// @return Total voting power at that time\\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\\n Point memory last_point = point;\\n uint t_i = (last_point.ts / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > t) {\\n t_i = t;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\\n if (t_i == t) {\\n break;\\n }\\n last_point.slope += d_slope;\\n last_point.ts = t_i;\\n }\\n\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(uint128(last_point.bias));\\n }\\n\\n function totalSupply() external view returns (uint) {\\n return totalSupplyAtT(block.timestamp);\\n }\\n\\n /// @notice Calculate total voting power\\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\\n /// @return Total voting power\\n function totalSupplyAtT(uint t) public view returns (uint) {\\n uint _epoch = epoch;\\n Point memory last_point = point_history[_epoch];\\n return _supply_at(last_point, t);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public attachments;\\n mapping(uint => bool) public voted;\\n\\n function setVoter(address _voter) external {\\n require(msg.sender == voter);\\n voter = _voter;\\n }\\n\\n function voting(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = true;\\n }\\n\\n function abstain(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = false;\\n }\\n\\n function attach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] + 1;\\n }\\n\\n function detach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] - 1;\\n }\\n\\n function merge(uint _from, uint _to) external {\\n require(attachments[_from] == 0 && !voted[_from], \\\"attached\\\");\\n require(_from != _to);\\n require(_isApprovedOrOwner(msg.sender, _from));\\n require(_isApprovedOrOwner(msg.sender, _to));\\n\\n LockedBalance memory _locked0 = locked[_from];\\n LockedBalance memory _locked1 = locked[_to];\\n uint value0 = uint(int256(_locked0.amount));\\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\\n\\n locked[_from] = LockedBalance(0, 0);\\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\\n _burn(_from);\\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of each accounts delegate\\n mapping(address => address) private _delegates;\\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\\n\\n /// @notice A record of delegated token checkpoints for each account, by index\\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint32) public numCheckpoints;\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping(address => uint) public nonces;\\n\\n /**\\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\\n * the delegator's own address if they haven't delegated.\\n * This avoids having to delegate to oneself.\\n */\\n function delegates(address delegator) public view returns (address) {\\n address current = _delegates[delegator];\\n return current == address(0) ? delegator : current;\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getVotes(address account) external view returns (uint) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n votes = votes + _balanceOfNFT(tId, block.timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint storage cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPastVotes(address account, uint timestamp)\\n public\\n view\\n returns (uint)\\n {\\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\\n // Sum votes\\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n // Use the provided input timestamp here to get the right decay\\n votes = votes + _balanceOfNFT(tId, timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\\n return totalSupplyAtT(timestamp);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _moveTokenDelegates(\\n address srcRep,\\n address dstRep,\\n uint _tokenId\\n ) internal {\\n if (srcRep != dstRep && _tokenId > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except _tokenId\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (tId != _tokenId) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n // All the same plus _tokenId\\n require(\\n dstRepOld.length + 1 <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n dstRepNew.push(_tokenId);\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _findWhatCheckpointToWrite(address account)\\n internal\\n view\\n returns (uint32)\\n {\\n uint _timestamp = block.timestamp;\\n uint32 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n return _nCheckPoints - 1;\\n } else {\\n return _nCheckPoints;\\n }\\n }\\n\\n function _moveAllDelegates(\\n address owner,\\n address srcRep,\\n address dstRep\\n ) internal {\\n // You can only redelegate what you own\\n if (srcRep != dstRep) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except what owner owns\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (idToOwner[tId] != owner) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n uint ownerTokenCount = ownerToNFTokenCount[owner];\\n require(\\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n // All the same\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n // Plus all that's owned\\n for (uint i = 0; i < ownerTokenCount; i++) {\\n uint tId = ownerToNFTokenIdList[owner][i];\\n dstRepNew.push(tId);\\n }\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\\n address currentDelegate = delegates(delegator);\\n\\n _delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n _moveAllDelegates(delegator, currentDelegate, delegatee);\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n if (delegatee == address(0)) delegatee = msg.sender;\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n function delegateBySig(\\n address delegatee,\\n uint nonce,\\n uint expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public {\\n bytes32 domainSeparator = keccak256(\\n abi.encode(\\n DOMAIN_TYPEHASH,\\n keccak256(bytes(name)),\\n keccak256(bytes(version)),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 structHash = keccak256(\\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash)\\n );\\n address signatory = ecrecover(digest, v, r, s);\\n require(\\n signatory != address(0),\\n \\\"VotingEscrow::delegateBySig: invalid signature\\\"\\n );\\n require(\\n nonce == nonces[signatory]++,\\n \\\"VotingEscrow::delegateBySig: invalid nonce\\\"\\n );\\n require(\\n block.timestamp <= expiry,\\n \\\"VotingEscrow::delegateBySig: signature expired\\\"\\n );\\n return _delegate(signatory, delegatee);\\n }\\n}\\n\",\"keccak256\":\"0x37e5ee306472a946a665be22bc1d370d566a575a1fac84f72f97b0575571d40d\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x41bbb2c41036ca64b2f6c9e973e8cfaa113ebc42af86702cd0d267f915a7e886\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60a06040526006805460ff191660011790553480156200001e57600080fd5b5060405162004a1c38038062004a1c8339810160408190526200004191620001b8565b6001600160a01b0382811660805260008054336001600160a01b031991821681178355600180548316909117815560028054909216938516939093179055437f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f0155427f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f005560046020527f9fe05126d2d9ecf60592e254dead906a4b2e492f36cca727682c38e9008c6ac1805460ff1990811684179091557f4267c0a6fd96b7a87f183ee8744f24d011423cd0e0142b3f563f183d8d9a456b8054821684179055635b5e139f60e01b82527e24030bcf4927897dffe721c2d8dda4bfd8910861687c42b03a463b43b04147805490911690921790915560055460405190913091600080516020620049fc833981519152908290a46005546040516000903090600080516020620049fc833981519152908390a45050620001f0565b80516001600160a01b0381168114620001b357600080fd5b919050565b60008060408385031215620001cc57600080fd5b620001d7836200019b565b9150620001e7602084016200019b565b90509250929050565b6080516147e26200021a60003960008181610b220152818161101801526133b501526147e26000f3fe608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea26469706673582212201dd8736f6bb54556070cca6edc44b533d010e5fbaca1866c9ae688ee4938ced064736f6c634300080d0033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea26469706673582212201dd8736f6bb54556070cca6edc44b533d010e5fbaca1866c9ae688ee4938ced064736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token_addr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"art_proxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromDelegate\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toDelegate\",\"type\":\"address\"}],\"name\":\"DelegateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"DelegateVotesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"locktime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum VotingEscrow.DepositType\",\"name\":\"deposit_type\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"prevSupply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"supply\",\"type\":\"uint256\"}],\"name\":\"Supply\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DELEGATION_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_DELEGATES\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"abstain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_approved\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"artProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"attach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"attachments\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"balanceOfAtNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_t\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFTAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"block_number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"checkpoints\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"create_lock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"create_lock_for\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"}],\"name\":\"delegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"delegateBySig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"}],\"name\":\"delegates\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"deposit_for\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"detach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastTotalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotesIndex\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"get_last_user_slope\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"increase_amount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"increase_unlock_time\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"isApprovedOrOwner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"locked\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"amount\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"locked__end\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_from\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_to\",\"type\":\"uint256\"}],\"name\":\"merge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"numCheckpoints\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ownership_change\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_proxy\",\"type\":\"address\"}],\"name\":\"setArtProxy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voter\",\"type\":\"address\"}],\"name\":\"setVoter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"slope_changes\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenIndex\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"t\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAtT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_idx\",\"type\":\"uint256\"}],\"name\":\"user_point_history__ts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"voted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"voting\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\",\"details\":\"Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\",\"kind\":\"dev\",\"methods\":{\"approve(address,uint256)\":{\"details\":\"Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address. Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner. Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP) Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"Address to be approved for the given NFT ID.\",\"_tokenId\":\"ID of the token to be approved.\"}},\"balanceOf(address)\":{\"details\":\"Returns the number of NFTs owned by `_owner`. Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\",\"params\":{\"_owner\":\"Address for whom to query the balance.\"}},\"constructor\":{\"params\":{\"token_addr\":\"`VELO` token address\"}},\"create_lock(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_value\":\"Amount to deposit\"}},\"create_lock_for(uint256,uint256,address)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_to\":\"Address to deposit\",\"_value\":\"Amount to deposit\"}},\"delegate(address)\":{\"params\":{\"delegatee\":\"The address to delegate votes to\"}},\"delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Delegates votes from signer to `delegatee`.\"},\"deposit_for(uint256,uint256)\":{\"details\":\"Anyone (even a smart contract) can deposit for someone else, but cannot extend their locktime and deposit for a brand new user\",\"params\":{\"_tokenId\":\"lock NFT\",\"_value\":\"Amount to add to user's lock\"}},\"getApproved(uint256)\":{\"details\":\"Get the approved address for a single NFT.\",\"params\":{\"_tokenId\":\"ID of the NFT to query the approval of.\"}},\"getVotes(address)\":{\"params\":{\"account\":\"The address to get votes balance\"},\"returns\":{\"_0\":\"The number of current votes for `account`\"}},\"get_last_user_slope(uint256)\":{\"params\":{\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Value of the slope\"}},\"increase_amount(uint256,uint256)\":{\"params\":{\"_value\":\"Amount of tokens to deposit and add to the lock\"}},\"increase_unlock_time(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"New number of seconds until tokens unlock\"}},\"isApprovedForAll(address,address)\":{\"details\":\"Checks if `_operator` is an approved operator for `_owner`.\",\"params\":{\"_operator\":\"The address that acts on behalf of the owner.\",\"_owner\":\"The address that owns the NFTs.\"}},\"locked__end(uint256)\":{\"params\":{\"_tokenId\":\"User NFT\"},\"returns\":{\"_0\":\"Epoch time of the lock end\"}},\"ownerOf(uint256)\":{\"details\":\"Returns the address of the owner of the NFT.\",\"params\":{\"_tokenId\":\"The identifier for an NFT.\"}},\"safeTransferFrom(address,address,uint256)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"safeTransferFrom(address,address,uint256,bytes)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_data\":\"Additional data with no specified format, sent in call to `_to`.\",\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"details\":\"Enables or disables approval for a third party (\\\"operator\\\") to manage all of `msg.sender`'s assets. It also emits the ApprovalForAll event. Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"True if the operators is approved, false to revoke approval.\",\"_operator\":\"Address to add to the set of authorized operators.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Interface identification is specified in ERC-165.\",\"params\":{\"_interfaceID\":\"Id of the interface\"}},\"tokenOfOwnerByIndex(address,uint256)\":{\"details\":\"Get token by index\"},\"tokenURI(uint256)\":{\"details\":\"Returns current token URI metadata\",\"params\":{\"_tokenId\":\"Token ID to fetch URI for.\"}},\"totalSupplyAt(uint256)\":{\"params\":{\"_block\":\"Block to calculate the total voting power at\"},\"returns\":{\"_0\":\"Total voting power at `_block`\"}},\"totalSupplyAtT(uint256)\":{\"details\":\"Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\",\"returns\":{\"_0\":\"Total voting power\"}},\"transferFrom(address,address,uint256)\":{\"details\":\"Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"user_point_history__ts(uint256,uint256)\":{\"params\":{\"_idx\":\"User epoch number\",\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Epoch time of the checkpoint\"}},\"withdraw(uint256)\":{\"details\":\"Only possible if the lock has expired\"}},\"stateVariables\":{\"ERC165_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC165\"},\"ERC721_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721\"},\"ERC721_METADATA_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721Metadata\"},\"_not_entered\":{\"details\":\"reentrancy guard\"},\"idToApprovals\":{\"details\":\"Mapping from NFT ID to approved address.\"},\"idToOwner\":{\"details\":\"Mapping from NFT ID to the address that owns it.\"},\"name\":{\"details\":\"Returns the token collection name.\"},\"ownerToNFTokenCount\":{\"details\":\"Mapping from owner address to count of his tokens.\"},\"ownerToNFTokenIdList\":{\"details\":\"Mapping from owner address to mapping of index to tokenIds\"},\"ownerToOperators\":{\"details\":\"Mapping from owner address to mapping of operator addresses.\"},\"supportedInterfaces\":{\"details\":\"Mapping of interface id to bool about whether or not it's supported\"},\"symbol\":{\"details\":\"Returns the token collection symbol.\"},\"tokenId\":{\"details\":\"Current count of token\"},\"tokenToOwnerIndex\":{\"details\":\"Mapping from NFT ID to index of owner\"}},\"title\":\"Voting Escrow\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DELEGATION_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the delegation struct used by the contract\"},\"DOMAIN_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the contract's domain\"},\"checkpoint()\":{\"notice\":\"Record global data to checkpoint\"},\"checkpoints(address,uint32)\":{\"notice\":\"A record of delegated token checkpoints for each account, by index\"},\"constructor\":{\"notice\":\"Contract constructor\"},\"create_lock(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\"},\"create_lock_for(uint256,uint256,address)\":{\"notice\":\"Deposit `_value` tokens for `_to` and lock for `_lock_duration`\"},\"delegate(address)\":{\"notice\":\"Delegate votes from `msg.sender` to `delegatee`\"},\"delegates(address)\":{\"notice\":\"Overrides the standard `Comp.sol` delegates mapping to return the delegator's own address if they haven't delegated. This avoids having to delegate to oneself.\"},\"deposit_for(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `_tokenId` and add to the lock\"},\"getVotes(address)\":{\"notice\":\"Gets the current votes balance for `account`\"},\"get_last_user_slope(uint256)\":{\"notice\":\"Get the most recently recorded rate of voting power decrease for `_tokenId`\"},\"increase_amount(uint256,uint256)\":{\"notice\":\"Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\"},\"increase_unlock_time(uint256,uint256)\":{\"notice\":\"Extend the unlock time for `_tokenId`\"},\"locked__end(uint256)\":{\"notice\":\"Get timestamp when `_tokenId`'s lock finishes\"},\"nonces(address)\":{\"notice\":\"A record of states for signing / validating signatures\"},\"numCheckpoints(address)\":{\"notice\":\"The number of checkpoints for each account\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"This works even if sender doesn't own any tokens at the time.\"},\"totalSupplyAt(uint256)\":{\"notice\":\"Calculate total voting power at some point in the past\"},\"totalSupplyAtT(uint256)\":{\"notice\":\"Calculate total voting power\"},\"transferFrom(address,address,uint256)\":{\"notice\":\"The caller is responsible to confirm that `_to` is capable of receiving NFTs or else they maybe be permanently lost.\"},\"user_point_history__ts(uint256,uint256)\":{\"notice\":\"Get the timestamp for checkpoint `_idx` for `_tokenId`\"},\"withdraw(uint256)\":{\"notice\":\"Withdraw all tokens for `_tokenId`\"}},\"notice\":\"veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFTVotes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VotingEscrow.sol\":\"VotingEscrow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VotingEscrow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IERC721, IERC721Metadata} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {IERC721Receiver} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {IERC20} from \\\"contracts/interfaces/IERC20.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\nimport {IVotingEscrow} from \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/// @title Voting Escrow\\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\\n enum DepositType {\\n DEPOSIT_FOR_TYPE,\\n CREATE_LOCK_TYPE,\\n INCREASE_LOCK_AMOUNT,\\n INCREASE_UNLOCK_TIME,\\n MERGE_TYPE\\n }\\n\\n struct LockedBalance {\\n int128 amount;\\n uint end;\\n }\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint ts;\\n uint blk; // block\\n }\\n /* We cannot really do block numbers per se b/c slope is per time, not per block\\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\\n * What we can do is to extrapolate ***At functions */\\n\\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\\n struct Checkpoint {\\n uint timestamp;\\n uint[] tokenIds;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Deposit(\\n address indexed provider,\\n uint tokenId,\\n uint value,\\n uint indexed locktime,\\n DepositType deposit_type,\\n uint ts\\n );\\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\\n event Supply(uint prevSupply, uint supply);\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n address public immutable token;\\n address public voter;\\n address public team;\\n address public artProxy;\\n\\n mapping(uint => Point) public point_history; // epoch -> unsigned point\\n\\n /// @dev Mapping of interface id to bool about whether or not it's supported\\n mapping(bytes4 => bool) internal supportedInterfaces;\\n\\n /// @dev ERC165 interface ID of ERC165\\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\\n\\n /// @dev ERC165 interface ID of ERC721\\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\\n\\n /// @dev ERC165 interface ID of ERC721Metadata\\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\\n\\n /// @dev Current count of token\\n uint internal tokenId;\\n\\n /// @notice Contract constructor\\n /// @param token_addr `VELO` token address\\n constructor(address token_addr, address art_proxy) {\\n token = token_addr;\\n voter = msg.sender;\\n team = msg.sender;\\n artProxy = art_proxy;\\n\\n point_history[0].blk = block.number;\\n point_history[0].ts = block.timestamp;\\n\\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\\n\\n // mint-ish\\n emit Transfer(address(0), address(this), tokenId);\\n // burn-ish\\n emit Transfer(address(this), address(0), tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n MODIFIERS\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev reentrancy guard\\n uint8 internal constant _not_entered = 1;\\n uint8 internal constant _entered = 2;\\n uint8 internal _entered_state = 1;\\n modifier nonreentrant() {\\n require(_entered_state == _not_entered);\\n _entered_state = _entered;\\n _;\\n _entered_state = _not_entered;\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string constant public name = \\\"veNFT\\\";\\n string constant public symbol = \\\"veNFT\\\";\\n string constant public version = \\\"1.0.0\\\";\\n uint8 constant public decimals = 18;\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team);\\n team = _team;\\n }\\n\\n function setArtProxy(address _proxy) external {\\n require(msg.sender == team);\\n artProxy = _proxy;\\n }\\n\\n /// @dev Returns current token URI metadata\\n /// @param _tokenId Token ID to fetch URI for.\\n function tokenURI(uint _tokenId) external view returns (string memory) {\\n require(idToOwner[_tokenId] != address(0), \\\"Query for nonexistent token\\\");\\n LockedBalance memory _locked = locked[_tokenId];\\n return IVeArtProxy(artProxy)._tokenURI(\\n _tokenId,\\n _balanceOfNFT(_tokenId, block.timestamp),\\n _locked.end,\\n uint(int256(_locked.amount))\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 BALANCE/OWNER STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to the address that owns it.\\n mapping(uint => address) internal idToOwner;\\n\\n /// @dev Mapping from owner address to count of his tokens.\\n mapping(address => uint) internal ownerToNFTokenCount;\\n\\n /// @dev Returns the address of the owner of the NFT.\\n /// @param _tokenId The identifier for an NFT.\\n function ownerOf(uint _tokenId) public view returns (address) {\\n return idToOwner[_tokenId];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function _balance(address _owner) internal view returns (uint) {\\n return ownerToNFTokenCount[_owner];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function balanceOf(address _owner) external view returns (uint) {\\n return _balance(_owner);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 APPROVAL STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to approved address.\\n mapping(uint => address) internal idToApprovals;\\n\\n /// @dev Mapping from owner address to mapping of operator addresses.\\n mapping(address => mapping(address => bool)) internal ownerToOperators;\\n\\n mapping(uint => uint) public ownership_change;\\n\\n /// @dev Get the approved address for a single NFT.\\n /// @param _tokenId ID of the NFT to query the approval of.\\n function getApproved(uint _tokenId) external view returns (address) {\\n return idToApprovals[_tokenId];\\n }\\n\\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\\n /// @param _owner The address that owns the NFTs.\\n /// @param _operator The address that acts on behalf of the owner.\\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\\n return (ownerToOperators[_owner])[_operator];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\\n /// @param _approved Address to be approved for the given NFT ID.\\n /// @param _tokenId ID of the token to be approved.\\n function approve(address _approved, uint _tokenId) public {\\n address owner = idToOwner[_tokenId];\\n // Throws if `_tokenId` is not a valid NFT\\n require(owner != address(0));\\n // Throws if `_approved` is the current owner\\n require(_approved != owner);\\n // Check requirements\\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\\n require(senderIsOwner || senderIsApprovedForAll);\\n // Set the approval\\n idToApprovals[_tokenId] = _approved;\\n emit Approval(owner, _approved, _tokenId);\\n }\\n\\n /// @dev Enables or disables approval for a third party (\\\"operator\\\") to manage all of\\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\\n /// @notice This works even if sender doesn't own any tokens at the time.\\n /// @param _operator Address to add to the set of authorized operators.\\n /// @param _approved True if the operators is approved, false to revoke approval.\\n function setApprovalForAll(address _operator, bool _approved) external {\\n // Throws if `_operator` is the `msg.sender`\\n assert(_operator != msg.sender);\\n ownerToOperators[msg.sender][_operator] = _approved;\\n emit ApprovalForAll(msg.sender, _operator, _approved);\\n }\\n\\n /* TRANSFER FUNCTIONS */\\n /// @dev Clear an approval of a given address\\n /// Throws if `_owner` is not the current owner.\\n function _clearApproval(address _owner, uint _tokenId) internal {\\n // Throws if `_owner` is not the current owner\\n assert(idToOwner[_tokenId] == _owner);\\n if (idToApprovals[_tokenId] != address(0)) {\\n // Reset approvals\\n idToApprovals[_tokenId] = address(0);\\n }\\n }\\n\\n /// @dev Returns whether the given spender can transfer a given token ID\\n /// @param _spender address of the spender to query\\n /// @param _tokenId uint ID of the token to be transferred\\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\\n address owner = idToOwner[_tokenId];\\n bool spenderIsOwner = owner == _spender;\\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\\n }\\n\\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\\n return _isApprovedOrOwner(_spender, _tokenId);\\n }\\n\\n /// @dev Exeute transfer of a NFT.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_tokenId` is not a valid NFT.\\n function _transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n address _sender\\n ) internal {\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n // Check requirements\\n require(_isApprovedOrOwner(_sender, _tokenId));\\n // Clear approval. Throws if `_from` is not the current owner\\n _clearApproval(_from, _tokenId);\\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\\n _removeTokenFrom(_from, _tokenId);\\n // auto re-delegate\\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\\n // Add NFT\\n _addTokenTo(_to, _tokenId);\\n // Set the block of ownership transfer (for Flash NFT protection)\\n ownership_change[_tokenId] = block.number;\\n // Log the transfer\\n emit Transfer(_from, _to, _tokenId);\\n }\\n\\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\\n /// they maybe be permanently lost.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n safeTransferFrom(_from, _to, _tokenId, \\\"\\\");\\n }\\n\\n function _isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n uint size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n /// @param _data Additional data with no specified format, sent in call to `_to`.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n bytes memory _data\\n ) public {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n\\n if (_isContract(_to)) {\\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\\n revert(\\\"ERC721: ERC721Receiver rejected tokens\\\");\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert('ERC721: transfer to non ERC721Receiver implementer');\\n } else {\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC165 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Interface identification is specified in ERC-165.\\n /// @param _interfaceID Id of the interface\\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\\n return supportedInterfaces[_interfaceID];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from owner address to mapping of index to tokenIds\\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\\n\\n /// @dev Mapping from NFT ID to index of owner\\n mapping(uint => uint) internal tokenToOwnerIndex;\\n\\n /// @dev Get token by index\\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\\n return ownerToNFTokenIdList[_owner][_tokenIndex];\\n }\\n\\n /// @dev Add a NFT to an index mapping to a given address\\n /// @param _to address of the receiver\\n /// @param _tokenId uint ID Of the token to be added\\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\\n uint current_count = _balance(_to);\\n\\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\\n tokenToOwnerIndex[_tokenId] = current_count;\\n }\\n\\n /// @dev Add a NFT to a given address\\n /// Throws if `_tokenId` is owned by someone.\\n function _addTokenTo(address _to, uint _tokenId) internal {\\n // Throws if `_tokenId` is owned by someone\\n assert(idToOwner[_tokenId] == address(0));\\n // Change the owner\\n idToOwner[_tokenId] = _to;\\n // Update owner token index tracking\\n _addTokenToOwnerList(_to, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_to] += 1;\\n }\\n\\n /// @dev Function to mint tokens\\n /// Throws if `_to` is zero address.\\n /// Throws if `_tokenId` is owned by someone.\\n /// @param _to The address that will receive the minted tokens.\\n /// @param _tokenId The token id to mint.\\n /// @return A boolean that indicates if the operation was successful.\\n function _mint(address _to, uint _tokenId) internal returns (bool) {\\n // Throws if `_to` is zero address\\n assert(_to != address(0));\\n // checkpoint for gov\\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\\n // Add NFT. Throws if `_tokenId` is owned by someone\\n _addTokenTo(_to, _tokenId);\\n emit Transfer(address(0), _to, _tokenId);\\n return true;\\n }\\n\\n /// @dev Remove a NFT from an index mapping to a given address\\n /// @param _from address of the sender\\n /// @param _tokenId uint ID Of the token to be removed\\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\\n // Delete\\n uint current_count = _balance(_from) - 1;\\n uint current_index = tokenToOwnerIndex[_tokenId];\\n\\n if (current_count == current_index) {\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n } else {\\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\\n\\n // Add\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[lastTokenId] = current_index;\\n\\n // Delete\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n }\\n }\\n\\n /// @dev Remove a NFT from a given address\\n /// Throws if `_from` is not the current owner.\\n function _removeTokenFrom(address _from, uint _tokenId) internal {\\n // Throws if `_from` is not the current owner\\n assert(idToOwner[_tokenId] == _from);\\n // Change the owner\\n idToOwner[_tokenId] = address(0);\\n // Update owner token index tracking\\n _removeTokenFromOwnerList(_from, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_from] -= 1;\\n }\\n\\n function _burn(uint _tokenId) internal {\\n require(_isApprovedOrOwner(msg.sender, _tokenId), \\\"caller is not owner nor approved\\\");\\n\\n address owner = ownerOf(_tokenId);\\n\\n // Clear approval\\n approve(address(0), _tokenId);\\n // checkpoint for gov\\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\\n // Remove token\\n _removeTokenFrom(msg.sender, _tokenId);\\n emit Transfer(owner, address(0), _tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public user_point_epoch;\\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\\n mapping(uint => LockedBalance) public locked;\\n uint public epoch;\\n mapping(uint => int128) public slope_changes; // time -> signed slope change\\n uint public supply;\\n\\n uint internal constant WEEK = 1 weeks;\\n uint internal constant MAXTIME = 4 * 365 * 86400;\\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\\n uint internal constant MULTIPLIER = 1 ether;\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @return Value of the slope\\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\\n uint uepoch = user_point_epoch[_tokenId];\\n return user_point_history[_tokenId][uepoch].slope;\\n }\\n\\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @param _idx User epoch number\\n /// @return Epoch time of the checkpoint\\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\\n return user_point_history[_tokenId][_idx].ts;\\n }\\n\\n /// @notice Get timestamp when `_tokenId`'s lock finishes\\n /// @param _tokenId User NFT\\n /// @return Epoch time of the lock end\\n function locked__end(uint _tokenId) external view returns (uint) {\\n return locked[_tokenId].end;\\n }\\n\\n /// @notice Record global and per-user data to checkpoint\\n /// @param _tokenId NFT token ID. No user checkpoint if 0\\n /// @param old_locked Pevious locked amount / end lock time for the user\\n /// @param new_locked New locked amount / end lock time for the user\\n function _checkpoint(\\n uint _tokenId,\\n LockedBalance memory old_locked,\\n LockedBalance memory new_locked\\n ) internal {\\n Point memory u_old;\\n Point memory u_new;\\n int128 old_dslope = 0;\\n int128 new_dslope = 0;\\n uint _epoch = epoch;\\n\\n if (_tokenId != 0) {\\n // Calculate slopes and biases\\n // Kept at zero when they have to\\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\\n u_old.slope = old_locked.amount / iMAXTIME;\\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\\n }\\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\\n u_new.slope = new_locked.amount / iMAXTIME;\\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\\n }\\n\\n // Read values of scheduled changes in the slope\\n // old_locked.end can be in the past and in the future\\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\\n old_dslope = slope_changes[old_locked.end];\\n if (new_locked.end != 0) {\\n if (new_locked.end == old_locked.end) {\\n new_dslope = old_dslope;\\n } else {\\n new_dslope = slope_changes[new_locked.end];\\n }\\n }\\n }\\n\\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\\n if (_epoch > 0) {\\n last_point = point_history[_epoch];\\n }\\n uint last_checkpoint = last_point.ts;\\n // initial_last_point is used for extrapolation to calculate block number\\n // (approximately, for *At methods) and save them\\n // as we cannot figure that out exactly from inside the contract\\n Point memory initial_last_point = last_point;\\n uint block_slope = 0; // dblock/dt\\n if (block.timestamp > last_point.ts) {\\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\\n }\\n // If last point is already recorded in this block, slope=0\\n // But that's ok b/c we know the block in such case\\n\\n // Go over weeks to fill history and calculate what the current point is\\n {\\n uint t_i = (last_checkpoint / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n // Hopefully it won't happen that this won't get used in 5 years!\\n // If it does, users will be able to withdraw but vote weight will be broken\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > block.timestamp) {\\n t_i = block.timestamp;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\\n last_point.slope += d_slope;\\n if (last_point.bias < 0) {\\n // This can happen\\n last_point.bias = 0;\\n }\\n if (last_point.slope < 0) {\\n // This cannot happen - just in case\\n last_point.slope = 0;\\n }\\n last_checkpoint = t_i;\\n last_point.ts = t_i;\\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\\n _epoch += 1;\\n if (t_i == block.timestamp) {\\n last_point.blk = block.number;\\n break;\\n } else {\\n point_history[_epoch] = last_point;\\n }\\n }\\n }\\n\\n epoch = _epoch;\\n // Now point_history is filled until t=now\\n\\n if (_tokenId != 0) {\\n // If last point was in this block, the slope change has been applied already\\n // But in such case we have 0 slope(s)\\n last_point.slope += (u_new.slope - u_old.slope);\\n last_point.bias += (u_new.bias - u_old.bias);\\n if (last_point.slope < 0) {\\n last_point.slope = 0;\\n }\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n }\\n\\n // Record the changed point into history\\n point_history[_epoch] = last_point;\\n\\n if (_tokenId != 0) {\\n // Schedule the slope changes (slope is going down)\\n // We subtract new_user_slope from [new_locked.end]\\n // and add old_user_slope to [old_locked.end]\\n if (old_locked.end > block.timestamp) {\\n // old_dslope was - u_old.slope, so we cancel that\\n old_dslope += u_old.slope;\\n if (new_locked.end == old_locked.end) {\\n old_dslope -= u_new.slope; // It was a new deposit, not extension\\n }\\n slope_changes[old_locked.end] = old_dslope;\\n }\\n\\n if (new_locked.end > block.timestamp) {\\n if (new_locked.end > old_locked.end) {\\n new_dslope -= u_new.slope; // old slope disappeared at this point\\n slope_changes[new_locked.end] = new_dslope;\\n }\\n // else: we recorded it already in old_dslope\\n }\\n // Now handle user history\\n uint user_epoch = user_point_epoch[_tokenId] + 1;\\n\\n user_point_epoch[_tokenId] = user_epoch;\\n u_new.ts = block.timestamp;\\n u_new.blk = block.number;\\n user_point_history[_tokenId][user_epoch] = u_new;\\n }\\n }\\n\\n /// @notice Deposit and lock tokens for a user\\n /// @param _tokenId NFT that holds lock\\n /// @param _value Amount to deposit\\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\\n /// @param locked_balance Previous locked amount / timestamp\\n /// @param deposit_type The type of deposit\\n function _deposit_for(\\n uint _tokenId,\\n uint _value,\\n uint unlock_time,\\n LockedBalance memory locked_balance,\\n DepositType deposit_type\\n ) internal {\\n LockedBalance memory _locked = locked_balance;\\n uint supply_before = supply;\\n\\n supply = supply_before + _value;\\n LockedBalance memory old_locked;\\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\\n // Adding to existing lock, or if a lock is expired - creating a new one\\n _locked.amount += int128(int256(_value));\\n if (unlock_time != 0) {\\n _locked.end = unlock_time;\\n }\\n locked[_tokenId] = _locked;\\n\\n // Possibilities:\\n // Both old_locked.end could be current or expired (>/< block.timestamp)\\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\\n // _locked.end > block.timestamp (always)\\n _checkpoint(_tokenId, old_locked, _locked);\\n\\n address from = msg.sender;\\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\\n assert(IERC20(token).transferFrom(from, address(this), _value));\\n }\\n\\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\\n emit Supply(supply_before, supply_before + _value);\\n }\\n\\n function block_number() external view returns (uint) {\\n return block.number;\\n }\\n\\n /// @notice Record global data to checkpoint\\n function checkpoint() external {\\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\\n }\\n\\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\\n /// cannot extend their locktime and deposit for a brand new user\\n /// @param _tokenId lock NFT\\n /// @param _value Amount to add to user's lock\\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n require(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_value > 0); // dev: need non-zero value\\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n ++tokenId;\\n uint _tokenId = tokenId;\\n _mint(_to, _tokenId);\\n\\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\\n return _tokenId;\\n }\\n\\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, msg.sender);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, _to);\\n }\\n\\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\\n /// @param _value Amount of tokens to deposit and add to the lock\\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n assert(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\\n }\\n\\n /// @notice Extend the unlock time for `_tokenId`\\n /// @param _lock_duration New number of seconds until tokens unlock\\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_locked.end > block.timestamp, 'Lock expired');\\n require(_locked.amount > 0, 'Nothing is locked');\\n require(unlock_time > _locked.end, 'Can only increase lock duration');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\\n }\\n\\n /// @notice Withdraw all tokens for `_tokenId`\\n /// @dev Only possible if the lock has expired\\n function withdraw(uint _tokenId) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n require(block.timestamp >= _locked.end, \\\"The lock didn't expire\\\");\\n uint value = uint(int256(_locked.amount));\\n\\n locked[_tokenId] = LockedBalance(0,0);\\n uint supply_before = supply;\\n supply = supply_before - value;\\n\\n // old_locked can have either expired <= timestamp or zero end\\n // _locked has only 0 end\\n // Both can have >= 0 amount\\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\\n\\n assert(IERC20(token).transfer(msg.sender, value));\\n\\n // Burn the NFT\\n _burn(_tokenId);\\n\\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\\n emit Supply(supply_before, supply_before - value);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\\n // They measure the weights for the purpose of voting, so they don't represent\\n // real coins.\\n\\n /// @notice Binary search to estimate timestamp for block number\\n /// @param _block Block to find\\n /// @param max_epoch Don't go beyond this epoch\\n /// @return Approximate timestamp for block\\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\\n // Binary search\\n uint _min = 0;\\n uint _max = max_epoch;\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (point_history[_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n /// @notice Get the current voting power for `_tokenId`\\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\\n /// @param _tokenId NFT for lock\\n /// @param _t Epoch time to return voting power at\\n /// @return User voting power\\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\\n uint _epoch = user_point_epoch[_tokenId];\\n if (_epoch == 0) {\\n return 0;\\n } else {\\n Point memory last_point = user_point_history[_tokenId][_epoch];\\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(int256(last_point.bias));\\n }\\n }\\n\\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\\n if (ownership_change[_tokenId] == block.number) return 0;\\n return _balanceOfNFT(_tokenId, block.timestamp);\\n }\\n\\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\\n return _balanceOfNFT(_tokenId, _t);\\n }\\n\\n /// @notice Measure voting power of `_tokenId` at block height `_block`\\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\\n /// @param _tokenId User's wallet NFT\\n /// @param _block Block to calculate the voting power at\\n /// @return Voting power\\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\\n // Copying and pasting totalSupply code because Vyper cannot pass by\\n // reference yet\\n assert(_block <= block.number);\\n\\n // Binary search\\n uint _min = 0;\\n uint _max = user_point_epoch[_tokenId];\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (user_point_history[_tokenId][_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n\\n Point memory upoint = user_point_history[_tokenId][_min];\\n\\n uint max_epoch = epoch;\\n uint _epoch = _find_block_epoch(_block, max_epoch);\\n Point memory point_0 = point_history[_epoch];\\n uint d_block = 0;\\n uint d_t = 0;\\n if (_epoch < max_epoch) {\\n Point memory point_1 = point_history[_epoch + 1];\\n d_block = point_1.blk - point_0.blk;\\n d_t = point_1.ts - point_0.ts;\\n } else {\\n d_block = block.number - point_0.blk;\\n d_t = block.timestamp - point_0.ts;\\n }\\n uint block_time = point_0.ts;\\n if (d_block != 0) {\\n block_time += (d_t * (_block - point_0.blk)) / d_block;\\n }\\n\\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\\n if (upoint.bias >= 0) {\\n return uint(uint128(upoint.bias));\\n } else {\\n return 0;\\n }\\n }\\n\\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\\n return _balanceOfAtNFT(_tokenId, _block);\\n }\\n\\n /// @notice Calculate total voting power at some point in the past\\n /// @param _block Block to calculate the total voting power at\\n /// @return Total voting power at `_block`\\n function totalSupplyAt(uint _block) external view returns (uint) {\\n assert(_block <= block.number);\\n uint _epoch = epoch;\\n uint target_epoch = _find_block_epoch(_block, _epoch);\\n\\n Point memory point = point_history[target_epoch];\\n uint dt = 0;\\n if (target_epoch < _epoch) {\\n Point memory point_next = point_history[target_epoch + 1];\\n if (point.blk != point_next.blk) {\\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\\n }\\n } else {\\n if (point.blk != block.number) {\\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\\n }\\n }\\n // Now dt contains info on how far are we beyond point\\n return _supply_at(point, point.ts + dt);\\n }\\n /// @notice Calculate total voting power at some point in the past\\n /// @param point The point (bias/slope) to start search from\\n /// @param t Time to calculate the total voting power at\\n /// @return Total voting power at that time\\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\\n Point memory last_point = point;\\n uint t_i = (last_point.ts / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > t) {\\n t_i = t;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\\n if (t_i == t) {\\n break;\\n }\\n last_point.slope += d_slope;\\n last_point.ts = t_i;\\n }\\n\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(uint128(last_point.bias));\\n }\\n\\n function totalSupply() external view returns (uint) {\\n return totalSupplyAtT(block.timestamp);\\n }\\n\\n /// @notice Calculate total voting power\\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\\n /// @return Total voting power\\n function totalSupplyAtT(uint t) public view returns (uint) {\\n uint _epoch = epoch;\\n Point memory last_point = point_history[_epoch];\\n return _supply_at(last_point, t);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public attachments;\\n mapping(uint => bool) public voted;\\n\\n function setVoter(address _voter) external {\\n require(msg.sender == voter);\\n voter = _voter;\\n }\\n\\n function voting(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = true;\\n }\\n\\n function abstain(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = false;\\n }\\n\\n function attach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] + 1;\\n }\\n\\n function detach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] - 1;\\n }\\n\\n function merge(uint _from, uint _to) external {\\n require(attachments[_from] == 0 && !voted[_from], \\\"attached\\\");\\n require(_from != _to);\\n require(_isApprovedOrOwner(msg.sender, _from));\\n require(_isApprovedOrOwner(msg.sender, _to));\\n\\n LockedBalance memory _locked0 = locked[_from];\\n LockedBalance memory _locked1 = locked[_to];\\n uint value0 = uint(int256(_locked0.amount));\\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\\n\\n locked[_from] = LockedBalance(0, 0);\\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\\n _burn(_from);\\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of each accounts delegate\\n mapping(address => address) private _delegates;\\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\\n\\n /// @notice A record of delegated token checkpoints for each account, by index\\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint32) public numCheckpoints;\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping(address => uint) public nonces;\\n\\n /**\\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\\n * the delegator's own address if they haven't delegated.\\n * This avoids having to delegate to oneself.\\n */\\n function delegates(address delegator) public view returns (address) {\\n address current = _delegates[delegator];\\n return current == address(0) ? delegator : current;\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getVotes(address account) external view returns (uint) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n votes = votes + _balanceOfNFT(tId, block.timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint storage cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPastVotes(address account, uint timestamp)\\n public\\n view\\n returns (uint)\\n {\\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\\n // Sum votes\\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n // Use the provided input timestamp here to get the right decay\\n votes = votes + _balanceOfNFT(tId, timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\\n return totalSupplyAtT(timestamp);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _moveTokenDelegates(\\n address srcRep,\\n address dstRep,\\n uint _tokenId\\n ) internal {\\n if (srcRep != dstRep && _tokenId > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except _tokenId\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (tId != _tokenId) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n // All the same plus _tokenId\\n require(\\n dstRepOld.length + 1 <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n dstRepNew.push(_tokenId);\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _findWhatCheckpointToWrite(address account)\\n internal\\n view\\n returns (uint32)\\n {\\n uint _timestamp = block.timestamp;\\n uint32 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n return _nCheckPoints - 1;\\n } else {\\n return _nCheckPoints;\\n }\\n }\\n\\n function _moveAllDelegates(\\n address owner,\\n address srcRep,\\n address dstRep\\n ) internal {\\n // You can only redelegate what you own\\n if (srcRep != dstRep) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except what owner owns\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (idToOwner[tId] != owner) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n uint ownerTokenCount = ownerToNFTokenCount[owner];\\n require(\\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n // All the same\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n // Plus all that's owned\\n for (uint i = 0; i < ownerTokenCount; i++) {\\n uint tId = ownerToNFTokenIdList[owner][i];\\n dstRepNew.push(tId);\\n }\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\\n address currentDelegate = delegates(delegator);\\n\\n _delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n _moveAllDelegates(delegator, currentDelegate, delegatee);\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n if (delegatee == address(0)) delegatee = msg.sender;\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n function delegateBySig(\\n address delegatee,\\n uint nonce,\\n uint expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public {\\n bytes32 domainSeparator = keccak256(\\n abi.encode(\\n DOMAIN_TYPEHASH,\\n keccak256(bytes(name)),\\n keccak256(bytes(version)),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 structHash = keccak256(\\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash)\\n );\\n address signatory = ecrecover(digest, v, r, s);\\n require(\\n signatory != address(0),\\n \\\"VotingEscrow::delegateBySig: invalid signature\\\"\\n );\\n require(\\n nonce == nonces[signatory]++,\\n \\\"VotingEscrow::delegateBySig: invalid nonce\\\"\\n );\\n require(\\n block.timestamp <= expiry,\\n \\\"VotingEscrow::delegateBySig: signature expired\\\"\\n );\\n return _delegate(signatory, delegatee);\\n }\\n}\\n\",\"keccak256\":\"0x37e5ee306472a946a665be22bc1d370d566a575a1fac84f72f97b0575571d40d\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x41bbb2c41036ca64b2f6c9e973e8cfaa113ebc42af86702cd0d267f915a7e886\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a06040526006805460ff191660011790553480156200001e57600080fd5b5060405162004a1c38038062004a1c8339810160408190526200004191620001b8565b6001600160a01b0382811660805260008054336001600160a01b031991821681178355600180548316909117815560028054909216938516939093179055437f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f0155427f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f005560046020527f9fe05126d2d9ecf60592e254dead906a4b2e492f36cca727682c38e9008c6ac1805460ff1990811684179091557f4267c0a6fd96b7a87f183ee8744f24d011423cd0e0142b3f563f183d8d9a456b8054821684179055635b5e139f60e01b82527e24030bcf4927897dffe721c2d8dda4bfd8910861687c42b03a463b43b04147805490911690921790915560055460405190913091600080516020620049fc833981519152908290a46005546040516000903090600080516020620049fc833981519152908390a45050620001f0565b80516001600160a01b0381168114620001b357600080fd5b919050565b60008060408385031215620001cc57600080fd5b620001d7836200019b565b9150620001e7602084016200019b565b90509250929050565b6080516147e26200021a60003960008181610b220152818161101801526133b501526147e26000f3fe608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea26469706673582212200d861f6646b49aa0a1731ef5e7e97f6ca91f05890c57fa056a41a43c6168d99f64736f6c634300080d0033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea26469706673582212200d861f6646b49aa0a1731ef5e7e97f6ca91f05890c57fa056a41a43c6168d99f64736f6c634300080d0033", "devdoc": { "author": "Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)", "details": "Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).", diff --git a/dist/deploy/15_init.js b/dist/deploy/15_init.js index 575d14d7..53dbd798 100644 --- a/dist/deploy/15_init.js +++ b/dist/deploy/15_init.js @@ -1,50 +1,60 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const arbTestnetConfig_1 = __importDefault(require("../tasks/deploy/constants/arbTestnetConfig")); -const ARB_TEST_CONFIG = arbTestnetConfig_1.default; +'use strict' +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod } + } +Object.defineProperty(exports, '__esModule', { value: true }) +const arbTestnetConfig_1 = __importDefault( + require('../tasks/deploy/constants/arbTestnetConfig') +) +const ARB_TEST_CONFIG = arbTestnetConfig_1.default const func = async function (hre) { - const { deployments, ethers } = hre; - const velo = await ethers.getContract("Velo"); - const pairFactory = await ethers.getContract("PairFactory"); - const escrow = await ethers.getContract("VotingEscrow"); - const voter = await ethers.getContract("Voter"); - const distributor = await ethers.getContract("RewardsDistributor"); - const governor = await ethers.getContract("VeloGovernor"); - const minter = await ethers.getContract("Minter"); - const receiver = await ethers.getContract("RedemptionReceiver"); - const claim = await deployments.get("MerkleClaim"); - // Initialize - await velo.initialMint(ARB_TEST_CONFIG.teamEOA); - console.log("Initial minted"); - await velo.setRedemptionReceiver(receiver.address); - console.log("RedemptionReceiver set"); - await velo.setMerkleClaim(claim.address); - console.log("MerkleClaim set"); - await velo.setMinter(minter.address); - console.log("Minter set"); - await pairFactory.setPauser(ARB_TEST_CONFIG.teamMultisig); - console.log("Pauser set"); - await escrow.setVoter(voter.address); - console.log("Voter set", "voter address: ", voter.address, "escrow address: ", escrow.address); - await escrow.setTeam(ARB_TEST_CONFIG.teamMultisig); - console.log("Team set for escrow"); - await voter.setGovernor(ARB_TEST_CONFIG.teamMultisig); - console.log("Governor set"); - await voter.setEmergencyCouncil(ARB_TEST_CONFIG.teamMultisig); - console.log("Emergency Council set"); - await distributor.setDepositor(minter.address); - console.log("Depositor set"); - await receiver.setTeam(ARB_TEST_CONFIG.teamMultisig); - console.log("Team set for receiver"); - await governor.setTeam(ARB_TEST_CONFIG.teamMultisig); - console.log("Team set for governor"); - await minter.setTeam(ARB_TEST_CONFIG.teamMultisig); - console.log("Team set for minter"); - return true; -}; -exports.default = func; -func.tags = ["init_deploy"]; -func.id = "init_deploy"; + const { deployments, ethers } = hre + const velo = await ethers.getContract('Velo') + const pairFactory = await ethers.getContract('PairFactory') + const escrow = await ethers.getContract('VotingEscrow') + const voter = await ethers.getContract('Voter') + const distributor = await ethers.getContract('RewardsDistributor') + const governor = await ethers.getContract('VeloGovernor') + const minter = await ethers.getContract('Minter') + const receiver = await ethers.getContract('RedemptionReceiver') + const claim = await deployments.get('MerkleClaim') + // Initialize + await velo.initialMint(ARB_TEST_CONFIG.teamEOA) + console.log('Initial minted') + await velo.setRedemptionReceiver(receiver.address) + console.log('RedemptionReceiver set') + await velo.setMerkleClaim(claim.address) + console.log('MerkleClaim set') + await velo.setMinter(minter.address) + console.log('Minter set') + await pairFactory.setPauser(ARB_TEST_CONFIG.teamMultisig) + console.log('Pauser set') + await escrow.setVoter(voter.address) + console.log( + 'Voter set', + 'voter address: ', + voter.address, + 'escrow address: ', + escrow.address + ) + await escrow.setTeam(ARB_TEST_CONFIG.teamMultisig) + console.log('Team set for escrow') + await voter.setGovernor(ARB_TEST_CONFIG.teamMultisig) + console.log('Governor set') + await voter.setEmergencyCouncil(ARB_TEST_CONFIG.teamMultisig) + console.log('Emergency Council set') + await distributor.setDepositor(minter.address) + console.log('Depositor set') + await receiver.setTeam(ARB_TEST_CONFIG.teamMultisig) + console.log('Team set for receiver') + await governor.setTeam(ARB_TEST_CONFIG.teamMultisig) + console.log('Team set for governor') + await minter.setTeam(ARB_TEST_CONFIG.teamMultisig) + console.log('Team set for minter') + return true +} +exports.default = func +func.tags = ['init_deploy'] +func.id = 'init_deploy' diff --git a/dist/hardhat.config.js b/dist/hardhat.config.js index 298ab360..8a77776c 100644 --- a/dist/hardhat.config.js +++ b/dist/hardhat.config.js @@ -1,111 +1,109 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -require("@nomiclabs/hardhat-ethers"); -require("@nomiclabs/hardhat-etherscan"); -require("@nomiclabs/hardhat-waffle"); -require("@typechain/hardhat"); -require("hardhat-preprocessor"); -require("hardhat-abi-exporter"); -require("hardhat-deploy"); -const fs_1 = __importDefault(require("fs")); -const path_1 = require("path"); -const dotenv_1 = require("dotenv"); -(0, dotenv_1.config)({ path: (0, path_1.resolve)(__dirname, "./.env") }); -require("./checkEnv"); +'use strict' +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod } + } +Object.defineProperty(exports, '__esModule', { value: true }) +require('@nomiclabs/hardhat-ethers') +require('@nomiclabs/hardhat-etherscan') +require('@nomiclabs/hardhat-waffle') +require('@typechain/hardhat') +require('hardhat-preprocessor') +require('hardhat-abi-exporter') +require('hardhat-deploy') +const fs_1 = __importDefault(require('fs')) +const path_1 = require('path') +const dotenv_1 = require('dotenv') +;(0, dotenv_1.config)({ path: (0, path_1.resolve)(__dirname, './.env') }) +require('./checkEnv') const remappings = fs_1.default - .readFileSync("remappings.txt", "utf8") - .split("\n") - .filter(Boolean) - .map((line) => line.trim().split("=")); + .readFileSync('remappings.txt', 'utf8') + .split('\n') + .filter(Boolean) + .map(line => line.trim().split('=')) const config = { - networks: { - hardhat: { - initialBaseFeePerGas: 0, - forking: { - url: `https://arb-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY}`, - blockNumber: 16051852, - }, - }, - opera: { - url: "https://rpc.fantom.network", - accounts: [process.env.PRIVATE_KEY], - }, - arbitrum: { - url: `https://arb-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY}`, - accounts: [process.env.PRIVATE_KEY], - chainId: 42161, - saveDeployments: true, - verify: { - etherscan: { - apiUrl: "https://api.arbiscan.io/api", - }, - }, - }, - arbitrumGoerli: { - url: `https://arb-goerli.g.alchemy.com/v2/${process.env.ALCHEMY_GOERLI_ARBITRUM_API_KEY}`, - accounts: [process.env.PRIVATE_KEY], - chainId: 421613, - saveDeployments: true, - verify: { - etherscan: { - apiUrl: "https://api-goerli.arbiscan.io/", - apiKey: process.env.ARB_SCAN_API_KEY, - }, - }, - }, - ftmTestnet: { - url: "https://rpc.testnet.fantom.network", - accounts: [process.env.PRIVATE_KEY], - }, - optimisticEthereum: { - url: "https://mainnet.optimism.io", - accounts: [process.env.PRIVATE_KEY], - }, - optimisticKovan: { - url: "https://kovan.optimism.io", - accounts: [process.env.PRIVATE_KEY], - }, + networks: { + hardhat: { + initialBaseFeePerGas: 0, + forking: { + url: `https://arb-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY}`, + blockNumber: 16051852 + } }, - solidity: { - version: "0.8.13", - settings: { - optimizer: { - enabled: true, - runs: 200, - }, - }, + opera: { + url: 'https://rpc.fantom.network', + accounts: [process.env.PRIVATE_KEY] }, - namedAccounts: { - deployer: 0, + arbitrum: { + url: `https://arb-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY}`, + accounts: [process.env.PRIVATE_KEY], + chainId: 42161, + saveDeployments: true, + verify: { + etherscan: { + apiUrl: 'https://api.arbiscan.io/api' + } + } }, - // This fully resolves paths for imports in the ./lib directory for Hardhat - preprocess: { - eachLine: (hre) => ({ - transform: (line) => { - if (!line.match(/^\s*import /i)) { - return line; - } - const remapping = remappings.find(([find]) => line.match('"' + find)); - if (!remapping) { - return line; - } - const [find, replace] = remapping; - return line.replace('"' + find, '"' + replace); - }, - }), + arbitrumGoerli: { + url: `https://arb-goerli.g.alchemy.com/v2/${process.env.ALCHEMY_GOERLI_ARBITRUM_API_KEY}`, + accounts: [process.env.PRIVATE_KEY], + chainId: 421613, + saveDeployments: true, + verify: { + etherscan: { + apiUrl: 'https://api-goerli.arbiscan.io/', + apiKey: process.env.ARB_SCAN_API_KEY + } + } }, - etherscan: { - apiKey: { - opera: process.env.FTM_SCAN_API_KEY, - ftmTestnet: process.env.FTM_SCAN_API_KEY, - optimisticEthereum: process.env.OP_SCAN_API_KEY, - optimisticKovan: process.env.OP_SCAN_API_KEY, - arbitrum: process.env.ARB_SCAN_API_KEY, - arbitrumGoerli: process.env.ARB_SCAN_API_KEY, - }, + ftmTestnet: { + url: 'https://rpc.testnet.fantom.network', + accounts: [process.env.PRIVATE_KEY] }, -}; -exports.default = config; + optimisticEthereum: { + url: 'https://mainnet.optimism.io', + accounts: [process.env.PRIVATE_KEY] + } + }, + solidity: { + version: '0.8.13', + settings: { + optimizer: { + enabled: true, + runs: 200 + } + } + }, + namedAccounts: { + deployer: 0 + }, + // This fully resolves paths for imports in the ./lib directory for Hardhat + preprocess: { + eachLine: hre => ({ + transform: line => { + if (!line.match(/^\s*import /i)) { + return line + } + const remapping = remappings.find(([find]) => line.match('"' + find)) + if (!remapping) { + return line + } + const [find, replace] = remapping + return line.replace('"' + find, '"' + replace) + } + }) + }, + etherscan: { + apiKey: { + opera: process.env.FTM_SCAN_API_KEY, + ftmTestnet: process.env.FTM_SCAN_API_KEY, + optimisticEthereum: process.env.OP_SCAN_API_KEY, + + arbitrum: process.env.ARB_SCAN_API_KEY, + arbitrumGoerli: process.env.ARB_SCAN_API_KEY + } + } +} +exports.default = config diff --git a/dist/tasks/deploy/constants/arbTestnetConfig.d.ts b/dist/tasks/deploy/constants/arbTestnetConfig.d.ts deleted file mode 100644 index 0ef81208..00000000 --- a/dist/tasks/deploy/constants/arbTestnetConfig.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { ethers } from 'ethers'; -declare const arbTestnetConfig: { - lzChainId: number; - lzEndpoint: string; - WETH: string; - USDC: string; - teamEOA: string; - teamMultisig: string; - emergencyCouncil: string; - merkleRoot: string; - tokenWhitelist: string[]; - partnerAddrs: string[]; - partnerAmts: ethers.BigNumber[]; - partnerMax: ethers.BigNumber; -}; -export default arbTestnetConfig; diff --git a/dist/tasks/deploy/constants/arbTestnetConfig.js b/dist/tasks/deploy/constants/arbTestnetConfig.js index 642db67b..f7e6aabb 100644 --- a/dist/tasks/deploy/constants/arbTestnetConfig.js +++ b/dist/tasks/deploy/constants/arbTestnetConfig.js @@ -1,82 +1,93 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const ethers_1 = require("ethers"); -const TOKEN_DECIMALS = ethers_1.ethers.BigNumber.from('10').pow(ethers_1.ethers.BigNumber.from('18')); -const MILLION = ethers_1.ethers.BigNumber.from('10').pow(ethers_1.ethers.BigNumber.from('6')); -const FOUR_MILLION = ethers_1.ethers.BigNumber.from('4').mul(MILLION).mul(TOKEN_DECIMALS); -const TEN_MILLION = ethers_1.ethers.BigNumber.from('10').mul(MILLION).mul(TOKEN_DECIMALS); +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) +const ethers_1 = require('ethers') +const TOKEN_DECIMALS = ethers_1.ethers.BigNumber.from('10').pow( + ethers_1.ethers.BigNumber.from('18') +) +const MILLION = ethers_1.ethers.BigNumber.from('10').pow( + ethers_1.ethers.BigNumber.from('6') +) +const FOUR_MILLION = ethers_1.ethers.BigNumber.from('4') + .mul(MILLION) + .mul(TOKEN_DECIMALS) +const TEN_MILLION = ethers_1.ethers.BigNumber.from('10') + .mul(MILLION) + .mul(TOKEN_DECIMALS) const TWENTY_MILLION = ethers_1.ethers.BigNumber.from('20') - .mul(MILLION) - .mul(TOKEN_DECIMALS); -const PARTNER_MAX = ethers_1.ethers.BigNumber.from('78').mul(MILLION).mul(TOKEN_DECIMALS); -const TEAM_MULTISIG = '0xb074ec6c37659525EEf2Fb44478077901F878012'; -const TEAM_EOA = '0xe247340f06FCB7eb904F16a48C548221375b5b96'; -const arbTestnetConfig = { - // Chain const - lzChainId: 11, - lzEndpoint: '0x3c2269811836af69497E5F486A85D7316753cf62', - // Tokens - WETH: '0x4200000000000000000000000000000000000006', - USDC: '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', - // Addresses - teamEOA: TEAM_EOA, - teamMultisig: TEAM_MULTISIG, - emergencyCouncil: '0xcC2D01030eC2cd187346F70bFc483F24488C32E8', - merkleRoot: '0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f', - tokenWhitelist: [ - '0x4200000000000000000000000000000000000042', - '0x4200000000000000000000000000000000000006', - '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', - '0x2E3D870790dC77A83DD1d18184Acc7439A53f475', - '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', - '0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9', - '0x217D47011b23BB961eB6D93cA9945B7501a5BB11', - '0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb', - '0x67CCEA5bb16181E7b4109c9c2143c24a1c2205Be', - '0x9e1028F5F1D5eDE59748FFceE5532509976840E0', - '0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4', - '0xCB8FA9a76b8e203D8C3797bF438d8FB81Ea3326A', - '0x3E29D3A9316dAB217754d13b28646B76607c5f04', - '0x8aE125E8653821E851F12A49F7765db9a9ce7384', - '0x10010078a54396F62c96dF8532dc2B4847d47ED3', - // "", // BTRFLY -- N/A - // "", // pxVELO -- N/A - '0xc40F949F8a4e094D1b49a23ea9241D289B7b2819' // LUSD - // "", // wstETH -- N/A - // "", // HOP -- N/A - ], - partnerAddrs: [ - TEAM_EOA, - '0x4a84675512949f81EBFEAAcC6C00D03eDd329de5', - TEAM_EOA, - '0xa283139017a2f5BAdE8d8e25412C600055D318F8', - '0xDcf664d0f76E99eaA2DBD569474d0E75dC899FCD', - '0x489863b61C625a15C74FB4C21486baCb4A3937AB', - '0x641f26c67A5D0829Ae61019131093B6a7c7d18a3', - '0xC224bf25Dcc99236F00843c7D8C4194abE8AA94a', - '0xB6DACAE4eF97b4817d54df8e005269f509f803f9', - TEAM_EOA, - TEAM_EOA, - '0x0dF840dCbf1229262A4125C1fc559bd338eC9491', - '0x2E33A660742e813aD948fB9f7d682FE461E5fbf3', - '0xd2D4e9024D8C90aB52032a9F1e0d92D4cE20191B' // LUSD - ], - partnerAmts: [ - TEN_MILLION, - TWENTY_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION - ], - partnerMax: PARTNER_MAX -}; -exports.default = arbTestnetConfig; + .mul(MILLION) + .mul(TOKEN_DECIMALS) +const PARTNER_MAX = ethers_1.ethers.BigNumber.from('78') + .mul(MILLION) + .mul(TOKEN_DECIMALS) +const TEAM_MULTISIG = '0x069e85D4F1010DD961897dC8C095FBB5FF297434' +const TEAM_EOA = '0x069e85D4F1010DD961897dC8C095FBB5FF297434' +const arbHardhatConfig = { + // Chain const + lzChainId: 110, + lzEndpoint: '0x3c2269811836af69497E5F486A85D7316753cf62', + // Tokens + WETH: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', + USDC: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', + // Addresses + teamEOA: TEAM_EOA, + teamMultisig: TEAM_MULTISIG, + emergencyCouncil: '0xcC2D01030eC2cd187346F70bFc483F24488C32E8', + merkleRoot: + '0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f', + tokenWhitelist: [ + '0x4200000000000000000000000000000000000042', + '0x4200000000000000000000000000000000000006', + '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', + '0x2E3D870790dC77A83DD1d18184Acc7439A53f475', + '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', + '0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9', + '0x217D47011b23BB961eB6D93cA9945B7501a5BB11', + '0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb', + '0x67CCEA5bb16181E7b4109c9c2143c24a1c2205Be', + '0x9e1028F5F1D5eDE59748FFceE5532509976840E0', + '0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4', + '0xCB8FA9a76b8e203D8C3797bF438d8FB81Ea3326A', + '0x3E29D3A9316dAB217754d13b28646B76607c5f04', + '0x8aE125E8653821E851F12A49F7765db9a9ce7384', + '0x10010078a54396F62c96dF8532dc2B4847d47ED3', + // "", // BTRFLY -- N/A + // "", // pxVELO -- N/A + '0xc40F949F8a4e094D1b49a23ea9241D289B7b2819' // LUSD + // "", // wstETH -- N/A + // "", // HOP -- N/A + ], + partnerAddrs: [ + TEAM_EOA, + '0x4a84675512949f81EBFEAAcC6C00D03eDd329de5', + TEAM_EOA, + '0xa283139017a2f5BAdE8d8e25412C600055D318F8', + '0xDcf664d0f76E99eaA2DBD569474d0E75dC899FCD', + '0x489863b61C625a15C74FB4C21486baCb4A3937AB', + '0x641f26c67A5D0829Ae61019131093B6a7c7d18a3', + '0xC224bf25Dcc99236F00843c7D8C4194abE8AA94a', + '0xB6DACAE4eF97b4817d54df8e005269f509f803f9', + TEAM_EOA, + TEAM_EOA, + '0x0dF840dCbf1229262A4125C1fc559bd338eC9491', + '0x2E33A660742e813aD948fB9f7d682FE461E5fbf3', + '0xd2D4e9024D8C90aB52032a9F1e0d92D4cE20191B' // LUSD + ], + partnerAmts: [ + TEN_MILLION, + TWENTY_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION + ], + partnerMax: PARTNER_MAX +} +exports.default = arbHardhatConfig diff --git a/exported.json b/exported.json index 65005d6b..f40f0efb 100644 --- a/exported.json +++ b/exported.json @@ -3,7 +3,7 @@ "chainId": "421613", "contracts": { "BribeFactory": { - "address": "0x5542edb529F7c963583e9B8e5339121cFCf4B606", + "address": "0x560b401d9F28F80980451d8582DEe903dD5295c3", "abi": [ { "inputs": [ @@ -72,7 +72,7 @@ ] }, "GaugeFactory": { - "address": "0x1Ac3032Dfd7e206BA6d08F453f38593b9A583052", + "address": "0xeAA8Ebb77A7e3b7AE2d8090E7A1c2F9B605dc919", "abi": [ { "inputs": [ @@ -134,7 +134,7 @@ ] }, "MerkleClaim": { - "address": "0x0a68F78212D69EfC6346B5F9d72BC5A301779BE9", + "address": "0x92eB499DBC33446Ace4f84Fba84E3A230370858D", "abi": [ { "inputs": [ @@ -242,7 +242,7 @@ ] }, "Minter": { - "address": "0xd2C3ebFB8e7e79CA84080a8551D86Df50B0F559d", + "address": "0x402f3c314149F252144EE4Ca8646b4a215ACD6aC", "abi": [ { "inputs": [ @@ -569,7 +569,7 @@ ] }, "PairFactory": { - "address": "0x7488AC81DC3908ff7141db4949e70D60A3Fd4DCc", + "address": "0x6389e934d35fC9e066FAb549C8DBc9FddaC10e0D", "abi": [ { "inputs": [], @@ -955,7 +955,7 @@ ] }, "RedemptionReceiver": { - "address": "0x08e352f2130d4b68d7B1264CD42191205B61b60f", + "address": "0x52018E83E84ebe30ac6923F3747c7aE503923aaB", "abi": [ { "inputs": [ @@ -1281,7 +1281,7 @@ ] }, "RewardsDistributor": { - "address": "0xf6CdA702C6Bd15d5C0A325CE8f9f88219fE5F445", + "address": "0xc4b9295487B4C43C1929299076820D8f55BBf957", "abi": [ { "inputs": [ @@ -1635,7 +1635,7 @@ ] }, "Router": { - "address": "0xCeaEA7A5cB3e7521DdE6717BCc99a4c8c60E07b6", + "address": "0x1B0aC6bf6f35E638f6cce8D69C6074561273dc52", "abi": [ { "inputs": [ @@ -2617,7 +2617,7 @@ ] }, "VeArtProxy": { - "address": "0x5e7569D02214289490d16bCE4F96B38071db1aD8", + "address": "0x821B98D42D3AB509AF4F54205f0c52B019b9E2D5", "abi": [ { "inputs": [ @@ -2656,7 +2656,7 @@ ] }, "Velo": { - "address": "0xe69b00A164047e7eB87B73971B0f340eEbFF9c81", + "address": "0x84Ca387E7ede764A3284c67Ff8c68a305a9030a0", "abi": [ { "inputs": [], @@ -3040,7 +3040,7 @@ ] }, "VeloGovernor": { - "address": "0x588ADD83f24690BceEbaa4266cd8DC65709DDa4d", + "address": "0x1a79b9daa3E741774bf67732F8a8B5820De8A53a", "abi": [ { "inputs": [ @@ -4098,7 +4098,7 @@ ] }, "VelodromeLibrary": { - "address": "0x233ed5d7FAed19F7b8A28844E2845FBF0F145Be2", + "address": "0xcbE4714A95f866EB9C2eB50856F431f9E7353Ab6", "abi": [ { "inputs": [ @@ -4289,7 +4289,7 @@ ] }, "Voter": { - "address": "0x574607c69f369f0535E77C5F7C35767Aee04879A", + "address": "0x854086d39955d28317aE3856399312b8Edb1B473", "abi": [ { "inputs": [ @@ -5433,7 +5433,7 @@ ] }, "VotingEscrow": { - "address": "0x6b938BA22FB5520fFB5D14c9C4Fef82a48761497", + "address": "0xBf05364D6cf1586852c18c6b1CbEe218E3e09885", "abi": [ { "inputs": [ diff --git a/hardhat.config.ts b/hardhat.config.ts index 38f4e9b3..57ba86b7 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -1,50 +1,52 @@ -import "@nomiclabs/hardhat-ethers"; -import "@nomiclabs/hardhat-etherscan"; -import "@nomiclabs/hardhat-waffle"; -import "@typechain/hardhat"; -import "hardhat-preprocessor"; -import "hardhat-abi-exporter"; -import "hardhat-deploy"; +import '@nomiclabs/hardhat-ethers' +import '@nomiclabs/hardhat-etherscan' +import '@nomiclabs/hardhat-waffle' +import '@typechain/hardhat' +import 'hardhat-preprocessor' +import 'hardhat-abi-exporter' +import 'hardhat-deploy' +import { config as dotenvConfig } from 'dotenv' +import { HardhatUserConfig, task } from 'hardhat/config' -import fs from "fs"; -import { resolve } from "path"; +import fs from 'fs' +import { resolve } from 'path' -import { config as dotenvConfig } from "dotenv"; -import { HardhatUserConfig } from "hardhat/config"; +import './tasks/accounts' +import './tasks/deploy' -dotenvConfig({ path: resolve(__dirname, "./.env") }); -import "./checkEnv"; +dotenvConfig({ path: resolve(__dirname, './.env') }) +import './checkEnv' const remappings = fs - .readFileSync("remappings.txt", "utf8") - .split("\n") + .readFileSync('remappings.txt', 'utf8') + .split('\n') .filter(Boolean) - .map((line) => line.trim().split("=")); + .map(line => line.trim().split('=')) const config: HardhatUserConfig = { networks: { - hardhat: { - initialBaseFeePerGas: 0, - forking: { - url: `https://arb-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY}`, - blockNumber: 16051852, - }, - }, - opera: { - url: "https://rpc.fantom.network", - accounts: [process.env.PRIVATE_KEY!], - }, - arbitrum: { - url: `https://arb-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY}`, - accounts: [process.env.PRIVATE_KEY!], - chainId: 42161, - saveDeployments: true, - verify: { - etherscan: { - apiUrl: "https://api.arbiscan.io/api", - }, - }, - }, + // hardhat: { + // initialBaseFeePerGas: 0, + // forking: { + // url: `https://arb-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY}`, + // blockNumber: 16051852 + // } + // }, + // opera: { + // url: 'https://rpc.fantom.network', + // accounts: [process.env.PRIVATE_KEY!] + // }, + // arbitrum: { + // url: `https://arb-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY}`, + // accounts: [process.env.PRIVATE_KEY!], + // chainId: 42161, + // saveDeployments: false, + // verify: { + // etherscan: { + // apiUrl: 'https://api.arbiscan.io/api' + // } + // } + // }, arbitrumGoerli: { url: `https://arb-goerli.g.alchemy.com/v2/${process.env.ALCHEMY_GOERLI_ARBITRUM_API_KEY}`, accounts: [process.env.PRIVATE_KEY!], @@ -52,64 +54,60 @@ const config: HardhatUserConfig = { saveDeployments: true, verify: { etherscan: { - apiUrl: "https://api-goerli.arbiscan.io/", - apiKey: process.env.ARB_SCAN_API_KEY!, - }, - }, - }, - ftmTestnet: { - url: "https://rpc.testnet.fantom.network", - accounts: [process.env.PRIVATE_KEY!], - }, - optimisticEthereum: { - url: "https://mainnet.optimism.io", - accounts: [process.env.PRIVATE_KEY!], - }, - optimisticKovan: { - url: "https://kovan.optimism.io", - accounts: [process.env.PRIVATE_KEY!], - }, + apiUrl: 'https://api-goerli.arbiscan.io/', + apiKey: process.env.ARB_SCAN_API_KEY! + } + } + } + // ftmTestnet: { + // url: 'https://rpc.testnet.fantom.network', + // accounts: [process.env.PRIVATE_KEY!] + // }, + // optimisticEthereum: { + // url: 'https://mainnet.optimism.io', + // accounts: [process.env.PRIVATE_KEY!] + // } }, solidity: { - version: "0.8.13", + version: '0.8.13', settings: { optimizer: { enabled: true, - runs: 200, - }, - }, + runs: 200 + } + } }, namedAccounts: { - deployer: 0, + deployer: 0 }, // This fully resolves paths for imports in the ./lib directory for Hardhat preprocess: { - eachLine: (hre) => ({ + eachLine: hre => ({ transform: (line: string) => { if (!line.match(/^\s*import /i)) { - return line; + return line } - const remapping = remappings.find(([find]) => line.match('"' + find)); + const remapping = remappings.find(([find]) => line.match('"' + find)) if (!remapping) { - return line; + return line } - const [find, replace] = remapping; - return line.replace('"' + find, '"' + replace); - }, - }), + const [find, replace] = remapping + return line.replace('"' + find, '"' + replace) + } + }) }, etherscan: { apiKey: { - opera: process.env.FTM_SCAN_API_KEY!, - ftmTestnet: process.env.FTM_SCAN_API_KEY!, - optimisticEthereum: process.env.OP_SCAN_API_KEY!, - optimisticKovan: process.env.OP_SCAN_API_KEY!, - arbitrum: process.env.ARB_SCAN_API_KEY!, - arbitrumGoerli: process.env.ARB_SCAN_API_KEY!, - }, - }, -}; + // opera: process.env.FTM_SCAN_API_KEY!, + // ftmTestnet: process.env.FTM_SCAN_API_KEY!, + // optimisticEthereum: process.env.OP_SCAN_API_KEY!, + + // arbitrum: process.env.ARB_SCAN_API_KEY!, + arbitrumGoerli: process.env.ARB_SCAN_API_KEY! + } + } +} -export default config; +export default config diff --git a/package.json b/package.json index 7c718fbe..1b63e2d1 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "lib": "lib" }, "scripts": { - "verify": "npx hardhat --network arbitrumGoerli etherscan-verify --solc-input --sleep" + "verify": "npx hardhat --network arbitrumGoerli etherscan-verify --solc-input --sleep", + "export": "npx hardhat --network arbitrumGoerli export --export ./exported.json" }, "devDependencies": { "@nomiclabs/hardhat-ethers": "yarn:hardhat-deploy-ethers", diff --git a/readme.md b/readme.md index 559d225d..001763e6 100644 --- a/readme.md +++ b/readme.md @@ -4,23 +4,30 @@ run this script after cloning the repo to get the openzeppelin contracts and fou https://github.com/Velocimeter/instruments/blob/master/gitsubmodules.sh +deploy command: +npx hardhat --network arbitrumGoerli deploy +verify command: +npx hardhat --network arbitrumGoerli etherscan-verify --solc-input --sleep + +export abis command: +npx hardhat --network arbitrumGoerli export --export ./exported.json { - BribeFactory: '0x5542edb529F7c963583e9B8e5339121cFCf4B606', - GaugeFactory: '0x1Ac3032Dfd7e206BA6d08F453f38593b9A583052', - MerkleClaim: '0x0a68F78212D69EfC6346B5F9d72BC5A301779BE9', - Minter: '0xd2C3ebFB8e7e79CA84080a8551D86Df50B0F559d', - PairFactory: '0x7488AC81DC3908ff7141db4949e70D60A3Fd4DCc', - RedemptionReceiver: '0x08e352f2130d4b68d7B1264CD42191205B61b60f', - RewardsDistributor: '0xf6CdA702C6Bd15d5C0A325CE8f9f88219fE5F445', - Router: '0xCeaEA7A5cB3e7521DdE6717BCc99a4c8c60E07b6', - VeArtProxy: '0x5e7569D02214289490d16bCE4F96B38071db1aD8', - Velo: '0xe69b00A164047e7eB87B73971B0f340eEbFF9c81', - VeloGovernor: '0x588ADD83f24690BceEbaa4266cd8DC65709DDa4d', - VelodromeLibrary: '0x233ed5d7FAed19F7b8A28844E2845FBF0F145Be2', - Voter: '0x574607c69f369f0535E77C5F7C35767Aee04879A', - VotingEscrow: '0x6b938BA22FB5520fFB5D14c9C4Fef82a48761497' + BribeFactory: '0x560b401d9F28F80980451d8582DEe903dD5295c3', + GaugeFactory: '0xeAA8Ebb77A7e3b7AE2d8090E7A1c2F9B605dc919', + MerkleClaim: '0x92eB499DBC33446Ace4f84Fba84E3A230370858D', + Minter: '0x402f3c314149F252144EE4Ca8646b4a215ACD6aC', + PairFactory: '0x6389e934d35fC9e066FAb549C8DBc9FddaC10e0D', + RedemptionReceiver: '0x52018E83E84ebe30ac6923F3747c7aE503923aaB', + RewardsDistributor: '0xc4b9295487B4C43C1929299076820D8f55BBf957', + Router: '0x1B0aC6bf6f35E638f6cce8D69C6074561273dc52', + VeArtProxy: '0x821B98D42D3AB509AF4F54205f0c52B019b9E2D5', + Velo: '0x84Ca387E7ede764A3284c67Ff8c68a305a9030a0', + VeloGovernor: '0x1a79b9daa3E741774bf67732F8a8B5820De8A53a', + VelodromeLibrary: '0xcbE4714A95f866EB9C2eB50856F431f9E7353Ab6', + Voter: '0x854086d39955d28317aE3856399312b8Edb1B473', + VotingEscrow: '0xBf05364D6cf1586852c18c6b1CbEe218E3e09885' } ## Testing diff --git a/tasks/accounts.ts b/tasks/accounts.ts new file mode 100644 index 00000000..008af1d9 --- /dev/null +++ b/tasks/accounts.ts @@ -0,0 +1,10 @@ +import { Signer } from '@ethersproject/abstract-signer' +import { task } from 'hardhat/config' + +task('accounts', 'Prints the list of accounts', async (_taskArgs, hre) => { + const accounts: Signer[] = await hre.ethers.getSigners() + + for (const account of accounts) { + console.log(await account.getAddress()) + } +}) diff --git a/tasks/deploy/constants/arbHardhatConfig.ts b/tasks/deploy/constants/arbHardhatConfig.ts index 1d1aa733..7a90f335 100644 --- a/tasks/deploy/constants/arbHardhatConfig.ts +++ b/tasks/deploy/constants/arbHardhatConfig.ts @@ -21,17 +21,18 @@ const arbHardhatConfig = { lzEndpoint: '0x3c2269811836af69497E5F486A85D7316753cf62', // Tokens - WETH: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', - USDC: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', + WETH: '0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83', // updated by dunks w/ arb agor WETH + USDC: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', //TODO // Addresses teamEOA: TEAM_EOA, teamMultisig: TEAM_MULTISIG, - emergencyCouncil: '0xcC2D01030eC2cd187346F70bFc483F24488C32E8', + emergencyCouncil: '0x069e85D4F1010DD961897dC8C095FBB5FF297434', merkleRoot: '0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f', tokenWhitelist: [ + // todo update whitelist with actual goerli tokens '0x4200000000000000000000000000000000000042', // OP '0x4200000000000000000000000000000000000006', // WETH '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', // USDC diff --git a/tasks/deploy/constants/arbTestnetConfig.ts b/tasks/deploy/constants/arbTestnetConfig.ts index 752a5642..7a90f335 100644 --- a/tasks/deploy/constants/arbTestnetConfig.ts +++ b/tasks/deploy/constants/arbTestnetConfig.ts @@ -12,26 +12,27 @@ const TWENTY_MILLION = ethers.BigNumber.from('20') .mul(TOKEN_DECIMALS) const PARTNER_MAX = ethers.BigNumber.from('78').mul(MILLION).mul(TOKEN_DECIMALS) -const TEAM_MULTISIG = '0xb074ec6c37659525EEf2Fb44478077901F878012' -const TEAM_EOA = '0xe247340f06FCB7eb904F16a48C548221375b5b96' +const TEAM_MULTISIG = '0x069e85D4F1010DD961897dC8C095FBB5FF297434' +const TEAM_EOA = '0x069e85D4F1010DD961897dC8C095FBB5FF297434' -const arbTestnetConfig = { +const arbHardhatConfig = { // Chain const - lzChainId: 11, + lzChainId: 110, lzEndpoint: '0x3c2269811836af69497E5F486A85D7316753cf62', // Tokens - WETH: '0x4200000000000000000000000000000000000006', - USDC: '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', + WETH: '0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83', // updated by dunks w/ arb agor WETH + USDC: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', //TODO // Addresses teamEOA: TEAM_EOA, teamMultisig: TEAM_MULTISIG, - emergencyCouncil: '0xcC2D01030eC2cd187346F70bFc483F24488C32E8', + emergencyCouncil: '0x069e85D4F1010DD961897dC8C095FBB5FF297434', merkleRoot: '0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f', tokenWhitelist: [ + // todo update whitelist with actual goerli tokens '0x4200000000000000000000000000000000000042', // OP '0x4200000000000000000000000000000000000006', // WETH '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', // USDC @@ -88,4 +89,4 @@ const arbTestnetConfig = { partnerMax: PARTNER_MAX } -export default arbTestnetConfig +export default arbHardhatConfig From 48b8e3be698fff44d7e88c32fc7733306f44bcc4 Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Tue, 17 Jan 2023 15:03:01 +1100 Subject: [PATCH 11/43] note some extra jobs --- deploy/15_init.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/deploy/15_init.ts b/deploy/15_init.ts index a275a5d4..3ddd28b4 100644 --- a/deploy/15_init.ts +++ b/deploy/15_init.ts @@ -65,6 +65,11 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { await minter.setTeam(ARB_TEST_CONFIG.teamMultisig) console.log('Team set for minter') + // create pair + // provide liq + // etc etc + // see forge tests for more details + return true } export default func From e9c9dd815b7b1ecc65fd361c33f90362931d6494 Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Wed, 18 Jan 2023 15:45:40 +1100 Subject: [PATCH 12/43] Revert "deployed to mainnet - problem with etherscan verify" This reverts commit 2b20bd48f3c3d9be7fb81c71e8ea4946cac33241. --- contracts/factories/BribeFactory.sol | 2 + deployments/arbitrum/.chainId | 1 + deployments/arbitrum/.migrations.json | 5 + deployments/arbitrum/BribeFactory.json | 128 + deployments/arbitrum/GaugeFactory.json | 113 + deployments/arbitrum/MerkleClaim.json | 220 + deployments/arbitrum/Minter.json | 427 + deployments/arbitrum/PairFactory.json | 577 ++ deployments/arbitrum/RedemptionReceiver.json | 428 + deployments/arbitrum/RewardsDistributor.json | 520 ++ deployments/arbitrum/Router.json | 1021 +++ deployments/arbitrum/VeArtProxy.json | 75 + deployments/arbitrum/Velo.json | 522 ++ deployments/arbitrum/VeloGovernor.json | 1459 ++++ deployments/arbitrum/VelodromeLibrary.json | 229 + deployments/arbitrum/Voter.json | 1418 ++++ deployments/arbitrum/VotingEscrow.json | 2339 ++++++ .../f93feb6db909c3f14d7eec3a3196fbbd.json | 238 + hardhat.config.ts | 49 +- mainnet-exported.json | 6960 +++++++++++++++++ package.json | 5 +- readme.md | 2 +- 22 files changed, 16713 insertions(+), 25 deletions(-) create mode 100644 deployments/arbitrum/.chainId create mode 100644 deployments/arbitrum/.migrations.json create mode 100644 deployments/arbitrum/BribeFactory.json create mode 100644 deployments/arbitrum/GaugeFactory.json create mode 100644 deployments/arbitrum/MerkleClaim.json create mode 100644 deployments/arbitrum/Minter.json create mode 100644 deployments/arbitrum/PairFactory.json create mode 100644 deployments/arbitrum/RedemptionReceiver.json create mode 100644 deployments/arbitrum/RewardsDistributor.json create mode 100644 deployments/arbitrum/Router.json create mode 100644 deployments/arbitrum/VeArtProxy.json create mode 100644 deployments/arbitrum/Velo.json create mode 100644 deployments/arbitrum/VeloGovernor.json create mode 100644 deployments/arbitrum/VelodromeLibrary.json create mode 100644 deployments/arbitrum/Voter.json create mode 100644 deployments/arbitrum/VotingEscrow.json create mode 100644 deployments/arbitrum/solcInputs/f93feb6db909c3f14d7eec3a3196fbbd.json create mode 100644 mainnet-exported.json diff --git a/contracts/factories/BribeFactory.sol b/contracts/factories/BribeFactory.sol index fda59613..6e19c8ed 100644 --- a/contracts/factories/BribeFactory.sol +++ b/contracts/factories/BribeFactory.sol @@ -19,3 +19,5 @@ contract BribeFactory is IBribeFactory { return last_external_bribe; } } + +// if this imports int and ext bribe why is the the gauge factory asking for those address as if they are deployed to an address. diff --git a/deployments/arbitrum/.chainId b/deployments/arbitrum/.chainId new file mode 100644 index 00000000..7df83ecb --- /dev/null +++ b/deployments/arbitrum/.chainId @@ -0,0 +1 @@ +42161 \ No newline at end of file diff --git a/deployments/arbitrum/.migrations.json b/deployments/arbitrum/.migrations.json new file mode 100644 index 00000000..92ece6a3 --- /dev/null +++ b/deployments/arbitrum/.migrations.json @@ -0,0 +1,5 @@ +{ + "init_deploy": 1673992762, + "whitelist": 1673992764, + "initial_dist": 1673992767 +} \ No newline at end of file diff --git a/deployments/arbitrum/BribeFactory.json b/deployments/arbitrum/BribeFactory.json new file mode 100644 index 00000000..5986839d --- /dev/null +++ b/deployments/arbitrum/BribeFactory.json @@ -0,0 +1,128 @@ +{ + "address": "0xBcC3c06e1D22E44Ac807D76A887fFB40765e0D16", + "abi": [ + { + "inputs": [ + { + "internalType": "address[]", + "name": "allowedRewards", + "type": "address[]" + } + ], + "name": "createExternalBribe", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "allowedRewards", + "type": "address[]" + } + ], + "name": "createInternalBribe", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "last_external_bribe", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "last_internal_bribe", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x7354518e1e037b7664110bd3a0f7ef13b1ee4eadbe7d059b4b536bf86b6250fa", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0xBcC3c06e1D22E44Ac807D76A887fFB40765e0D16", + "transactionIndex": 1, + "gasUsed": "26207536", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xfa162f78feb20b053135d6fb2f86d54a4dacf3af0fb526b6dd495cccbeb6e593", + "transactionHash": "0x7354518e1e037b7664110bd3a0f7ef13b1ee4eadbe7d059b4b536bf86b6250fa", + "logs": [], + "blockNumber": 53774033, + "cumulativeGasUsed": "26207536", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createExternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createInternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_external_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_internal_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/BribeFactory.sol\":\"BribeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/ExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract ExternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve; // \\u5929\\u4f7f\\u306e\\u305f\\u307e\\u3054\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balanceOf;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n _prevSupply = supplyCheckpoints[\\n getPriorSupplyIndex(_nextEpochStart + DURATION)\\n ].supply;\\n prevRewards.balanceOf =\\n (cp0.balanceOf *\\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (block.timestamp > _lastEpochEnd) {\\n reward +=\\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\\n }\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0xfe1e53dea8a63ce448c5856a740ed73038ad29a9dcd0f2a2752049b146bb4eb0\",\"license\":\"MIT\"},\"contracts/InternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract InternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve;\\n\\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 public constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n mapping(address => mapping(uint256 => uint256))\\n public userRewardPerTokenStored;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (totalSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / totalSupply);\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\\n _startTimestamp = endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][tokenId],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][tokenId]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n require(isReward[token]);\\n\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2dc302de5dfd95018d1fba7a3a1916d2c1fcf32859d19d38648767f13422a694\",\"license\":\"MIT\"},\"contracts/factories/BribeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IBribeFactory.sol\\\";\\nimport 'contracts/InternalBribe.sol';\\nimport 'contracts/ExternalBribe.sol';\\n\\ncontract BribeFactory is IBribeFactory {\\n address public last_internal_bribe;\\n address public last_external_bribe;\\n\\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\\n return last_internal_bribe;\\n }\\n\\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\\n return last_external_bribe;\\n }\\n}\\n\\n// if this imports int and ext bribe why is the the gauge factory asking for those address as if they are deployed to an address.\\n\",\"keccak256\":\"0xd107fb5a520bae9b655bec4ad2eb11d598e74d0eeda0db547e2526a907dea7ec\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50614cca806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea26469706673582212205fdc0cbedbaeaa0ba11c8120c027b2bca65c182779d5bf888b06502050a1f54a64736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea2646970667358221220d5f0eaed47ec9cb0f7332a517560bcb420138d14d674caf3674831366bf225f464736f6c634300080d0033a264697066735822122050c7efc34434eca9041cf3c63b65797031e5608706da7fccb31aad9274a6c62c64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea26469706673582212205fdc0cbedbaeaa0ba11c8120c027b2bca65c182779d5bf888b06502050a1f54a64736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea2646970667358221220d5f0eaed47ec9cb0f7332a517560bcb420138d14d674caf3674831366bf225f464736f6c634300080d0033a264697066735822122050c7efc34434eca9041cf3c63b65797031e5608706da7fccb31aad9274a6c62c64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 21321, + "contract": "contracts/factories/BribeFactory.sol:BribeFactory", + "label": "last_internal_bribe", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 21323, + "contract": "contracts/factories/BribeFactory.sol:BribeFactory", + "label": "last_external_bribe", + "offset": 0, + "slot": "1", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrum/GaugeFactory.json b/deployments/arbitrum/GaugeFactory.json new file mode 100644 index 00000000..06d3737d --- /dev/null +++ b/deployments/arbitrum/GaugeFactory.json @@ -0,0 +1,113 @@ +{ + "address": "0x2CCb061AD1b50211cF79f33e690452497941a2fe", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_pool", + "type": "address" + }, + { + "internalType": "address", + "name": "_internal_bribe", + "type": "address" + }, + { + "internalType": "address", + "name": "_external_bribe", + "type": "address" + }, + { + "internalType": "address", + "name": "_ve", + "type": "address" + }, + { + "internalType": "bool", + "name": "isPair", + "type": "bool" + }, + { + "internalType": "address[]", + "name": "allowedRewards", + "type": "address[]" + } + ], + "name": "createGauge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "last_gauge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x7ce753e4c58de4050464cc91803d46e3f6e11979f35747b219de8ced642739a6", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x2CCb061AD1b50211cF79f33e690452497941a2fe", + "transactionIndex": 2, + "gasUsed": "22465566", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x8411daf7bf6b95ca73cd5501cf340f0ad5b197b0b98168e0e20a0bf9a5405d66", + "transactionHash": "0x7ce753e4c58de4050464cc91803d46e3f6e11979f35747b219de8ced642739a6", + "logs": [], + "blockNumber": 53774021, + "cumulativeGasUsed": "23230219", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_internal_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_external_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_ve\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isPair\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_gauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/GaugeFactory.sol\":\"GaugeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Gauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\\ncontract Gauge is IGauge {\\n address public immutable stake; // the LP token that needs to be staked for rewards\\n address public immutable _ve; // the ve token used for gauges\\n address public immutable internal_bribe;\\n address public immutable external_bribe;\\n address public immutable voter;\\n\\n uint256 public derivedSupply;\\n mapping(address => uint256) public derivedBalances;\\n\\n bool public isForPair;\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 internal constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(address => uint256)) public lastEarn;\\n mapping(address => mapping(address => uint256))\\n public userRewardPerTokenStored;\\n\\n mapping(address => uint256) public tokenIds;\\n\\n uint256 public totalSupply;\\n mapping(address => uint256) public balanceOf;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n uint256 public fees0;\\n uint256 public fees1;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(\\n address _stake,\\n address _internal_bribe,\\n address _external_bribe,\\n address __ve,\\n address _voter,\\n bool _forPair,\\n address[] memory _allowedRewardTokens\\n ) {\\n stake = _stake;\\n internal_bribe = _internal_bribe;\\n external_bribe = _external_bribe;\\n _ve = __ve;\\n voter = _voter;\\n isForPair = _forPair;\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function claimFees()\\n external\\n lock\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n return _claimFees();\\n }\\n\\n function _claimFees()\\n internal\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n if (!isForPair) {\\n return (0, 0);\\n }\\n (claimed0, claimed1) = IPair(stake).claimFees();\\n if (claimed0 > 0 || claimed1 > 0) {\\n uint256 _fees0 = fees0 + claimed0;\\n uint256 _fees1 = fees1 + claimed1;\\n (address _token0, address _token1) = IPair(stake).tokens();\\n if (\\n _fees0 > IBribe(internal_bribe).left(_token0) &&\\n _fees0 / DURATION > 0\\n ) {\\n fees0 = 0;\\n _safeApprove(_token0, internal_bribe, _fees0);\\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\\n } else {\\n fees0 = _fees0;\\n }\\n if (\\n _fees1 > IBribe(internal_bribe).left(_token1) &&\\n _fees1 / DURATION > 0\\n ) {\\n fees1 = 0;\\n _safeApprove(_token1, internal_bribe, _fees1);\\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\\n } else {\\n fees1 = _fees1;\\n }\\n\\n emit ClaimFees(msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(address account, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(address account, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[account][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[account] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n derivedSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n function getReward(address account, address[] memory tokens) external lock {\\n require(msg.sender == account || msg.sender == voter);\\n _unlocked = 1;\\n IVoter(voter).distribute(address(this));\\n _unlocked = 2;\\n\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], account);\\n lastEarn[tokens[i]][account] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n\\n uint256 _derivedBalance = derivedBalances[account];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(account);\\n derivedBalances[account] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(account, derivedBalances[account]);\\n _writeSupplyCheckpoint();\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (derivedSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / derivedSupply);\\n }\\n\\n function derivedBalance(address account) public view returns (uint256) {\\n return balanceOf[account];\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\\n function earned(address token, address account)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][account],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[account] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[account] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[account][i];\\n Checkpoint memory cp1 = checkpoints[account][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[account][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][account]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n function depositAll(uint256 tokenId) external {\\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\\n }\\n\\n function deposit(uint256 amount, uint256 tokenId) public lock {\\n require(amount > 0);\\n _updateRewardForAllTokens();\\n\\n _safeTransferFrom(stake, msg.sender, address(this), amount);\\n totalSupply += amount;\\n balanceOf[msg.sender] += amount;\\n\\n if (tokenId > 0) {\\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\\n if (tokenIds[msg.sender] == 0) {\\n tokenIds[msg.sender] = tokenId;\\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\\n }\\n require(tokenIds[msg.sender] == tokenId);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, _derivedBalance);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function withdrawAll() external {\\n withdraw(balanceOf[msg.sender]);\\n }\\n\\n function withdraw(uint256 amount) public {\\n uint256 tokenId = 0;\\n if (amount == balanceOf[msg.sender]) {\\n tokenId = tokenIds[msg.sender];\\n }\\n withdrawToken(amount, tokenId);\\n }\\n\\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[msg.sender] -= amount;\\n _safeTransfer(stake, msg.sender, amount);\\n\\n if (tokenId > 0) {\\n require(tokenId == tokenIds[msg.sender]);\\n tokenIds[msg.sender] = 0;\\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(token != stake);\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"rewards tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n _claimFees();\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeApprove(\\n address token,\\n address spender,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x38cc0284dd60d8a1418d9c34e6be84911ca4a1b479dc129f19b9027e4c670e1f\",\"license\":\"MIT\"},\"contracts/factories/GaugeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/Gauge.sol';\\n\\ncontract GaugeFactory is IGaugeFactory {\\n address public last_gauge;\\n\\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\\n return last_gauge;\\n }\\n}\\n\",\"keccak256\":\"0x34f6ac4bdace9ef01d8cffda9b45842efae88b519230c67759b9936aee6acc9b\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50613b19806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea2646970667358221220656ccf09ce656ea8ebfb044a59e62cffea98cb78d8b1c3228ccdcceab4e0aee364736f6c634300080d0033a2646970667358221220b102ed748ff42223948c2bba31684751618fee0a65b5917ca364d53fe7ff82cd64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea2646970667358221220656ccf09ce656ea8ebfb044a59e62cffea98cb78d8b1c3228ccdcceab4e0aee364736f6c634300080d0033a2646970667358221220b102ed748ff42223948c2bba31684751618fee0a65b5917ca364d53fe7ff82cd64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 21380, + "contract": "contracts/factories/GaugeFactory.sol:GaugeFactory", + "label": "last_gauge", + "offset": 0, + "slot": "0", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrum/MerkleClaim.json b/deployments/arbitrum/MerkleClaim.json new file mode 100644 index 00000000..08d8fc91 --- /dev/null +++ b/deployments/arbitrum/MerkleClaim.json @@ -0,0 +1,220 @@ +{ + "address": "0xF32608868E215FC3164FDe378dca8D3741d0430A", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_velo", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_merkleRoot", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Claim", + "type": "event" + }, + { + "inputs": [], + "name": "VELO", + "outputs": [ + { + "internalType": "contract IVelo", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "name": "claim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "hasClaimed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "merkleRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x244a338c51a7d9d1bb2405db83d844b85ebaf2d138c09a2e359669375face8ca", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0xF32608868E215FC3164FDe378dca8D3741d0430A", + "transactionIndex": 1, + "gasUsed": "3703500", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xcd293d89707cc0c8794c85e899fc285f0d25f827069ba5aa5f91051780ccac52", + "transactionHash": "0x244a338c51a7d9d1bb2405db83d844b85ebaf2d138c09a2e359669375face8ca", + "logs": [], + "blockNumber": 53774144, + "cumulativeGasUsed": "3703500", + "status": 1, + "byzantium": true + }, + "args": [ + "0xC33f7f83CbB021846Cb9c58f2d8E3df428dbC8C1", + "0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f" + ], + "numDeployments": 1, + "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_velo\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"_merkleRoot\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Claim\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"VELO\",\"outputs\":[{\"internalType\":\"contract IVelo\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"hasClaimed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\",\"events\":{\"Claim(address,uint256)\":{\"params\":{\"amount\":\"of tokens claimed\",\"to\":\"recipient of claim\"}}},\"kind\":\"dev\",\"methods\":{\"claim(address,uint256,bytes32[])\":{\"params\":{\"amount\":\"of tokens owed to claimee\",\"proof\":\"merkle proof to prove address and amount are in tree\",\"to\":\"address of claimee\"}},\"constructor\":{\"params\":{\"_merkleRoot\":\"of claimees\",\"_velo\":\"address\"}}},\"title\":\"MerkleClaim\",\"version\":1},\"userdoc\":{\"events\":{\"Claim(address,uint256)\":{\"notice\":\"Emitted after a successful token claim\"}},\"kind\":\"user\",\"methods\":{\"VELO()\":{\"notice\":\"VELO token to claim\"},\"claim(address,uint256,bytes32[])\":{\"notice\":\"Allows claiming tokens if address is part of merkle tree\"},\"constructor\":{\"notice\":\"Creates a new MerkleClaim contract\"},\"hasClaimed(address)\":{\"notice\":\"Mapping of addresses who have claimed tokens\"},\"merkleRoot()\":{\"notice\":\"ERC20-claimee inclusion root\"}},\"notice\":\"Claims VELO for members of a merkle tree\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/MerkleClaim.sol\":\"MerkleClaim\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"},\"contracts/redeem/MerkleClaim.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity 0.8.13;\\n\\n/// ============ Imports ============\\n\\nimport {IVelo} from \\\"contracts/interfaces/IVelo.sol\\\";\\nimport {MerkleProof} from \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\\\"; // OZ: MerkleProof\\n\\n/// @title MerkleClaim\\n/// @notice Claims VELO for members of a merkle tree\\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\\ncontract MerkleClaim {\\n /// ============ Immutable storage ============\\n\\n /// @notice VELO token to claim\\n IVelo public immutable VELO;\\n /// @notice ERC20-claimee inclusion root\\n bytes32 public immutable merkleRoot;\\n\\n /// ============ Mutable storage ============\\n\\n /// @notice Mapping of addresses who have claimed tokens\\n mapping(address => bool) public hasClaimed;\\n\\n /// ============ Constructor ============\\n\\n /// @notice Creates a new MerkleClaim contract\\n /// @param _velo address\\n /// @param _merkleRoot of claimees\\n constructor(address _velo, bytes32 _merkleRoot) {\\n VELO = IVelo(_velo);\\n merkleRoot = _merkleRoot;\\n }\\n\\n /// ============ Events ============\\n\\n /// @notice Emitted after a successful token claim\\n /// @param to recipient of claim\\n /// @param amount of tokens claimed\\n event Claim(address indexed to, uint256 amount);\\n\\n /// ============ Functions ============\\n\\n /// @notice Allows claiming tokens if address is part of merkle tree\\n /// @param to address of claimee\\n /// @param amount of tokens owed to claimee\\n /// @param proof merkle proof to prove address and amount are in tree\\n function claim(\\n address to,\\n uint256 amount,\\n bytes32[] calldata proof\\n ) external {\\n // Throw if address has already claimed tokens\\n require(!hasClaimed[to], \\\"ALREADY_CLAIMED\\\");\\n\\n // Verify merkle proof, or revert if not in tree\\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\\n require(isValidLeaf, \\\"NOT_IN_MERKLE\\\");\\n\\n // Set address to claimed\\n hasClaimed[to] = true;\\n\\n // Claim tokens for address\\n require(VELO.claim(to, amount), \\\"CLAIM_FAILED\\\");\\n\\n // Emit claim event\\n emit Claim(to, amount);\\n }\\n}\\n\",\"keccak256\":\"0xb4724b0f4bf1f8a9f5ef9147e834b2d85ae61005ffc1d6b261f911c093f38270\",\"license\":\"AGPL-3.0-only\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev These functions deal with verification of Merkle Tree proofs.\\n *\\n * The tree and the proofs can be generated using our\\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\\n * You will find a quickstart guide in the readme.\\n *\\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\\n * hashing, or use a hash function other than keccak256 for hashing leaves.\\n * This is because the concatenation of a sorted pair of internal nodes in\\n * the merkle tree could be reinterpreted as a leaf value.\\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\\n * against this attack out of the box.\\n */\\nlibrary MerkleProof {\\n /**\\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\\n * defined by `root`. For this, a `proof` must be provided, containing\\n * sibling hashes on the branch from the leaf to the root of the tree. Each\\n * pair of leaves and each pair of pre-images are assumed to be sorted.\\n */\\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProof(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {verify}\\n *\\n * _Available since v4.7._\\n */\\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProofCalldata(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\\n * hash matches the root of the tree. When processing the proof, the pairs\\n * of leafs & pre-images are assumed to be sorted.\\n *\\n * _Available since v4.4._\\n */\\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Calldata version of {processProof}\\n *\\n * _Available since v4.7._\\n */\\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerify(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProof(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {multiProofVerify}\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerifyCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\\n * respectively.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProof(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n /**\\n * @dev Calldata version of {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProofCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\\n }\\n\\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x00, a)\\n mstore(0x20, b)\\n value := keccak256(0x00, 0x40)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcc76dbe53154a5bbd12fdd1613a73f73f3dc7c63d813be36f7ee606f52d6a7b3\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c060405234801561001057600080fd5b5060405161062638038061062683398101604081905261002f91610045565b6001600160a01b0390911660805260a05261007f565b6000806040838503121561005857600080fd5b82516001600160a01b038116811461006f57600080fd5b6020939093015192949293505050565b60805160a0516105766100b060003960008181605601526101ea01526000818160d8015261029601526105766000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633d13f8741461008b57806373b2e80e146100a0578063a0eeb39a146100d3575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61009e61009936600461043c565b610112565b005b6100c36100ae3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6100fa7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea26469706673582212207ff4a3058000aa2127bce11a4350a06b85715a38c4ec1fb8625704ba02ab001764736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633d13f8741461008b57806373b2e80e146100a0578063a0eeb39a146100d3575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61009e61009936600461043c565b610112565b005b6100c36100ae3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6100fa7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea26469706673582212207ff4a3058000aa2127bce11a4350a06b85715a38c4ec1fb8625704ba02ab001764736f6c634300080d0033", + "devdoc": { + "author": "Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)", + "events": { + "Claim(address,uint256)": { + "params": { + "amount": "of tokens claimed", + "to": "recipient of claim" + } + } + }, + "kind": "dev", + "methods": { + "claim(address,uint256,bytes32[])": { + "params": { + "amount": "of tokens owed to claimee", + "proof": "merkle proof to prove address and amount are in tree", + "to": "address of claimee" + } + }, + "constructor": { + "params": { + "_merkleRoot": "of claimees", + "_velo": "address" + } + } + }, + "title": "MerkleClaim", + "version": 1 + }, + "userdoc": { + "events": { + "Claim(address,uint256)": { + "notice": "Emitted after a successful token claim" + } + }, + "kind": "user", + "methods": { + "VELO()": { + "notice": "VELO token to claim" + }, + "claim(address,uint256,bytes32[])": { + "notice": "Allows claiming tokens if address is part of merkle tree" + }, + "constructor": { + "notice": "Creates a new MerkleClaim contract" + }, + "hasClaimed(address)": { + "notice": "Mapping of addresses who have claimed tokens" + }, + "merkleRoot()": { + "notice": "ERC20-claimee inclusion root" + } + }, + "notice": "Claims VELO for members of a merkle tree", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 24472, + "contract": "contracts/redeem/MerkleClaim.sol:MerkleClaim", + "label": "hasClaimed", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_bool)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrum/Minter.json b/deployments/arbitrum/Minter.json new file mode 100644 index 00000000..200f1a09 --- /dev/null +++ b/deployments/arbitrum/Minter.json @@ -0,0 +1,427 @@ +{ + "address": "0x68352C1560B43AFE60413E6caf9900d77988E44f", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "__voter", + "type": "address" + }, + { + "internalType": "address", + "name": "__ve", + "type": "address" + }, + { + "internalType": "address", + "name": "__rewards_distributor", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weekly", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "circulating_supply", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "circulating_emission", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "inputs": [], + "name": "MAX_TEAM_RATE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_rewards_distributor", + "outputs": [ + { + "internalType": "contract IRewardsDistributor", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_ve", + "outputs": [ + { + "internalType": "contract IVotingEscrow", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_velo", + "outputs": [ + { + "internalType": "contract IVelo", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_voter", + "outputs": [ + { + "internalType": "contract IVoter", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "active_period", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "calculate_emission", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_minted", + "type": "uint256" + } + ], + "name": "calculate_growth", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "circulating_emission", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "circulating_supply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "claimants", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "max", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingTeam", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_team", + "type": "address" + } + ], + "name": "setTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_teamRate", + "type": "uint256" + } + ], + "name": "setTeamRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "team", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "teamRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "update_period", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "weekly", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "weekly_emission", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x47bfaf1e72075b00d5a115b9f499c65033c3e758846fc068abae3d30ebe58f6b", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x68352C1560B43AFE60413E6caf9900d77988E44f", + "transactionIndex": 1, + "gasUsed": "8497822", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x182dfc9178650a0120d8627568d8f4bbd2cff0a2dd095e6931def59f5761e34b", + "transactionHash": "0x47bfaf1e72075b00d5a115b9f499c65033c3e758846fc068abae3d30ebe58f6b", + "logs": [], + "blockNumber": 53774119, + "cumulativeGasUsed": "8497822", + "status": 1, + "byzantium": true + }, + "args": [ + "0x29C487a354D11315059204Df4F7d8AB1aa008ebb", + "0x10Df81252069C1095F541FAca61646cb9Ae76703", + "0xd9891738458A5b1F1EfB5f82183b77c666d9064E" + ], + "numDeployments": 1, + "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__voter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__rewards_distributor\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weekly\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_supply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_emission\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_TEAM_RATE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_rewards_distributor\",\"outputs\":[{\"internalType\":\"contract IRewardsDistributor\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"contract IVotingEscrow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_velo\",\"outputs\":[{\"internalType\":\"contract IVelo\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_voter\",\"outputs\":[{\"internalType\":\"contract IVoter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"active_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"calculate_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minted\",\"type\":\"uint256\"}],\"name\":\"calculate_growth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"claimants\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingTeam\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_teamRate\",\"type\":\"uint256\"}],\"name\":\"setTeamRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"teamRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"update_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Minter.sol\":\"Minter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Minter.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IMinter.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVelo.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\\n\\ncontract Minter is IMinter {\\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\\n uint256 internal constant EMISSION = 990;\\n uint256 internal constant TAIL_EMISSION = 2;\\n uint256 internal constant PRECISION = 1000;\\n IVelo public immutable _velo;\\n IVoter public immutable _voter;\\n IVotingEscrow public immutable _ve;\\n IRewardsDistributor public immutable _rewards_distributor;\\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\\n uint256 public active_period;\\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\\n\\n address internal initializer;\\n address public team;\\n address public pendingTeam;\\n uint256 public teamRate;\\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\\n\\n event Mint(\\n address indexed sender,\\n uint256 weekly,\\n uint256 circulating_supply,\\n uint256 circulating_emission\\n );\\n\\n constructor(\\n address __voter, // the voting & distribution system\\n address __ve, // the ve(3,3) system that will be locked into\\n address __rewards_distributor // the distribution system that ensures users aren't diluted\\n ) {\\n initializer = msg.sender;\\n team = msg.sender;\\n teamRate = 30; // 30 bps = 0.03%\\n _velo = IVelo(IVotingEscrow(__ve).token());\\n _voter = IVoter(__voter);\\n _ve = IVotingEscrow(__ve);\\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\\n }\\n\\n function initialize(\\n address[] memory claimants,\\n uint256[] memory amounts,\\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\\n ) external {\\n require(initializer == msg.sender);\\n _velo.mint(address(this), max);\\n _velo.approve(address(_ve), type(uint256).max);\\n for (uint256 i = 0; i < claimants.length; i++) {\\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\\n }\\n initializer = address(0);\\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\\n }\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team, \\\"not team\\\");\\n pendingTeam = _team;\\n }\\n\\n function acceptTeam() external {\\n require(msg.sender == pendingTeam, \\\"not pending team\\\");\\n team = pendingTeam;\\n }\\n\\n function setTeamRate(uint256 _teamRate) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(_teamRate <= MAX_TEAM_RATE, \\\"rate too high\\\");\\n teamRate = _teamRate;\\n }\\n\\n // calculate circulating supply as total token supply - locked supply\\n function circulating_supply() public view returns (uint256) {\\n return _velo.totalSupply() - _ve.totalSupply();\\n }\\n\\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\\n function calculate_emission() public view returns (uint256) {\\n return (weekly * EMISSION) / PRECISION;\\n }\\n\\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\\n function weekly_emission() public view returns (uint256) {\\n return MathDunks.max(calculate_emission(), circulating_emission());\\n }\\n\\n // calculates tail end (infinity) emissions as 0.2% of total supply\\n function circulating_emission() public view returns (uint256) {\\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\\n }\\n\\n // calculate inflation and adjust ve balances accordingly\\n function calculate_growth(uint256 _minted) public view returns (uint256) {\\n uint256 _veTotal = _ve.totalSupply();\\n uint256 _veloTotal = _velo.totalSupply();\\n return\\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\\n _veTotal) /\\n _veloTotal /\\n 2;\\n }\\n\\n // update period can only be called once per cycle (1 week)\\n function update_period() external returns (uint256) {\\n uint256 _period = active_period;\\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\\n // only trigger if new week\\n _period = (block.timestamp / WEEK) * WEEK;\\n active_period = _period;\\n weekly = weekly_emission();\\n\\n uint256 _growth = calculate_growth(weekly);\\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\\n (PRECISION - teamRate);\\n uint256 _required = _growth + weekly + _teamEmissions;\\n uint256 _balanceOf = _velo.balanceOf(address(this));\\n if (_balanceOf < _required) {\\n _velo.mint(address(this), _required - _balanceOf);\\n }\\n\\n require(_velo.transfer(team, _teamEmissions));\\n require(_velo.transfer(address(_rewards_distributor), _growth));\\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\\n\\n _velo.approve(address(_voter), weekly);\\n _voter.notifyRewardAmount(weekly);\\n\\n emit Mint(\\n msg.sender,\\n weekly,\\n circulating_supply(),\\n circulating_emission()\\n );\\n }\\n return _period;\\n }\\n}\\n\",\"keccak256\":\"0x8dce50c09815e53982006f9ddc46cd52cf7ac86b0c1b7bb15c817f86fb990580\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x6101006040526a0c685fa11e01ec6f0000006000553480156200002157600080fd5b506040516200158938038062001589833981016040819052620000449162000156565b60028054336001600160a01b03199182168117909255600380549091169091179055601e60055560408051637e062a3560e11b815290516001600160a01b0384169163fc0c546a9160048083019260209291908290030181865afa158015620000b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d79190620001a0565b6001600160a01b0390811660805283811660a05282811660c052811660e05262093a808062000108816002620001db565b620001149042620001fd565b62000120919062000218565b6200012c9190620001db565b600155506200023b915050565b80516001600160a01b03811681146200015157600080fd5b919050565b6000806000606084860312156200016c57600080fd5b620001778462000139565b9250620001876020850162000139565b9150620001976040850162000139565b90509250925092565b600060208284031215620001b357600080fd5b620001be8262000139565b9392505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620001f857620001f8620001c5565b500290565b60008219821115620002135762000213620001c5565b500190565b6000826200023657634e487b7160e01b600052601260045260246000fd5b500490565b60805160a05160c05160e051611296620002f3600039600081816101f801528181610c3701528181610cde0152610d51015260008181610261015281816104b30152818161055f0152818161068901526108750152600081816101d101528181610e090152610ea301526000818161015101528181610426015281816104e30152818161070f015281816108f701528181610a5f01528181610ade01528181610ba801528181610c660152610dda01526112966000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c806378ef7f02116100ad578063b5cc143a11610071578063b5cc143a14610296578063cfc6c8ff1461029e578063d1399608146102a6578063e038c75a146102af578063ed29fc11146102b757600080fd5b806378ef7f021461022d578063851708131461023657806385f2aef2146102495780638dd598fb1461025c5780638e01fbfa1461028357600080fd5b80632e8f7b1f116100f45780632e8f7b1f146101b157806336d96faf146101c45780633db9b42a146101cc5780634b1cd5da146101f357806359d46ffc1461021a57600080fd5b806301c8e6fd1461013157806308aa44581461014c578063095cf5c61461018b5780631eebae80146101a057806326cfc17b146101a8575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b61019e610199366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61019e6101bf366004610fb8565b610353565b6101396103de565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b600454610173906001600160a01b031681565b61013960055481565b61019e6102443660046110a7565b6103f3565b600354610173906001600160a01b031681565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b610139610291366004610fb8565b610684565b61019e6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea2646970667358221220ca2234c7f93e2440b9fbf0fec3a7db175caf6e9740b210ee968450b35cc8333b64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c806378ef7f02116100ad578063b5cc143a11610071578063b5cc143a14610296578063cfc6c8ff1461029e578063d1399608146102a6578063e038c75a146102af578063ed29fc11146102b757600080fd5b806378ef7f021461022d578063851708131461023657806385f2aef2146102495780638dd598fb1461025c5780638e01fbfa1461028357600080fd5b80632e8f7b1f116100f45780632e8f7b1f146101b157806336d96faf146101c45780633db9b42a146101cc5780634b1cd5da146101f357806359d46ffc1461021a57600080fd5b806301c8e6fd1461013157806308aa44581461014c578063095cf5c61461018b5780631eebae80146101a057806326cfc17b146101a8575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b61019e610199366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61019e6101bf366004610fb8565b610353565b6101396103de565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b600454610173906001600160a01b031681565b61013960055481565b61019e6102443660046110a7565b6103f3565b600354610173906001600160a01b031681565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b610139610291366004610fb8565b610684565b61019e6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea2646970667358221220ca2234c7f93e2440b9fbf0fec3a7db175caf6e9740b210ee968450b35cc8333b64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 6187, + "contract": "contracts/Minter.sol:Minter", + "label": "weekly", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 6189, + "contract": "contracts/Minter.sol:Minter", + "label": "active_period", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 6200, + "contract": "contracts/Minter.sol:Minter", + "label": "initializer", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 6202, + "contract": "contracts/Minter.sol:Minter", + "label": "team", + "offset": 0, + "slot": "3", + "type": "t_address" + }, + { + "astId": 6204, + "contract": "contracts/Minter.sol:Minter", + "label": "pendingTeam", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 6206, + "contract": "contracts/Minter.sol:Minter", + "label": "teamRate", + "offset": 0, + "slot": "5", + "type": "t_uint256" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrum/PairFactory.json b/deployments/arbitrum/PairFactory.json new file mode 100644 index 00000000..c724ba2f --- /dev/null +++ b/deployments/arbitrum/PairFactory.json @@ -0,0 +1,577 @@ +{ + "address": "0xA2db791281CdeeBb1EEDc78a34989df2Bfd479bE", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token0", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token1", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "indexed": false, + "internalType": "address", + "name": "pair", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "PairCreated", + "type": "event" + }, + { + "inputs": [], + "name": "MAX_FEE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptFeeManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "acceptPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allPairs", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPairsLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "createPair", + "outputs": [ + { + "internalType": "address", + "name": "pair", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "feeManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_stable", + "type": "bool" + } + ], + "name": "getFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getInitializable", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "name": "getPair", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isPair", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pairCodeHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "pauser", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingFeeManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingPauser", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "_fee", + "type": "uint256" + } + ], + "name": "setFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_feeManager", + "type": "address" + } + ], + "name": "setFeeManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_state", + "type": "bool" + } + ], + "name": "setPause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_pauser", + "type": "address" + } + ], + "name": "setPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "stableFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "volatileFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x306e2d821d9c59dcbab8293e7535aa6a69903b449e099338d70dd1634e6e431f", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0xA2db791281CdeeBb1EEDc78a34989df2Bfd479bE", + "transactionIndex": 1, + "gasUsed": "30339230", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x9a41d528ac53283549a72da1405ffe146c73ff66abf7986ace7249bf7cd5fc1c", + "transactionHash": "0x306e2d821d9c59dcbab8293e7535aa6a69903b449e099338d70dd1634e6e431f", + "logs": [], + "blockNumber": 53774047, + "cumulativeGasUsed": "30339230", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"PairCreated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_FEE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allPairs\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"allPairsLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"createPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getInitializable\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"name\":\"getPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pairCodeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingFeeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingPauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_feeManager\",\"type\":\"address\"}],\"name\":\"setFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_state\",\"type\":\"bool\"}],\"name\":\"setPause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pauser\",\"type\":\"address\"}],\"name\":\"setPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stableFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"volatileFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/PairFactory.sol\":\"PairFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Pair.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairCallee.sol\\\";\\nimport \\\"contracts/factories/PairFactory.sol\\\";\\nimport \\\"contracts/PairFees.sol\\\";\\n\\n// The base pair of pools, either stable or volatile\\ncontract Pair is IPair {\\n string public name;\\n string public symbol;\\n uint8 public constant decimals = 18;\\n\\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\\n bool public immutable stable;\\n\\n uint256 public totalSupply = 0;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n mapping(address => uint256) public balanceOf;\\n\\n bytes32 internal DOMAIN_SEPARATOR;\\n // keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 internal constant PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n mapping(address => uint256) public nonces;\\n\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n\\n address public immutable token0;\\n address public immutable token1;\\n address public immutable fees;\\n address immutable factory;\\n\\n // Structure to capture time period obervations every 30 minutes, used for local oracles\\n struct Observation {\\n uint256 timestamp;\\n uint256 reserve0Cumulative;\\n uint256 reserve1Cumulative;\\n }\\n\\n // Capture oracle reading every 30 minutes\\n uint256 constant periodSize = 1800;\\n\\n Observation[] public observations;\\n\\n uint256 internal immutable decimals0;\\n uint256 internal immutable decimals1;\\n\\n uint256 public reserve0;\\n uint256 public reserve1;\\n uint256 public blockTimestampLast;\\n\\n uint256 public reserve0CumulativeLast;\\n uint256 public reserve1CumulativeLast;\\n\\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \\\"clean\\\"\\n // this further allows LP holders to easily claim fees for tokens they have/staked\\n uint256 public index0 = 0;\\n uint256 public index1 = 0;\\n\\n // position assigned to each LP to track their current index0 & index1 vs the global position\\n mapping(address => uint256) public supplyIndex0;\\n mapping(address => uint256) public supplyIndex1;\\n\\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\\n mapping(address => uint256) public claimable0;\\n mapping(address => uint256) public claimable1;\\n\\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\\n event Burn(\\n address indexed sender,\\n uint256 amount0,\\n uint256 amount1,\\n address indexed to\\n );\\n event Swap(\\n address indexed sender,\\n uint256 amount0In,\\n uint256 amount1In,\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address indexed to\\n );\\n event Sync(uint256 reserve0, uint256 reserve1);\\n event Claim(\\n address indexed sender,\\n address indexed recipient,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 amount\\n );\\n\\n constructor() {\\n factory = msg.sender;\\n (address _token0, address _token1, bool _stable) = PairFactory(\\n msg.sender\\n ).getInitializable();\\n (token0, token1, stable) = (_token0, _token1, _stable);\\n fees = address(new PairFees(_token0, _token1));\\n if (_stable) {\\n name = string(\\n abi.encodePacked(\\n \\\"StableV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"sAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n } else {\\n name = string(\\n abi.encodePacked(\\n \\\"VolatileV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"vAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n }\\n\\n decimals0 = 10**IERC20(_token0).decimals();\\n decimals1 = 10**IERC20(_token1).decimals();\\n\\n observations.push(Observation(block.timestamp, 0, 0));\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function observationLength() external view returns (uint256) {\\n return observations.length;\\n }\\n\\n function lastObservation() public view returns (Observation memory) {\\n return observations[observations.length - 1];\\n }\\n\\n function metadata()\\n external\\n view\\n returns (\\n uint256 dec0,\\n uint256 dec1,\\n uint256 r0,\\n uint256 r1,\\n bool st,\\n address t0,\\n address t1\\n )\\n {\\n return (\\n decimals0,\\n decimals1,\\n reserve0,\\n reserve1,\\n stable,\\n token0,\\n token1\\n );\\n }\\n\\n function tokens() external view returns (address, address) {\\n return (token0, token1);\\n }\\n\\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\\n _updateFor(msg.sender);\\n\\n claimed0 = claimable0[msg.sender];\\n claimed1 = claimable1[msg.sender];\\n\\n if (claimed0 > 0 || claimed1 > 0) {\\n claimable0[msg.sender] = 0;\\n claimable1[msg.sender] = 0;\\n\\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\\n\\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n // Accrue fees on token0\\n function _update0(uint256 amount) internal {\\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index0 += _ratio;\\n }\\n emit Fees(msg.sender, amount, 0);\\n }\\n\\n // Accrue fees on token1\\n function _update1(uint256 amount) internal {\\n _safeTransfer(token1, fees, amount);\\n uint256 _ratio = (amount * 1e18) / totalSupply;\\n if (_ratio > 0) {\\n index1 += _ratio;\\n }\\n emit Fees(msg.sender, 0, amount);\\n }\\n\\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\\n // Fees are segregated from core funds, so fees can never put liquidity at risk\\n function _updateFor(address recipient) internal {\\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\\n if (_supplied > 0) {\\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\\n uint256 _supplyIndex1 = supplyIndex1[recipient];\\n uint256 _index0 = index0; // get global index0 for accumulated fees\\n uint256 _index1 = index1;\\n supplyIndex0[recipient] = _index0; // update user current position to global position\\n supplyIndex1[recipient] = _index1;\\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\\n uint256 _delta1 = _index1 - _supplyIndex1;\\n if (_delta0 > 0) {\\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\\n claimable0[recipient] += _share;\\n }\\n if (_delta1 > 0) {\\n uint256 _share = (_supplied * _delta1) / 1e18;\\n claimable1[recipient] += _share;\\n }\\n } else {\\n supplyIndex0[recipient] = index0; // new users are set to the default global state\\n supplyIndex1[recipient] = index1;\\n }\\n }\\n\\n function getReserves()\\n public\\n view\\n returns (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n )\\n {\\n _reserve0 = reserve0;\\n _reserve1 = reserve1;\\n _blockTimestampLast = blockTimestampLast;\\n }\\n\\n // update reserves and, on the first call per block, price accumulators\\n function _update(\\n uint256 balance0,\\n uint256 balance1,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal {\\n uint256 blockTimestamp = block.timestamp;\\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\\n reserve0CumulativeLast += _reserve0 * timeElapsed;\\n reserve1CumulativeLast += _reserve1 * timeElapsed;\\n }\\n\\n Observation memory _point = lastObservation();\\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\\n if (timeElapsed > periodSize) {\\n observations.push(\\n Observation(\\n blockTimestamp,\\n reserve0CumulativeLast,\\n reserve1CumulativeLast\\n )\\n );\\n }\\n reserve0 = balance0;\\n reserve1 = balance1;\\n blockTimestampLast = blockTimestamp;\\n emit Sync(reserve0, reserve1);\\n }\\n\\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\\n function currentCumulativePrices()\\n public\\n view\\n returns (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n uint256 blockTimestamp\\n )\\n {\\n blockTimestamp = block.timestamp;\\n reserve0Cumulative = reserve0CumulativeLast;\\n reserve1Cumulative = reserve1CumulativeLast;\\n\\n // if time has elapsed since the last update on the pair, mock the accumulated price values\\n (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n ) = getReserves();\\n if (_blockTimestampLast != blockTimestamp) {\\n // subtraction overflow is desired\\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\\n reserve0Cumulative += _reserve0 * timeElapsed;\\n reserve1Cumulative += _reserve1 * timeElapsed;\\n }\\n }\\n\\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\\n function current(address tokenIn, uint256 amountIn)\\n external\\n view\\n returns (uint256 amountOut)\\n {\\n Observation memory _observation = lastObservation();\\n (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n\\n ) = currentCumulativePrices();\\n if (block.timestamp == _observation.timestamp) {\\n _observation = observations[observations.length - 2];\\n }\\n\\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\\n uint256 _reserve0 = (reserve0Cumulative -\\n _observation.reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (reserve1Cumulative -\\n _observation.reserve1Cumulative) / timeElapsed;\\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n // as per `current`, however allows user configured granularity, up to the full window size\\n function quote(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 granularity\\n ) external view returns (uint256 amountOut) {\\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\\n uint256 priceAverageCumulative;\\n for (uint256 i = 0; i < _prices.length; i++) {\\n priceAverageCumulative += _prices[i];\\n }\\n return priceAverageCumulative / granularity;\\n }\\n\\n // returns a memory set of twap prices\\n function prices(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points\\n ) external view returns (uint256[] memory) {\\n return sample(tokenIn, amountIn, points, 1);\\n }\\n\\n function sample(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points,\\n uint256 window\\n ) public view returns (uint256[] memory) {\\n uint256[] memory _prices = new uint256[](points);\\n\\n uint256 length = observations.length - 1;\\n uint256 i = length - (points * window);\\n uint256 nextIndex = 0;\\n uint256 index = 0;\\n\\n for (; i < length; i += window) {\\n nextIndex = i + window;\\n uint256 timeElapsed = observations[nextIndex].timestamp -\\n observations[i].timestamp;\\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\\n observations[i].reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\\n observations[i].reserve1Cumulative) / timeElapsed;\\n _prices[index] = _getAmountOut(\\n amountIn,\\n tokenIn,\\n _reserve0,\\n _reserve1\\n );\\n // index < length; length cannot overflow\\n unchecked {\\n index = index + 1;\\n }\\n }\\n return _prices;\\n }\\n\\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\\n // standard uniswap v2 implementation\\n function mint(address to) external lock returns (uint256 liquidity) {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\\n uint256 _amount0 = _balance0 - _reserve0;\\n uint256 _amount1 = _balance1 - _reserve1;\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n if (_totalSupply == 0) {\\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\\n } else {\\n liquidity = MathDunks.min(\\n (_amount0 * _totalSupply) / _reserve0,\\n (_amount1 * _totalSupply) / _reserve1\\n );\\n }\\n require(liquidity > 0, \\\"ILM\\\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\\n _mint(to, liquidity);\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Mint(msg.sender, _amount0, _amount1);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n // standard uniswap v2 implementation\\n function burn(address to)\\n external\\n lock\\n returns (uint256 amount0, uint256 amount1)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n (address _token0, address _token1) = (token0, token1);\\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\\n uint256 _liquidity = balanceOf[address(this)];\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\\n require(amount0 > 0 && amount1 > 0, \\\"ILB\\\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\\n _burn(address(this), _liquidity);\\n _safeTransfer(_token0, to, amount0);\\n _safeTransfer(_token1, to, amount1);\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Burn(msg.sender, amount0, amount1, to);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n function swap(\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address to,\\n bytes calldata data\\n ) external lock {\\n require(!PairFactory(factory).isPaused());\\n require(amount0Out > 0 || amount1Out > 0, \\\"IOA\\\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \\\"IL\\\"); // Pair: INSUFFICIENT_LIQUIDITY\\n\\n uint256 _balance0;\\n uint256 _balance1;\\n {\\n // scope for _token{0,1}, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n require(to != _token0 && to != _token1, \\\"IT\\\"); // Pair: INVALID_TO\\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\\n if (data.length > 0)\\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n }\\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\\n ? _balance0 - (_reserve0 - amount0Out)\\n : 0;\\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\\n ? _balance1 - (_reserve1 - amount1Out)\\n : 0;\\n require(amount0In > 0 || amount1In > 0, \\\"IIA\\\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\\n {\\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n if (amount0In > 0)\\n _update0(\\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token0 and move them out of pool\\n if (amount1In > 0)\\n _update1(\\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token1 and move them out of pool\\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \\\"K\\\"); // Pair: K\\n }\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\\n }\\n\\n // force balances to match reserves\\n function skim(address to) external lock {\\n (address _token0, address _token1) = (token0, token1);\\n _safeTransfer(\\n _token0,\\n to,\\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\\n );\\n _safeTransfer(\\n _token1,\\n to,\\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\\n );\\n }\\n\\n // force reserves to match balances\\n function sync() external lock {\\n _update(\\n IERC20(token0).balanceOf(address(this)),\\n IERC20(token1).balanceOf(address(this)),\\n reserve0,\\n reserve1\\n );\\n }\\n\\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\\n 1e18 +\\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\\n 1e18;\\n }\\n\\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (3 * x0 * ((y * y) / 1e18)) /\\n 1e18 +\\n ((((x0 * x0) / 1e18) * x0) / 1e18);\\n }\\n\\n function _get_y(\\n uint256 x0,\\n uint256 xy,\\n uint256 y\\n ) internal pure returns (uint256) {\\n for (uint256 i = 0; i < 255; i++) {\\n uint256 y_prev = y;\\n uint256 k = _f(x0, y);\\n if (k < xy) {\\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\\n y = y + dy;\\n } else {\\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getAmountOut(uint256 amountIn, address tokenIn)\\n external\\n view\\n returns (uint256)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n function _getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal view returns (uint256) {\\n if (stable) {\\n uint256 xy = _k(_reserve0, _reserve1);\\n _reserve0 = (_reserve0 * 1e18) / decimals0;\\n _reserve1 = (_reserve1 * 1e18) / decimals1;\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0\\n ? (amountIn * 1e18) / decimals0\\n : (amountIn * 1e18) / decimals1;\\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\\n } else {\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n return (amountIn * reserveB) / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\\n if (stable) {\\n uint256 _x = (x * 1e18) / decimals0;\\n uint256 _y = (y * 1e18) / decimals1;\\n uint256 _a = (_x * _y) / 1e18;\\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return (_a * _b) / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n\\n function _mint(address dst, uint256 amount) internal {\\n _updateFor(dst); // balances must be updated on mint/burn/transfer\\n totalSupply += amount;\\n balanceOf[dst] += amount;\\n emit Transfer(address(0), dst, amount);\\n }\\n\\n function _burn(address dst, uint256 amount) internal {\\n _updateFor(dst);\\n totalSupply -= amount;\\n balanceOf[dst] -= amount;\\n emit Transfer(dst, address(0), amount);\\n }\\n\\n function approve(address spender, uint256 amount) external returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external {\\n require(deadline >= block.timestamp, \\\"Pair: EXPIRED\\\");\\n DOMAIN_SEPARATOR = keccak256(\\n abi.encode(\\n keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n ),\\n keccak256(bytes(name)),\\n keccak256(bytes(\\\"1\\\")),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR,\\n keccak256(\\n abi.encode(\\n PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n );\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n require(\\n recoveredAddress != address(0) && recoveredAddress == owner,\\n \\\"Pair: INVALID_SIGNATURE\\\"\\n );\\n allowance[owner][spender] = value;\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function transfer(address dst, uint256 amount) external returns (bool) {\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 amount\\n ) external returns (bool) {\\n address spender = msg.sender;\\n uint256 spenderAllowance = allowance[src][spender];\\n\\n if (spender != src && spenderAllowance != type(uint256).max) {\\n uint256 newAllowance = spenderAllowance - amount;\\n allowance[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n function _transferTokens(\\n address src,\\n address dst,\\n uint256 amount\\n ) internal {\\n _updateFor(src); // update fee position for src\\n _updateFor(dst); // update fee position for dst\\n\\n balanceOf[src] -= amount;\\n balanceOf[dst] += amount;\\n\\n emit Transfer(src, dst, amount);\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x4f508747645f4480e0b0f23d952fa9b82af1d9bc60b15b8cd1f542ee136043d1\",\"license\":\"MIT\"},\"contracts/PairFees.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IERC20.sol';\\n\\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\\ncontract PairFees {\\n\\n address internal immutable pair; // The pair it is bonded to\\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\\n\\n constructor(address _token0, address _token1) {\\n pair = msg.sender;\\n token0 = _token0;\\n token1 = _token1;\\n }\\n\\n function _safeTransfer(address token,address to,uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n // Allow the pair to transfer fees to users\\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\\n require(msg.sender == pair);\\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\\n }\\n\\n}\\n\",\"keccak256\":\"0xb772e192bab353f8642e89a95ef4ef0255d1caef08444101d7fe34469c1000ca\",\"license\":\"MIT\"},\"contracts/factories/PairFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/Pair.sol';\\n\\ncontract PairFactory is IPairFactory {\\n\\n bool public isPaused;\\n address public pauser;\\n address public pendingPauser;\\n\\n uint256 public stableFee;\\n uint256 public volatileFee;\\n uint256 public constant MAX_FEE = 5; // 0.05%\\n address public feeManager;\\n address public pendingFeeManager;\\n\\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\\n address[] public allPairs;\\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\\n\\n address internal _temp0;\\n address internal _temp1;\\n bool internal _temp;\\n\\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\\n\\n constructor() {\\n pauser = msg.sender;\\n isPaused = false;\\n feeManager = msg.sender;\\n stableFee = 2; // 0.02%\\n volatileFee = 2;\\n }\\n\\n function allPairsLength() external view returns (uint) {\\n return allPairs.length;\\n }\\n\\n function setPauser(address _pauser) external {\\n require(msg.sender == pauser);\\n pendingPauser = _pauser;\\n }\\n\\n function acceptPauser() external {\\n require(msg.sender == pendingPauser);\\n pauser = pendingPauser;\\n }\\n\\n function setPause(bool _state) external {\\n require(msg.sender == pauser);\\n isPaused = _state;\\n }\\n\\n function setFeeManager(address _feeManager) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n pendingFeeManager = _feeManager;\\n }\\n\\n function acceptFeeManager() external {\\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\\n feeManager = pendingFeeManager;\\n }\\n\\n function setFee(bool _stable, uint256 _fee) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n require(_fee <= MAX_FEE, 'fee too high');\\n require(_fee != 0, 'fee must be nonzero');\\n if (_stable) {\\n stableFee = _fee;\\n } else {\\n volatileFee = _fee;\\n }\\n }\\n\\n function getFee(bool _stable) public view returns(uint256) {\\n return _stable ? stableFee : volatileFee;\\n }\\n\\n function pairCodeHash() external pure returns (bytes32) {\\n return keccak256(type(Pair).creationCode);\\n }\\n\\n function getInitializable() external view returns (address, address, bool) {\\n return (_temp0, _temp1, _temp);\\n }\\n\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\\n (_temp0, _temp1, _temp) = (token0, token1, stable);\\n pair = address(new Pair{salt:salt}());\\n getPair[token0][token1][stable] = pair;\\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\\n allPairs.push(pair);\\n isPair[pair] = true;\\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\\n }\\n}\\n\",\"keccak256\":\"0x9b7984117a5a32188aa9ddf42b6cff024240579ab30f3776f7a201285d813e4f\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairCallee.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairCallee {\\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x3ac2de2c7a08bf59fd1006e4d108b247916369de15fbd048b72ca2b7814023ca\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50600080546001600160a81b03191633610100810260ff1916919091178255600480546001600160a01b0319169091179055600280805560035561519190819061005a90396000f3fe60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea2646970667358221220270f4e3352962d1c128c52f446c9e0a94cfd4293f1f3d44b28a148af57736d1a64736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea26469706673582212204d9e84053035e063a46827cca65ab59fad4e23ed0078ae98f8e2cc371de9f9ef64736f6c634300080d0033a2646970667358221220dfffcd46a9d232648bdc2dd9222c658d5554eef6a609556964e00d872e0d720d64736f6c634300080d0033", + "deployedBytecode": "0x60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea2646970667358221220270f4e3352962d1c128c52f446c9e0a94cfd4293f1f3d44b28a148af57736d1a64736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea26469706673582212204d9e84053035e063a46827cca65ab59fad4e23ed0078ae98f8e2cc371de9f9ef64736f6c634300080d0033a2646970667358221220dfffcd46a9d232648bdc2dd9222c658d5554eef6a609556964e00d872e0d720d64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 21428, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "isPaused", + "offset": 0, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 21430, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "pauser", + "offset": 1, + "slot": "0", + "type": "t_address" + }, + { + "astId": 21432, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "pendingPauser", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 21434, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "stableFee", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 21436, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "volatileFee", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 21441, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "feeManager", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 21443, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "pendingFeeManager", + "offset": 0, + "slot": "5", + "type": "t_address" + }, + { + "astId": 21451, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "getPair", + "offset": 0, + "slot": "6", + "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_bool,t_address)))" + }, + { + "astId": 21454, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "allPairs", + "offset": 0, + "slot": "7", + "type": "t_array(t_address)dyn_storage" + }, + { + "astId": 21458, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "isPair", + "offset": 0, + "slot": "8", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 21460, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "_temp0", + "offset": 0, + "slot": "9", + "type": "t_address" + }, + { + "astId": 21462, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "_temp1", + "offset": 0, + "slot": "10", + "type": "t_address" + }, + { + "astId": 21464, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "_temp", + "offset": 20, + "slot": "10", + "type": "t_bool" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "base": "t_address", + "encoding": "dynamic_array", + "label": "address[]", + "numberOfBytes": "32" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_address,t_mapping(t_address,t_mapping(t_bool,t_address)))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => mapping(bool => address)))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_mapping(t_bool,t_address))" + }, + "t_mapping(t_address,t_mapping(t_bool,t_address))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(bool => address))", + "numberOfBytes": "32", + "value": "t_mapping(t_bool,t_address)" + }, + "t_mapping(t_bool,t_address)": { + "encoding": "mapping", + "key": "t_bool", + "label": "mapping(bool => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrum/RedemptionReceiver.json b/deployments/arbitrum/RedemptionReceiver.json new file mode 100644 index 00000000..8bf7f47c --- /dev/null +++ b/deployments/arbitrum/RedemptionReceiver.json @@ -0,0 +1,428 @@ +{ + "address": "0x79f8A0BFDF42f3FB6FeaE1839C9F3f926b582F9b", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_usdc", + "type": "address" + }, + { + "internalType": "address", + "name": "_velo", + "type": "address" + }, + { + "internalType": "uint16", + "name": "_fantomChainId", + "type": "uint16" + }, + { + "internalType": "address", + "name": "_endpoint", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "fantomSender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemableUSDC", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemableVELO", + "type": "uint256" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "inputs": [], + "name": "ELIGIBLE_WEVE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "USDC", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VELO", + "outputs": [ + { + "internalType": "contract IVelo", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "toAddressBytes", + "type": "bytes" + } + ], + "name": "addressFromPackedBytes", + "outputs": [ + { + "internalType": "address", + "name": "toAddress", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "claimLeftovers", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "deployed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "endpoint", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "fantomChainId", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "fantomSender", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_fantomSender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_redeemableUSDC", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_redeemableVELO", + "type": "uint256" + } + ], + "name": "initializeReceiverWith", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "leftoverVELO", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "srcChainId", + "type": "uint16" + }, + { + "internalType": "bytes", + "name": "srcAddress", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "lzReceive", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountWEVE", + "type": "uint256" + } + ], + "name": "previewRedeem", + "outputs": [ + { + "internalType": "uint256", + "name": "shareOfUSDC", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "shareOfVELO", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "redeemableUSDC", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "redeemableVELO", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "redeemedWEVE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_team", + "type": "address" + } + ], + "name": "setTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "team", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x41d9bceec612e0def27e125f77f82babdfd5b92f314b906ea4ca94ce79d0ce7d", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x79f8A0BFDF42f3FB6FeaE1839C9F3f926b582F9b", + "transactionIndex": 1, + "gasUsed": "7099388", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xeeb50f2fa50ab544b9e7082b769b888a533ef57280c25a50daa9d4fae286e79e", + "transactionHash": "0x41d9bceec612e0def27e125f77f82babdfd5b92f314b906ea4ca94ce79d0ce7d", + "logs": [], + "blockNumber": 53774137, + "cumulativeGasUsed": "7099388", + "status": 1, + "byzantium": true + }, + "args": [ + "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8", + "0xC33f7f83CbB021846Cb9c58f2d8E3df428dbC8C1", + 10012, + "0x3c2269811836af69497E5F486A85D7316753cf62" + ], + "numDeployments": 1, + "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_usdc\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_velo\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"_fantomChainId\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"_endpoint\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fantomSender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableUSDC\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableVELO\",\"type\":\"uint256\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ELIGIBLE_WEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"USDC\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VELO\",\"outputs\":[{\"internalType\":\"contract IVelo\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"toAddressBytes\",\"type\":\"bytes\"}],\"name\":\"addressFromPackedBytes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimLeftovers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endpoint\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomChainId\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_fantomSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableVELO\",\"type\":\"uint256\"}],\"name\":\"initializeReceiverWith\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"leftoverVELO\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"srcChainId\",\"type\":\"uint16\"},{\"internalType\":\"bytes\",\"name\":\"srcAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"lzReceive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountWEVE\",\"type\":\"uint256\"}],\"name\":\"previewRedeem\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"shareOfUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shareOfVELO\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableUSDC\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableVELO\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemedWEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process This contract is responsible for receiving the LZ message and distributing USDC + VELO\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/RedemptionReceiver.sol\":\"RedemptionReceiver\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"},\"contracts/redeem/RedemptionReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\\\";\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IVelo.sol\\\";\\n\\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\\ncontract RedemptionReceiver is ILayerZeroReceiver {\\n IERC20 public immutable USDC;\\n IVelo public immutable VELO;\\n\\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\\n address public immutable endpoint;\\n\\n address public team;\\n uint256 public immutable deployed;\\n\\n address public fantomSender;\\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\\n uint256 public redeemedWEVE;\\n uint256 public redeemableUSDC;\\n uint256 public redeemableVELO;\\n uint256 public leftoverVELO;\\n\\n constructor(\\n address _usdc,\\n address _velo,\\n uint16 _fantomChainId,\\n address _endpoint\\n ) {\\n require(_fantomChainId == 12 || _fantomChainId == 10012, \\\"CHAIN_ID_NOT_FTM\\\");\\n\\n USDC = IERC20(_usdc);\\n VELO = IVelo(_velo);\\n\\n fantomChainId = _fantomChainId;\\n endpoint = _endpoint;\\n\\n team = msg.sender;\\n deployed = block.timestamp;\\n }\\n\\n modifier onlyTeam() {\\n require(msg.sender == team, \\\"ONLY_TEAM\\\");\\n _;\\n }\\n\\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\\n\\n function initializeReceiverWith(\\n address _fantomSender,\\n uint256 _redeemableUSDC,\\n uint256 _redeemableVELO\\n ) external onlyTeam {\\n require(fantomSender == address(0), \\\"ALREADY_INITIALIZED\\\");\\n require(\\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n fantomSender = _fantomSender;\\n redeemableUSDC = _redeemableUSDC;\\n redeemableVELO = _redeemableVELO;\\n leftoverVELO = _redeemableVELO;\\n\\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\\n }\\n\\n function setTeam(address _team) external onlyTeam {\\n team = _team;\\n }\\n\\n function previewRedeem(uint256 amountWEVE)\\n public\\n view\\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\\n {\\n // pro rata USDC\\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\\n // pro rata VELO\\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\\n }\\n\\n function lzReceive(\\n uint16 srcChainId,\\n bytes memory srcAddress,\\n uint64,\\n bytes memory payload\\n ) external override {\\n require(fantomSender != address(0), \\\"NOT_INITIALIZED\\\");\\n require(\\n msg.sender == endpoint &&\\n srcChainId == fantomChainId &&\\n addressFromPackedBytes(srcAddress) == fantomSender,\\n \\\"UNAUTHORIZED_CALLER\\\"\\n );\\n\\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\\n payload,\\n (address, uint256)\\n );\\n\\n require(\\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\\n \\\"cannot redeem more than eligible\\\"\\n );\\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\\n\\n require(\\n USDC.transfer(redemptionAddress, shareOfUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n leftoverVELO -= shareOfVELO; // this will revert if underflows\\n require(\\n VELO.claim(redemptionAddress, shareOfVELO),\\n \\\"CLAIM_FAILED\\\"\\n );\\n }\\n\\n function addressFromPackedBytes(bytes memory toAddressBytes)\\n public\\n pure\\n returns (address toAddress)\\n {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n toAddress := mload(add(toAddressBytes, 20))\\n }\\n }\\n\\n function claimLeftovers() external onlyTeam {\\n require(block.timestamp >= deployed + 30 days, \\\"LEFTOVERS_NOT_CLAIMABLE\\\");\\n require(\\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n }\\n}\\n\",\"keccak256\":\"0xb5c76f083e5076206e2713b64eed8bfc782715c19f6993ac8e97b1db898ae304\",\"license\":\"MIT\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\nimport \\\"./ILayerZeroUserApplicationConfig.sol\\\";\\n\\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\\n // @param _dstChainId - the destination chain identifier\\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\\n // @param _payload - a custom bytes payload to send to the destination contract\\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\\n\\n // @notice used by the messaging library to publish verified payload\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source contract (as bytes) at the source chain\\n // @param _dstAddress - the address on destination chain\\n // @param _nonce - the unbound message ordering nonce\\n // @param _gasLimit - the gas limit for external contract execution\\n // @param _payload - verified payload to send to the destination contract\\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\\n\\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\\n\\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\\n // @param _srcAddress - the source chain contract address\\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\\n\\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\\n // @param _dstChainId - the destination chain identifier\\n // @param _userApplication - the user app address on this EVM chain\\n // @param _payload - the custom message to send over LayerZero\\n // @param _payInZRO - if false, user app pays the protocol fee in native token\\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\\n\\n // @notice get this Endpoint's immutable source identifier\\n function getChainId() external view returns (uint16);\\n\\n // @notice the interface to retry failed message on this Endpoint destination\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n // @param _payload - the payload to be retried\\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\\n\\n // @notice query if any STORED payload (message blocking) at the endpoint.\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\\n\\n // @notice query if the _libraryAddress is valid for sending msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getSendLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the _libraryAddress is valid for receiving msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the non-reentrancy guard for send() is on\\n // @return true if the guard is on. false otherwise\\n function isSendingPayload() external view returns (bool);\\n\\n // @notice query if the non-reentrancy guard for receive() is on\\n // @return true if the guard is on. false otherwise\\n function isReceivingPayload() external view returns (bool);\\n\\n // @notice get the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _userApplication - the contract address of the user application\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\\n\\n // @notice get the send() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getSendVersion(address _userApplication) external view returns (uint16);\\n\\n // @notice get the lzReceive() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getReceiveVersion(address _userApplication) external view returns (uint16);\\n}\\n\",\"keccak256\":\"0xbc2e0022d4d53d136830aa90037be2ed7a0966f5fd1b409bf5986185984c495f\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroReceiver {\\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\\n // @param _srcChainId - the source endpoint identifier\\n // @param _srcAddress - the source sending contract address from the source chain\\n // @param _nonce - the ordered message nonce\\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\\n}\\n\",\"keccak256\":\"0xd1617e455d90d41556bba636bc440627d301ec481de16ff04fbd520333c3c6f3\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroUserApplicationConfig {\\n // @notice set the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n // @param _config - configuration in the bytes. can encode arbitrary content.\\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\\n\\n // @notice set the send() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setSendVersion(uint16 _version) external;\\n\\n // @notice set the lzReceive() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setReceiveVersion(uint16 _version) external;\\n\\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\\n // @param _srcChainId - the chainId of the source chain\\n // @param _srcAddress - the contract address of the source contract at the source chain\\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\\n}\\n\",\"keccak256\":\"0xdc7e072cf3064081a8edf4a286ca43ddecc24330f2923d96f416f9d3f6538447\",\"license\":\"BUSL-1.1\"}},\"version\":1}", + "bytecode": "0x61012060405234801561001157600080fd5b50604051610f81380380610f81833981016040819052610030916100e2565b8161ffff16600c148061004857508161ffff1661271c145b61008b5760405162461bcd60e51b815260206004820152601060248201526f434841494e5f49445f4e4f545f46544d60801b604482015260640160405180910390fd5b6001600160a01b0393841660805291831660a05261ffff1660c0521660e052600080546001600160a01b03191633179055426101005261013f565b80516001600160a01b03811681146100dd57600080fd5b919050565b600080600080608085870312156100f857600080fd5b610101856100c6565b935061010f602086016100c6565b9250604085015161ffff8116811461012657600080fd5b9150610134606086016100c6565b905092959194509250565b60805160a05160c05160e05161010051610dcd6101b4600039600081816102d601526108c00152600081816101940152610352015260008181610245015261037c01526000818161027f015261059f01526000818161021e015281816104d70152818161078e015261094c0152610dcd6000f3fe608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a0eeb39a11610071578063a0eeb39a1461027a578063a408bb4c146102a1578063aaa8f2ef146102a9578063b8ea6281146102bc578063f905c15a146102d157600080fd5b80636bfd23a7146101fd57806385f2aef21461020657806389a3027114610219578063997a03b71461024057600080fd5b80634cdad506116100e95780634cdad506146101675780635e280f111461018f57806363b4eb8d146101ce57806368ecc6bc146101e15780636ac55083146101f457600080fd5b80621d35671461011a578063095cf5c61461012f578063221798ad1461014257806347db1a6a1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60045481565b6040519081526020015b60405180910390f35b61014b60035481565b61017a610175366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b6001546101b6906001600160a01b031681565b61012d6101ef366004610be5565b6106f3565b61014b60055481565b61014b60025481565b6000546101b6906001600160a01b031681565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6102677f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101b66102ca366004610c1a565b6014015190565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea2646970667358221220be3f6e571af6d97b3ed3a0c9501b02f06dd795e10bb929bfc6cfc207850f0e6864736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a0eeb39a11610071578063a0eeb39a1461027a578063a408bb4c146102a1578063aaa8f2ef146102a9578063b8ea6281146102bc578063f905c15a146102d157600080fd5b80636bfd23a7146101fd57806385f2aef21461020657806389a3027114610219578063997a03b71461024057600080fd5b80634cdad506116100e95780634cdad506146101675780635e280f111461018f57806363b4eb8d146101ce57806368ecc6bc146101e15780636ac55083146101f457600080fd5b80621d35671461011a578063095cf5c61461012f578063221798ad1461014257806347db1a6a1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60045481565b6040519081526020015b60405180910390f35b61014b60035481565b61017a610175366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b6001546101b6906001600160a01b031681565b61012d6101ef366004610be5565b6106f3565b61014b60055481565b61014b60025481565b6000546101b6906001600160a01b031681565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6102677f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101b66102ca366004610c1a565b6014015190565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea2646970667358221220be3f6e571af6d97b3ed3a0c9501b02f06dd795e10bb929bfc6cfc207850f0e6864736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "notice": "Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process This contract is responsible for receiving the LZ message and distributing USDC + VELO", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 24584, + "contract": "contracts/redeem/RedemptionReceiver.sol:RedemptionReceiver", + "label": "team", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 24588, + "contract": "contracts/redeem/RedemptionReceiver.sol:RedemptionReceiver", + "label": "fantomSender", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 24595, + "contract": "contracts/redeem/RedemptionReceiver.sol:RedemptionReceiver", + "label": "redeemedWEVE", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 24597, + "contract": "contracts/redeem/RedemptionReceiver.sol:RedemptionReceiver", + "label": "redeemableUSDC", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 24599, + "contract": "contracts/redeem/RedemptionReceiver.sol:RedemptionReceiver", + "label": "redeemableVELO", + "offset": 0, + "slot": "4", + "type": "t_uint256" + }, + { + "astId": 24601, + "contract": "contracts/redeem/RedemptionReceiver.sol:RedemptionReceiver", + "label": "leftoverVELO", + "offset": 0, + "slot": "5", + "type": "t_uint256" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrum/RewardsDistributor.json b/deployments/arbitrum/RewardsDistributor.json new file mode 100644 index 00000000..2536ab7d --- /dev/null +++ b/deployments/arbitrum/RewardsDistributor.json @@ -0,0 +1,520 @@ +{ + "address": "0xd9891738458A5b1F1EfB5f82183b77c666d9064E", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_voting_escrow", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "time", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "CheckpointToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "claim_epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "max_epoch", + "type": "uint256" + } + ], + "name": "Claimed", + "type": "event" + }, + { + "inputs": [], + "name": "checkpoint_token", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "checkpoint_total_supply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "claim", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "_tokenIds", + "type": "uint256[]" + } + ], + "name": "claim_many", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "claimable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "depositor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "last_token_time", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_depositor", + "type": "address" + } + ], + "name": "setDepositor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "start_time", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "time_cursor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "time_cursor_of", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "timestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token_last_balance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "tokens_per_week", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "user_epoch_of", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_timestamp", + "type": "uint256" + } + ], + "name": "ve_for_at", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "ve_supply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "voting_escrow", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xe554178d001c647246f9fa171b880e693ee215d6d4368948f9b6ceaab032ad0e", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0xd9891738458A5b1F1EfB5f82183b77c666d9064E", + "transactionIndex": 1, + "gasUsed": "11169043", + "logsBloom": "0x00000000000000000000000008000000000000000000000000000000000000000000000000000000000000002000000000000008000000000000000000240000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000408000000001000000000000000000000000000000000000", + "blockHash": "0xa69e0e8d19a1dbf3e8917d55c7d42c64e52fd279b93d02d2c7eda3a98a2ed9b6", + "transactionHash": "0xe554178d001c647246f9fa171b880e693ee215d6d4368948f9b6ceaab032ad0e", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 53774100, + "transactionHash": "0xe554178d001c647246f9fa171b880e693ee215d6d4368948f9b6ceaab032ad0e", + "address": "0xC33f7f83CbB021846Cb9c58f2d8E3df428dbC8C1", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000d9891738458a5b1f1efb5f82183b77c666d9064e", + "0x00000000000000000000000010df81252069c1095f541faca61646cb9ae76703" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 0, + "blockHash": "0xa69e0e8d19a1dbf3e8917d55c7d42c64e52fd279b93d02d2c7eda3a98a2ed9b6" + } + ], + "blockNumber": 53774100, + "cumulativeGasUsed": "11169043", + "status": 1, + "byzantium": true + }, + "args": [ + "0x10Df81252069C1095F541FAca61646cb9Ae76703" + ], + "numDeployments": 1, + "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voting_escrow\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"time\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"CheckpointToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"claim_epoch\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"max_epoch\",\"type\":\"uint256\"}],\"name\":\"Claimed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"checkpoint_token\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint_total_supply\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"_tokenIds\",\"type\":\"uint256[]\"}],\"name\":\"claim_many\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_token_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"}],\"name\":\"setDepositor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"start_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"time_cursor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"time_cursor_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token_last_balance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"tokens_per_week\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_epoch_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"ve_for_at\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ve_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voting_escrow\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RewardsDistributor.sol\":\"RewardsDistributor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/*\\n\\n@title Curve Fee Distribution modified for ve(3,3) emissions\\n@author Curve Finance, andrecronje\\n@license MIT\\n\\n*/\\n\\ncontract RewardsDistributor is IRewardsDistributor {\\n event CheckpointToken(uint256 time, uint256 tokens);\\n\\n event Claimed(\\n uint256 tokenId,\\n uint256 amount,\\n uint256 claim_epoch,\\n uint256 max_epoch\\n );\\n\\n uint256 constant WEEK = 7 * 86400;\\n\\n uint256 public start_time;\\n uint256 public time_cursor;\\n mapping(uint256 => uint256) public time_cursor_of;\\n mapping(uint256 => uint256) public user_epoch_of;\\n\\n uint256 public last_token_time;\\n uint256[1000000000000000] public tokens_per_week;\\n\\n address public voting_escrow;\\n address public token;\\n uint256 public token_last_balance;\\n\\n uint256[1000000000000000] public ve_supply;\\n\\n address public depositor;\\n\\n constructor(address _voting_escrow) {\\n uint256 _t = (block.timestamp / WEEK) * WEEK;\\n start_time = _t;\\n last_token_time = _t;\\n time_cursor = _t;\\n address _token = IVotingEscrow(_voting_escrow).token();\\n token = _token;\\n voting_escrow = _voting_escrow;\\n depositor = msg.sender;\\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\\n }\\n\\n function timestamp() external view returns (uint256) {\\n return (block.timestamp / WEEK) * WEEK;\\n }\\n\\n function _checkpoint_token() internal {\\n uint256 token_balance = IERC20(token).balanceOf(address(this));\\n uint256 to_distribute = token_balance - token_last_balance;\\n token_last_balance = token_balance;\\n\\n uint256 t = last_token_time;\\n uint256 since_last = block.timestamp - t;\\n last_token_time = block.timestamp;\\n uint256 this_week = (t / WEEK) * WEEK;\\n uint256 next_week = 0;\\n\\n for (uint256 i = 0; i < 20; i++) {\\n next_week = this_week + WEEK;\\n if (block.timestamp < next_week) {\\n if (since_last == 0 && block.timestamp == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (block.timestamp - t)) /\\n since_last;\\n }\\n break;\\n } else {\\n if (since_last == 0 && next_week == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (next_week - t)) /\\n since_last;\\n }\\n }\\n t = next_week;\\n this_week = next_week;\\n }\\n emit CheckpointToken(block.timestamp, to_distribute);\\n }\\n\\n function checkpoint_token() external {\\n assert(msg.sender == depositor);\\n _checkpoint_token();\\n }\\n\\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\\n internal\\n view\\n returns (uint256)\\n {\\n uint256 _min = 0;\\n uint256 _max = IVotingEscrow(ve).epoch();\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n _mid\\n );\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function _find_timestamp_user_epoch(\\n address ve,\\n uint256 tokenId,\\n uint256 _timestamp,\\n uint256 max_user_epoch\\n ) internal view returns (uint256) {\\n uint256 _min = 0;\\n uint256 _max = max_user_epoch;\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\\n .user_point_history(tokenId, _mid);\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\\n external\\n view\\n returns (uint256)\\n {\\n address ve = voting_escrow;\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _timestamp,\\n max_user_epoch\\n );\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n epoch\\n );\\n return\\n MathDunks.max(\\n uint256(\\n int256(\\n pt.bias -\\n pt.slope *\\n (int128(int256(_timestamp - pt.ts)))\\n )\\n ),\\n 0\\n );\\n }\\n\\n function _checkpoint_total_supply() internal {\\n address ve = voting_escrow;\\n uint256 t = time_cursor;\\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\\n IVotingEscrow(ve).checkpoint();\\n\\n for (uint256 i = 0; i < 20; i++) {\\n if (t > rounded_timestamp) {\\n break;\\n } else {\\n uint256 epoch = _find_timestamp_epoch(ve, t);\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n epoch\\n );\\n int128 dt = 0;\\n if (t > pt.ts) {\\n dt = int128(int256(t - pt.ts));\\n }\\n ve_supply[t] = MathDunks.max(\\n uint256(int256(pt.bias - pt.slope * dt)),\\n 0\\n );\\n }\\n t += WEEK;\\n }\\n time_cursor = t;\\n }\\n\\n function checkpoint_total_supply() external {\\n _checkpoint_total_supply();\\n }\\n\\n function _claim(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\\n user_epoch_of[_tokenId] = user_epoch;\\n time_cursor_of[_tokenId] = week_cursor;\\n\\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\\n\\n return to_distribute;\\n }\\n\\n function _claimable(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal view returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n return to_distribute;\\n }\\n\\n function claimable(uint256 _tokenId) external view returns (uint256) {\\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\\n return _claimable(_tokenId, voting_escrow, _last_token_time);\\n }\\n\\n function claim(uint256 _tokenId) external returns (uint256) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\\n token_last_balance -= amount;\\n }\\n return amount;\\n }\\n\\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n address _voting_escrow = voting_escrow;\\n uint256 total = 0;\\n\\n for (uint256 i = 0; i < _tokenIds.length; i++) {\\n uint256 _tokenId = _tokenIds[i];\\n if (_tokenId == 0) break;\\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\\n total += amount;\\n }\\n }\\n if (total != 0) {\\n token_last_balance -= total;\\n }\\n\\n return true;\\n }\\n\\n // Once off event on contract initialize\\n function setDepositor(address _depositor) external {\\n require(msg.sender == depositor);\\n depositor = _depositor;\\n }\\n}\\n\",\"keccak256\":\"0xdbcfb11d65c6ca7d63baba42fb2f1222478c6ca78d8e81970032eff5e034e09b\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b5060405162001b9f38038062001b9f83398101604081905262000034916200019f565b600062093a80620000468142620001d1565b620000529190620001f4565b90508060008190555080600481905550806001819055506000826001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000aa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d091906200019f565b66038d7ea4c6800680546001600160a01b038381166001600160a01b0319928316811790935566038d7ea4c6800580549188169183168217905566071afd498d00088054909216331790915560405163095ea7b360e01b8152600481019190915260001960248201529192509063095ea7b3906044016020604051808303816000875af115801562000166573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200018c919062000222565b6200019657600080fd5b50505062000246565b600060208284031215620001b257600080fd5b81516001600160a01b0381168114620001ca57600080fd5b9392505050565b600082620001ef57634e487b7160e01b600052601260045260246000fd5b500490565b60008160001904831182151516156200021d57634e487b7160e01b600052601160045260246000fd5b500290565b6000602082840312156200023557600080fd5b81518015158114620001ca57600080fd5b61194980620002566000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea26469706673582212201bd70ac15ed6cd0b251036f174a839aeb92aa432fe7d09fa6cb45a0a25d2cda964736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea26469706673582212201bd70ac15ed6cd0b251036f174a839aeb92aa432fe7d09fa6cb45a0a25d2cda964736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 9410, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "start_time", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 9412, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "time_cursor", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 9416, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "time_cursor_of", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 9420, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "user_epoch_of", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 9422, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "last_token_time", + "offset": 0, + "slot": "4", + "type": "t_uint256" + }, + { + "astId": 9426, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "tokens_per_week", + "offset": 0, + "slot": "5", + "type": "t_array(t_uint256)1000000000000000_storage" + }, + { + "astId": 9428, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "voting_escrow", + "offset": 0, + "slot": "1000000000000005", + "type": "t_address" + }, + { + "astId": 9430, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "token", + "offset": 0, + "slot": "1000000000000006", + "type": "t_address" + }, + { + "astId": 9432, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "token_last_balance", + "offset": 0, + "slot": "1000000000000007", + "type": "t_uint256" + }, + { + "astId": 9436, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "ve_supply", + "offset": 0, + "slot": "1000000000000008", + "type": "t_array(t_uint256)1000000000000000_storage" + }, + { + "astId": 9438, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "depositor", + "offset": 0, + "slot": "2000000000000008", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)1000000000000000_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[1000000000000000]", + "numberOfBytes": "32000000000000000" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrum/Router.json b/deployments/arbitrum/Router.json new file mode 100644 index 00000000..b4febac4 --- /dev/null +++ b/deployments/arbitrum/Router.json @@ -0,0 +1,1021 @@ +{ + "address": "0x07d2FCFa095d52652cBC664F105F2d9Fb3799a47", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_factory", + "type": "address" + }, + { + "internalType": "address", + "name": "_weth", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "internalType": "struct Router.route[]", + "name": "routes", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "UNSAFE_swapExactTokensForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "amountADesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBDesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountAMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "addLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "amountTokenDesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountTokenMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETHMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "addLiquidityETH", + "outputs": [ + { + "internalType": "uint256", + "name": "amountToken", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETH", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + } + ], + "name": "getAmountOut", + "outputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "internalType": "struct Router.route[]", + "name": "routes", + "type": "tuple[]" + } + ], + "name": "getAmountsOut", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "reserveA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveB", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pair", + "type": "address" + } + ], + "name": "isPair", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "pairFor", + "outputs": [ + { + "internalType": "address", + "name": "pair", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "amountADesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBDesired", + "type": "uint256" + } + ], + "name": "quoteAddLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "name": "quoteRemoveLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountAMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "removeLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountTokenMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETHMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "removeLiquidityETH", + "outputs": [ + { + "internalType": "uint256", + "name": "amountToken", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETH", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountTokenMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETHMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "approveMax", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "removeLiquidityETHWithPermit", + "outputs": [ + { + "internalType": "uint256", + "name": "amountToken", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETH", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountAMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "approveMax", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "removeLiquidityWithPermit", + "outputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + } + ], + "name": "sortTokens", + "outputs": [ + { + "internalType": "address", + "name": "token0", + "type": "address" + }, + { + "internalType": "address", + "name": "token1", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "internalType": "struct Router.route[]", + "name": "routes", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactETHForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "internalType": "struct Router.route[]", + "name": "routes", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForETH", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "internalType": "struct Router.route[]", + "name": "routes", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenFrom", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenTo", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensSimple", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "weth", + "outputs": [ + { + "internalType": "contract IWETH", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x58eee942780ca824821a4aef9f4304d94dd16c37a1ac23c577ba412ac0d70d02", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x07d2FCFa095d52652cBC664F105F2d9Fb3799a47", + "transactionIndex": 1, + "gasUsed": "21117639", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xdaf429b1b8dd495aa7f78158cec510bd2d72bd844f7958bcd0e873c420a9f54e", + "transactionHash": "0x58eee942780ca824821a4aef9f4304d94dd16c37a1ac23c577ba412ac0d70d02", + "logs": [], + "blockNumber": 53774061, + "cumulativeGasUsed": "21117639", + "status": 1, + "byzantium": true + }, + "args": [ + "0xA2db791281CdeeBb1EEDc78a34989df2Bfd479bE", + "0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83" + ], + "numDeployments": 1, + "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_weth\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"UNSAFE_swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"}],\"name\":\"getAmountsOut\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reserveA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"pairFor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"}],\"name\":\"quoteAddLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"name\":\"quoteRemoveLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityETHWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"}],\"name\":\"sortTokens\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactETHForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForETH\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenFrom\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenTo\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokensSimple\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weth\",\"outputs\":[{\"internalType\":\"contract IWETH\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Router.sol\":\"Router\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Router.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairFactory.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\nimport \\\"contracts/interfaces/IWETH.sol\\\";\\n\\ncontract Router is IRouter {\\n struct route {\\n address from;\\n address to;\\n bool stable;\\n }\\n\\n address public immutable factory;\\n IWETH public immutable weth;\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n bytes32 immutable pairCodeHash;\\n\\n modifier ensure(uint256 deadline) {\\n require(deadline >= block.timestamp, \\\"Router: EXPIRED\\\");\\n _;\\n }\\n\\n constructor(address _factory, address _weth) {\\n factory = _factory;\\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\\n weth = IWETH(_weth);\\n }\\n\\n receive() external payable {\\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\\n }\\n\\n function sortTokens(address tokenA, address tokenB)\\n public\\n pure\\n returns (address token0, address token1)\\n {\\n require(tokenA != tokenB, \\\"Router: IDENTICAL_ADDRESSES\\\");\\n (token0, token1) = tokenA < tokenB\\n ? (tokenA, tokenB)\\n : (tokenB, tokenA);\\n require(token0 != address(0), \\\"Router: ZERO_ADDRESS\\\");\\n }\\n\\n // calculates the CREATE2 address for a pair without making any external calls\\n function pairFor(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (address pair) {\\n (address token0, address token1) = sortTokens(tokenA, tokenB);\\n pair = address(\\n uint160(\\n uint256(\\n keccak256(\\n abi.encodePacked(\\n hex\\\"ff\\\",\\n factory,\\n keccak256(abi.encodePacked(token0, token1, stable)),\\n pairCodeHash // init code hash\\n )\\n )\\n )\\n )\\n );\\n }\\n\\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\\n function quoteLiquidity(\\n uint256 amountA,\\n uint256 reserveA,\\n uint256 reserveB\\n ) internal pure returns (uint256 amountB) {\\n require(amountA > 0, \\\"Router: INSUFFICIENT_AMOUNT\\\");\\n require(reserveA > 0 && reserveB > 0, \\\"Router: INSUFFICIENT_LIQUIDITY\\\");\\n amountB = (amountA * reserveB) / reserveA;\\n }\\n\\n // fetches and sorts the reserves for a pair\\n function getReserves(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (uint256 reserveA, uint256 reserveB) {\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (uint256 reserve0, uint256 reserve1, ) = IPair(\\n pairFor(tokenA, tokenB, stable)\\n ).getReserves();\\n (reserveA, reserveB) = tokenA == token0\\n ? (reserve0, reserve1)\\n : (reserve1, reserve0);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n address tokenOut\\n ) external view returns (uint256 amount, bool stable) {\\n address pair = pairFor(tokenIn, tokenOut, true);\\n uint256 amountStable;\\n uint256 amountVolatile;\\n if (IPairFactory(factory).isPair(pair)) {\\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n pair = pairFor(tokenIn, tokenOut, false);\\n if (IPairFactory(factory).isPair(pair)) {\\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n return\\n amountStable > amountVolatile\\n ? (amountStable, true)\\n : (amountVolatile, false);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountsOut(uint256 amountIn, route[] memory routes)\\n public\\n view\\n returns (uint256[] memory amounts)\\n {\\n require(routes.length >= 1, \\\"Router: INVALID_PATH\\\");\\n amounts = new uint256[](routes.length + 1);\\n amounts[0] = amountIn;\\n for (uint256 i = 0; i < routes.length; i++) {\\n address pair = pairFor(\\n routes[i].from,\\n routes[i].to,\\n routes[i].stable\\n );\\n if (IPairFactory(factory).isPair(pair)) {\\n amounts[i + 1] = IPair(pair).getAmountOut(\\n amounts[i],\\n routes[i].from\\n );\\n }\\n }\\n }\\n\\n function isPair(address pair) external view returns (bool) {\\n return IPairFactory(factory).isPair(pair);\\n }\\n\\n function quoteAddLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired\\n )\\n external\\n view\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n (uint256 reserveA, uint256 reserveB) = (0, 0);\\n uint256 _totalSupply = 0;\\n if (_pair != address(0)) {\\n _totalSupply = IERC20(_pair).totalSupply();\\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\\n }\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n }\\n }\\n }\\n\\n function quoteRemoveLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity\\n ) external view returns (uint256 amountA, uint256 amountB) {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n\\n if (_pair == address(0)) {\\n return (0, 0);\\n }\\n\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n uint256 _totalSupply = IERC20(_pair).totalSupply();\\n\\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\\n }\\n\\n function _addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin\\n ) internal returns (uint256 amountA, uint256 amountB) {\\n require(amountADesired >= amountAMin);\\n require(amountBDesired >= amountBMin);\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n if (_pair == address(0)) {\\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\\n }\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n require(\\n amountBOptimal >= amountBMin,\\n \\\"Router: INSUFFICIENT_B_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n assert(amountAOptimal <= amountADesired);\\n require(\\n amountAOptimal >= amountAMin,\\n \\\"Router: INSUFFICIENT_A_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n }\\n }\\n }\\n\\n function addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n ensure(deadline)\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n (amountA, amountB) = _addLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n amountADesired,\\n amountBDesired,\\n amountAMin,\\n amountBMin\\n );\\n address pair = pairFor(tokenA, tokenB, stable);\\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\\n liquidity = IPair(pair).mint(to);\\n }\\n\\n function addLiquidityETH(\\n address token,\\n bool stable,\\n uint256 amountTokenDesired,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n payable\\n ensure(deadline)\\n returns (\\n uint256 amountToken,\\n uint256 amountETH,\\n uint256 liquidity\\n )\\n {\\n (amountToken, amountETH) = _addLiquidity(\\n token,\\n address(weth),\\n stable,\\n amountTokenDesired,\\n msg.value,\\n amountTokenMin,\\n amountETHMin\\n );\\n address pair = pairFor(token, address(weth), stable);\\n _safeTransferFrom(token, msg.sender, pair, amountToken);\\n weth.deposit{value: amountETH}();\\n assert(weth.transfer(pair, amountETH));\\n liquidity = IPair(pair).mint(to);\\n // refund dust eth, if any\\n if (msg.value > amountETH)\\n _safeTransferETH(msg.sender, msg.value - amountETH);\\n }\\n\\n // **** REMOVE LIQUIDITY ****\\n function removeLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (amountA, amountB) = tokenA == token0\\n ? (amount0, amount1)\\n : (amount1, amount0);\\n require(amountA >= amountAMin, \\\"Router: INSUFFICIENT_A_AMOUNT\\\");\\n require(amountB >= amountBMin, \\\"Router: INSUFFICIENT_B_AMOUNT\\\");\\n }\\n\\n function removeLiquidityETH(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\\n (amountToken, amountETH) = removeLiquidity(\\n token,\\n address(weth),\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n address(this),\\n deadline\\n );\\n _safeTransfer(token, to, amountToken);\\n weth.withdraw(amountETH);\\n _safeTransferETH(to, amountETH);\\n }\\n\\n function removeLiquidityWithPermit(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n {\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(\\n msg.sender,\\n address(this),\\n value,\\n deadline,\\n v,\\n r,\\n s\\n );\\n }\\n\\n (amountA, amountB) = removeLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n liquidity,\\n amountAMin,\\n amountBMin,\\n to,\\n deadline\\n );\\n }\\n\\n function removeLiquidityETHWithPermit(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountToken, uint256 amountETH) {\\n address pair = pairFor(token, address(weth), stable);\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\\n (amountToken, amountETH) = removeLiquidityETH(\\n token,\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n to,\\n deadline\\n );\\n }\\n\\n // **** SWAP ****\\n // requires the initial amount to have already been sent to the first pair\\n function _swap(\\n uint256[] memory amounts,\\n route[] memory routes,\\n address _to\\n ) internal virtual {\\n for (uint256 i = 0; i < routes.length; i++) {\\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\\n uint256 amountOut = amounts[i + 1];\\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\\n ? (uint256(0), amountOut)\\n : (amountOut, uint256(0));\\n address to = i < routes.length - 1\\n ? pairFor(\\n routes[i + 1].from,\\n routes[i + 1].to,\\n routes[i + 1].stable\\n )\\n : _to;\\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\\n amount0Out,\\n amount1Out,\\n to,\\n new bytes(0)\\n );\\n }\\n }\\n\\n function swapExactTokensForTokensSimple(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n address tokenFrom,\\n address tokenTo,\\n bool stable,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n route[] memory routes = new route[](1);\\n routes[0].from = tokenFrom;\\n routes[0].to = tokenTo;\\n routes[0].stable = stable;\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForTokens(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactETHForTokens(\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\\n require(routes[0].from == address(weth), \\\"Router: INVALID_PATH\\\");\\n amounts = getAmountsOut(msg.value, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n weth.deposit{value: amounts[0]}();\\n assert(\\n weth.transfer(\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n )\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForETH(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n require(\\n routes[routes.length - 1].to == address(weth),\\n \\\"Router: INVALID_PATH\\\"\\n );\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, address(this));\\n weth.withdraw(amounts[amounts.length - 1]);\\n _safeTransferETH(to, amounts[amounts.length - 1]);\\n }\\n\\n function UNSAFE_swapExactTokensForTokens(\\n uint256[] memory amounts,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory) {\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n return amounts;\\n }\\n\\n function _safeTransferETH(address to, uint256 value) internal {\\n (bool success, ) = to.call{value: value}(new bytes(0));\\n require(success, \\\"TransferHelper: ETH_TRANSFER_FAILED\\\");\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x3d84c846129d645eec66c37a493bb7fb401a2524497f450eaced155088305ead\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"},\"contracts/interfaces/IWETH.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n function transfer(address to, uint256 value) external returns (bool);\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0x20ad0b3a319a36e3430f0d8512ee3755de8f85a80effe78d06f333f5326ee3d7\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x60e06040523480156200001157600080fd5b50604051620039bc380380620039bc8339810160408190526200003491620000d8565b6001600160a01b038216608081905260408051631355724960e31b81529051639aab9248916004808201926020929091908290030181865afa1580156200007f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000a5919062000110565b60c0526001600160a01b031660a052506200012a565b80516001600160a01b0381168114620000d357600080fd5b919050565b60008060408385031215620000ec57600080fd5b620000f783620000bb565b91506200010760208401620000bb565b90509250929050565b6000602082840312156200012357600080fd5b5051919050565b60805160a05160c0516137c8620001f46000396000610ef901526000818161013e0152818161020b0152818161091901528181610b5801528181610da901528181611470015281816115830152818161161101528181611de901528181611e1f01528181611e5401528181611ee901528181612028015261207801526000818161042d01528181610c3e01528181610ebe015281816111770152818161128b0152818161199601528181611b0a01528181612115015281816126ff01526127a001526137c86000f3fe60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea2646970667358221220a5fbebccdd681576dc540b9cee199053b5ccdd41b782b05a7748e7178173beea64736f6c634300080d0033", + "deployedBytecode": "0x60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea2646970667358221220a5fbebccdd681576dc540b9cee199053b5ccdd41b782b05a7748e7178173beea64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/arbitrum/VeArtProxy.json b/deployments/arbitrum/VeArtProxy.json new file mode 100644 index 00000000..d8ad686b --- /dev/null +++ b/deployments/arbitrum/VeArtProxy.json @@ -0,0 +1,75 @@ +{ + "address": "0x4b40D5E4401EC24673cc9d4799457a3B5827c581", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_balanceOf", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_locked_end", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "_tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "output", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "transactionHash": "0xaea6c881d8fbd586965699a9451e8f32ed3536b204ecb1e490df8cf5677141a9", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x4b40D5E4401EC24673cc9d4799457a3B5827c581", + "transactionIndex": 1, + "gasUsed": "5573204", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x34ad78b9a516d065f84e2b2c7125282551cc3907f1f97aaacb94abb885b05833", + "transactionHash": "0xaea6c881d8fbd586965699a9451e8f32ed3536b204ecb1e490df8cf5677141a9", + "logs": [], + "blockNumber": 53774078, + "cumulativeGasUsed": "5573204", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_locked_end\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"_tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"output\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VeArtProxy.sol\":\"VeArtProxy\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\nimport {Base64} from \\\"contracts/libraries/Base64.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\n\\ncontract VeArtProxy is IVeArtProxy {\\n function toString(uint value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT license\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint temp = value;\\n uint digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\\n output = '';\\n output = string(abi.encodePacked(output, \\\"token \\\", toString(_tokenId), ''));\\n output = string(abi.encodePacked(output, \\\"balanceOf \\\", toString(_balanceOf), ''));\\n output = string(abi.encodePacked(output, \\\"locked_end \\\", toString(_locked_end), ''));\\n output = string(abi.encodePacked(output, \\\"value \\\", toString(_value), ''));\\n\\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\\\"name\\\": \\\"lock #', toString(_tokenId), '\\\", \\\"description\\\": \\\"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\\\", \\\"image\\\": \\\"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\\\"}'))));\\n output = string(abi.encodePacked('data:application/json;base64,', json));\\n }\\n}\\n\",\"keccak256\":\"0x8757d8095922dcad7af8c6820415049fd7d5af61a5580719210e5e91a31d80b1\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/libraries/Base64.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n/// [MIT License]\\n/// @title Base64\\n/// @notice Provides a function for encoding some bytes in base64\\n/// @author Brecht Devos \\nlibrary Base64 {\\n bytes internal constant TABLE = \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\";\\n\\n /// @notice Encodes some bytes to the base64 representation\\n function encode(bytes memory data) internal pure returns (string memory) {\\n uint len = data.length;\\n if (len == 0) return \\\"\\\";\\n\\n // multiply by 4/3 rounded up\\n uint encodedLen = 4 * ((len + 2) / 3);\\n\\n // Add some extra buffer at the end\\n bytes memory result = new bytes(encodedLen + 32);\\n\\n bytes memory table = TABLE;\\n\\n assembly {\\n let tablePtr := add(table, 1)\\n let resultPtr := add(result, 32)\\n\\n for {\\n let i := 0\\n } lt(i, len) {\\n\\n } {\\n i := add(i, 3)\\n let input := and(mload(add(data, i)), 0xffffff)\\n\\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\\n out := shl(224, out)\\n\\n mstore(resultPtr, out)\\n\\n resultPtr := add(resultPtr, 4)\\n }\\n\\n switch mod(len, 3)\\n case 1 {\\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\\n }\\n case 2 {\\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\\n }\\n\\n mstore(result, encodedLen)\\n }\\n\\n return string(result);\\n }\\n}\\n\",\"keccak256\":\"0x55535e1e0a14bbac370fe5f25df23aa88c678b915af53517672130f9a54f7e3e\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610a2b806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f64726f6d65206c6f636010918401918201527f6b732c2063616e206265207573656420746f20626f6f7374206761756765207960308201527f69656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c206160508201527f6e64207265636569766520627269626573222c2022696d616765223a2022646160708201527f74613a696d6167652f7376672b786d6c3b6261736536342c0000000000000000609082015283516107718160a8840160208801610435565b61227d60f01b60a8929091019182015260aa01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212205e17183bb106171fcd25152691eea4fe7c51c6576ba7661fd1601ee5ea93b74a64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f64726f6d65206c6f636010918401918201527f6b732c2063616e206265207573656420746f20626f6f7374206761756765207960308201527f69656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c206160508201527f6e64207265636569766520627269626573222c2022696d616765223a2022646160708201527f74613a696d6167652f7376672b786d6c3b6261736536342c0000000000000000609082015283516107718160a8840160208801610435565b61227d60f01b60a8929091019182015260aa01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212205e17183bb106171fcd25152691eea4fe7c51c6576ba7661fd1601ee5ea93b74a64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/arbitrum/Velo.json b/deployments/arbitrum/Velo.json new file mode 100644 index 00000000..4ad69e78 --- /dev/null +++ b/deployments/arbitrum/Velo.json @@ -0,0 +1,522 @@ +{ + "address": "0xC33f7f83CbB021846Cb9c58f2d8E3df428dbC8C1", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "claim", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_recipient", + "type": "address" + } + ], + "name": "initialMint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initialMinted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "merkleClaim", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "minter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "redemptionReceiver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_merkleClaim", + "type": "address" + } + ], + "name": "setMerkleClaim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_minter", + "type": "address" + } + ], + "name": "setMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_receiver", + "type": "address" + } + ], + "name": "setRedemptionReceiver", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xffa193d4b9355b17aa943a70e0dad7e919672eeef37e2a9646f47103b7244388", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0xC33f7f83CbB021846Cb9c58f2d8E3df428dbC8C1", + "transactionIndex": 1, + "gasUsed": "4625703", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000010000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000002000000000000000000000000000000000000000000000000000020000000000000000000408000080001000000000000000000000000000000000000", + "blockHash": "0x436fae4d7172ee616208fbf2059b4d011715c33f785ba6db4b0ac62acbb0a7fe", + "transactionHash": "0xffa193d4b9355b17aa943a70e0dad7e919672eeef37e2a9646f47103b7244388", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 53774010, + "transactionHash": "0xffa193d4b9355b17aa943a70e0dad7e919672eeef37e2a9646f47103b7244388", + "address": "0xC33f7f83CbB021846Cb9c58f2d8E3df428dbC8C1", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000053f3b51fd7f327e1ec4e6eaa3a049149cb2acad2" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000", + "logIndex": 0, + "blockHash": "0x436fae4d7172ee616208fbf2059b4d011715c33f785ba6db4b0ac62acbb0a7fe" + } + ], + "blockNumber": 53774010, + "cumulativeGasUsed": "4625703", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"initialMint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialMinted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleClaim\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redemptionReceiver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_merkleClaim\",\"type\":\"address\"}],\"name\":\"setMerkleClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"setMinter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_receiver\",\"type\":\"address\"}],\"name\":\"setRedemptionReceiver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Velo.sol\":\"Velo\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Velo.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IVelo.sol\\\";\\n\\ncontract Velo is IVelo {\\n\\n string public constant name = \\\"Velodrome\\\";\\n string public constant symbol = \\\"VELO\\\";\\n uint8 public constant decimals = 18;\\n uint public totalSupply = 0;\\n\\n mapping(address => uint) public balanceOf;\\n mapping(address => mapping(address => uint)) public allowance;\\n\\n bool public initialMinted;\\n address public minter;\\n address public redemptionReceiver;\\n address public merkleClaim;\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n\\n constructor() {\\n minter = msg.sender;\\n _mint(msg.sender, 0);\\n }\\n\\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\\n function setMinter(address _minter) external {\\n require(msg.sender == minter);\\n minter = _minter;\\n }\\n\\n function setRedemptionReceiver(address _receiver) external {\\n require(msg.sender == minter);\\n redemptionReceiver = _receiver;\\n }\\n\\n function setMerkleClaim(address _merkleClaim) external {\\n require(msg.sender == minter);\\n merkleClaim = _merkleClaim;\\n }\\n\\n // Initial mint: total 82M\\n // 4M for \\\"Genesis\\\" pools\\n // 30M for liquid team allocation (40M excl init veNFT)\\n // 48M for future partners\\n function initialMint(address _recipient) external {\\n require(msg.sender == minter && !initialMinted);\\n initialMinted = true;\\n _mint(_recipient, 82 * 1e6 * 1e18);\\n }\\n\\n function approve(address _spender, uint _value) external returns (bool) {\\n allowance[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n function _mint(address _to, uint _amount) internal returns (bool) {\\n totalSupply += _amount;\\n unchecked {\\n balanceOf[_to] += _amount;\\n }\\n emit Transfer(address(0x0), _to, _amount);\\n return true;\\n }\\n\\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\\n balanceOf[_from] -= _value;\\n unchecked {\\n balanceOf[_to] += _value;\\n }\\n emit Transfer(_from, _to, _value);\\n return true;\\n }\\n\\n function transfer(address _to, uint _value) external returns (bool) {\\n return _transfer(msg.sender, _to, _value);\\n }\\n\\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\\n uint allowed_from = allowance[_from][msg.sender];\\n if (allowed_from != type(uint).max) {\\n allowance[_from][msg.sender] -= _value;\\n }\\n return _transfer(_from, _to, _value);\\n }\\n\\n function mint(address account, uint amount) external returns (bool) {\\n require(msg.sender == minter);\\n _mint(account, amount);\\n return true;\\n }\\n\\n function claim(address account, uint amount) external returns (bool) {\\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\\n _mint(account, amount);\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xb5231de79b43d576febc9d6a0ebee8c4f251ec109869ce7a3e0afc2a185d0246\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"}},\"version\":1}", + "bytecode": "0x60806040526000805534801561001457600080fd5b5060038054610100600160a81b0319163361010081029190911790915561003c906000610042565b506100d9565b60008160008082825461005591906100b3565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a350600192915050565b600082198211156100d457634e487b7160e01b600052601160045260246000fd5b500190565b61082c806100e86000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ac578063dd62ed3e146102bf578063e752c44a146102ea578063ec676a25146102fd578063fca3b5aa1461031057600080fd5b806395d89b4114610241578063a9059cbb14610264578063aad3ec9614610277578063c268f9ba1461028a578063ca1c4de91461029f57600080fd5b806323b872dd116100f457806323b872dd146101ce578063313ce567146101e157806340c10f19146101fb5780635e05fe501461020e57806370a082311461022157600080fd5b806306fdde03146101265780630754617214610164578063095ea7b31461019457806318160ddd146101b7575b600080fd5b61014e6040518060400160405280600981526020016856656c6f64726f6d6560b81b81525081565b60405161015b919061068c565b60405180910390f35b60035461017c9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015b565b6101a76101a23660046106fd565b610323565b604051901515815260200161015b565b6101c060005481565b60405190815260200161015b565b6101a76101dc366004610727565b61038f565b6101e9601281565b60405160ff909116815260200161015b565b6101a76102093660046106fd565b610409565b60045461017c906001600160a01b031681565b6101c061022f366004610763565b60016020526000908152604090205481565b61014e6040518060400160405280600481526020016356454c4f60e01b81525081565b6101a76102723660046106fd565b61043c565b6101a76102853660046106fd565b610450565b61029d610298366004610763565b61047f565b005b6003546101a79060ff1681565b61029d6102ba366004610763565b6104d0565b6101c06102cd36600461077e565b600260209081526000928352604080842090915290825290205481565b60055461017c906001600160a01b031681565b61029d61030b366004610763565b61050e565b61029d61031e366004610763565b61054c565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259061037e9086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f5576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103ef9084906107c7565b90915550505b610400858585610590565b95945050505050565b60035460009061010090046001600160a01b0316331461042857600080fd5b6104328383610627565b5060019392505050565b6000610449338484610590565b9392505050565b6004546000906001600160a01b031633148061047657506005546001600160a01b031633145b61042857600080fd5b60035461010090046001600160a01b0316331480156104a1575060035460ff16155b6104aa57600080fd5b6003805460ff191660011790556104cc816a43d42ce83da41d92000000610627565b5050565b60035461010090046001600160a01b031633146104ec57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052a57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056857600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105ba9084906107c7565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106159086815260200190565b60405180910390a35060019392505050565b60008160008082825461063a91906107de565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910161037e565b600060208083528351808285015260005b818110156106b95785810183015185820160400152820161069d565b818111156106cb576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106f857600080fd5b919050565b6000806040838503121561071057600080fd5b610719836106e1565b946020939093013593505050565b60008060006060848603121561073c57600080fd5b610745846106e1565b9250610753602085016106e1565b9150604084013590509250925092565b60006020828403121561077557600080fd5b610449826106e1565b6000806040838503121561079157600080fd5b61079a836106e1565b91506107a8602084016106e1565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107d9576107d96107b1565b500390565b600082198211156107f1576107f16107b1565b50019056fea2646970667358221220423a2d241b85b1ebdbd332cb4cda4288b557560fafa1ab700b6868cd6228949764736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ac578063dd62ed3e146102bf578063e752c44a146102ea578063ec676a25146102fd578063fca3b5aa1461031057600080fd5b806395d89b4114610241578063a9059cbb14610264578063aad3ec9614610277578063c268f9ba1461028a578063ca1c4de91461029f57600080fd5b806323b872dd116100f457806323b872dd146101ce578063313ce567146101e157806340c10f19146101fb5780635e05fe501461020e57806370a082311461022157600080fd5b806306fdde03146101265780630754617214610164578063095ea7b31461019457806318160ddd146101b7575b600080fd5b61014e6040518060400160405280600981526020016856656c6f64726f6d6560b81b81525081565b60405161015b919061068c565b60405180910390f35b60035461017c9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015b565b6101a76101a23660046106fd565b610323565b604051901515815260200161015b565b6101c060005481565b60405190815260200161015b565b6101a76101dc366004610727565b61038f565b6101e9601281565b60405160ff909116815260200161015b565b6101a76102093660046106fd565b610409565b60045461017c906001600160a01b031681565b6101c061022f366004610763565b60016020526000908152604090205481565b61014e6040518060400160405280600481526020016356454c4f60e01b81525081565b6101a76102723660046106fd565b61043c565b6101a76102853660046106fd565b610450565b61029d610298366004610763565b61047f565b005b6003546101a79060ff1681565b61029d6102ba366004610763565b6104d0565b6101c06102cd36600461077e565b600260209081526000928352604080842090915290825290205481565b60055461017c906001600160a01b031681565b61029d61030b366004610763565b61050e565b61029d61031e366004610763565b61054c565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259061037e9086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f5576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103ef9084906107c7565b90915550505b610400858585610590565b95945050505050565b60035460009061010090046001600160a01b0316331461042857600080fd5b6104328383610627565b5060019392505050565b6000610449338484610590565b9392505050565b6004546000906001600160a01b031633148061047657506005546001600160a01b031633145b61042857600080fd5b60035461010090046001600160a01b0316331480156104a1575060035460ff16155b6104aa57600080fd5b6003805460ff191660011790556104cc816a43d42ce83da41d92000000610627565b5050565b60035461010090046001600160a01b031633146104ec57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052a57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056857600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105ba9084906107c7565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106159086815260200190565b60405180910390a35060019392505050565b60008160008082825461063a91906107de565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910161037e565b600060208083528351808285015260005b818110156106b95785810183015185820160400152820161069d565b818111156106cb576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106f857600080fd5b919050565b6000806040838503121561071057600080fd5b610719836106e1565b946020939093013593505050565b60008060006060848603121561073c57600080fd5b610745846106e1565b9250610753602085016106e1565b9150604084013590509250925092565b60006020828403121561077557600080fd5b610449826106e1565b6000806040838503121561079157600080fd5b61079a836106e1565b91506107a8602084016106e1565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107d9576107d96107b1565b500390565b600082198211156107f1576107f16107b1565b50019056fea2646970667358221220423a2d241b85b1ebdbd332cb4cda4288b557560fafa1ab700b6868cd6228949764736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 13061, + "contract": "contracts/Velo.sol:Velo", + "label": "totalSupply", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 13065, + "contract": "contracts/Velo.sol:Velo", + "label": "balanceOf", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 13071, + "contract": "contracts/Velo.sol:Velo", + "label": "allowance", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 13073, + "contract": "contracts/Velo.sol:Velo", + "label": "initialMinted", + "offset": 0, + "slot": "3", + "type": "t_bool" + }, + { + "astId": 13075, + "contract": "contracts/Velo.sol:Velo", + "label": "minter", + "offset": 1, + "slot": "3", + "type": "t_address" + }, + { + "astId": 13077, + "contract": "contracts/Velo.sol:Velo", + "label": "redemptionReceiver", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 13079, + "contract": "contracts/Velo.sol:Velo", + "label": "merkleClaim", + "offset": 0, + "slot": "5", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrum/VeloGovernor.json b/deployments/arbitrum/VeloGovernor.json new file mode 100644 index 00000000..6a7f196a --- /dev/null +++ b/deployments/arbitrum/VeloGovernor.json @@ -0,0 +1,1459 @@ +{ + "address": "0x60ea1F72695cF5735767b7CeA917E09290A06b9B", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IVotes", + "name": "_ve", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "Empty", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "ProposalCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldQuorumNumerator", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newQuorumNumerator", + "type": "uint256" + } + ], + "name": "QuorumNumeratorUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "VoteCast", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "VoteCastWithParams", + "type": "event" + }, + { + "inputs": [], + "name": "BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COUNTING_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "EXTENDED_BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_PROPOSAL_NUMERATOR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PROPOSAL_DENOMINATOR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + } + ], + "name": "castVote", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "castVoteBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "castVoteWithReason", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "castVoteWithReasonAndParamsBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "execute", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockTimestamp", + "type": "uint256" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockTimestamp", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "getVotesWithParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasVoted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "hashProposal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalDeadline", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalNumerator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "againstVotes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "forVotes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "abstainVotes", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "propose", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "blockTimestamp", + "type": "uint256" + } + ], + "name": "quorum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "quorumDenominator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "quorumNumerator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "relay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "numerator", + "type": "uint256" + } + ], + "name": "setProposalNumerator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newTeam", + "type": "address" + } + ], + "name": "setTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "state", + "outputs": [ + { + "internalType": "enum IGovernor.ProposalState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "team", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IVotes", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newQuorumNumerator", + "type": "uint256" + } + ], + "name": "updateQuorumNumerator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "votingPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x498c7739318dfed4b13af314ce03fca12e58b8fa9f84661a5a4c53e930ad3038", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x60ea1F72695cF5735767b7CeA917E09290A06b9B", + "transactionIndex": 2, + "gasUsed": "21626542", + "logsBloom": "0x00000000000000008100000000001000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7a607345aceb2c6b75da59fa82ae038fb7ea243da7c8f2cf3f273ac59deb6745", + "transactionHash": "0x498c7739318dfed4b13af314ce03fca12e58b8fa9f84661a5a4c53e930ad3038", + "logs": [ + { + "transactionIndex": 2, + "blockNumber": 53774131, + "transactionHash": "0x498c7739318dfed4b13af314ce03fca12e58b8fa9f84661a5a4c53e930ad3038", + "address": "0x60ea1F72695cF5735767b7CeA917E09290A06b9B", + "topics": [ + "0x0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004", + "logIndex": 1, + "blockHash": "0x7a607345aceb2c6b75da59fa82ae038fb7ea243da7c8f2cf3f273ac59deb6745" + } + ], + "blockNumber": 53774131, + "cumulativeGasUsed": "22131559", + "status": 1, + "byzantium": true + }, + "args": [ + "0x10Df81252069C1095F541FAca61646cb9Ae76703" + ], + "numDeployments": 1, + "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"_ve\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"Empty\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"proposer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"string[]\",\"name\":\"signatures\",\"type\":\"string[]\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"ProposalCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldQuorumNumerator\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"QuorumNumeratorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"VoteCast\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"VoteCastWithParams\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"COUNTING_MODE\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EXTENDED_BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_PROPOSAL_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROPOSAL_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"}],\"name\":\"castVote\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"castVoteWithReason\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"castVoteWithReasonAndParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteWithReasonAndParamsBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"execute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"getVotesWithParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasVoted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"hashProposal\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalDeadline\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalSnapshot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"againstVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"forVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"abstainVotes\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"propose\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"quorum\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumDenominator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"}],\"name\":\"setProposalNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTeam\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"state\",\"outputs\":[{\"internalType\":\"enum IGovernor.ProposalState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"updateQuorumNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"Empty()\":[{\"details\":\"An operation (e.g. {front}) couldn't be completed due to the queue being empty.\"}]},\"kind\":\"dev\",\"methods\":{\"COUNTING_MODE()\":{\"details\":\"See {IGovernor-COUNTING_MODE}.\"},\"castVote(uint256,uint8)\":{\"details\":\"See {IGovernor-castVote}.\"},\"castVoteBySig(uint256,uint8,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteBySig}.\"},\"castVoteWithReason(uint256,uint8,string)\":{\"details\":\"See {IGovernor-castVoteWithReason}.\"},\"castVoteWithReasonAndParams(uint256,uint8,string,bytes)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParams}.\"},\"castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParamsBySig}.\"},\"execute(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-execute}.\"},\"getVotes(address,uint256)\":{\"details\":\"See {IGovernor-getVotes}.\"},\"getVotesWithParams(address,uint256,bytes)\":{\"details\":\"See {IGovernor-getVotesWithParams}.\"},\"hasVoted(uint256,address)\":{\"details\":\"See {IGovernor-hasVoted}.\"},\"hashProposal(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-hashProposal}. The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in advance, before the proposal is submitted. Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the same proposal (with same operation and same description) will have the same id if submitted on multiple governors across multiple networks. This also means that in order to execute the same operation twice (on the same governor) the proposer will have to change the description in order to avoid proposal id conflicts.\"},\"name()\":{\"details\":\"See {IGovernor-name}.\"},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155BatchReceived}.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155Received}.\"},\"onERC721Received(address,address,uint256,bytes)\":{\"details\":\"See {IERC721Receiver-onERC721Received}.\"},\"proposalDeadline(uint256)\":{\"details\":\"See {IGovernor-proposalDeadline}.\"},\"proposalSnapshot(uint256)\":{\"details\":\"See {IGovernor-proposalSnapshot}.\"},\"proposalThreshold()\":{\"details\":\"Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\"},\"proposalVotes(uint256)\":{\"details\":\"Accessor to the internal vote counts.\"},\"propose(address[],uint256[],bytes[],string)\":{\"details\":\"See {IGovernor-propose}.\"},\"quorum(uint256)\":{\"details\":\"Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\"},\"quorumDenominator()\":{\"details\":\"Returns the quorum denominator. Defaults to 100, but may be overridden.\"},\"quorumNumerator()\":{\"details\":\"Returns the current quorum numerator. See {quorumDenominator}.\"},\"relay(address,uint256,bytes)\":{\"details\":\"Relays a transaction or function call to an arbitrary target. In cases where the governance executor is some contract other than the governor itself, like when using a timelock, this function can be invoked in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake. Note that if the executor is simply the governor itself, use of `relay` is redundant.\"},\"state(uint256)\":{\"details\":\"See {IGovernor-state}.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"updateQuorumNumerator(uint256)\":{\"details\":\"Changes the quorum numerator. Emits a {QuorumNumeratorUpdated} event. Requirements: - Must be called through a governance proposal. - New numerator must be smaller or equal to the denominator.\"},\"version()\":{\"details\":\"See {IGovernor-version}.\"},\"votingDelay()\":{\"details\":\"Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\"},\"votingPeriod()\":{\"details\":\"Delay, in number of blocks, between the vote start and vote ends. NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting duration compared to the voting delay.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"votingDelay()\":{\"notice\":\"module:user-config\"},\"votingPeriod()\":{\"notice\":\"module:user-config\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VeloGovernor.sol\":\"VeloGovernor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VeloGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IGovernor} from \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\nimport {L2GovernorCountingSimple} from \\\"contracts/governance/L2GovernorCountingSimple.sol\\\";\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\nimport {L2GovernorVotesQuorumFraction} from \\\"contracts/governance/L2GovernorVotesQuorumFraction.sol\\\";\\n\\ncontract VeloGovernor is\\n L2Governor,\\n L2GovernorCountingSimple,\\n L2GovernorVotes,\\n L2GovernorVotesQuorumFraction\\n{\\n address public team;\\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\\n uint256 public proposalNumerator = 2; // start at 0.02%\\n\\n constructor(IVotes _ve)\\n L2Governor(\\\"Velodrome Governor\\\")\\n L2GovernorVotes(_ve)\\n L2GovernorVotesQuorumFraction(4) // 4%\\n {\\n team = msg.sender;\\n }\\n\\n function votingDelay() public pure override(IGovernor) returns (uint256) {\\n return 15 minutes; // 1 block\\n }\\n\\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\\n return 1 weeks;\\n }\\n\\n function setTeam(address newTeam) external {\\n require(msg.sender == team, \\\"not team\\\");\\n team = newTeam;\\n }\\n\\n function setProposalNumerator(uint256 numerator) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \\\"numerator too high\\\");\\n proposalNumerator = numerator;\\n }\\n\\n function proposalThreshold()\\n public\\n view\\n override(L2Governor)\\n returns (uint256)\\n {\\n return\\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\\n PROPOSAL_DENOMINATOR;\\n }\\n}\\n\",\"keccak256\":\"0xbdbc34fd1c78fdffb528f7a2f450e75457cb089369204f4671ec241aa0eb3a7e\",\"license\":\"MIT\"},\"contracts/governance/L2Governor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Address.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Context.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\\n *\\n * @dev Core of the governance system, designed to be extended though various modules.\\n *\\n * This contract is abstract and requires several function to be implemented in various modules:\\n *\\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\\n * - A voting module must implement {_getVotes}\\n * - Additionanly, the {votingPeriod} must also be implemented\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\\n using SafeCast for uint256;\\n using Timers for Timers.Timestamp;\\n\\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\\\"Ballot(uint256 proposalId,uint8 support)\\\");\\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\\n keccak256(\\\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\\\");\\n\\n struct ProposalCore {\\n Timers.Timestamp voteStart;\\n Timers.Timestamp voteEnd;\\n bool executed;\\n bool canceled;\\n }\\n\\n string private _name;\\n\\n mapping(uint256 => ProposalCore) private _proposals;\\n\\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\\n\\n /**\\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\\n * parameter setters in {GovernorSettings} are protected using this modifier.\\n *\\n * The governance executing address may be different from the Governor's own address, for example it could be a\\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\\n * for example, additional timelock proposers are not able to change governance parameters without going through the\\n * governance protocol (since v4.6).\\n */\\n modifier onlyGovernance() {\\n require(_msgSender() == _executor(), \\\"Governor: onlyGovernance\\\");\\n if (_executor() != address(this)) {\\n bytes32 msgDataHash = keccak256(_msgData());\\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\\n while (_governanceCall.popFront() != msgDataHash) {}\\n }\\n _;\\n }\\n\\n /**\\n * @dev Sets the value for {name} and {version}\\n */\\n constructor(string memory name_) EIP712(name_, version()) {\\n _name = name_;\\n }\\n\\n /**\\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\\n */\\n receive() external payable virtual {\\n require(_executor() == address(this));\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\\n // include the castVoteWithReasonAndParams() function as standard\\n return\\n interfaceId ==\\n (type(IGovernor).interfaceId ^\\n this.castVoteWithReasonAndParams.selector ^\\n this.castVoteWithReasonAndParamsBySig.selector ^\\n this.getVotesWithParams.selector) ||\\n interfaceId == type(IGovernor).interfaceId ||\\n interfaceId == type(IERC1155Receiver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IGovernor-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IGovernor-version}.\\n */\\n function version() public view virtual override returns (string memory) {\\n return \\\"1\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hashProposal}.\\n *\\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\\n * advance, before the proposal is submitted.\\n *\\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual override returns (uint256) {\\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\\n }\\n\\n /**\\n * @dev See {IGovernor-state}.\\n */\\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n\\n if (proposal.executed) {\\n return ProposalState.Executed;\\n }\\n\\n if (proposal.canceled) {\\n return ProposalState.Canceled;\\n }\\n\\n uint256 start = proposalSnapshot(proposalId);\\n\\n if (start == 0) {\\n revert(\\\"Governor: unknown proposal id\\\");\\n }\\n\\n if (start >= block.timestamp) {\\n return ProposalState.Pending;\\n }\\n\\n uint256 deadline = proposalDeadline(proposalId);\\n\\n if (deadline >= block.timestamp) {\\n return ProposalState.Active;\\n }\\n\\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\\n return ProposalState.Succeeded;\\n } else {\\n return ProposalState.Defeated;\\n }\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalSnapshot}.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteStart.getDeadline();\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalDeadline}.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteEnd.getDeadline();\\n }\\n\\n /**\\n * @dev Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\\n */\\n function proposalThreshold() public view virtual returns (uint256) {\\n return 0;\\n }\\n\\n /**\\n * @dev Amount of votes already cast passes the threshold limit.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Is the proposal successful or not.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) internal view virtual returns (uint256);\\n\\n /**\\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\\n *\\n * Note: Support is generic and can represent various things depending on the voting system used.\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory params\\n ) internal virtual;\\n\\n /**\\n * @dev Default additional encoded parameters used by castVote methods that don't include them\\n *\\n * Note: Should be overridden by specific implementations to use an appropriate value, the\\n * meaning of the additional params, in the context of that implementation\\n */\\n function _defaultParams() internal view virtual returns (bytes memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-propose}.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual override returns (uint256) {\\n require(\\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\\n \\\"Governor: proposer votes below proposal threshold\\\"\\n );\\n\\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\\n\\n require(targets.length == values.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length == calldatas.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length > 0, \\\"Governor: empty proposal\\\");\\n\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(proposal.voteStart.isUnset(), \\\"Governor: proposal already exists\\\");\\n\\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\\n uint64 deadline = start + votingPeriod().toUint64();\\n\\n proposal.voteStart.setDeadline(start);\\n proposal.voteEnd.setDeadline(deadline);\\n\\n emit ProposalCreated(\\n proposalId,\\n _msgSender(),\\n targets,\\n values,\\n new string[](targets.length),\\n calldatas,\\n start,\\n deadline,\\n description\\n );\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-execute}.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual override returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n\\n ProposalState status = state(proposalId);\\n require(\\n status == ProposalState.Succeeded || status == ProposalState.Queued,\\n \\\"Governor: proposal not successful\\\"\\n );\\n _proposals[proposalId].executed = true;\\n\\n emit ProposalExecuted(proposalId);\\n\\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\\n _execute(proposalId, targets, values, calldatas, descriptionHash);\\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\\n */\\n function _execute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n string memory errorMessage = \\\"Governor: call reverted without message\\\";\\n for (uint256 i = 0; i < targets.length; ++i) {\\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\\n Address.verifyCallResult(success, returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Hook before execution is triggered.\\n */\\n function _beforeExecute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory, /* values */\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n for (uint256 i = 0; i < targets.length; ++i) {\\n if (targets[i] == address(this)) {\\n _governanceCall.pushBack(keccak256(calldatas[i]));\\n }\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook after execution is triggered.\\n */\\n function _afterExecute(\\n uint256, /* proposalId */\\n address[] memory, /* targets */\\n uint256[] memory, /* values */\\n bytes[] memory, /* calldatas */\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n if (!_governanceCall.empty()) {\\n _governanceCall.clear();\\n }\\n }\\n }\\n\\n /**\\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\\n * canceled to allow distinguishing it from executed proposals.\\n *\\n * Emits a {IGovernor-ProposalCanceled} event.\\n */\\n function _cancel(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) internal virtual returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n ProposalState status = state(proposalId);\\n\\n require(\\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\\n \\\"Governor: proposal not active\\\"\\n );\\n _proposals[proposalId].canceled = true;\\n\\n emit ProposalCanceled(proposalId);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotes}.\\n */\\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, _defaultParams());\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotesWithParams}.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVote}.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReason}.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteBySig}.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\\n v,\\n r,\\n s\\n );\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(\\n keccak256(\\n abi.encode(\\n EXTENDED_BALLOT_TYPEHASH,\\n proposalId,\\n support,\\n keccak256(bytes(reason)),\\n keccak256(params)\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason\\n ) internal virtual returns (uint256) {\\n return _castVote(proposalId, account, support, reason, _defaultParams());\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason,\\n bytes memory params\\n ) internal virtual returns (uint256) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(state(proposalId) == ProposalState.Active, \\\"Governor: vote not currently active\\\");\\n\\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\\n _countVote(proposalId, account, support, weight, params);\\n\\n if (params.length == 0) {\\n emit VoteCast(account, proposalId, support, weight, reason);\\n } else {\\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\\n }\\n\\n return weight;\\n }\\n\\n /**\\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\\n */\\n function relay(\\n address target,\\n uint256 value,\\n bytes calldata data\\n ) external virtual onlyGovernance {\\n Address.functionCallWithValue(target, data, value);\\n }\\n\\n /**\\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\\n * through another contract such as a timelock.\\n */\\n function _executor() internal view virtual returns (address) {\\n return address(this);\\n }\\n\\n /**\\n * @dev See {IERC721Receiver-onERC721Received}.\\n */\\n function onERC721Received(\\n address,\\n address,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155Received}.\\n */\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\\n */\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] memory,\\n uint256[] memory,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155BatchReceived.selector;\\n }\\n}\\n\",\"keccak256\":\"0xa2846313b89a871807cdebd0225b0bf8f23b17505ab8b3288549ec54a5a4a71b\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorCountingSimple.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\\n *\\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorCountingSimple is L2Governor {\\n /**\\n * @dev Supported vote types. Matches Governor Bravo ordering.\\n */\\n enum VoteType {\\n Against,\\n For,\\n Abstain\\n }\\n\\n struct ProposalVote {\\n uint256 againstVotes;\\n uint256 forVotes;\\n uint256 abstainVotes;\\n mapping(address => bool) hasVoted;\\n }\\n\\n mapping(uint256 => ProposalVote) private _proposalVotes;\\n\\n /**\\n * @dev See {IGovernor-COUNTING_MODE}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual override returns (string memory) {\\n return \\\"support=bravo&quorum=for,abstain\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hasVoted}.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\\n return _proposalVotes[proposalId].hasVoted[account];\\n }\\n\\n /**\\n * @dev Accessor to the internal vote counts.\\n */\\n function proposalVotes(uint256 proposalId)\\n public\\n view\\n virtual\\n returns (\\n uint256 againstVotes,\\n uint256 forVotes,\\n uint256 abstainVotes\\n )\\n {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\\n }\\n\\n /**\\n * @dev See {Governor-_quorumReached}.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return proposalvote.forVotes > proposalvote.againstVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory // params\\n ) internal virtual override {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n require(!proposalvote.hasVoted[account], \\\"GovernorVotingSimple: vote already cast\\\");\\n proposalvote.hasVoted[account] = true;\\n\\n if (support == uint8(VoteType.Against)) {\\n proposalvote.againstVotes += weight;\\n } else if (support == uint8(VoteType.For)) {\\n proposalvote.forVotes += weight;\\n } else if (support == uint8(VoteType.Abstain)) {\\n proposalvote.abstainVotes += weight;\\n } else {\\n revert(\\\"GovernorVotingSimple: invalid value for enum VoteType\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xdc37daa24118a6e6ba5208b4abefa1632af2ff340135ca6c6d7237f70102d5db\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotes is L2Governor {\\n IVotes public immutable token;\\n\\n constructor(IVotes tokenAddress) {\\n token = tokenAddress;\\n }\\n\\n /**\\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory /*params*/\\n ) internal view virtual override returns (uint256) {\\n return token.getPastVotes(account, blockTimestamp);\\n }\\n}\\n\",\"keccak256\":\"0x605a7de71228dda3cb8fd878cac313a86bc5841fd34d7344214346ba46e63af1\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotesQuorumFraction.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\\n * fraction of the total supply.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\\n uint256 private _quorumNumerator;\\n\\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\\n\\n /**\\n * @dev Initialize quorum as a fraction of the token's total supply.\\n *\\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\\n * customized by overriding {quorumDenominator}.\\n */\\n constructor(uint256 quorumNumeratorValue) {\\n _updateQuorumNumerator(quorumNumeratorValue);\\n }\\n\\n /**\\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\\n */\\n function quorumNumerator() public view virtual returns (uint256) {\\n return _quorumNumerator;\\n }\\n\\n /**\\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\\n */\\n function quorumDenominator() public view virtual returns (uint256) {\\n return 100;\\n }\\n\\n /**\\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\\n */\\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - Must be called through a governance proposal.\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\\n _updateQuorumNumerator(newQuorumNumerator);\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\\n require(\\n newQuorumNumerator <= quorumDenominator(),\\n \\\"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\\\"\\n );\\n\\n uint256 oldQuorumNumerator = _quorumNumerator;\\n _quorumNumerator = newQuorumNumerator;\\n\\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\\n }\\n}\\n\",\"keccak256\":\"0xe66d29c0ffd2274de933d80e11d68891f3acc3f078be4560a2b493b7d88dcb7f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Interface of the {Governor} core.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract IGovernor is IERC165 {\\n enum ProposalState {\\n Pending,\\n Active,\\n Canceled,\\n Defeated,\\n Succeeded,\\n Queued,\\n Expired,\\n Executed\\n }\\n\\n /**\\n * @dev Emitted when a proposal is created.\\n */\\n event ProposalCreated(\\n uint256 proposalId,\\n address proposer,\\n address[] targets,\\n uint256[] values,\\n string[] signatures,\\n bytes[] calldatas,\\n uint256 startBlock,\\n uint256 endBlock,\\n string description\\n );\\n\\n /**\\n * @dev Emitted when a proposal is canceled.\\n */\\n event ProposalCanceled(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a proposal is executed.\\n */\\n event ProposalExecuted(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a vote is cast without params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n */\\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\\n\\n /**\\n * @dev Emitted when a vote is cast with params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\\n */\\n event VoteCastWithParams(\\n address indexed voter,\\n uint256 proposalId,\\n uint8 support,\\n uint256 weight,\\n string reason,\\n bytes params\\n );\\n\\n /**\\n * @notice module:core\\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\\n */\\n function name() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \\\"1\\\"\\n */\\n function version() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:voting\\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\\n *\\n * There are 2 standard keys: `support` and `quorum`.\\n *\\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\\n * - `quorum=bravo` means that only For votes are counted towards quorum.\\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\\n *\\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\\n * name that describes the behavior. For example:\\n *\\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\\n *\\n * NOTE: The string can be decoded by the standard\\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\\n * JavaScript class.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Current state of a proposal, following Compound's convention\\n */\\n function state(uint256 proposalId) public view virtual returns (ProposalState);\\n\\n /**\\n * @notice module:core\\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\\n * beginning of the following block.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\\n * during this block.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\\n */\\n function votingDelay() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of blocks, between the vote start and vote ends.\\n *\\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\\n * duration compared to the voting delay.\\n */\\n function votingPeriod() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Minimum number of cast voted required for a proposal to be successful.\\n *\\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\\n */\\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber`.\\n *\\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\\n * multiple), {ERC20Votes} tokens.\\n */\\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockNumber,\\n bytes memory params\\n ) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:voting\\n * @dev Returns whether `account` has cast a vote on `proposalId`.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\\n\\n /**\\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\\n * {IGovernor-votingPeriod} blocks after the voting starts.\\n *\\n * Emits a {ProposalCreated} event.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\\n * deadline to be reached.\\n *\\n * Emits a {ProposalExecuted} event.\\n *\\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Cast a vote\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xa52d593ff06a2353f78fa149da31f2ca94f03d1eff99bde41977fa2fe985a92f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2e53602b96c1bf97c731ed3e2a981b4f85e23a9410a5ebd36e549a4cc93340dc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x2626d8ab3dfdad0fad630c212ad146d59473d0f48b771784c61a7c1dbbea1f3f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Tooling for timepoints, timers and delays\\n */\\nlibrary Timers {\\n struct Timestamp {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(Timestamp storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(Timestamp memory timer) internal view returns (bool) {\\n return timer._deadline > block.timestamp;\\n }\\n\\n function isExpired(Timestamp memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.timestamp;\\n }\\n\\n struct BlockNumber {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(BlockNumber storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(BlockNumber memory timer) internal view returns (bool) {\\n return timer._deadline > block.number;\\n }\\n\\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.number;\\n }\\n}\\n\",\"keccak256\":\"0x29791a62950a7983e02a673639c1a781d1e448691800456c2ce4b99715391b14\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS,\\n InvalidSignatureV // Deprecated in v4.8\\n }\\n\\n function _throwError(RecoverError error) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert(\\\"ECDSA: invalid signature\\\");\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert(\\\"ECDSA: invalid signature 's' value\\\");\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature` or error string. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\\n if (signature.length == 65) {\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n /// @solidity memory-safe-assembly\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n return tryRecover(hash, v, r, s);\\n } else {\\n return (address(0), RecoverError.InvalidSignatureLength);\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, signature);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n *\\n * _Available since v4.2._\\n */\\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature);\\n }\\n\\n return (signer, RecoverError.NoError);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from `s`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", Strings.toString(s.length), s));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Typed Data, created from a\\n * `domainSeparator` and a `structHash`. This produces hash corresponding\\n * to the one signed with the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\\n * JSON-RPC method as part of EIP-712.\\n *\\n * See {recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n }\\n}\\n\",\"keccak256\":\"0x54ee424bfc83ce63b2a918b9a1efb5090a0fb68dbd1de3b10bc667776885dd4f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ECDSA.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n /* solhint-disable var-name-mixedcase */\\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n // invalidate the cached domain separator if the chain id changes.\\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n uint256 private immutable _CACHED_CHAIN_ID;\\n address private immutable _CACHED_THIS;\\n\\n bytes32 private immutable _HASHED_NAME;\\n bytes32 private immutable _HASHED_VERSION;\\n bytes32 private immutable _TYPE_HASH;\\n\\n /* solhint-enable var-name-mixedcase */\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n constructor(string memory name, string memory version) {\\n bytes32 hashedName = keccak256(bytes(name));\\n bytes32 hashedVersion = keccak256(bytes(version));\\n bytes32 typeHash = keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n );\\n _HASHED_NAME = hashedName;\\n _HASHED_VERSION = hashedVersion;\\n _CACHED_CHAIN_ID = block.chainid;\\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n _CACHED_THIS = address(this);\\n _TYPE_HASH = typeHash;\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\\n return _CACHED_DOMAIN_SEPARATOR;\\n } else {\\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n }\\n }\\n\\n function _buildDomainSeparator(\\n bytes32 typeHash,\\n bytes32 nameHash,\\n bytes32 versionHash\\n ) private view returns (bytes32) {\\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\\n }\\n}\\n\",\"keccak256\":\"0x948d8b2d18f38141ec78c5229d770d950ebc781ed3f44cc9e3ccbb9fded5846a\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\\n\\nimport \\\"./EIP712.sol\\\";\\n\",\"keccak256\":\"0xea30c402170bc240354b74e6c6f6a8e5bdb1935d90d168cc58c0654461c6a72b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3546b156d97633f7f8cad536d5454c81d1d604687c02b2eb105fdc33cb962b41\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\\npragma solidity ^0.8.4;\\n\\nimport \\\"../math/SafeCast.sol\\\";\\n\\n/**\\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\\n * the existing queue contents are left in storage.\\n *\\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\\n * used in storage, and not in memory.\\n * ```\\n * DoubleEndedQueue.Bytes32Deque queue;\\n * ```\\n *\\n * _Available since v4.6._\\n */\\nlibrary DoubleEndedQueue {\\n /**\\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\\n */\\n error Empty();\\n\\n /**\\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\\n */\\n error OutOfBounds();\\n\\n /**\\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\\n *\\n * Struct members have an underscore prefix indicating that they are \\\"private\\\" and should not be read or written to\\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\\n * lead to unexpected behavior.\\n *\\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\\n * data[end - 1].\\n */\\n struct Bytes32Deque {\\n int128 _begin;\\n int128 _end;\\n mapping(int128 => bytes32) _data;\\n }\\n\\n /**\\n * @dev Inserts an item at the end of the queue.\\n */\\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 backIndex = deque._end;\\n deque._data[backIndex] = value;\\n unchecked {\\n deque._end = backIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Removes the item at the end of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n value = deque._data[backIndex];\\n delete deque._data[backIndex];\\n deque._end = backIndex;\\n }\\n\\n /**\\n * @dev Inserts an item at the beginning of the queue.\\n */\\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 frontIndex;\\n unchecked {\\n frontIndex = deque._begin - 1;\\n }\\n deque._data[frontIndex] = value;\\n deque._begin = frontIndex;\\n }\\n\\n /**\\n * @dev Removes the item at the beginning of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n value = deque._data[frontIndex];\\n delete deque._data[frontIndex];\\n unchecked {\\n deque._begin = frontIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Returns the item at the beginning of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n return deque._data[frontIndex];\\n }\\n\\n /**\\n * @dev Returns the item at the end of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n return deque._data[backIndex];\\n }\\n\\n /**\\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\\n * `length(deque) - 1`.\\n *\\n * Reverts with `OutOfBounds` if the index is out of bounds.\\n */\\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\\n // int256(deque._begin) is a safe upcast\\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\\n if (idx >= deque._end) revert OutOfBounds();\\n return deque._data[idx];\\n }\\n\\n /**\\n * @dev Resets the queue back to being empty.\\n *\\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\\n * out on potential gas refunds.\\n */\\n function clear(Bytes32Deque storage deque) internal {\\n deque._begin = 0;\\n deque._end = 0;\\n }\\n\\n /**\\n * @dev Returns the number of items in the queue.\\n */\\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\\n // We also assume there are at most int256.max items in the queue.\\n unchecked {\\n return uint256(int256(deque._end) - int256(deque._begin));\\n }\\n }\\n\\n /**\\n * @dev Returns true if the queue is empty.\\n */\\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\\n return deque._end <= deque._begin;\\n }\\n}\\n\",\"keccak256\":\"0x4859ffd6dd69382a1462930c00b6e394007da80e78e510f56930271034737bf2\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x61016060405260026007553480156200001757600080fd5b506040516200328f3803806200328f8339810160408190526200003a91620002e1565b600481604051806040016040528060128152602001712b32b637b23937b6b29023b7bb32b93737b960711b81525080620000796200015360201b60201c565b815160208084019190912082518383012060e08290526101008190524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81880181905281830187905260608201869052608082019490945230818401528151808203909301835260c00190528051940193909320919290916080523060c05261012052505082516200011f92506000915060208401906200023b565b50506001600160a01b03166101405262000139816200016e565b5050600680546001600160a01b031916331790556200034f565b6040805180820190915260018152603160f81b602082015290565b6064811115620001f65760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a40160405180910390fd5b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b828054620002499062000313565b90600052602060002090601f0160209004810192826200026d5760008555620002b8565b82601f106200028857805160ff1916838001178555620002b8565b82800160010185558215620002b8579182015b82811115620002b85782518255916020019190600101906200029b565b50620002c6929150620002ca565b5090565b5b80821115620002c65760008155600101620002cb565b600060208284031215620002f457600080fd5b81516001600160a01b03811681146200030c57600080fd5b9392505050565b600181811c908216806200032857607f821691505b6020821081036200034957634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e051610100516101205161014051612ed0620003bf600039600081816107df0152818161120f015281816113e40152611a0601526000611b2301526000611b7201526000611b4d01526000611aa601526000611ad001526000611afa0152612ed06000f3fe6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220ae86954b26ceef75c9e85ea3a516f1caaf64b51a491c8f94a0c7edfb9738a80664736f6c634300080d0033", + "deployedBytecode": "0x6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220ae86954b26ceef75c9e85ea3a516f1caaf64b51a491c8f94a0c7edfb9738a80664736f6c634300080d0033", + "devdoc": { + "errors": { + "Empty()": [ + { + "details": "An operation (e.g. {front}) couldn't be completed due to the queue being empty." + } + ] + }, + "kind": "dev", + "methods": { + "COUNTING_MODE()": { + "details": "See {IGovernor-COUNTING_MODE}." + }, + "castVote(uint256,uint8)": { + "details": "See {IGovernor-castVote}." + }, + "castVoteBySig(uint256,uint8,uint8,bytes32,bytes32)": { + "details": "See {IGovernor-castVoteBySig}." + }, + "castVoteWithReason(uint256,uint8,string)": { + "details": "See {IGovernor-castVoteWithReason}." + }, + "castVoteWithReasonAndParams(uint256,uint8,string,bytes)": { + "details": "See {IGovernor-castVoteWithReasonAndParams}." + }, + "castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32)": { + "details": "See {IGovernor-castVoteWithReasonAndParamsBySig}." + }, + "execute(address[],uint256[],bytes[],bytes32)": { + "details": "See {IGovernor-execute}." + }, + "getVotes(address,uint256)": { + "details": "See {IGovernor-getVotes}." + }, + "getVotesWithParams(address,uint256,bytes)": { + "details": "See {IGovernor-getVotesWithParams}." + }, + "hasVoted(uint256,address)": { + "details": "See {IGovernor-hasVoted}." + }, + "hashProposal(address[],uint256[],bytes[],bytes32)": { + "details": "See {IGovernor-hashProposal}. The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in advance, before the proposal is submitted. Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the same proposal (with same operation and same description) will have the same id if submitted on multiple governors across multiple networks. This also means that in order to execute the same operation twice (on the same governor) the proposer will have to change the description in order to avoid proposal id conflicts." + }, + "name()": { + "details": "See {IGovernor-name}." + }, + "onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)": { + "details": "See {IERC1155Receiver-onERC1155BatchReceived}." + }, + "onERC1155Received(address,address,uint256,uint256,bytes)": { + "details": "See {IERC1155Receiver-onERC1155Received}." + }, + "onERC721Received(address,address,uint256,bytes)": { + "details": "See {IERC721Receiver-onERC721Received}." + }, + "proposalDeadline(uint256)": { + "details": "See {IGovernor-proposalDeadline}." + }, + "proposalSnapshot(uint256)": { + "details": "See {IGovernor-proposalSnapshot}." + }, + "proposalThreshold()": { + "details": "Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_." + }, + "proposalVotes(uint256)": { + "details": "Accessor to the internal vote counts." + }, + "propose(address[],uint256[],bytes[],string)": { + "details": "See {IGovernor-propose}." + }, + "quorum(uint256)": { + "details": "Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`." + }, + "quorumDenominator()": { + "details": "Returns the quorum denominator. Defaults to 100, but may be overridden." + }, + "quorumNumerator()": { + "details": "Returns the current quorum numerator. See {quorumDenominator}." + }, + "relay(address,uint256,bytes)": { + "details": "Relays a transaction or function call to an arbitrary target. In cases where the governance executor is some contract other than the governor itself, like when using a timelock, this function can be invoked in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake. Note that if the executor is simply the governor itself, use of `relay` is redundant." + }, + "state(uint256)": { + "details": "See {IGovernor-state}." + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + }, + "updateQuorumNumerator(uint256)": { + "details": "Changes the quorum numerator. Emits a {QuorumNumeratorUpdated} event. Requirements: - Must be called through a governance proposal. - New numerator must be smaller or equal to the denominator." + }, + "version()": { + "details": "See {IGovernor-version}." + }, + "votingDelay()": { + "details": "Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to leave time for users to buy voting power, or delegate it, before the voting of a proposal starts." + }, + "votingPeriod()": { + "details": "Delay, in number of blocks, between the vote start and vote ends. NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting duration compared to the voting delay." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "votingDelay()": { + "notice": "module:user-config" + }, + "votingPeriod()": { + "notice": "module:user-config" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 21935, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "_name", + "offset": 0, + "slot": "0", + "type": "t_string_storage" + }, + { + "astId": 21940, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "_proposals", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_uint256,t_struct(ProposalCore)21933_storage)" + }, + { + "astId": 21943, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "_governanceCall", + "offset": 0, + "slot": "2", + "type": "t_struct(Bytes32Deque)30247_storage" + }, + { + "astId": 23199, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "_proposalVotes", + "offset": 0, + "slot": "4", + "type": "t_mapping(t_uint256,t_struct(ProposalVote)23194_storage)" + }, + { + "astId": 23452, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "_quorumNumerator", + "offset": 0, + "slot": "5", + "type": "t_uint256" + }, + { + "astId": 13423, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "team", + "offset": 0, + "slot": "6", + "type": "t_address" + }, + { + "astId": 13432, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "proposalNumerator", + "offset": 0, + "slot": "7", + "type": "t_uint256" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_int128": { + "encoding": "inplace", + "label": "int128", + "numberOfBytes": "16" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_int128,t_bytes32)": { + "encoding": "mapping", + "key": "t_int128", + "label": "mapping(int128 => bytes32)", + "numberOfBytes": "32", + "value": "t_bytes32" + }, + "t_mapping(t_uint256,t_struct(ProposalCore)21933_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct L2Governor.ProposalCore)", + "numberOfBytes": "32", + "value": "t_struct(ProposalCore)21933_storage" + }, + "t_mapping(t_uint256,t_struct(ProposalVote)23194_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct L2GovernorCountingSimple.ProposalVote)", + "numberOfBytes": "32", + "value": "t_struct(ProposalVote)23194_storage" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Bytes32Deque)30247_storage": { + "encoding": "inplace", + "label": "struct DoubleEndedQueue.Bytes32Deque", + "members": [ + { + "astId": 30240, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "_begin", + "offset": 0, + "slot": "0", + "type": "t_int128" + }, + { + "astId": 30242, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "_end", + "offset": 16, + "slot": "0", + "type": "t_int128" + }, + { + "astId": 30246, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "_data", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_int128,t_bytes32)" + } + ], + "numberOfBytes": "64" + }, + "t_struct(ProposalCore)21933_storage": { + "encoding": "inplace", + "label": "struct L2Governor.ProposalCore", + "members": [ + { + "astId": 21925, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "voteStart", + "offset": 0, + "slot": "0", + "type": "t_struct(Timestamp)26448_storage" + }, + { + "astId": 21928, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "voteEnd", + "offset": 0, + "slot": "1", + "type": "t_struct(Timestamp)26448_storage" + }, + { + "astId": 21930, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "executed", + "offset": 0, + "slot": "2", + "type": "t_bool" + }, + { + "astId": 21932, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "canceled", + "offset": 1, + "slot": "2", + "type": "t_bool" + } + ], + "numberOfBytes": "96" + }, + "t_struct(ProposalVote)23194_storage": { + "encoding": "inplace", + "label": "struct L2GovernorCountingSimple.ProposalVote", + "members": [ + { + "astId": 23185, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "againstVotes", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 23187, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "forVotes", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 23189, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "abstainVotes", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 23193, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "hasVoted", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_address,t_bool)" + } + ], + "numberOfBytes": "128" + }, + "t_struct(Timestamp)26448_storage": { + "encoding": "inplace", + "label": "struct Timers.Timestamp", + "members": [ + { + "astId": 26447, + "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "label": "_deadline", + "offset": 0, + "slot": "0", + "type": "t_uint64" + } + ], + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint64": { + "encoding": "inplace", + "label": "uint64", + "numberOfBytes": "8" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrum/VelodromeLibrary.json b/deployments/arbitrum/VelodromeLibrary.json new file mode 100644 index 00000000..960d9cfb --- /dev/null +++ b/deployments/arbitrum/VelodromeLibrary.json @@ -0,0 +1,229 @@ +{ + "address": "0x8CBC99B41851A410A4C74200d628e895c940C641", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_router", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getAmountOut", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getMinimumValue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getSample", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getTradeDiff", + "outputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "pair", + "type": "address" + } + ], + "name": "getTradeDiff", + "outputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xd197d093ad294467129d1d8c6384c422818fc283b348e18634ce9b310f76367c", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x8CBC99B41851A410A4C74200d628e895c940C641", + "transactionIndex": 1, + "gasUsed": "6231687", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc6f3b7805971285327398751e75c0027fcdbf29a68502b76e2526d60cff3e216", + "transactionHash": "0xd197d093ad294467129d1d8c6384c422818fc283b348e18634ce9b310f76367c", + "logs": [], + "blockNumber": 53774068, + "cumulativeGasUsed": "6231687", + "status": 1, + "byzantium": true + }, + "args": [ + "0x07d2FCFa095d52652cBC664F105F2d9Fb3799a47" + ], + "numDeployments": 1, + "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getMinimumValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getSample\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VelodromeLibrary.sol\":\"VelodromeLibrary\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VelodromeLibrary.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\n\\ncontract VelodromeLibrary {\\n IRouter internal immutable router;\\n\\n constructor(address _router) {\\n router = IRouter(_router);\\n }\\n\\n function _f(uint x0, uint y) internal pure returns (uint) {\\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\\n }\\n\\n function _d(uint x0, uint y) internal pure returns (uint) {\\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\\n }\\n\\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\\n for (uint i = 0; i < 255; i++) {\\n uint y_prev = y;\\n uint k = _f(x0, y);\\n if (k < xy) {\\n uint dy = (xy - k)*1e18/_d(x0, y);\\n y = y + dy;\\n } else {\\n uint dy = (k - xy)*1e18/_d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n }\\n\\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return (sample, r0, r1);\\n }\\n\\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\\n if (stable) {\\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\\n _reserve0 = _reserve0 * 1e18 / decimals0;\\n _reserve1 = _reserve1 * 1e18 / decimals1;\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\\n } else {\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n return amountIn * reserveB / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\\n if (stable) {\\n uint _x = x * 1e18 / decimals0;\\n uint _y = y * 1e18 / decimals1;\\n uint _a = (_x * _y) / 1e18;\\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return _a * _b / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n \\n}\\n\",\"keccak256\":\"0x01df9d4f97d905560776a0b2d29e6dc1337dc952fdc3d8bfbfde99a510a62c1c\",\"license\":\"MIT\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"}},\"version\":1}", + "bytecode": "0x60a060405234801561001057600080fd5b5060405161100238038061100283398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051610f626100a06000396000818161010c015281816102730152818161043701526105cb0152610f626000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea2646970667358221220e18be31ac379d23de05581201cfe992cc3fb78706bfad366c4328404d527c38d64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea2646970667358221220e18be31ac379d23de05581201cfe992cc3fb78706bfad366c4328404d527c38d64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/arbitrum/Voter.json b/deployments/arbitrum/Voter.json new file mode 100644 index 00000000..10fa498b --- /dev/null +++ b/deployments/arbitrum/Voter.json @@ -0,0 +1,1418 @@ +{ + "address": "0x29C487a354D11315059204Df4F7d8AB1aa008ebb", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "__ve", + "type": "address" + }, + { + "internalType": "address", + "name": "_factory", + "type": "address" + }, + { + "internalType": "address", + "name": "_gauges", + "type": "address" + }, + { + "internalType": "address", + "name": "_bribes", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + } + ], + "name": "Abstained", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Attach", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "lp", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Detach", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DistributeReward", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "internal_bribe", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "external_bribe", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "GaugeCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + } + ], + "name": "GaugeKilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + } + ], + "name": "GaugeRevived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "reward", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "NotifyReward", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + } + ], + "name": "Voted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "whitelister", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "Whitelisted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "lp", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [], + "name": "_ve", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "attachTokenToGauge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bribefactory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_bribes", + "type": "address[]" + }, + { + "internalType": "address[][]", + "name": "_tokens", + "type": "address[][]" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "claimBribes", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_fees", + "type": "address[]" + }, + { + "internalType": "address[][]", + "name": "_tokens", + "type": "address[][]" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "claimFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_gauges", + "type": "address[]" + }, + { + "internalType": "address[][]", + "name": "_tokens", + "type": "address[][]" + } + ], + "name": "claimRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "claimable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_pool", + "type": "address" + } + ], + "name": "createGauge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "detachTokenFromGauge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_gauges", + "type": "address[]" + } + ], + "name": "distribute", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gauge", + "type": "address" + } + ], + "name": "distribute", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "start", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "finish", + "type": "uint256" + } + ], + "name": "distribute", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "distribute", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_gauges", + "type": "address[]" + } + ], + "name": "distributeFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "distro", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "emergencyCouncil", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "emitDeposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "emitWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "external_bribes", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gaugefactory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "gauges", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_tokens", + "type": "address[]" + }, + { + "internalType": "address", + "name": "_minter", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "internal_bribes", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isAlive", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isGauge", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isWhitelisted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gauge", + "type": "address" + } + ], + "name": "killGauge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "lastVoted", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "length", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "notifyRewardAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "poke", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "poolForGauge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "poolVote", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "pools", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "reset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gauge", + "type": "address" + } + ], + "name": "reviveGauge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_council", + "type": "address" + } + ], + "name": "setEmergencyCouncil", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_governor", + "type": "address" + } + ], + "name": "setGovernor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalWeight", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "updateAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_gauges", + "type": "address[]" + } + ], + "name": "updateFor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "start", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "end", + "type": "uint256" + } + ], + "name": "updateForRange", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gauge", + "type": "address" + } + ], + "name": "updateGauge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "usedWeights", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "_poolVote", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "_weights", + "type": "uint256[]" + } + ], + "name": "vote", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "votes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "weights", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + } + ], + "name": "whitelist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x6525dd63638ff4ed2b7e6556e27d3903e730609c0503ea6facd921de9c091e43", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x29C487a354D11315059204Df4F7d8AB1aa008ebb", + "transactionIndex": 1, + "gasUsed": "21064022", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x52e0ff5d75dfe71eff1e0a08b81f63681b1af7d28d6d0b1d0a83bdf04a49458c", + "transactionHash": "0x6525dd63638ff4ed2b7e6556e27d3903e730609c0503ea6facd921de9c091e43", + "logs": [], + "blockNumber": 53774108, + "cumulativeGasUsed": "21064022", + "status": 1, + "byzantium": true + }, + "args": [ + "0x10Df81252069C1095F541FAca61646cb9Ae76703", + "0xA2db791281CdeeBb1EEDc78a34989df2Bfd479bE", + "0x2CCb061AD1b50211cF79f33e690452497941a2fe", + "0xBcC3c06e1D22E44Ac807D76A887fFB40765e0D16" + ], + "numDeployments": 1, + "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_gauges\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_bribes\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Abstained\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Attach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Detach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributeReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"internal_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"external_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"name\":\"GaugeCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeKilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeRevived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"reward\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NotifyReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Voted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"whitelister\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"Whitelisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"attachTokenToGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bribefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_bribes\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimBribes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_fees\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"}],\"name\":\"claimRewards\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"detachTokenFromGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"finish\",\"type\":\"uint256\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distributeFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distro\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"emergencyCouncil\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"external_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gaugefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"gauges\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_tokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"internal_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isAlive\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isGauge\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isWhitelisted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"killGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"lastVoted\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"length\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"notifyRewardAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"poke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolForGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"poolVote\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"reset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"reviveGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_council\",\"type\":\"address\"}],\"name\":\"setEmergencyCouncil\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"setGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalWeight\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"updateFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"name\":\"updateForRange\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"updateGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedWeights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"_poolVote\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_weights\",\"type\":\"uint256[]\"}],\"name\":\"vote\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"votes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"weights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"whitelist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Voter.sol\":\"Voter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Voter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/libraries/Math.sol';\\nimport 'contracts/interfaces/IBribe.sol';\\nimport 'contracts/interfaces/IBribeFactory.sol';\\nimport 'contracts/interfaces/IGauge.sol';\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/interfaces/IERC20.sol';\\nimport 'contracts/interfaces/IMinter.sol';\\nimport 'contracts/interfaces/IPair.sol';\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/interfaces/IVoter.sol';\\nimport 'contracts/interfaces/IVotingEscrow.sol';\\n\\ncontract Voter is IVoter {\\n\\n address public immutable _ve; // the ve token that governs these contracts\\n address public immutable factory; // the PairFactory\\n address internal immutable base;\\n address public immutable gaugefactory;\\n address public immutable bribefactory;\\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\\n address public minter;\\n address public governor; // should be set to an IGovernor\\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\\n\\n uint public totalWeight; // total voting weight\\n\\n address[] public pools; // all pools viable for incentives\\n mapping(address => address) public gauges; // pool => gauge\\n mapping(address => address) public poolForGauge; // gauge => pool\\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\\n mapping(address => uint256) public weights; // pool => weight\\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\\n mapping(uint => address[]) public poolVote; // nft => pools\\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\\n mapping(address => bool) public isGauge;\\n mapping(address => bool) public isWhitelisted;\\n mapping(address => bool) public isAlive;\\n\\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\\n event GaugeKilled(address indexed gauge);\\n event GaugeRevived(address indexed gauge);\\n event Voted(address indexed voter, uint tokenId, uint256 weight);\\n event Abstained(uint tokenId, uint256 weight);\\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\\n event Whitelisted(address indexed whitelister, address indexed token);\\n\\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\\n _ve = __ve;\\n factory = _factory;\\n base = IVotingEscrow(__ve).token();\\n gaugefactory = _gauges;\\n bribefactory = _bribes;\\n minter = msg.sender;\\n governor = msg.sender;\\n emergencyCouncil = msg.sender;\\n }\\n\\n // simple re-entrancy check\\n uint internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n modifier onlyNewEpoch(uint _tokenId) {\\n // ensure new epoch since last vote \\n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \\\"TOKEN_ALREADY_VOTED_THIS_EPOCH\\\");\\n _;\\n }\\n\\n function initialize(address[] memory _tokens, address _minter) external {\\n require(msg.sender == minter);\\n for (uint i = 0; i < _tokens.length; i++) {\\n _whitelist(_tokens[i]);\\n }\\n minter = _minter;\\n }\\n\\n function setGovernor(address _governor) public {\\n require(msg.sender == governor);\\n governor = _governor;\\n }\\n\\n function setEmergencyCouncil(address _council) public {\\n require(msg.sender == emergencyCouncil);\\n emergencyCouncil = _council;\\n }\\n\\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n lastVoted[_tokenId] = block.timestamp;\\n _reset(_tokenId);\\n IVotingEscrow(_ve).abstain(_tokenId);\\n }\\n\\n function _reset(uint _tokenId) internal {\\n address[] storage _poolVote = poolVote[_tokenId];\\n uint _poolVoteCnt = _poolVote.length;\\n uint256 _totalWeight = 0;\\n\\n for (uint i = 0; i < _poolVoteCnt; i ++) {\\n address _pool = _poolVote[i];\\n uint256 _votes = votes[_tokenId][_pool];\\n\\n if (_votes != 0) {\\n _updateFor(gauges[_pool]);\\n weights[_pool] -= _votes;\\n votes[_tokenId][_pool] -= _votes;\\n if (_votes > 0) {\\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n _totalWeight += _votes;\\n } else {\\n _totalWeight -= _votes;\\n }\\n emit Abstained(_tokenId, _votes);\\n }\\n }\\n totalWeight -= uint256(_totalWeight);\\n usedWeights[_tokenId] = 0;\\n delete poolVote[_tokenId];\\n }\\n\\n function poke(uint _tokenId) external {\\n address[] memory _poolVote = poolVote[_tokenId];\\n uint _poolCnt = _poolVote.length;\\n uint256[] memory _weights = new uint256[](_poolCnt);\\n\\n for (uint i = 0; i < _poolCnt; i ++) {\\n _weights[i] = votes[_tokenId][_poolVote[i]];\\n }\\n\\n _vote(_tokenId, _poolVote, _weights);\\n }\\n\\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\\n _reset(_tokenId);\\n uint _poolCnt = _poolVote.length;\\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\\n uint256 _totalVoteWeight = 0;\\n uint256 _totalWeight = 0;\\n uint256 _usedWeight = 0;\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n _totalVoteWeight += _weights[i];\\n }\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n address _pool = _poolVote[i];\\n address _gauge = gauges[_pool];\\n\\n if (isGauge[_gauge]) {\\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\\n require(votes[_tokenId][_pool] == 0);\\n require(_poolWeight != 0);\\n _updateFor(_gauge);\\n\\n poolVote[_tokenId].push(_pool);\\n\\n weights[_pool] += _poolWeight;\\n votes[_tokenId][_pool] += _poolWeight;\\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n _usedWeight += _poolWeight;\\n _totalWeight += _poolWeight;\\n emit Voted(msg.sender, _tokenId, _poolWeight);\\n }\\n }\\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\\n totalWeight += uint256(_totalWeight);\\n usedWeights[_tokenId] = uint256(_usedWeight);\\n }\\n\\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n require(_poolVote.length == _weights.length);\\n lastVoted[tokenId] = block.timestamp;\\n _vote(tokenId, _poolVote, _weights);\\n }\\n\\n function whitelist(address _token) public {\\n require(msg.sender == governor);\\n _whitelist(_token);\\n }\\n\\n function _whitelist(address _token) internal {\\n require(!isWhitelisted[_token]);\\n isWhitelisted[_token] = true;\\n emit Whitelisted(msg.sender, _token);\\n }\\n\\n function createGauge(address _pool) external returns (address) {\\n require(gauges[_pool] == address(0x0), \\\"exists\\\");\\n address[] memory allowedRewards = new address[](3);\\n address[] memory internalRewards = new address[](2);\\n bool isPair = IPairFactory(factory).isPair(_pool);\\n address tokenA;\\n address tokenB;\\n\\n if (isPair) {\\n (tokenA, tokenB) = IPair(_pool).tokens();\\n allowedRewards[0] = tokenA;\\n allowedRewards[1] = tokenB;\\n internalRewards[0] = tokenA;\\n internalRewards[1] = tokenB;\\n\\n if (base != tokenA && base != tokenB) {\\n allowedRewards[2] = base;\\n }\\n }\\n\\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\\n require(isPair, \\\"!_pool\\\");\\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \\\"!whitelisted\\\");\\n }\\n\\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\\n\\n IERC20(base).approve(_gauge, type(uint).max);\\n internal_bribes[_gauge] = _internal_bribe;\\n external_bribes[_gauge] = _external_bribe;\\n gauges[_pool] = _gauge;\\n poolForGauge[_gauge] = _pool;\\n isGauge[_gauge] = true;\\n isAlive[_gauge] = true;\\n _updateFor(_gauge);\\n pools.push(_pool);\\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\\n return _gauge;\\n }\\n\\n function killGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(isAlive[_gauge], \\\"gauge already dead\\\");\\n isAlive[_gauge] = false;\\n claimable[_gauge] = 0;\\n emit GaugeKilled(_gauge);\\n }\\n\\n function reviveGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(!isAlive[_gauge], \\\"gauge already alive\\\");\\n isAlive[_gauge] = true;\\n emit GaugeRevived(_gauge);\\n }\\n\\n function attachTokenToGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\\n emit Attach(account, msg.sender, tokenId);\\n }\\n\\n function emitDeposit(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]);\\n emit Deposit(account, msg.sender, tokenId, amount);\\n }\\n\\n function detachTokenFromGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\\n emit Detach(account, msg.sender, tokenId);\\n }\\n\\n function emitWithdraw(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n emit Withdraw(account, msg.sender, tokenId, amount);\\n }\\n\\n function length() external view returns (uint) {\\n return pools.length;\\n }\\n\\n uint internal index;\\n mapping(address => uint) internal supplyIndex;\\n mapping(address => uint) public claimable;\\n\\n function notifyRewardAmount(uint amount) external {\\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index += _ratio;\\n }\\n emit NotifyReward(msg.sender, base, amount);\\n }\\n\\n function updateFor(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n _updateFor(_gauges[i]);\\n }\\n }\\n\\n function updateForRange(uint start, uint end) public {\\n for (uint i = start; i < end; i++) {\\n _updateFor(gauges[pools[i]]);\\n }\\n }\\n\\n function updateAll() external {\\n updateForRange(0, pools.length);\\n }\\n\\n function updateGauge(address _gauge) external {\\n _updateFor(_gauge);\\n }\\n\\n function _updateFor(address _gauge) internal {\\n address _pool = poolForGauge[_gauge];\\n uint256 _supplied = weights[_pool];\\n if (_supplied > 0) {\\n uint _supplyIndex = supplyIndex[_gauge];\\n uint _index = index; // get global index0 for accumulated distro\\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\\n if (_delta > 0) {\\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\\n if (isAlive[_gauge]) {\\n claimable[_gauge] += _share;\\n }\\n }\\n } else {\\n supplyIndex[_gauge] = index; // new users are set to the default global state\\n }\\n }\\n\\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\\n }\\n }\\n\\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _bribes.length; i++) {\\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _fees.length; i++) {\\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function distributeFees(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n if (IGauge(_gauges[i]).isForPair()){\\n IGauge(_gauges[i]).claimFees();\\n }\\n }\\n }\\n\\n function distribute(address _gauge) public lock {\\n IMinter(minter).update_period();\\n _updateFor(_gauge); // should set claimable to 0 if killed\\n uint _claimable = claimable[_gauge];\\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\\n claimable[_gauge] = 0;\\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\\n emit DistributeReward(msg.sender, _gauge, _claimable);\\n }\\n }\\n\\n function distro() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute(uint start, uint finish) public {\\n for (uint x = start; x < finish; x++) {\\n distribute(gauges[pools[x]]);\\n }\\n }\\n\\n function distribute(address[] memory _gauges) external {\\n for (uint x = 0; x < _gauges.length; x++) {\\n distribute(_gauges[x]);\\n }\\n }\\n\\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2ff3fc2765dfa0c54870e428d3a2c625f413fb6e10ed7742e786ab4404aae6dc\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x61012060405260016011553480156200001757600080fd5b5060405162003656380380620036568339810160408190526200003a916200011c565b6001600160a01b03808516608081905290841660a05260408051637e062a3560e11b8152905163fc0c546a916004808201926020929091908290030181865afa1580156200008c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b2919062000179565b6001600160a01b0390811660c05291821660e0521661010052505060008054336001600160a01b03199182168117909255600180548216831790556002805490911690911790556200019e565b80516001600160a01b03811681146200011757600080fd5b919050565b600080600080608085870312156200013357600080fd5b6200013e85620000ff565b93506200014e60208601620000ff565b92506200015e60408601620000ff565b91506200016e60608601620000ff565b905092959194509250565b6000602082840312156200018c57600080fd5b6200019782620000ff565b9392505050565b60805160a05160c05160e051610100516133e062000276600039600081816103e701528181611c680152611ce60152600081816104d30152611d79015260008181610b9401528181610c0d01528181610edd01528181610f9901528181611acd01528181611b0601528181611b380152611e5a0152600081816106fc015261192401526000818161058c0152818161092b015281816109d701528181610c9a01528181611069015281816111ea0152818161131a015281816114d901528181611dab015281816125e501526129a801526133e06000f3fe608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea26469706673582212202ba017d0b62c0f1d47ae8bb31cfdd049608b388bc02e3c268f1b267d8dd357d564736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea26469706673582212202ba017d0b62c0f1d47ae8bb31cfdd049608b388bc02e3c268f1b267d8dd357d564736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 14322, + "contract": "contracts/Voter.sol:Voter", + "label": "minter", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 14324, + "contract": "contracts/Voter.sol:Voter", + "label": "governor", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 14326, + "contract": "contracts/Voter.sol:Voter", + "label": "emergencyCouncil", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 14328, + "contract": "contracts/Voter.sol:Voter", + "label": "totalWeight", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 14331, + "contract": "contracts/Voter.sol:Voter", + "label": "pools", + "offset": 0, + "slot": "4", + "type": "t_array(t_address)dyn_storage" + }, + { + "astId": 14335, + "contract": "contracts/Voter.sol:Voter", + "label": "gauges", + "offset": 0, + "slot": "5", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 14339, + "contract": "contracts/Voter.sol:Voter", + "label": "poolForGauge", + "offset": 0, + "slot": "6", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 14343, + "contract": "contracts/Voter.sol:Voter", + "label": "internal_bribes", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 14347, + "contract": "contracts/Voter.sol:Voter", + "label": "external_bribes", + "offset": 0, + "slot": "8", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 14351, + "contract": "contracts/Voter.sol:Voter", + "label": "weights", + "offset": 0, + "slot": "9", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 14357, + "contract": "contracts/Voter.sol:Voter", + "label": "votes", + "offset": 0, + "slot": "10", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))" + }, + { + "astId": 14362, + "contract": "contracts/Voter.sol:Voter", + "label": "poolVote", + "offset": 0, + "slot": "11", + "type": "t_mapping(t_uint256,t_array(t_address)dyn_storage)" + }, + { + "astId": 14366, + "contract": "contracts/Voter.sol:Voter", + "label": "usedWeights", + "offset": 0, + "slot": "12", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 14370, + "contract": "contracts/Voter.sol:Voter", + "label": "lastVoted", + "offset": 0, + "slot": "13", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 14374, + "contract": "contracts/Voter.sol:Voter", + "label": "isGauge", + "offset": 0, + "slot": "14", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 14378, + "contract": "contracts/Voter.sol:Voter", + "label": "isWhitelisted", + "offset": 0, + "slot": "15", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 14382, + "contract": "contracts/Voter.sol:Voter", + "label": "isAlive", + "offset": 0, + "slot": "16", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 14528, + "contract": "contracts/Voter.sol:Voter", + "label": "_unlocked", + "offset": 0, + "slot": "17", + "type": "t_uint256" + }, + { + "astId": 15620, + "contract": "contracts/Voter.sol:Voter", + "label": "index", + "offset": 0, + "slot": "18", + "type": "t_uint256" + }, + { + "astId": 15624, + "contract": "contracts/Voter.sol:Voter", + "label": "supplyIndex", + "offset": 0, + "slot": "19", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 15628, + "contract": "contracts/Voter.sol:Voter", + "label": "claimable", + "offset": 0, + "slot": "20", + "type": "t_mapping(t_address,t_uint256)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "base": "t_address", + "encoding": "dynamic_array", + "label": "address[]", + "numberOfBytes": "32" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_address)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_uint256,t_array(t_address)dyn_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => address[])", + "numberOfBytes": "32", + "value": "t_array(t_address)dyn_storage" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrum/VotingEscrow.json b/deployments/arbitrum/VotingEscrow.json new file mode 100644 index 00000000..b308be02 --- /dev/null +++ b/deployments/arbitrum/VotingEscrow.json @@ -0,0 +1,2339 @@ +{ + "address": "0x10Df81252069C1095F541FAca61646cb9Ae76703", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "token_addr", + "type": "address" + }, + { + "internalType": "address", + "name": "art_proxy", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "fromDelegate", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "toDelegate", + "type": "address" + } + ], + "name": "DelegateChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "DelegateVotesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "locktime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum VotingEscrow.DepositType", + "name": "deposit_type", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "ts", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "prevSupply", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "supply", + "type": "uint256" + } + ], + "name": "Supply", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "ts", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [], + "name": "DELEGATION_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DOMAIN_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_DELEGATES", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "abstain", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_approved", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "artProxy", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "attach", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "attachments", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_block", + "type": "uint256" + } + ], + "name": "balanceOfAtNFT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "balanceOfNFT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_t", + "type": "uint256" + } + ], + "name": "balanceOfNFTAt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "block_number", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkpoint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "name": "checkpoints", + "outputs": [ + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_lock_duration", + "type": "uint256" + } + ], + "name": "create_lock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_lock_duration", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + } + ], + "name": "create_lock_for", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + } + ], + "name": "delegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "delegateBySig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "delegates", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "deposit_for", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "detach", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "epoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "getPastTotalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "getPastVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "getPastVotesIndex", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "get_last_user_slope", + "outputs": [ + { + "internalType": "int128", + "name": "", + "type": "int128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "increase_amount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_lock_duration", + "type": "uint256" + } + ], + "name": "increase_unlock_time", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "isApprovedOrOwner", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "locked", + "outputs": [ + { + "internalType": "int128", + "name": "amount", + "type": "int128" + }, + { + "internalType": "uint256", + "name": "end", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "locked__end", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_from", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_to", + "type": "uint256" + } + ], + "name": "merge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "numCheckpoints", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "ownership_change", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "point_history", + "outputs": [ + { + "internalType": "int128", + "name": "bias", + "type": "int128" + }, + { + "internalType": "int128", + "name": "slope", + "type": "int128" + }, + { + "internalType": "uint256", + "name": "ts", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "blk", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "_approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_proxy", + "type": "address" + } + ], + "name": "setArtProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_team", + "type": "address" + } + ], + "name": "setTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_voter", + "type": "address" + } + ], + "name": "setVoter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "slope_changes", + "outputs": [ + { + "internalType": "int128", + "name": "", + "type": "int128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "supply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_interfaceID", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "team", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenIndex", + "type": "uint256" + } + ], + "name": "tokenOfOwnerByIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_block", + "type": "uint256" + } + ], + "name": "totalSupplyAt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "t", + "type": "uint256" + } + ], + "name": "totalSupplyAtT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "user_point_epoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "user_point_history", + "outputs": [ + { + "internalType": "int128", + "name": "bias", + "type": "int128" + }, + { + "internalType": "int128", + "name": "slope", + "type": "int128" + }, + { + "internalType": "uint256", + "name": "ts", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "blk", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_idx", + "type": "uint256" + } + ], + "name": "user_point_history__ts", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "voted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "voter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "voting", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x0d188c6284ab3f8819012287ed29c698d71269b7a82470a6dc166a8d66485061", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x10Df81252069C1095F541FAca61646cb9Ae76703", + "transactionIndex": 1, + "gasUsed": "30673850", + "logsBloom": "0x00000000000000000000000008000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000040000000000000000000000000008000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000010000102000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x0300bc4c5219d7cde2f65e67a4050d0df88e8cf53a3168d85b5211d4eb901d1a", + "transactionHash": "0x0d188c6284ab3f8819012287ed29c698d71269b7a82470a6dc166a8d66485061", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 53774090, + "transactionHash": "0x0d188c6284ab3f8819012287ed29c698d71269b7a82470a6dc166a8d66485061", + "address": "0x10Df81252069C1095F541FAca61646cb9Ae76703", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000010df81252069c1095f541faca61646cb9ae76703", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x0300bc4c5219d7cde2f65e67a4050d0df88e8cf53a3168d85b5211d4eb901d1a" + }, + { + "transactionIndex": 1, + "blockNumber": 53774090, + "transactionHash": "0x0d188c6284ab3f8819012287ed29c698d71269b7a82470a6dc166a8d66485061", + "address": "0x10Df81252069C1095F541FAca61646cb9Ae76703", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x00000000000000000000000010df81252069c1095f541faca61646cb9ae76703", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0x0300bc4c5219d7cde2f65e67a4050d0df88e8cf53a3168d85b5211d4eb901d1a" + } + ], + "blockNumber": 53774090, + "cumulativeGasUsed": "30673850", + "status": 1, + "byzantium": true + }, + "args": [ + "0xC33f7f83CbB021846Cb9c58f2d8E3df428dbC8C1", + "0x4b40D5E4401EC24673cc9d4799457a3B5827c581" + ], + "numDeployments": 1, + "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token_addr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"art_proxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromDelegate\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toDelegate\",\"type\":\"address\"}],\"name\":\"DelegateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"DelegateVotesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"locktime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum VotingEscrow.DepositType\",\"name\":\"deposit_type\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"prevSupply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"supply\",\"type\":\"uint256\"}],\"name\":\"Supply\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DELEGATION_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_DELEGATES\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"abstain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_approved\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"artProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"attach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"attachments\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"balanceOfAtNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_t\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFTAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"block_number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"checkpoints\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"create_lock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"create_lock_for\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"}],\"name\":\"delegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"delegateBySig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"}],\"name\":\"delegates\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"deposit_for\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"detach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastTotalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotesIndex\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"get_last_user_slope\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"increase_amount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"increase_unlock_time\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"isApprovedOrOwner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"locked\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"amount\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"locked__end\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_from\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_to\",\"type\":\"uint256\"}],\"name\":\"merge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"numCheckpoints\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ownership_change\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_proxy\",\"type\":\"address\"}],\"name\":\"setArtProxy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voter\",\"type\":\"address\"}],\"name\":\"setVoter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"slope_changes\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenIndex\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"t\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAtT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_idx\",\"type\":\"uint256\"}],\"name\":\"user_point_history__ts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"voted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"voting\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\",\"details\":\"Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\",\"kind\":\"dev\",\"methods\":{\"approve(address,uint256)\":{\"details\":\"Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address. Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner. Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP) Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"Address to be approved for the given NFT ID.\",\"_tokenId\":\"ID of the token to be approved.\"}},\"balanceOf(address)\":{\"details\":\"Returns the number of NFTs owned by `_owner`. Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\",\"params\":{\"_owner\":\"Address for whom to query the balance.\"}},\"constructor\":{\"params\":{\"token_addr\":\"`VELO` token address\"}},\"create_lock(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_value\":\"Amount to deposit\"}},\"create_lock_for(uint256,uint256,address)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_to\":\"Address to deposit\",\"_value\":\"Amount to deposit\"}},\"delegate(address)\":{\"params\":{\"delegatee\":\"The address to delegate votes to\"}},\"delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Delegates votes from signer to `delegatee`.\"},\"deposit_for(uint256,uint256)\":{\"details\":\"Anyone (even a smart contract) can deposit for someone else, but cannot extend their locktime and deposit for a brand new user\",\"params\":{\"_tokenId\":\"lock NFT\",\"_value\":\"Amount to add to user's lock\"}},\"getApproved(uint256)\":{\"details\":\"Get the approved address for a single NFT.\",\"params\":{\"_tokenId\":\"ID of the NFT to query the approval of.\"}},\"getVotes(address)\":{\"params\":{\"account\":\"The address to get votes balance\"},\"returns\":{\"_0\":\"The number of current votes for `account`\"}},\"get_last_user_slope(uint256)\":{\"params\":{\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Value of the slope\"}},\"increase_amount(uint256,uint256)\":{\"params\":{\"_value\":\"Amount of tokens to deposit and add to the lock\"}},\"increase_unlock_time(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"New number of seconds until tokens unlock\"}},\"isApprovedForAll(address,address)\":{\"details\":\"Checks if `_operator` is an approved operator for `_owner`.\",\"params\":{\"_operator\":\"The address that acts on behalf of the owner.\",\"_owner\":\"The address that owns the NFTs.\"}},\"locked__end(uint256)\":{\"params\":{\"_tokenId\":\"User NFT\"},\"returns\":{\"_0\":\"Epoch time of the lock end\"}},\"ownerOf(uint256)\":{\"details\":\"Returns the address of the owner of the NFT.\",\"params\":{\"_tokenId\":\"The identifier for an NFT.\"}},\"safeTransferFrom(address,address,uint256)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"safeTransferFrom(address,address,uint256,bytes)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_data\":\"Additional data with no specified format, sent in call to `_to`.\",\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"details\":\"Enables or disables approval for a third party (\\\"operator\\\") to manage all of `msg.sender`'s assets. It also emits the ApprovalForAll event. Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"True if the operators is approved, false to revoke approval.\",\"_operator\":\"Address to add to the set of authorized operators.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Interface identification is specified in ERC-165.\",\"params\":{\"_interfaceID\":\"Id of the interface\"}},\"tokenOfOwnerByIndex(address,uint256)\":{\"details\":\"Get token by index\"},\"tokenURI(uint256)\":{\"details\":\"Returns current token URI metadata\",\"params\":{\"_tokenId\":\"Token ID to fetch URI for.\"}},\"totalSupplyAt(uint256)\":{\"params\":{\"_block\":\"Block to calculate the total voting power at\"},\"returns\":{\"_0\":\"Total voting power at `_block`\"}},\"totalSupplyAtT(uint256)\":{\"details\":\"Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\",\"returns\":{\"_0\":\"Total voting power\"}},\"transferFrom(address,address,uint256)\":{\"details\":\"Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"user_point_history__ts(uint256,uint256)\":{\"params\":{\"_idx\":\"User epoch number\",\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Epoch time of the checkpoint\"}},\"withdraw(uint256)\":{\"details\":\"Only possible if the lock has expired\"}},\"stateVariables\":{\"ERC165_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC165\"},\"ERC721_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721\"},\"ERC721_METADATA_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721Metadata\"},\"_not_entered\":{\"details\":\"reentrancy guard\"},\"idToApprovals\":{\"details\":\"Mapping from NFT ID to approved address.\"},\"idToOwner\":{\"details\":\"Mapping from NFT ID to the address that owns it.\"},\"name\":{\"details\":\"Returns the token collection name.\"},\"ownerToNFTokenCount\":{\"details\":\"Mapping from owner address to count of his tokens.\"},\"ownerToNFTokenIdList\":{\"details\":\"Mapping from owner address to mapping of index to tokenIds\"},\"ownerToOperators\":{\"details\":\"Mapping from owner address to mapping of operator addresses.\"},\"supportedInterfaces\":{\"details\":\"Mapping of interface id to bool about whether or not it's supported\"},\"symbol\":{\"details\":\"Returns the token collection symbol.\"},\"tokenId\":{\"details\":\"Current count of token\"},\"tokenToOwnerIndex\":{\"details\":\"Mapping from NFT ID to index of owner\"}},\"title\":\"Voting Escrow\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DELEGATION_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the delegation struct used by the contract\"},\"DOMAIN_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the contract's domain\"},\"checkpoint()\":{\"notice\":\"Record global data to checkpoint\"},\"checkpoints(address,uint32)\":{\"notice\":\"A record of delegated token checkpoints for each account, by index\"},\"constructor\":{\"notice\":\"Contract constructor\"},\"create_lock(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\"},\"create_lock_for(uint256,uint256,address)\":{\"notice\":\"Deposit `_value` tokens for `_to` and lock for `_lock_duration`\"},\"delegate(address)\":{\"notice\":\"Delegate votes from `msg.sender` to `delegatee`\"},\"delegates(address)\":{\"notice\":\"Overrides the standard `Comp.sol` delegates mapping to return the delegator's own address if they haven't delegated. This avoids having to delegate to oneself.\"},\"deposit_for(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `_tokenId` and add to the lock\"},\"getVotes(address)\":{\"notice\":\"Gets the current votes balance for `account`\"},\"get_last_user_slope(uint256)\":{\"notice\":\"Get the most recently recorded rate of voting power decrease for `_tokenId`\"},\"increase_amount(uint256,uint256)\":{\"notice\":\"Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\"},\"increase_unlock_time(uint256,uint256)\":{\"notice\":\"Extend the unlock time for `_tokenId`\"},\"locked__end(uint256)\":{\"notice\":\"Get timestamp when `_tokenId`'s lock finishes\"},\"nonces(address)\":{\"notice\":\"A record of states for signing / validating signatures\"},\"numCheckpoints(address)\":{\"notice\":\"The number of checkpoints for each account\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"This works even if sender doesn't own any tokens at the time.\"},\"totalSupplyAt(uint256)\":{\"notice\":\"Calculate total voting power at some point in the past\"},\"totalSupplyAtT(uint256)\":{\"notice\":\"Calculate total voting power\"},\"transferFrom(address,address,uint256)\":{\"notice\":\"The caller is responsible to confirm that `_to` is capable of receiving NFTs or else they maybe be permanently lost.\"},\"user_point_history__ts(uint256,uint256)\":{\"notice\":\"Get the timestamp for checkpoint `_idx` for `_tokenId`\"},\"withdraw(uint256)\":{\"notice\":\"Withdraw all tokens for `_tokenId`\"}},\"notice\":\"veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFTVotes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VotingEscrow.sol\":\"VotingEscrow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VotingEscrow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IERC721, IERC721Metadata} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {IERC721Receiver} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {IERC20} from \\\"contracts/interfaces/IERC20.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\nimport {IVotingEscrow} from \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/// @title Voting Escrow\\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\\n enum DepositType {\\n DEPOSIT_FOR_TYPE,\\n CREATE_LOCK_TYPE,\\n INCREASE_LOCK_AMOUNT,\\n INCREASE_UNLOCK_TIME,\\n MERGE_TYPE\\n }\\n\\n struct LockedBalance {\\n int128 amount;\\n uint end;\\n }\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint ts;\\n uint blk; // block\\n }\\n /* We cannot really do block numbers per se b/c slope is per time, not per block\\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\\n * What we can do is to extrapolate ***At functions */\\n\\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\\n struct Checkpoint {\\n uint timestamp;\\n uint[] tokenIds;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Deposit(\\n address indexed provider,\\n uint tokenId,\\n uint value,\\n uint indexed locktime,\\n DepositType deposit_type,\\n uint ts\\n );\\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\\n event Supply(uint prevSupply, uint supply);\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n address public immutable token;\\n address public voter;\\n address public team;\\n address public artProxy;\\n\\n mapping(uint => Point) public point_history; // epoch -> unsigned point\\n\\n /// @dev Mapping of interface id to bool about whether or not it's supported\\n mapping(bytes4 => bool) internal supportedInterfaces;\\n\\n /// @dev ERC165 interface ID of ERC165\\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\\n\\n /// @dev ERC165 interface ID of ERC721\\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\\n\\n /// @dev ERC165 interface ID of ERC721Metadata\\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\\n\\n /// @dev Current count of token\\n uint internal tokenId;\\n\\n /// @notice Contract constructor\\n /// @param token_addr `VELO` token address\\n constructor(address token_addr, address art_proxy) {\\n token = token_addr;\\n voter = msg.sender;\\n team = msg.sender;\\n artProxy = art_proxy;\\n\\n point_history[0].blk = block.number;\\n point_history[0].ts = block.timestamp;\\n\\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\\n\\n // mint-ish\\n emit Transfer(address(0), address(this), tokenId);\\n // burn-ish\\n emit Transfer(address(this), address(0), tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n MODIFIERS\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev reentrancy guard\\n uint8 internal constant _not_entered = 1;\\n uint8 internal constant _entered = 2;\\n uint8 internal _entered_state = 1;\\n modifier nonreentrant() {\\n require(_entered_state == _not_entered);\\n _entered_state = _entered;\\n _;\\n _entered_state = _not_entered;\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string constant public name = \\\"veNFT\\\";\\n string constant public symbol = \\\"veNFT\\\";\\n string constant public version = \\\"1.0.0\\\";\\n uint8 constant public decimals = 18;\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team);\\n team = _team;\\n }\\n\\n function setArtProxy(address _proxy) external {\\n require(msg.sender == team);\\n artProxy = _proxy;\\n }\\n\\n /// @dev Returns current token URI metadata\\n /// @param _tokenId Token ID to fetch URI for.\\n function tokenURI(uint _tokenId) external view returns (string memory) {\\n require(idToOwner[_tokenId] != address(0), \\\"Query for nonexistent token\\\");\\n LockedBalance memory _locked = locked[_tokenId];\\n return IVeArtProxy(artProxy)._tokenURI(\\n _tokenId,\\n _balanceOfNFT(_tokenId, block.timestamp),\\n _locked.end,\\n uint(int256(_locked.amount))\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 BALANCE/OWNER STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to the address that owns it.\\n mapping(uint => address) internal idToOwner;\\n\\n /// @dev Mapping from owner address to count of his tokens.\\n mapping(address => uint) internal ownerToNFTokenCount;\\n\\n /// @dev Returns the address of the owner of the NFT.\\n /// @param _tokenId The identifier for an NFT.\\n function ownerOf(uint _tokenId) public view returns (address) {\\n return idToOwner[_tokenId];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function _balance(address _owner) internal view returns (uint) {\\n return ownerToNFTokenCount[_owner];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function balanceOf(address _owner) external view returns (uint) {\\n return _balance(_owner);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 APPROVAL STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to approved address.\\n mapping(uint => address) internal idToApprovals;\\n\\n /// @dev Mapping from owner address to mapping of operator addresses.\\n mapping(address => mapping(address => bool)) internal ownerToOperators;\\n\\n mapping(uint => uint) public ownership_change;\\n\\n /// @dev Get the approved address for a single NFT.\\n /// @param _tokenId ID of the NFT to query the approval of.\\n function getApproved(uint _tokenId) external view returns (address) {\\n return idToApprovals[_tokenId];\\n }\\n\\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\\n /// @param _owner The address that owns the NFTs.\\n /// @param _operator The address that acts on behalf of the owner.\\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\\n return (ownerToOperators[_owner])[_operator];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\\n /// @param _approved Address to be approved for the given NFT ID.\\n /// @param _tokenId ID of the token to be approved.\\n function approve(address _approved, uint _tokenId) public {\\n address owner = idToOwner[_tokenId];\\n // Throws if `_tokenId` is not a valid NFT\\n require(owner != address(0));\\n // Throws if `_approved` is the current owner\\n require(_approved != owner);\\n // Check requirements\\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\\n require(senderIsOwner || senderIsApprovedForAll);\\n // Set the approval\\n idToApprovals[_tokenId] = _approved;\\n emit Approval(owner, _approved, _tokenId);\\n }\\n\\n /// @dev Enables or disables approval for a third party (\\\"operator\\\") to manage all of\\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\\n /// @notice This works even if sender doesn't own any tokens at the time.\\n /// @param _operator Address to add to the set of authorized operators.\\n /// @param _approved True if the operators is approved, false to revoke approval.\\n function setApprovalForAll(address _operator, bool _approved) external {\\n // Throws if `_operator` is the `msg.sender`\\n assert(_operator != msg.sender);\\n ownerToOperators[msg.sender][_operator] = _approved;\\n emit ApprovalForAll(msg.sender, _operator, _approved);\\n }\\n\\n /* TRANSFER FUNCTIONS */\\n /// @dev Clear an approval of a given address\\n /// Throws if `_owner` is not the current owner.\\n function _clearApproval(address _owner, uint _tokenId) internal {\\n // Throws if `_owner` is not the current owner\\n assert(idToOwner[_tokenId] == _owner);\\n if (idToApprovals[_tokenId] != address(0)) {\\n // Reset approvals\\n idToApprovals[_tokenId] = address(0);\\n }\\n }\\n\\n /// @dev Returns whether the given spender can transfer a given token ID\\n /// @param _spender address of the spender to query\\n /// @param _tokenId uint ID of the token to be transferred\\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\\n address owner = idToOwner[_tokenId];\\n bool spenderIsOwner = owner == _spender;\\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\\n }\\n\\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\\n return _isApprovedOrOwner(_spender, _tokenId);\\n }\\n\\n /// @dev Exeute transfer of a NFT.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_tokenId` is not a valid NFT.\\n function _transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n address _sender\\n ) internal {\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n // Check requirements\\n require(_isApprovedOrOwner(_sender, _tokenId));\\n // Clear approval. Throws if `_from` is not the current owner\\n _clearApproval(_from, _tokenId);\\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\\n _removeTokenFrom(_from, _tokenId);\\n // auto re-delegate\\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\\n // Add NFT\\n _addTokenTo(_to, _tokenId);\\n // Set the block of ownership transfer (for Flash NFT protection)\\n ownership_change[_tokenId] = block.number;\\n // Log the transfer\\n emit Transfer(_from, _to, _tokenId);\\n }\\n\\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\\n /// they maybe be permanently lost.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n safeTransferFrom(_from, _to, _tokenId, \\\"\\\");\\n }\\n\\n function _isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n uint size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n /// @param _data Additional data with no specified format, sent in call to `_to`.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n bytes memory _data\\n ) public {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n\\n if (_isContract(_to)) {\\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\\n revert(\\\"ERC721: ERC721Receiver rejected tokens\\\");\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert('ERC721: transfer to non ERC721Receiver implementer');\\n } else {\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC165 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Interface identification is specified in ERC-165.\\n /// @param _interfaceID Id of the interface\\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\\n return supportedInterfaces[_interfaceID];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from owner address to mapping of index to tokenIds\\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\\n\\n /// @dev Mapping from NFT ID to index of owner\\n mapping(uint => uint) internal tokenToOwnerIndex;\\n\\n /// @dev Get token by index\\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\\n return ownerToNFTokenIdList[_owner][_tokenIndex];\\n }\\n\\n /// @dev Add a NFT to an index mapping to a given address\\n /// @param _to address of the receiver\\n /// @param _tokenId uint ID Of the token to be added\\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\\n uint current_count = _balance(_to);\\n\\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\\n tokenToOwnerIndex[_tokenId] = current_count;\\n }\\n\\n /// @dev Add a NFT to a given address\\n /// Throws if `_tokenId` is owned by someone.\\n function _addTokenTo(address _to, uint _tokenId) internal {\\n // Throws if `_tokenId` is owned by someone\\n assert(idToOwner[_tokenId] == address(0));\\n // Change the owner\\n idToOwner[_tokenId] = _to;\\n // Update owner token index tracking\\n _addTokenToOwnerList(_to, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_to] += 1;\\n }\\n\\n /// @dev Function to mint tokens\\n /// Throws if `_to` is zero address.\\n /// Throws if `_tokenId` is owned by someone.\\n /// @param _to The address that will receive the minted tokens.\\n /// @param _tokenId The token id to mint.\\n /// @return A boolean that indicates if the operation was successful.\\n function _mint(address _to, uint _tokenId) internal returns (bool) {\\n // Throws if `_to` is zero address\\n assert(_to != address(0));\\n // checkpoint for gov\\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\\n // Add NFT. Throws if `_tokenId` is owned by someone\\n _addTokenTo(_to, _tokenId);\\n emit Transfer(address(0), _to, _tokenId);\\n return true;\\n }\\n\\n /// @dev Remove a NFT from an index mapping to a given address\\n /// @param _from address of the sender\\n /// @param _tokenId uint ID Of the token to be removed\\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\\n // Delete\\n uint current_count = _balance(_from) - 1;\\n uint current_index = tokenToOwnerIndex[_tokenId];\\n\\n if (current_count == current_index) {\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n } else {\\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\\n\\n // Add\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[lastTokenId] = current_index;\\n\\n // Delete\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n }\\n }\\n\\n /// @dev Remove a NFT from a given address\\n /// Throws if `_from` is not the current owner.\\n function _removeTokenFrom(address _from, uint _tokenId) internal {\\n // Throws if `_from` is not the current owner\\n assert(idToOwner[_tokenId] == _from);\\n // Change the owner\\n idToOwner[_tokenId] = address(0);\\n // Update owner token index tracking\\n _removeTokenFromOwnerList(_from, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_from] -= 1;\\n }\\n\\n function _burn(uint _tokenId) internal {\\n require(_isApprovedOrOwner(msg.sender, _tokenId), \\\"caller is not owner nor approved\\\");\\n\\n address owner = ownerOf(_tokenId);\\n\\n // Clear approval\\n approve(address(0), _tokenId);\\n // checkpoint for gov\\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\\n // Remove token\\n _removeTokenFrom(msg.sender, _tokenId);\\n emit Transfer(owner, address(0), _tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public user_point_epoch;\\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\\n mapping(uint => LockedBalance) public locked;\\n uint public epoch;\\n mapping(uint => int128) public slope_changes; // time -> signed slope change\\n uint public supply;\\n\\n uint internal constant WEEK = 1 weeks;\\n uint internal constant MAXTIME = 4 * 365 * 86400;\\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\\n uint internal constant MULTIPLIER = 1 ether;\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @return Value of the slope\\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\\n uint uepoch = user_point_epoch[_tokenId];\\n return user_point_history[_tokenId][uepoch].slope;\\n }\\n\\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @param _idx User epoch number\\n /// @return Epoch time of the checkpoint\\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\\n return user_point_history[_tokenId][_idx].ts;\\n }\\n\\n /// @notice Get timestamp when `_tokenId`'s lock finishes\\n /// @param _tokenId User NFT\\n /// @return Epoch time of the lock end\\n function locked__end(uint _tokenId) external view returns (uint) {\\n return locked[_tokenId].end;\\n }\\n\\n /// @notice Record global and per-user data to checkpoint\\n /// @param _tokenId NFT token ID. No user checkpoint if 0\\n /// @param old_locked Pevious locked amount / end lock time for the user\\n /// @param new_locked New locked amount / end lock time for the user\\n function _checkpoint(\\n uint _tokenId,\\n LockedBalance memory old_locked,\\n LockedBalance memory new_locked\\n ) internal {\\n Point memory u_old;\\n Point memory u_new;\\n int128 old_dslope = 0;\\n int128 new_dslope = 0;\\n uint _epoch = epoch;\\n\\n if (_tokenId != 0) {\\n // Calculate slopes and biases\\n // Kept at zero when they have to\\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\\n u_old.slope = old_locked.amount / iMAXTIME;\\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\\n }\\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\\n u_new.slope = new_locked.amount / iMAXTIME;\\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\\n }\\n\\n // Read values of scheduled changes in the slope\\n // old_locked.end can be in the past and in the future\\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\\n old_dslope = slope_changes[old_locked.end];\\n if (new_locked.end != 0) {\\n if (new_locked.end == old_locked.end) {\\n new_dslope = old_dslope;\\n } else {\\n new_dslope = slope_changes[new_locked.end];\\n }\\n }\\n }\\n\\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\\n if (_epoch > 0) {\\n last_point = point_history[_epoch];\\n }\\n uint last_checkpoint = last_point.ts;\\n // initial_last_point is used for extrapolation to calculate block number\\n // (approximately, for *At methods) and save them\\n // as we cannot figure that out exactly from inside the contract\\n Point memory initial_last_point = last_point;\\n uint block_slope = 0; // dblock/dt\\n if (block.timestamp > last_point.ts) {\\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\\n }\\n // If last point is already recorded in this block, slope=0\\n // But that's ok b/c we know the block in such case\\n\\n // Go over weeks to fill history and calculate what the current point is\\n {\\n uint t_i = (last_checkpoint / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n // Hopefully it won't happen that this won't get used in 5 years!\\n // If it does, users will be able to withdraw but vote weight will be broken\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > block.timestamp) {\\n t_i = block.timestamp;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\\n last_point.slope += d_slope;\\n if (last_point.bias < 0) {\\n // This can happen\\n last_point.bias = 0;\\n }\\n if (last_point.slope < 0) {\\n // This cannot happen - just in case\\n last_point.slope = 0;\\n }\\n last_checkpoint = t_i;\\n last_point.ts = t_i;\\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\\n _epoch += 1;\\n if (t_i == block.timestamp) {\\n last_point.blk = block.number;\\n break;\\n } else {\\n point_history[_epoch] = last_point;\\n }\\n }\\n }\\n\\n epoch = _epoch;\\n // Now point_history is filled until t=now\\n\\n if (_tokenId != 0) {\\n // If last point was in this block, the slope change has been applied already\\n // But in such case we have 0 slope(s)\\n last_point.slope += (u_new.slope - u_old.slope);\\n last_point.bias += (u_new.bias - u_old.bias);\\n if (last_point.slope < 0) {\\n last_point.slope = 0;\\n }\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n }\\n\\n // Record the changed point into history\\n point_history[_epoch] = last_point;\\n\\n if (_tokenId != 0) {\\n // Schedule the slope changes (slope is going down)\\n // We subtract new_user_slope from [new_locked.end]\\n // and add old_user_slope to [old_locked.end]\\n if (old_locked.end > block.timestamp) {\\n // old_dslope was - u_old.slope, so we cancel that\\n old_dslope += u_old.slope;\\n if (new_locked.end == old_locked.end) {\\n old_dslope -= u_new.slope; // It was a new deposit, not extension\\n }\\n slope_changes[old_locked.end] = old_dslope;\\n }\\n\\n if (new_locked.end > block.timestamp) {\\n if (new_locked.end > old_locked.end) {\\n new_dslope -= u_new.slope; // old slope disappeared at this point\\n slope_changes[new_locked.end] = new_dslope;\\n }\\n // else: we recorded it already in old_dslope\\n }\\n // Now handle user history\\n uint user_epoch = user_point_epoch[_tokenId] + 1;\\n\\n user_point_epoch[_tokenId] = user_epoch;\\n u_new.ts = block.timestamp;\\n u_new.blk = block.number;\\n user_point_history[_tokenId][user_epoch] = u_new;\\n }\\n }\\n\\n /// @notice Deposit and lock tokens for a user\\n /// @param _tokenId NFT that holds lock\\n /// @param _value Amount to deposit\\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\\n /// @param locked_balance Previous locked amount / timestamp\\n /// @param deposit_type The type of deposit\\n function _deposit_for(\\n uint _tokenId,\\n uint _value,\\n uint unlock_time,\\n LockedBalance memory locked_balance,\\n DepositType deposit_type\\n ) internal {\\n LockedBalance memory _locked = locked_balance;\\n uint supply_before = supply;\\n\\n supply = supply_before + _value;\\n LockedBalance memory old_locked;\\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\\n // Adding to existing lock, or if a lock is expired - creating a new one\\n _locked.amount += int128(int256(_value));\\n if (unlock_time != 0) {\\n _locked.end = unlock_time;\\n }\\n locked[_tokenId] = _locked;\\n\\n // Possibilities:\\n // Both old_locked.end could be current or expired (>/< block.timestamp)\\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\\n // _locked.end > block.timestamp (always)\\n _checkpoint(_tokenId, old_locked, _locked);\\n\\n address from = msg.sender;\\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\\n assert(IERC20(token).transferFrom(from, address(this), _value));\\n }\\n\\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\\n emit Supply(supply_before, supply_before + _value);\\n }\\n\\n function block_number() external view returns (uint) {\\n return block.number;\\n }\\n\\n /// @notice Record global data to checkpoint\\n function checkpoint() external {\\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\\n }\\n\\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\\n /// cannot extend their locktime and deposit for a brand new user\\n /// @param _tokenId lock NFT\\n /// @param _value Amount to add to user's lock\\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n require(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_value > 0); // dev: need non-zero value\\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n ++tokenId;\\n uint _tokenId = tokenId;\\n _mint(_to, _tokenId);\\n\\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\\n return _tokenId;\\n }\\n\\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, msg.sender);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, _to);\\n }\\n\\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\\n /// @param _value Amount of tokens to deposit and add to the lock\\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n assert(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\\n }\\n\\n /// @notice Extend the unlock time for `_tokenId`\\n /// @param _lock_duration New number of seconds until tokens unlock\\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_locked.end > block.timestamp, 'Lock expired');\\n require(_locked.amount > 0, 'Nothing is locked');\\n require(unlock_time > _locked.end, 'Can only increase lock duration');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\\n }\\n\\n /// @notice Withdraw all tokens for `_tokenId`\\n /// @dev Only possible if the lock has expired\\n function withdraw(uint _tokenId) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n require(block.timestamp >= _locked.end, \\\"The lock didn't expire\\\");\\n uint value = uint(int256(_locked.amount));\\n\\n locked[_tokenId] = LockedBalance(0,0);\\n uint supply_before = supply;\\n supply = supply_before - value;\\n\\n // old_locked can have either expired <= timestamp or zero end\\n // _locked has only 0 end\\n // Both can have >= 0 amount\\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\\n\\n assert(IERC20(token).transfer(msg.sender, value));\\n\\n // Burn the NFT\\n _burn(_tokenId);\\n\\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\\n emit Supply(supply_before, supply_before - value);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\\n // They measure the weights for the purpose of voting, so they don't represent\\n // real coins.\\n\\n /// @notice Binary search to estimate timestamp for block number\\n /// @param _block Block to find\\n /// @param max_epoch Don't go beyond this epoch\\n /// @return Approximate timestamp for block\\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\\n // Binary search\\n uint _min = 0;\\n uint _max = max_epoch;\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (point_history[_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n /// @notice Get the current voting power for `_tokenId`\\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\\n /// @param _tokenId NFT for lock\\n /// @param _t Epoch time to return voting power at\\n /// @return User voting power\\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\\n uint _epoch = user_point_epoch[_tokenId];\\n if (_epoch == 0) {\\n return 0;\\n } else {\\n Point memory last_point = user_point_history[_tokenId][_epoch];\\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(int256(last_point.bias));\\n }\\n }\\n\\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\\n if (ownership_change[_tokenId] == block.number) return 0;\\n return _balanceOfNFT(_tokenId, block.timestamp);\\n }\\n\\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\\n return _balanceOfNFT(_tokenId, _t);\\n }\\n\\n /// @notice Measure voting power of `_tokenId` at block height `_block`\\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\\n /// @param _tokenId User's wallet NFT\\n /// @param _block Block to calculate the voting power at\\n /// @return Voting power\\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\\n // Copying and pasting totalSupply code because Vyper cannot pass by\\n // reference yet\\n assert(_block <= block.number);\\n\\n // Binary search\\n uint _min = 0;\\n uint _max = user_point_epoch[_tokenId];\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (user_point_history[_tokenId][_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n\\n Point memory upoint = user_point_history[_tokenId][_min];\\n\\n uint max_epoch = epoch;\\n uint _epoch = _find_block_epoch(_block, max_epoch);\\n Point memory point_0 = point_history[_epoch];\\n uint d_block = 0;\\n uint d_t = 0;\\n if (_epoch < max_epoch) {\\n Point memory point_1 = point_history[_epoch + 1];\\n d_block = point_1.blk - point_0.blk;\\n d_t = point_1.ts - point_0.ts;\\n } else {\\n d_block = block.number - point_0.blk;\\n d_t = block.timestamp - point_0.ts;\\n }\\n uint block_time = point_0.ts;\\n if (d_block != 0) {\\n block_time += (d_t * (_block - point_0.blk)) / d_block;\\n }\\n\\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\\n if (upoint.bias >= 0) {\\n return uint(uint128(upoint.bias));\\n } else {\\n return 0;\\n }\\n }\\n\\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\\n return _balanceOfAtNFT(_tokenId, _block);\\n }\\n\\n /// @notice Calculate total voting power at some point in the past\\n /// @param _block Block to calculate the total voting power at\\n /// @return Total voting power at `_block`\\n function totalSupplyAt(uint _block) external view returns (uint) {\\n assert(_block <= block.number);\\n uint _epoch = epoch;\\n uint target_epoch = _find_block_epoch(_block, _epoch);\\n\\n Point memory point = point_history[target_epoch];\\n uint dt = 0;\\n if (target_epoch < _epoch) {\\n Point memory point_next = point_history[target_epoch + 1];\\n if (point.blk != point_next.blk) {\\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\\n }\\n } else {\\n if (point.blk != block.number) {\\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\\n }\\n }\\n // Now dt contains info on how far are we beyond point\\n return _supply_at(point, point.ts + dt);\\n }\\n /// @notice Calculate total voting power at some point in the past\\n /// @param point The point (bias/slope) to start search from\\n /// @param t Time to calculate the total voting power at\\n /// @return Total voting power at that time\\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\\n Point memory last_point = point;\\n uint t_i = (last_point.ts / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > t) {\\n t_i = t;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\\n if (t_i == t) {\\n break;\\n }\\n last_point.slope += d_slope;\\n last_point.ts = t_i;\\n }\\n\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(uint128(last_point.bias));\\n }\\n\\n function totalSupply() external view returns (uint) {\\n return totalSupplyAtT(block.timestamp);\\n }\\n\\n /// @notice Calculate total voting power\\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\\n /// @return Total voting power\\n function totalSupplyAtT(uint t) public view returns (uint) {\\n uint _epoch = epoch;\\n Point memory last_point = point_history[_epoch];\\n return _supply_at(last_point, t);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public attachments;\\n mapping(uint => bool) public voted;\\n\\n function setVoter(address _voter) external {\\n require(msg.sender == voter);\\n voter = _voter;\\n }\\n\\n function voting(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = true;\\n }\\n\\n function abstain(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = false;\\n }\\n\\n function attach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] + 1;\\n }\\n\\n function detach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] - 1;\\n }\\n\\n function merge(uint _from, uint _to) external {\\n require(attachments[_from] == 0 && !voted[_from], \\\"attached\\\");\\n require(_from != _to);\\n require(_isApprovedOrOwner(msg.sender, _from));\\n require(_isApprovedOrOwner(msg.sender, _to));\\n\\n LockedBalance memory _locked0 = locked[_from];\\n LockedBalance memory _locked1 = locked[_to];\\n uint value0 = uint(int256(_locked0.amount));\\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\\n\\n locked[_from] = LockedBalance(0, 0);\\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\\n _burn(_from);\\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of each accounts delegate\\n mapping(address => address) private _delegates;\\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\\n\\n /// @notice A record of delegated token checkpoints for each account, by index\\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint32) public numCheckpoints;\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping(address => uint) public nonces;\\n\\n /**\\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\\n * the delegator's own address if they haven't delegated.\\n * This avoids having to delegate to oneself.\\n */\\n function delegates(address delegator) public view returns (address) {\\n address current = _delegates[delegator];\\n return current == address(0) ? delegator : current;\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getVotes(address account) external view returns (uint) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n votes = votes + _balanceOfNFT(tId, block.timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint storage cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPastVotes(address account, uint timestamp)\\n public\\n view\\n returns (uint)\\n {\\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\\n // Sum votes\\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n // Use the provided input timestamp here to get the right decay\\n votes = votes + _balanceOfNFT(tId, timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\\n return totalSupplyAtT(timestamp);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _moveTokenDelegates(\\n address srcRep,\\n address dstRep,\\n uint _tokenId\\n ) internal {\\n if (srcRep != dstRep && _tokenId > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except _tokenId\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (tId != _tokenId) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n // All the same plus _tokenId\\n require(\\n dstRepOld.length + 1 <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n dstRepNew.push(_tokenId);\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _findWhatCheckpointToWrite(address account)\\n internal\\n view\\n returns (uint32)\\n {\\n uint _timestamp = block.timestamp;\\n uint32 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n return _nCheckPoints - 1;\\n } else {\\n return _nCheckPoints;\\n }\\n }\\n\\n function _moveAllDelegates(\\n address owner,\\n address srcRep,\\n address dstRep\\n ) internal {\\n // You can only redelegate what you own\\n if (srcRep != dstRep) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except what owner owns\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (idToOwner[tId] != owner) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n uint ownerTokenCount = ownerToNFTokenCount[owner];\\n require(\\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n // All the same\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n // Plus all that's owned\\n for (uint i = 0; i < ownerTokenCount; i++) {\\n uint tId = ownerToNFTokenIdList[owner][i];\\n dstRepNew.push(tId);\\n }\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\\n address currentDelegate = delegates(delegator);\\n\\n _delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n _moveAllDelegates(delegator, currentDelegate, delegatee);\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n if (delegatee == address(0)) delegatee = msg.sender;\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n function delegateBySig(\\n address delegatee,\\n uint nonce,\\n uint expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public {\\n bytes32 domainSeparator = keccak256(\\n abi.encode(\\n DOMAIN_TYPEHASH,\\n keccak256(bytes(name)),\\n keccak256(bytes(version)),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 structHash = keccak256(\\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash)\\n );\\n address signatory = ecrecover(digest, v, r, s);\\n require(\\n signatory != address(0),\\n \\\"VotingEscrow::delegateBySig: invalid signature\\\"\\n );\\n require(\\n nonce == nonces[signatory]++,\\n \\\"VotingEscrow::delegateBySig: invalid nonce\\\"\\n );\\n require(\\n block.timestamp <= expiry,\\n \\\"VotingEscrow::delegateBySig: signature expired\\\"\\n );\\n return _delegate(signatory, delegatee);\\n }\\n}\\n\",\"keccak256\":\"0x37e5ee306472a946a665be22bc1d370d566a575a1fac84f72f97b0575571d40d\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x41bbb2c41036ca64b2f6c9e973e8cfaa113ebc42af86702cd0d267f915a7e886\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a06040526006805460ff191660011790553480156200001e57600080fd5b5060405162004a1c38038062004a1c8339810160408190526200004191620001b8565b6001600160a01b0382811660805260008054336001600160a01b031991821681178355600180548316909117815560028054909216938516939093179055437f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f0155427f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f005560046020527f9fe05126d2d9ecf60592e254dead906a4b2e492f36cca727682c38e9008c6ac1805460ff1990811684179091557f4267c0a6fd96b7a87f183ee8744f24d011423cd0e0142b3f563f183d8d9a456b8054821684179055635b5e139f60e01b82527e24030bcf4927897dffe721c2d8dda4bfd8910861687c42b03a463b43b04147805490911690921790915560055460405190913091600080516020620049fc833981519152908290a46005546040516000903090600080516020620049fc833981519152908390a45050620001f0565b80516001600160a01b0381168114620001b357600080fd5b919050565b60008060408385031215620001cc57600080fd5b620001d7836200019b565b9150620001e7602084016200019b565b90509250929050565b6080516147e26200021a60003960008181610b220152818161101801526133b501526147e26000f3fe608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea2646970667358221220245dd4da7f4eb9a32bfed7d913c4bc4316ce8585e535cd4e280eb72cdc5dab1c64736f6c634300080d0033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea2646970667358221220245dd4da7f4eb9a32bfed7d913c4bc4316ce8585e535cd4e280eb72cdc5dab1c64736f6c634300080d0033", + "devdoc": { + "author": "Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)", + "details": "Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).", + "kind": "dev", + "methods": { + "approve(address,uint256)": { + "details": "Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address. Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner. Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP) Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)", + "params": { + "_approved": "Address to be approved for the given NFT ID.", + "_tokenId": "ID of the token to be approved." + } + }, + "balanceOf(address)": { + "details": "Returns the number of NFTs owned by `_owner`. Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.", + "params": { + "_owner": "Address for whom to query the balance." + } + }, + "constructor": { + "params": { + "token_addr": "`VELO` token address" + } + }, + "create_lock(uint256,uint256)": { + "params": { + "_lock_duration": "Number of seconds to lock tokens for (rounded down to nearest week)", + "_value": "Amount to deposit" + } + }, + "create_lock_for(uint256,uint256,address)": { + "params": { + "_lock_duration": "Number of seconds to lock tokens for (rounded down to nearest week)", + "_to": "Address to deposit", + "_value": "Amount to deposit" + } + }, + "delegate(address)": { + "params": { + "delegatee": "The address to delegate votes to" + } + }, + "delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)": { + "details": "Delegates votes from signer to `delegatee`." + }, + "deposit_for(uint256,uint256)": { + "details": "Anyone (even a smart contract) can deposit for someone else, but cannot extend their locktime and deposit for a brand new user", + "params": { + "_tokenId": "lock NFT", + "_value": "Amount to add to user's lock" + } + }, + "getApproved(uint256)": { + "details": "Get the approved address for a single NFT.", + "params": { + "_tokenId": "ID of the NFT to query the approval of." + } + }, + "getVotes(address)": { + "params": { + "account": "The address to get votes balance" + }, + "returns": { + "_0": "The number of current votes for `account`" + } + }, + "get_last_user_slope(uint256)": { + "params": { + "_tokenId": "token of the NFT" + }, + "returns": { + "_0": "Value of the slope" + } + }, + "increase_amount(uint256,uint256)": { + "params": { + "_value": "Amount of tokens to deposit and add to the lock" + } + }, + "increase_unlock_time(uint256,uint256)": { + "params": { + "_lock_duration": "New number of seconds until tokens unlock" + } + }, + "isApprovedForAll(address,address)": { + "details": "Checks if `_operator` is an approved operator for `_owner`.", + "params": { + "_operator": "The address that acts on behalf of the owner.", + "_owner": "The address that owns the NFTs." + } + }, + "locked__end(uint256)": { + "params": { + "_tokenId": "User NFT" + }, + "returns": { + "_0": "Epoch time of the lock end" + } + }, + "ownerOf(uint256)": { + "details": "Returns the address of the owner of the NFT.", + "params": { + "_tokenId": "The identifier for an NFT." + } + }, + "safeTransferFrom(address,address,uint256)": { + "details": "Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.", + "params": { + "_from": "The current owner of the NFT.", + "_to": "The new owner.", + "_tokenId": "The NFT to transfer." + } + }, + "safeTransferFrom(address,address,uint256,bytes)": { + "details": "Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.", + "params": { + "_data": "Additional data with no specified format, sent in call to `_to`.", + "_from": "The current owner of the NFT.", + "_to": "The new owner.", + "_tokenId": "The NFT to transfer." + } + }, + "setApprovalForAll(address,bool)": { + "details": "Enables or disables approval for a third party (\"operator\") to manage all of `msg.sender`'s assets. It also emits the ApprovalForAll event. Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)", + "params": { + "_approved": "True if the operators is approved, false to revoke approval.", + "_operator": "Address to add to the set of authorized operators." + } + }, + "supportsInterface(bytes4)": { + "details": "Interface identification is specified in ERC-165.", + "params": { + "_interfaceID": "Id of the interface" + } + }, + "tokenOfOwnerByIndex(address,uint256)": { + "details": "Get token by index" + }, + "tokenURI(uint256)": { + "details": "Returns current token URI metadata", + "params": { + "_tokenId": "Token ID to fetch URI for." + } + }, + "totalSupplyAt(uint256)": { + "params": { + "_block": "Block to calculate the total voting power at" + }, + "returns": { + "_0": "Total voting power at `_block`" + } + }, + "totalSupplyAtT(uint256)": { + "details": "Adheres to the ERC20 `totalSupply` interface for Aragon compatibility", + "returns": { + "_0": "Total voting power" + } + }, + "transferFrom(address,address,uint256)": { + "details": "Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT.", + "params": { + "_from": "The current owner of the NFT.", + "_to": "The new owner.", + "_tokenId": "The NFT to transfer." + } + }, + "user_point_history__ts(uint256,uint256)": { + "params": { + "_idx": "User epoch number", + "_tokenId": "token of the NFT" + }, + "returns": { + "_0": "Epoch time of the checkpoint" + } + }, + "withdraw(uint256)": { + "details": "Only possible if the lock has expired" + } + }, + "stateVariables": { + "ERC165_INTERFACE_ID": { + "details": "ERC165 interface ID of ERC165" + }, + "ERC721_INTERFACE_ID": { + "details": "ERC165 interface ID of ERC721" + }, + "ERC721_METADATA_INTERFACE_ID": { + "details": "ERC165 interface ID of ERC721Metadata" + }, + "_not_entered": { + "details": "reentrancy guard" + }, + "idToApprovals": { + "details": "Mapping from NFT ID to approved address." + }, + "idToOwner": { + "details": "Mapping from NFT ID to the address that owns it." + }, + "name": { + "details": "Returns the token collection name." + }, + "ownerToNFTokenCount": { + "details": "Mapping from owner address to count of his tokens." + }, + "ownerToNFTokenIdList": { + "details": "Mapping from owner address to mapping of index to tokenIds" + }, + "ownerToOperators": { + "details": "Mapping from owner address to mapping of operator addresses." + }, + "supportedInterfaces": { + "details": "Mapping of interface id to bool about whether or not it's supported" + }, + "symbol": { + "details": "Returns the token collection symbol." + }, + "tokenId": { + "details": "Current count of token" + }, + "tokenToOwnerIndex": { + "details": "Mapping from NFT ID to index of owner" + } + }, + "title": "Voting Escrow", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "DELEGATION_TYPEHASH()": { + "notice": "The EIP-712 typehash for the delegation struct used by the contract" + }, + "DOMAIN_TYPEHASH()": { + "notice": "The EIP-712 typehash for the contract's domain" + }, + "checkpoint()": { + "notice": "Record global data to checkpoint" + }, + "checkpoints(address,uint32)": { + "notice": "A record of delegated token checkpoints for each account, by index" + }, + "constructor": { + "notice": "Contract constructor" + }, + "create_lock(uint256,uint256)": { + "notice": "Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`" + }, + "create_lock_for(uint256,uint256,address)": { + "notice": "Deposit `_value` tokens for `_to` and lock for `_lock_duration`" + }, + "delegate(address)": { + "notice": "Delegate votes from `msg.sender` to `delegatee`" + }, + "delegates(address)": { + "notice": "Overrides the standard `Comp.sol` delegates mapping to return the delegator's own address if they haven't delegated. This avoids having to delegate to oneself." + }, + "deposit_for(uint256,uint256)": { + "notice": "Deposit `_value` tokens for `_tokenId` and add to the lock" + }, + "getVotes(address)": { + "notice": "Gets the current votes balance for `account`" + }, + "get_last_user_slope(uint256)": { + "notice": "Get the most recently recorded rate of voting power decrease for `_tokenId`" + }, + "increase_amount(uint256,uint256)": { + "notice": "Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time" + }, + "increase_unlock_time(uint256,uint256)": { + "notice": "Extend the unlock time for `_tokenId`" + }, + "locked__end(uint256)": { + "notice": "Get timestamp when `_tokenId`'s lock finishes" + }, + "nonces(address)": { + "notice": "A record of states for signing / validating signatures" + }, + "numCheckpoints(address)": { + "notice": "The number of checkpoints for each account" + }, + "setApprovalForAll(address,bool)": { + "notice": "This works even if sender doesn't own any tokens at the time." + }, + "totalSupplyAt(uint256)": { + "notice": "Calculate total voting power at some point in the past" + }, + "totalSupplyAtT(uint256)": { + "notice": "Calculate total voting power" + }, + "transferFrom(address,address,uint256)": { + "notice": "The caller is responsible to confirm that `_to` is capable of receiving NFTs or else they maybe be permanently lost." + }, + "user_point_history__ts(uint256,uint256)": { + "notice": "Get the timestamp for checkpoint `_idx` for `_tokenId`" + }, + "withdraw(uint256)": { + "notice": "Withdraw all tokens for `_tokenId`" + } + }, + "notice": "veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFTVotes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 16268, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "voter", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 16270, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "team", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 16272, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "artProxy", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 16277, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "point_history", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint256,t_struct(Point)16227_storage)" + }, + { + "astId": 16282, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "supportedInterfaces", + "offset": 0, + "slot": "4", + "type": "t_mapping(t_bytes4,t_bool)" + }, + { + "astId": 16297, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "tokenId", + "offset": 0, + "slot": "5", + "type": "t_uint256" + }, + { + "astId": 16392, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "_entered_state", + "offset": 0, + "slot": "6", + "type": "t_uint8" + }, + { + "astId": 16511, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "idToOwner", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_uint256,t_address)" + }, + { + "astId": 16516, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "ownerToNFTokenCount", + "offset": 0, + "slot": "8", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 16560, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "idToApprovals", + "offset": 0, + "slot": "9", + "type": "t_mapping(t_uint256,t_address)" + }, + { + "astId": 16567, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "ownerToOperators", + "offset": 0, + "slot": "10", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" + }, + { + "astId": 16571, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "ownership_change", + "offset": 0, + "slot": "11", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 17016, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "ownerToNFTokenIdList", + "offset": 0, + "slot": "12", + "type": "t_mapping(t_address,t_mapping(t_uint256,t_uint256))" + }, + { + "astId": 17021, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "tokenToOwnerIndex", + "offset": 0, + "slot": "13", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 17326, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "user_point_epoch", + "offset": 0, + "slot": "14", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 17333, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "user_point_history", + "offset": 0, + "slot": "15", + "type": "t_mapping(t_uint256,t_array(t_struct(Point)16227_storage)1000000000_storage)" + }, + { + "astId": 17338, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "locked", + "offset": 0, + "slot": "16", + "type": "t_mapping(t_uint256,t_struct(LockedBalance)16218_storage)" + }, + { + "astId": 17340, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "epoch", + "offset": 0, + "slot": "17", + "type": "t_uint256" + }, + { + "astId": 17344, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "slope_changes", + "offset": 0, + "slot": "18", + "type": "t_mapping(t_uint256,t_int128)" + }, + { + "astId": 17346, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "supply", + "offset": 0, + "slot": "19", + "type": "t_uint256" + }, + { + "astId": 19217, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "attachments", + "offset": 0, + "slot": "20", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 19221, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "voted", + "offset": 0, + "slot": "21", + "type": "t_mapping(t_uint256,t_bool)" + }, + { + "astId": 19452, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "_delegates", + "offset": 0, + "slot": "22", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 19463, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "checkpoints", + "offset": 0, + "slot": "23", + "type": "t_mapping(t_address,t_mapping(t_uint32,t_struct(Checkpoint)16233_storage))" + }, + { + "astId": 19468, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "numCheckpoints", + "offset": 0, + "slot": "24", + "type": "t_mapping(t_address,t_uint32)" + }, + { + "astId": 19473, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "nonces", + "offset": 0, + "slot": "25", + "type": "t_mapping(t_address,t_uint256)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(Point)16227_storage)1000000000_storage": { + "base": "t_struct(Point)16227_storage", + "encoding": "inplace", + "label": "struct VotingEscrow.Point[1000000000]", + "numberOfBytes": "96000000000" + }, + "t_array(t_uint256)dyn_storage": { + "base": "t_uint256", + "encoding": "dynamic_array", + "label": "uint256[]", + "numberOfBytes": "32" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes4": { + "encoding": "inplace", + "label": "bytes4", + "numberOfBytes": "4" + }, + "t_int128": { + "encoding": "inplace", + "label": "int128", + "numberOfBytes": "16" + }, + "t_mapping(t_address,t_address)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_bool)" + }, + "t_mapping(t_address,t_mapping(t_uint256,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(uint256 => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_uint256,t_uint256)" + }, + "t_mapping(t_address,t_mapping(t_uint32,t_struct(Checkpoint)16233_storage))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(uint32 => struct VotingEscrow.Checkpoint))", + "numberOfBytes": "32", + "value": "t_mapping(t_uint32,t_struct(Checkpoint)16233_storage)" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_address,t_uint32)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint32)", + "numberOfBytes": "32", + "value": "t_uint32" + }, + "t_mapping(t_bytes4,t_bool)": { + "encoding": "mapping", + "key": "t_bytes4", + "label": "mapping(bytes4 => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_uint256,t_address)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_uint256,t_array(t_struct(Point)16227_storage)1000000000_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct VotingEscrow.Point[1000000000])", + "numberOfBytes": "32", + "value": "t_array(t_struct(Point)16227_storage)1000000000_storage" + }, + "t_mapping(t_uint256,t_bool)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_uint256,t_int128)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => int128)", + "numberOfBytes": "32", + "value": "t_int128" + }, + "t_mapping(t_uint256,t_struct(LockedBalance)16218_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct VotingEscrow.LockedBalance)", + "numberOfBytes": "32", + "value": "t_struct(LockedBalance)16218_storage" + }, + "t_mapping(t_uint256,t_struct(Point)16227_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct VotingEscrow.Point)", + "numberOfBytes": "32", + "value": "t_struct(Point)16227_storage" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_uint32,t_struct(Checkpoint)16233_storage)": { + "encoding": "mapping", + "key": "t_uint32", + "label": "mapping(uint32 => struct VotingEscrow.Checkpoint)", + "numberOfBytes": "32", + "value": "t_struct(Checkpoint)16233_storage" + }, + "t_struct(Checkpoint)16233_storage": { + "encoding": "inplace", + "label": "struct VotingEscrow.Checkpoint", + "members": [ + { + "astId": 16229, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "timestamp", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 16232, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "tokenIds", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)dyn_storage" + } + ], + "numberOfBytes": "64" + }, + "t_struct(LockedBalance)16218_storage": { + "encoding": "inplace", + "label": "struct VotingEscrow.LockedBalance", + "members": [ + { + "astId": 16215, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "amount", + "offset": 0, + "slot": "0", + "type": "t_int128" + }, + { + "astId": 16217, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "end", + "offset": 0, + "slot": "1", + "type": "t_uint256" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Point)16227_storage": { + "encoding": "inplace", + "label": "struct VotingEscrow.Point", + "members": [ + { + "astId": 16220, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "bias", + "offset": 0, + "slot": "0", + "type": "t_int128" + }, + { + "astId": 16222, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "slope", + "offset": 16, + "slot": "0", + "type": "t_int128" + }, + { + "astId": 16224, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "ts", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 16226, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "blk", + "offset": 0, + "slot": "2", + "type": "t_uint256" + } + ], + "numberOfBytes": "96" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "encoding": "inplace", + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrum/solcInputs/f93feb6db909c3f14d7eec3a3196fbbd.json b/deployments/arbitrum/solcInputs/f93feb6db909c3f14d7eec3a3196fbbd.json new file mode 100644 index 00000000..565546d0 --- /dev/null +++ b/deployments/arbitrum/solcInputs/f93feb6db909c3f14d7eec3a3196fbbd.json @@ -0,0 +1,238 @@ +{ + "language": "Solidity", + "sources": { + "contracts/ExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/factories/BribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n\n// if this imports int and ext bribe why is the the gauge factory asking for those address as if they are deployed to an address.\n" + }, + "contracts/factories/GaugeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" + }, + "contracts/factories/PairFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" + }, + "contracts/factories/WrappedExternalBribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" + }, + "contracts/Gauge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/governance/L2Governor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" + }, + "contracts/governance/L2GovernorCountingSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" + }, + "contracts/governance/L2GovernorVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" + }, + "contracts/governance/L2GovernorVotesQuorumFraction.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" + }, + "contracts/interfaces/IBribe.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IBribeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IERC20.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" + }, + "contracts/interfaces/IGauge.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" + }, + "contracts/interfaces/IGaugeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IMinter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" + }, + "contracts/interfaces/IPair.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IPairCallee.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" + }, + "contracts/interfaces/IPairFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" + }, + "contracts/interfaces/IRewardsDistributor.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" + }, + "contracts/interfaces/IRouter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" + }, + "contracts/interfaces/IVeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" + }, + "contracts/interfaces/IVelo.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" + }, + "contracts/interfaces/IVoter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" + }, + "contracts/interfaces/IVotingEscrow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" + }, + "contracts/interfaces/IWETH.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" + }, + "contracts/InternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/libraries/Base64.sol": { + "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" + }, + "contracts/libraries/Math.sol": { + "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" + }, + "contracts/Minter.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" + }, + "contracts/Pair.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/PairFees.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" + }, + "contracts/redeem/MerkleClaim.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" + }, + "contracts/redeem/RedemptionReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" + }, + "contracts/redeem/RedemptionSender.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" + }, + "contracts/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" + }, + "contracts/Router.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" + }, + "contracts/Velo.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" + }, + "contracts/VelodromeLibrary.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" + }, + "contracts/VeloGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" + }, + "contracts/Voter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VotingEscrow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" + }, + "contracts/WrappedExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + }, + "libraries": { + "": { + "__CACHE_BREAKER__": "0x0000000000000031363733393932363534393236" + } + } + } +} \ No newline at end of file diff --git a/hardhat.config.ts b/hardhat.config.ts index 57ba86b7..3e9269da 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -25,28 +25,29 @@ const remappings = fs const config: HardhatUserConfig = { networks: { - // hardhat: { - // initialBaseFeePerGas: 0, - // forking: { - // url: `https://arb-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY}`, - // blockNumber: 16051852 - // } - // }, - // opera: { - // url: 'https://rpc.fantom.network', - // accounts: [process.env.PRIVATE_KEY!] - // }, - // arbitrum: { - // url: `https://arb-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY}`, - // accounts: [process.env.PRIVATE_KEY!], - // chainId: 42161, - // saveDeployments: false, - // verify: { - // etherscan: { - // apiUrl: 'https://api.arbiscan.io/api' - // } - // } - // }, + hardhat: { + initialBaseFeePerGas: 0, + forking: { + url: `https://arb-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY}`, + blockNumber: 16051852 + } + }, + opera: { + url: 'https://rpc.fantom.network', + accounts: [process.env.PRIVATE_KEY!] + }, + arbitrum: { + url: `https://arb-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY}`, + accounts: [process.env.PRIVATE_KEY!], + chainId: 42161, + saveDeployments: true, + verify: { + etherscan: { + apiUrl: 'https://api.arbiscan.io/api/', + apiKey: process.env.ARB_SCAN_API_KEY! + } + } + }, arbitrumGoerli: { url: `https://arb-goerli.g.alchemy.com/v2/${process.env.ALCHEMY_GOERLI_ARBITRUM_API_KEY}`, accounts: [process.env.PRIVATE_KEY!], @@ -55,7 +56,9 @@ const config: HardhatUserConfig = { verify: { etherscan: { apiUrl: 'https://api-goerli.arbiscan.io/', - apiKey: process.env.ARB_SCAN_API_KEY! + apiKey: { + arbitrumOne: 'Dyp61CtoHxyYVSrAY7oD6IzSVzOgkJuf' + } } } } diff --git a/mainnet-exported.json b/mainnet-exported.json new file mode 100644 index 00000000..98570470 --- /dev/null +++ b/mainnet-exported.json @@ -0,0 +1,6960 @@ +{ + "name": "arbitrum", + "chainId": "42161", + "contracts": { + "BribeFactory": { + "address": "0xBcC3c06e1D22E44Ac807D76A887fFB40765e0D16", + "abi": [ + { + "inputs": [ + { + "internalType": "address[]", + "name": "allowedRewards", + "type": "address[]" + } + ], + "name": "createExternalBribe", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "allowedRewards", + "type": "address[]" + } + ], + "name": "createInternalBribe", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "last_external_bribe", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "last_internal_bribe", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "GaugeFactory": { + "address": "0x2CCb061AD1b50211cF79f33e690452497941a2fe", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_pool", + "type": "address" + }, + { + "internalType": "address", + "name": "_internal_bribe", + "type": "address" + }, + { + "internalType": "address", + "name": "_external_bribe", + "type": "address" + }, + { + "internalType": "address", + "name": "_ve", + "type": "address" + }, + { + "internalType": "bool", + "name": "isPair", + "type": "bool" + }, + { + "internalType": "address[]", + "name": "allowedRewards", + "type": "address[]" + } + ], + "name": "createGauge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "last_gauge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "MerkleClaim": { + "address": "0xF32608868E215FC3164FDe378dca8D3741d0430A", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_velo", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_merkleRoot", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Claim", + "type": "event" + }, + { + "inputs": [], + "name": "VELO", + "outputs": [ + { + "internalType": "contract IVelo", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "name": "claim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "hasClaimed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "merkleRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "Minter": { + "address": "0x68352C1560B43AFE60413E6caf9900d77988E44f", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "__voter", + "type": "address" + }, + { + "internalType": "address", + "name": "__ve", + "type": "address" + }, + { + "internalType": "address", + "name": "__rewards_distributor", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weekly", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "circulating_supply", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "circulating_emission", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "inputs": [], + "name": "MAX_TEAM_RATE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_rewards_distributor", + "outputs": [ + { + "internalType": "contract IRewardsDistributor", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_ve", + "outputs": [ + { + "internalType": "contract IVotingEscrow", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_velo", + "outputs": [ + { + "internalType": "contract IVelo", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_voter", + "outputs": [ + { + "internalType": "contract IVoter", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "active_period", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "calculate_emission", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_minted", + "type": "uint256" + } + ], + "name": "calculate_growth", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "circulating_emission", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "circulating_supply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "claimants", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "max", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingTeam", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_team", + "type": "address" + } + ], + "name": "setTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_teamRate", + "type": "uint256" + } + ], + "name": "setTeamRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "team", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "teamRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "update_period", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "weekly", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "weekly_emission", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "PairFactory": { + "address": "0xA2db791281CdeeBb1EEDc78a34989df2Bfd479bE", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token0", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token1", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "indexed": false, + "internalType": "address", + "name": "pair", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "PairCreated", + "type": "event" + }, + { + "inputs": [], + "name": "MAX_FEE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptFeeManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "acceptPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allPairs", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPairsLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "createPair", + "outputs": [ + { + "internalType": "address", + "name": "pair", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "feeManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_stable", + "type": "bool" + } + ], + "name": "getFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getInitializable", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "name": "getPair", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isPair", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pairCodeHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "pauser", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingFeeManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingPauser", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "_fee", + "type": "uint256" + } + ], + "name": "setFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_feeManager", + "type": "address" + } + ], + "name": "setFeeManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_state", + "type": "bool" + } + ], + "name": "setPause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_pauser", + "type": "address" + } + ], + "name": "setPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "stableFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "volatileFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "RedemptionReceiver": { + "address": "0x79f8A0BFDF42f3FB6FeaE1839C9F3f926b582F9b", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_usdc", + "type": "address" + }, + { + "internalType": "address", + "name": "_velo", + "type": "address" + }, + { + "internalType": "uint16", + "name": "_fantomChainId", + "type": "uint16" + }, + { + "internalType": "address", + "name": "_endpoint", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "fantomSender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemableUSDC", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemableVELO", + "type": "uint256" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "inputs": [], + "name": "ELIGIBLE_WEVE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "USDC", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VELO", + "outputs": [ + { + "internalType": "contract IVelo", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "toAddressBytes", + "type": "bytes" + } + ], + "name": "addressFromPackedBytes", + "outputs": [ + { + "internalType": "address", + "name": "toAddress", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "claimLeftovers", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "deployed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "endpoint", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "fantomChainId", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "fantomSender", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_fantomSender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_redeemableUSDC", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_redeemableVELO", + "type": "uint256" + } + ], + "name": "initializeReceiverWith", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "leftoverVELO", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "srcChainId", + "type": "uint16" + }, + { + "internalType": "bytes", + "name": "srcAddress", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "lzReceive", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountWEVE", + "type": "uint256" + } + ], + "name": "previewRedeem", + "outputs": [ + { + "internalType": "uint256", + "name": "shareOfUSDC", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "shareOfVELO", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "redeemableUSDC", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "redeemableVELO", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "redeemedWEVE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_team", + "type": "address" + } + ], + "name": "setTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "team", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "RewardsDistributor": { + "address": "0xd9891738458A5b1F1EfB5f82183b77c666d9064E", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_voting_escrow", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "time", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "CheckpointToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "claim_epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "max_epoch", + "type": "uint256" + } + ], + "name": "Claimed", + "type": "event" + }, + { + "inputs": [], + "name": "checkpoint_token", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "checkpoint_total_supply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "claim", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "_tokenIds", + "type": "uint256[]" + } + ], + "name": "claim_many", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "claimable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "depositor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "last_token_time", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_depositor", + "type": "address" + } + ], + "name": "setDepositor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "start_time", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "time_cursor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "time_cursor_of", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "timestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token_last_balance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "tokens_per_week", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "user_epoch_of", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_timestamp", + "type": "uint256" + } + ], + "name": "ve_for_at", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "ve_supply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "voting_escrow", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "Router": { + "address": "0x07d2FCFa095d52652cBC664F105F2d9Fb3799a47", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_factory", + "type": "address" + }, + { + "internalType": "address", + "name": "_weth", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "internalType": "struct Router.route[]", + "name": "routes", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "UNSAFE_swapExactTokensForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "amountADesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBDesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountAMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "addLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "amountTokenDesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountTokenMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETHMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "addLiquidityETH", + "outputs": [ + { + "internalType": "uint256", + "name": "amountToken", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETH", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + } + ], + "name": "getAmountOut", + "outputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "internalType": "struct Router.route[]", + "name": "routes", + "type": "tuple[]" + } + ], + "name": "getAmountsOut", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "reserveA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveB", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pair", + "type": "address" + } + ], + "name": "isPair", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "pairFor", + "outputs": [ + { + "internalType": "address", + "name": "pair", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "amountADesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBDesired", + "type": "uint256" + } + ], + "name": "quoteAddLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "name": "quoteRemoveLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountAMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "removeLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountTokenMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETHMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "removeLiquidityETH", + "outputs": [ + { + "internalType": "uint256", + "name": "amountToken", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETH", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountTokenMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETHMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "approveMax", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "removeLiquidityETHWithPermit", + "outputs": [ + { + "internalType": "uint256", + "name": "amountToken", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETH", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountAMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "approveMax", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "removeLiquidityWithPermit", + "outputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + } + ], + "name": "sortTokens", + "outputs": [ + { + "internalType": "address", + "name": "token0", + "type": "address" + }, + { + "internalType": "address", + "name": "token1", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "internalType": "struct Router.route[]", + "name": "routes", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactETHForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "internalType": "struct Router.route[]", + "name": "routes", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForETH", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "internalType": "struct Router.route[]", + "name": "routes", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenFrom", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenTo", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensSimple", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "weth", + "outputs": [ + { + "internalType": "contract IWETH", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VeArtProxy": { + "address": "0x4b40D5E4401EC24673cc9d4799457a3B5827c581", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_balanceOf", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_locked_end", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "_tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "output", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } + ] + }, + "Velo": { + "address": "0xC33f7f83CbB021846Cb9c58f2d8E3df428dbC8C1", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "claim", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_recipient", + "type": "address" + } + ], + "name": "initialMint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initialMinted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "merkleClaim", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "minter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "redemptionReceiver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_merkleClaim", + "type": "address" + } + ], + "name": "setMerkleClaim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_minter", + "type": "address" + } + ], + "name": "setMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_receiver", + "type": "address" + } + ], + "name": "setRedemptionReceiver", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "VeloGovernor": { + "address": "0x60ea1F72695cF5735767b7CeA917E09290A06b9B", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IVotes", + "name": "_ve", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "Empty", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "ProposalCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldQuorumNumerator", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newQuorumNumerator", + "type": "uint256" + } + ], + "name": "QuorumNumeratorUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "VoteCast", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "VoteCastWithParams", + "type": "event" + }, + { + "inputs": [], + "name": "BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COUNTING_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "EXTENDED_BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_PROPOSAL_NUMERATOR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PROPOSAL_DENOMINATOR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + } + ], + "name": "castVote", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "castVoteBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "castVoteWithReason", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "castVoteWithReasonAndParamsBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "execute", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockTimestamp", + "type": "uint256" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockTimestamp", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "getVotesWithParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasVoted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "hashProposal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalDeadline", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalNumerator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "againstVotes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "forVotes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "abstainVotes", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "propose", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "blockTimestamp", + "type": "uint256" + } + ], + "name": "quorum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "quorumDenominator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "quorumNumerator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "relay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "numerator", + "type": "uint256" + } + ], + "name": "setProposalNumerator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newTeam", + "type": "address" + } + ], + "name": "setTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "state", + "outputs": [ + { + "internalType": "enum IGovernor.ProposalState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "team", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IVotes", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newQuorumNumerator", + "type": "uint256" + } + ], + "name": "updateQuorumNumerator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "votingPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VelodromeLibrary": { + "address": "0x8CBC99B41851A410A4C74200d628e895c940C641", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_router", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getAmountOut", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getMinimumValue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getSample", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getTradeDiff", + "outputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "pair", + "type": "address" + } + ], + "name": "getTradeDiff", + "outputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "Voter": { + "address": "0x29C487a354D11315059204Df4F7d8AB1aa008ebb", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "__ve", + "type": "address" + }, + { + "internalType": "address", + "name": "_factory", + "type": "address" + }, + { + "internalType": "address", + "name": "_gauges", + "type": "address" + }, + { + "internalType": "address", + "name": "_bribes", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + } + ], + "name": "Abstained", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Attach", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "lp", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Detach", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DistributeReward", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "internal_bribe", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "external_bribe", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "GaugeCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + } + ], + "name": "GaugeKilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + } + ], + "name": "GaugeRevived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "reward", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "NotifyReward", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + } + ], + "name": "Voted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "whitelister", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "Whitelisted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "lp", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [], + "name": "_ve", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "attachTokenToGauge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bribefactory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_bribes", + "type": "address[]" + }, + { + "internalType": "address[][]", + "name": "_tokens", + "type": "address[][]" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "claimBribes", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_fees", + "type": "address[]" + }, + { + "internalType": "address[][]", + "name": "_tokens", + "type": "address[][]" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "claimFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_gauges", + "type": "address[]" + }, + { + "internalType": "address[][]", + "name": "_tokens", + "type": "address[][]" + } + ], + "name": "claimRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "claimable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_pool", + "type": "address" + } + ], + "name": "createGauge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "detachTokenFromGauge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_gauges", + "type": "address[]" + } + ], + "name": "distribute", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gauge", + "type": "address" + } + ], + "name": "distribute", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "start", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "finish", + "type": "uint256" + } + ], + "name": "distribute", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "distribute", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_gauges", + "type": "address[]" + } + ], + "name": "distributeFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "distro", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "emergencyCouncil", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "emitDeposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "emitWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "external_bribes", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gaugefactory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "gauges", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_tokens", + "type": "address[]" + }, + { + "internalType": "address", + "name": "_minter", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "internal_bribes", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isAlive", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isGauge", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isWhitelisted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gauge", + "type": "address" + } + ], + "name": "killGauge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "lastVoted", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "length", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "notifyRewardAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "poke", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "poolForGauge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "poolVote", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "pools", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "reset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gauge", + "type": "address" + } + ], + "name": "reviveGauge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_council", + "type": "address" + } + ], + "name": "setEmergencyCouncil", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_governor", + "type": "address" + } + ], + "name": "setGovernor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalWeight", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "updateAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_gauges", + "type": "address[]" + } + ], + "name": "updateFor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "start", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "end", + "type": "uint256" + } + ], + "name": "updateForRange", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gauge", + "type": "address" + } + ], + "name": "updateGauge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "usedWeights", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "_poolVote", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "_weights", + "type": "uint256[]" + } + ], + "name": "vote", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "votes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "weights", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + } + ], + "name": "whitelist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "VotingEscrow": { + "address": "0x10Df81252069C1095F541FAca61646cb9Ae76703", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "token_addr", + "type": "address" + }, + { + "internalType": "address", + "name": "art_proxy", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "fromDelegate", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "toDelegate", + "type": "address" + } + ], + "name": "DelegateChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "DelegateVotesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "locktime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum VotingEscrow.DepositType", + "name": "deposit_type", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "ts", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "prevSupply", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "supply", + "type": "uint256" + } + ], + "name": "Supply", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "ts", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [], + "name": "DELEGATION_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DOMAIN_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_DELEGATES", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "abstain", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_approved", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "artProxy", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "attach", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "attachments", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_block", + "type": "uint256" + } + ], + "name": "balanceOfAtNFT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "balanceOfNFT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_t", + "type": "uint256" + } + ], + "name": "balanceOfNFTAt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "block_number", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkpoint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "name": "checkpoints", + "outputs": [ + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_lock_duration", + "type": "uint256" + } + ], + "name": "create_lock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_lock_duration", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + } + ], + "name": "create_lock_for", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + } + ], + "name": "delegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "delegateBySig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "delegates", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "deposit_for", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "detach", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "epoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "getPastTotalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "getPastVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "getPastVotesIndex", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "get_last_user_slope", + "outputs": [ + { + "internalType": "int128", + "name": "", + "type": "int128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "increase_amount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_lock_duration", + "type": "uint256" + } + ], + "name": "increase_unlock_time", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "isApprovedOrOwner", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "locked", + "outputs": [ + { + "internalType": "int128", + "name": "amount", + "type": "int128" + }, + { + "internalType": "uint256", + "name": "end", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "locked__end", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_from", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_to", + "type": "uint256" + } + ], + "name": "merge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "numCheckpoints", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "ownership_change", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "point_history", + "outputs": [ + { + "internalType": "int128", + "name": "bias", + "type": "int128" + }, + { + "internalType": "int128", + "name": "slope", + "type": "int128" + }, + { + "internalType": "uint256", + "name": "ts", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "blk", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "_approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_proxy", + "type": "address" + } + ], + "name": "setArtProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_team", + "type": "address" + } + ], + "name": "setTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_voter", + "type": "address" + } + ], + "name": "setVoter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "slope_changes", + "outputs": [ + { + "internalType": "int128", + "name": "", + "type": "int128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "supply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_interfaceID", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "team", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenIndex", + "type": "uint256" + } + ], + "name": "tokenOfOwnerByIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_block", + "type": "uint256" + } + ], + "name": "totalSupplyAt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "t", + "type": "uint256" + } + ], + "name": "totalSupplyAtT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "user_point_epoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "user_point_history", + "outputs": [ + { + "internalType": "int128", + "name": "bias", + "type": "int128" + }, + { + "internalType": "int128", + "name": "slope", + "type": "int128" + }, + { + "internalType": "uint256", + "name": "ts", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "blk", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_idx", + "type": "uint256" + } + ], + "name": "user_point_history__ts", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "voted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "voter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "voting", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] + } + } +} \ No newline at end of file diff --git a/package.json b/package.json index 1b63e2d1..f8b4de84 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,10 @@ }, "scripts": { "verify": "npx hardhat --network arbitrumGoerli etherscan-verify --solc-input --sleep", - "export": "npx hardhat --network arbitrumGoerli export --export ./exported.json" + "export": "npx hardhat --network arbitrumGoerli export --export ./exported.json", + "exportMainnet": "npx hardhat --network arbitrum export --export ./mainnet-exported.json", + "deploy": "npx hardhat --network arbitrumGoerli", + "verifyMainnet": "npx hardhat --network arbitrum etherscan-verify --solc-input --sleep" }, "devDependencies": { "@nomiclabs/hardhat-ethers": "yarn:hardhat-deploy-ethers", diff --git a/readme.md b/readme.md index 001763e6..f23ca64f 100644 --- a/readme.md +++ b/readme.md @@ -29,7 +29,7 @@ npx hardhat --network arbitrumGoerli export --export ./exported.json Voter: '0x854086d39955d28317aE3856399312b8Edb1B473', VotingEscrow: '0xBf05364D6cf1586852c18c6b1CbEe218E3e09885' } - +// asdfa;kjsdhf ## Testing This repo uses both Foundry (for Solidity testing) and Hardhat (for deployment). From 060749719740c52da2338b622699edde6f61f575 Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Wed, 18 Jan 2023 15:49:33 +1100 Subject: [PATCH 13/43] keep deployments in gitignor --- .gitignore | 4 +- .../230cd08a65e08d438d74567532df4760.json | 238 ++++++++++++++++++ .../2aff87e12ab2599f097157a40df1b1f2.json | 238 ++++++++++++++++++ .../44ac1d7fba4690e053e773a8c0d73438.json | 238 ++++++++++++++++++ .../97fe41ab3f7afe2e310d7855146d97a7.json | 238 ++++++++++++++++++ .../a6a0d6751205558353275c1f5e5364e9.json | 238 ++++++++++++++++++ .../b32caaa26f5963725c04cc29c5c19ad6.json | 238 ++++++++++++++++++ deployments/arbitrumOne.zip | Bin 0 -> 315032 bytes 8 files changed, 1430 insertions(+), 2 deletions(-) create mode 100644 deployments/arbitrumGoerli/solcInputs/230cd08a65e08d438d74567532df4760.json create mode 100644 deployments/arbitrumGoerli/solcInputs/2aff87e12ab2599f097157a40df1b1f2.json create mode 100644 deployments/arbitrumGoerli/solcInputs/44ac1d7fba4690e053e773a8c0d73438.json create mode 100644 deployments/arbitrumGoerli/solcInputs/97fe41ab3f7afe2e310d7855146d97a7.json create mode 100644 deployments/arbitrumGoerli/solcInputs/a6a0d6751205558353275c1f5e5364e9.json create mode 100644 deployments/arbitrumGoerli/solcInputs/b32caaa26f5963725c04cc29c5c19ad6.json create mode 100644 deployments/arbitrumOne.zip diff --git a/.gitignore b/.gitignore index 93b74371..09800555 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ # for verify args.js -/contracts/deploy/ + .env # Foundry @@ -32,4 +32,4 @@ lib/openzeppelin-contracts lib/forge-std lib/LayerZero lib/forge-std -deployments/arbitrumGoerli/solcInputs/ + diff --git a/deployments/arbitrumGoerli/solcInputs/230cd08a65e08d438d74567532df4760.json b/deployments/arbitrumGoerli/solcInputs/230cd08a65e08d438d74567532df4760.json new file mode 100644 index 00000000..260b8af2 --- /dev/null +++ b/deployments/arbitrumGoerli/solcInputs/230cd08a65e08d438d74567532df4760.json @@ -0,0 +1,238 @@ +{ + "language": "Solidity", + "sources": { + "contracts/ExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/factories/BribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" + }, + "contracts/factories/GaugeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" + }, + "contracts/factories/PairFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" + }, + "contracts/factories/WrappedExternalBribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" + }, + "contracts/Gauge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/governance/L2Governor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" + }, + "contracts/governance/L2GovernorCountingSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" + }, + "contracts/governance/L2GovernorVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" + }, + "contracts/governance/L2GovernorVotesQuorumFraction.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" + }, + "contracts/interfaces/IBribe.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IBribeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IERC20.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" + }, + "contracts/interfaces/IGauge.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" + }, + "contracts/interfaces/IGaugeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IMinter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" + }, + "contracts/interfaces/IPair.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IPairCallee.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" + }, + "contracts/interfaces/IPairFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" + }, + "contracts/interfaces/IRewardsDistributor.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" + }, + "contracts/interfaces/IRouter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" + }, + "contracts/interfaces/IVeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" + }, + "contracts/interfaces/IVelo.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" + }, + "contracts/interfaces/IVoter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" + }, + "contracts/interfaces/IVotingEscrow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" + }, + "contracts/interfaces/IWETH.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" + }, + "contracts/InternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/libraries/Base64.sol": { + "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" + }, + "contracts/libraries/Math.sol": { + "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" + }, + "contracts/Minter.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" + }, + "contracts/Pair.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/PairFees.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" + }, + "contracts/redeem/MerkleClaim.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" + }, + "contracts/redeem/RedemptionReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" + }, + "contracts/redeem/RedemptionSender.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" + }, + "contracts/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" + }, + "contracts/Router.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" + }, + "contracts/Velo.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" + }, + "contracts/VelodromeLibrary.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" + }, + "contracts/VeloGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" + }, + "contracts/Voter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VotingEscrow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" + }, + "contracts/WrappedExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + }, + "libraries": { + "": { + "__CACHE_BREAKER__": "0x0000000000000031363733363638383730363032" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/2aff87e12ab2599f097157a40df1b1f2.json b/deployments/arbitrumGoerli/solcInputs/2aff87e12ab2599f097157a40df1b1f2.json new file mode 100644 index 00000000..b313280b --- /dev/null +++ b/deployments/arbitrumGoerli/solcInputs/2aff87e12ab2599f097157a40df1b1f2.json @@ -0,0 +1,238 @@ +{ + "language": "Solidity", + "sources": { + "contracts/ExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/factories/BribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" + }, + "contracts/factories/GaugeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" + }, + "contracts/factories/PairFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" + }, + "contracts/factories/WrappedExternalBribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" + }, + "contracts/Gauge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/governance/L2Governor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" + }, + "contracts/governance/L2GovernorCountingSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" + }, + "contracts/governance/L2GovernorVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" + }, + "contracts/governance/L2GovernorVotesQuorumFraction.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" + }, + "contracts/interfaces/IBribe.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IBribeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IERC20.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" + }, + "contracts/interfaces/IGauge.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" + }, + "contracts/interfaces/IGaugeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IMinter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" + }, + "contracts/interfaces/IPair.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IPairCallee.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" + }, + "contracts/interfaces/IPairFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" + }, + "contracts/interfaces/IRewardsDistributor.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" + }, + "contracts/interfaces/IRouter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" + }, + "contracts/interfaces/IVeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" + }, + "contracts/interfaces/IVelo.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" + }, + "contracts/interfaces/IVoter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" + }, + "contracts/interfaces/IVotingEscrow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" + }, + "contracts/interfaces/IWETH.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" + }, + "contracts/InternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/libraries/Base64.sol": { + "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" + }, + "contracts/libraries/Math.sol": { + "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" + }, + "contracts/Minter.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" + }, + "contracts/Pair.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/PairFees.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" + }, + "contracts/redeem/MerkleClaim.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" + }, + "contracts/redeem/RedemptionReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" + }, + "contracts/redeem/RedemptionSender.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" + }, + "contracts/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" + }, + "contracts/Router.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" + }, + "contracts/Velo.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" + }, + "contracts/VelodromeLibrary.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" + }, + "contracts/VeloGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" + }, + "contracts/Voter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VotingEscrow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" + }, + "contracts/WrappedExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + }, + "libraries": { + "": { + "__CACHE_BREAKER__": "0x0000000000000031363733363638353936353432" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/44ac1d7fba4690e053e773a8c0d73438.json b/deployments/arbitrumGoerli/solcInputs/44ac1d7fba4690e053e773a8c0d73438.json new file mode 100644 index 00000000..32ed5454 --- /dev/null +++ b/deployments/arbitrumGoerli/solcInputs/44ac1d7fba4690e053e773a8c0d73438.json @@ -0,0 +1,238 @@ +{ + "language": "Solidity", + "sources": { + "contracts/ExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/factories/BribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" + }, + "contracts/factories/GaugeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" + }, + "contracts/factories/PairFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" + }, + "contracts/factories/WrappedExternalBribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" + }, + "contracts/Gauge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/governance/L2Governor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" + }, + "contracts/governance/L2GovernorCountingSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" + }, + "contracts/governance/L2GovernorVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" + }, + "contracts/governance/L2GovernorVotesQuorumFraction.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" + }, + "contracts/interfaces/IBribe.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IBribeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IERC20.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" + }, + "contracts/interfaces/IGauge.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" + }, + "contracts/interfaces/IGaugeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IMinter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" + }, + "contracts/interfaces/IPair.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IPairCallee.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" + }, + "contracts/interfaces/IPairFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" + }, + "contracts/interfaces/IRewardsDistributor.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" + }, + "contracts/interfaces/IRouter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" + }, + "contracts/interfaces/IVeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" + }, + "contracts/interfaces/IVelo.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" + }, + "contracts/interfaces/IVoter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" + }, + "contracts/interfaces/IVotingEscrow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" + }, + "contracts/interfaces/IWETH.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" + }, + "contracts/InternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/libraries/Base64.sol": { + "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" + }, + "contracts/libraries/Math.sol": { + "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" + }, + "contracts/Minter.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" + }, + "contracts/Pair.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/PairFees.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" + }, + "contracts/redeem/MerkleClaim.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" + }, + "contracts/redeem/RedemptionReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" + }, + "contracts/redeem/RedemptionSender.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" + }, + "contracts/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" + }, + "contracts/Router.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" + }, + "contracts/Velo.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" + }, + "contracts/VelodromeLibrary.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" + }, + "contracts/VeloGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" + }, + "contracts/Voter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VotingEscrow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" + }, + "contracts/WrappedExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + }, + "libraries": { + "": { + "__CACHE_BREAKER__": "0x0000000000000031363733373432343733333937" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/97fe41ab3f7afe2e310d7855146d97a7.json b/deployments/arbitrumGoerli/solcInputs/97fe41ab3f7afe2e310d7855146d97a7.json new file mode 100644 index 00000000..ab266da5 --- /dev/null +++ b/deployments/arbitrumGoerli/solcInputs/97fe41ab3f7afe2e310d7855146d97a7.json @@ -0,0 +1,238 @@ +{ + "language": "Solidity", + "sources": { + "contracts/ExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/factories/BribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" + }, + "contracts/factories/GaugeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" + }, + "contracts/factories/PairFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" + }, + "contracts/factories/WrappedExternalBribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" + }, + "contracts/Gauge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/governance/L2Governor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" + }, + "contracts/governance/L2GovernorCountingSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" + }, + "contracts/governance/L2GovernorVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" + }, + "contracts/governance/L2GovernorVotesQuorumFraction.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" + }, + "contracts/interfaces/IBribe.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IBribeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IERC20.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" + }, + "contracts/interfaces/IGauge.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" + }, + "contracts/interfaces/IGaugeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IMinter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" + }, + "contracts/interfaces/IPair.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IPairCallee.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" + }, + "contracts/interfaces/IPairFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" + }, + "contracts/interfaces/IRewardsDistributor.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" + }, + "contracts/interfaces/IRouter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" + }, + "contracts/interfaces/IVeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" + }, + "contracts/interfaces/IVelo.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" + }, + "contracts/interfaces/IVoter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" + }, + "contracts/interfaces/IVotingEscrow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" + }, + "contracts/interfaces/IWETH.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" + }, + "contracts/InternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/libraries/Base64.sol": { + "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" + }, + "contracts/libraries/Math.sol": { + "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" + }, + "contracts/Minter.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" + }, + "contracts/Pair.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/PairFees.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" + }, + "contracts/redeem/MerkleClaim.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" + }, + "contracts/redeem/RedemptionReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" + }, + "contracts/redeem/RedemptionSender.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" + }, + "contracts/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" + }, + "contracts/Router.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" + }, + "contracts/Velo.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" + }, + "contracts/VelodromeLibrary.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" + }, + "contracts/VeloGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" + }, + "contracts/Voter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VotingEscrow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" + }, + "contracts/WrappedExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + }, + "libraries": { + "": { + "__CACHE_BREAKER__": "0x0000000000000031363733363638333035323839" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/a6a0d6751205558353275c1f5e5364e9.json b/deployments/arbitrumGoerli/solcInputs/a6a0d6751205558353275c1f5e5364e9.json new file mode 100644 index 00000000..9b6f3828 --- /dev/null +++ b/deployments/arbitrumGoerli/solcInputs/a6a0d6751205558353275c1f5e5364e9.json @@ -0,0 +1,238 @@ +{ + "language": "Solidity", + "sources": { + "contracts/ExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/factories/BribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" + }, + "contracts/factories/GaugeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" + }, + "contracts/factories/PairFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" + }, + "contracts/factories/WrappedExternalBribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" + }, + "contracts/Gauge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/governance/L2Governor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" + }, + "contracts/governance/L2GovernorCountingSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" + }, + "contracts/governance/L2GovernorVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" + }, + "contracts/governance/L2GovernorVotesQuorumFraction.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" + }, + "contracts/interfaces/IBribe.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IBribeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IERC20.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" + }, + "contracts/interfaces/IGauge.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" + }, + "contracts/interfaces/IGaugeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IMinter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" + }, + "contracts/interfaces/IPair.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IPairCallee.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" + }, + "contracts/interfaces/IPairFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" + }, + "contracts/interfaces/IRewardsDistributor.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" + }, + "contracts/interfaces/IRouter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" + }, + "contracts/interfaces/IVeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" + }, + "contracts/interfaces/IVelo.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" + }, + "contracts/interfaces/IVoter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" + }, + "contracts/interfaces/IVotingEscrow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" + }, + "contracts/interfaces/IWETH.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" + }, + "contracts/InternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/libraries/Base64.sol": { + "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" + }, + "contracts/libraries/Math.sol": { + "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" + }, + "contracts/Minter.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" + }, + "contracts/Pair.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/PairFees.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" + }, + "contracts/redeem/MerkleClaim.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" + }, + "contracts/redeem/RedemptionReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" + }, + "contracts/redeem/RedemptionSender.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" + }, + "contracts/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" + }, + "contracts/Router.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" + }, + "contracts/Velo.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" + }, + "contracts/VelodromeLibrary.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" + }, + "contracts/VeloGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" + }, + "contracts/Voter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VotingEscrow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" + }, + "contracts/WrappedExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + }, + "libraries": { + "": { + "__CACHE_BREAKER__": "0x0000000000000031363733373430393437383838" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/b32caaa26f5963725c04cc29c5c19ad6.json b/deployments/arbitrumGoerli/solcInputs/b32caaa26f5963725c04cc29c5c19ad6.json new file mode 100644 index 00000000..df96ac00 --- /dev/null +++ b/deployments/arbitrumGoerli/solcInputs/b32caaa26f5963725c04cc29c5c19ad6.json @@ -0,0 +1,238 @@ +{ + "language": "Solidity", + "sources": { + "contracts/ExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/factories/BribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" + }, + "contracts/factories/GaugeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" + }, + "contracts/factories/PairFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" + }, + "contracts/factories/WrappedExternalBribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" + }, + "contracts/Gauge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/governance/L2Governor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" + }, + "contracts/governance/L2GovernorCountingSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" + }, + "contracts/governance/L2GovernorVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" + }, + "contracts/governance/L2GovernorVotesQuorumFraction.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" + }, + "contracts/interfaces/IBribe.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IBribeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IERC20.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" + }, + "contracts/interfaces/IGauge.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" + }, + "contracts/interfaces/IGaugeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IMinter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" + }, + "contracts/interfaces/IPair.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IPairCallee.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" + }, + "contracts/interfaces/IPairFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" + }, + "contracts/interfaces/IRewardsDistributor.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" + }, + "contracts/interfaces/IRouter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" + }, + "contracts/interfaces/IVeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" + }, + "contracts/interfaces/IVelo.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" + }, + "contracts/interfaces/IVoter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" + }, + "contracts/interfaces/IVotingEscrow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" + }, + "contracts/interfaces/IWETH.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" + }, + "contracts/InternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/libraries/Base64.sol": { + "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" + }, + "contracts/libraries/Math.sol": { + "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" + }, + "contracts/Minter.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" + }, + "contracts/Pair.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/PairFees.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" + }, + "contracts/redeem/MerkleClaim.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" + }, + "contracts/redeem/RedemptionReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" + }, + "contracts/redeem/RedemptionSender.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" + }, + "contracts/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" + }, + "contracts/Router.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" + }, + "contracts/Velo.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" + }, + "contracts/VelodromeLibrary.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" + }, + "contracts/VeloGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" + }, + "contracts/Voter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VotingEscrow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" + }, + "contracts/WrappedExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + }, + "libraries": { + "": { + "__CACHE_BREAKER__": "0x0000000000000031363733373336393333303139" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumOne.zip b/deployments/arbitrumOne.zip new file mode 100644 index 0000000000000000000000000000000000000000..5edfa33c54766e2d835ed296d0b69aceb7c60fab GIT binary patch literal 315032 zcmY&7!yo*V%xTD+qP}n=A78JZJn6+`~SKR_jdKF+7ElxdfK&j zukMzYf`q~Z`=1r=!>pPyGR_A5U;IBn`ws?=h8E6_E;ft|M&u_YVol#RvO7f#%aHc>F?vgvV4gwkmC{r*#EB?h_PmQtPchj z_XZAz_y1}NI$9W-h#D9<+c|ptujo~eRnlQ=1IgQ`aQ3%6H~aNnG$0Wy9!g^DzSdZx zEAp{{uyHy!rXCZ61m5zzvaGAEN^^d->f09t9uEe$Ttu8WoSO((g5FOUl|Dq|zrXo@ zW6YYuU_oMcZS%VSI*xeRJNSAQVQfyxqk6Q^@Lgmt{3>21W|INcZ>S)|WEXw6N zZP+4SeMS1&{q;Lxq}tZi-MMxHC7o7OHMFs(9q&)9tYC?`@_#&9UAtGhS?Jz@qN1v9 zu5LpOcxisyaj#y(!ezE4(^vMLt7hBJFUA7EjQ4zg^_PIB|Kx2|tEqEa{sLf_yf zy8!-gH*H@1FGH^1c=)=yI=WdarCo3ZPd%}1X`jAcE@z#ecdz&|MKg@wV;0E+lObzY zdg>$HjGgSrEIT$=&v8K*e06^6*}K?o55|5*3~r&hU#Lx9uff6YI?5&#__Q@t=e5h7 z$%@WG27~Gw3RpSKt<9#V)`0NJtMOVIXZF9H3zg_a4*x!fpIp6q!gvW|b1&<5M~<$B zLW1tb+?^gHN2((mUfL7$d=&ju%iokRiwq)R&Qqy)BBa%Qy;N9DOH}W+g{+g?)Q}Tbz57z z`4f8^R+I)m-yim0P;v}*dOn7AjJ3LbjcM;4ag<$EQD07&yF~CtT41)1vn_>JQ3|O- zHa2?cg023?w)TamDO*_sm&ku#-_=OCb#?3*FQ?Sxw!`#x*0Kn9fBJeq3U_aG(?;#^ zhp26Qc9pV}o`-y%kHyXOK^)n?PSv~)D-QK(>sZ77=+XlOP*&r#v;P>m9nsrkTxMN} z)A%C~oAgTvkT1HsKMGf9_AZ@7+=qg1f;0zKYeX^#W*p`W`I{!pauQ2&bDoxPaBIdt zdUXH&h?Fdl$0*^`IKJr2-YnfH>MRYMn2fS@H5^WM=<$EA0_ zktKi>cm$uF+mq=UmQ)rKq<&C=BJ^){L7 zXS8pxFLp6u3?5b^RpU<2n_j?TXL~2Xt(?1K!<8+P>yT0R_x{ig-`nT+%frx!p7-0_ z_s2sNHeD$dvh?WtZu!p6=yFBDkTjs;f5P6D2G@)ZVYRcWcKo)!cUz~2p;%{Y z=gGadNXCfng<@6<0eQQW^t`?CaWs?napU$?e|2><-3xjJlWRR#-tO*ueV*z2IIo(x zzz0pyHmz}1^cnze!Fd9{ZS-{Xwl3NAe14*E|9b23V}DO$W#IYNui>fz%V$~q_6~hm z#LDx%^P-rxyxW<&Vn2zw>#N({h*T(LKNn|vM- zM5dr2ok0UI$4)LDcbR^+o=zPeE^O8#D`0?hX#be0g)OXJ_6>lVH~c1IcPJ=xfRkfB z>V_@`w4~OiQlk$m!~j3->}X}*sMv~sHLwdG#b&R@xyOtdAcZ(|@ zw{E?2EIZ=~CvryX!%5)l1gFPqJa27J^J~BSTG{h-^&S~foihRl%0H~VI<^QcT@lF3 z?fKZ))4)rAD~+x=90HgWVQKBo9lH)Ppmlm-rSEqb0#N-+_|_j7ZN9G_fBFkfJg0QL zV&M+{T47rYAP7r&dhe*!)BeRK0IN>&Rds>NjEcSZb|)R~I!OG7f0E@H+zQ)ai$2BZS{ccY$t+EmD39xTjQR}+$)l_E% zFRRX-=?=m8@J>gZq!oT@LM`n5!gyG*H|q6^pZv2-Qap=>Fx%nkc3wYSOuo%2RTYydiKD&mbMFt#ZUpxhe&BuVLZq*Hy$_gnz1q0$x-niJ{Z|G&Q+}_ra#t1Zt=5uLIj7$jlEivI?OEP$l7(f947WNvH^vox_td{1 ze_pP>W694=VO>w4GbwJ=S+^P9SGqNmTsj|@2ctHmqE*4Q{L%hY@H9{N_wMW#mECRH zU4D0LZLgLI2$|yw;5}6o!dkVICIpSS+c^V$@ARIIP5BhO=Q(DME3|hK0j+&K;1hEz z(g7o7P8U<$S!JNOZ#PhKO}E($$^aw-l?GGQ509oJ4xXg*T+{F>()626E7b#|Avs30 zAOY0AjLBtG6q(O9C(t+EUq8OiVsUz+Q?u>KSeONkwv@zvLC0Yp%veq+6ALif<|U~2Yvr7VK!&Z zN?w)f&4R6ltb4Jh`^>H@98K(UE4tKDN1K1AcNO_$WJoA| zvV+w6X(sywz(XPxRT13R0TT{SCi>uDS;MI_dW1ZBVbPJyoVJg9qI5@fz-+jz(0w%H zJ+lpbeOywU@aC=D4}*S7YmfIo??~EyF<>5MWPQHu>ioo^QNGZG0 z1)p8~*HBT>iTO}^HunS*ng%tU-#3hUJS7P(|E|m`jqUv{KxNZ4kY-22dkxnm9|Pu! zlDhjEayA|NznDH_GT$`<;;pH)+ZtH7!1J;3vF!eWyNh3LT8w-G+o_o<~wQI)^% z8qo}9n_-6W&{}*~;Ugy?GKl<5NPombMsP!@bKoD0E1F4p&jWI%uDEToPggS!(p6<$ z*%`FXysN=@l1h7DFp^GXn)(CnLgTcZHI`a<7Qk^?9NU2&Dv^qh`J%B`N9IH3gAK)% zH3ShK+n^Df`MmcBo8S%T+V%}OROjFGF$dF_C>!PUf|C>#Ko46yMRyHHD7{JeYly$E z{qfk#o?nOGoL`N5Ge#g6v9dR~66><}R}QM{2gSq0T}@o=+;P867j?QgBB;PdC=7bj z;Op?|eq*bvt~E_AiS2J@*d@|=u<3wbyE)IXtO(~TCw3b44IF^mkf8;?$gY|x1Kw!voL^fjd= zGCu2mO(KEm%t>gC2fPfJL&T1oHTz%oy-jzDAVN*E=j+7W)G_$AxQ!J4ZA*KaT_8z_Ke20wD_*; z&yA8Oh0A!J$Tji2xu0Ng0?K z^@9b{alW)hT&kQDlP24O<*(PiUQJc3iAGL4htjQ~_v{FF31v=upG6(nDh`Gj5)1=m zIJb13KgqO*8qD^oN@Vd)+3B+k_wU|4s|26uL+~Fn+S9!uZN#~Dog1G7BkfSI>5~ZM zvZ|NP;uvxEiT}>&K71U&XKr6A?IKV>YH}}&)PyBEIIWB@ZZ9JkS#h~^HYvEHePSRU z>oOP>NJb(NoH&d^d(zA5e?^`GOCpC3%tWa5Q%x>F#9kp`E)e>K46SN22S}F-7IMv#-arB(zn4ppEb3TYv!>_EA)p7& zm3j~_UMq}J2X%kqsXnW9koE0kL}~R!wKj$v{SgB6MX9ZH=Sxw1D0Sn2x7zFg{oSbu z>&Q4MAsG7sAj3T!Ry-vM%g(E=C-iqQwohy?gR}02uHF_mCm2l-r19nnlHX~YNyIt- z`o~6}O)e>kF9eSM`p3?kG-LqHK;(T#M1V9ZgQ6=8J@Q7**z2 zT18&rpr2v#i(EMR_iF@4Ks$JywXfCtwl^Y_Beswjt&IxOGOH+d5B)@GU8ZDKC#GvT zq5`X_e2qnz?~fwp%GzYA4cXMr3&{<5H^dfLeE*xneQ2ppVJ5U>(*De+VAZ)uPcf%%p8mphjim1-v1I#L2D9!IFAN}ap zyITM2e@#4gH*LK=JDw0&_f}uCXFX!+#|GdXt&@)EAk&g-4{?cI-LR*6T@Nol9IsIi zFS|PMz8;v5Cp;#(<14m>wiRiOsCF|>M0#bD3$rG{-gjI(|3}41V%C2^ukcsBC-qwi%aidDm&#)92p}fn3NH<8=wxTppGh*lZ!|{ah?*}rs@o##W`FP5Zmz~{k_>#(9 zv_BR~qSU!_TIaQ}$}|R!G%05qb9XJyXtsZgy^2Z1-n%w@0U4L`XxpTDjvmmfxp!Rx z9|KvC8BvIl0Ck}270&jP)TnFK_qC7TIzn=JwVJH9tvANvg!rT#KObDS2|Q9|pa*^& za5|ux)h;_f5EdnatD=gghe9kw2(KaV#a13w3Q z@F&bPYyC`!2#xmam_>41uN*rO(UkrQl3tKNBGP~zyC3JKgKcwn_Xldk`)bEFAI>j? zaysX^o2ZfGO;AgwIe%(EbsIK`L$d!pZpoi0qK-TsP;Gu(|9c&Kk3qk+YvM>+ z_|$Tn>-slkelNk;m;Ax3sUp4Y13P8Yu*BeAcd}LCC;3N#4VJ_3l)Lm4S z>R#d$8KI*i7$xP@yH|UzS)m@LexLe-9Y>;>&<`g@3_M*5m_LCH{*@Dh)K5?3kw^wfu{`6P- zo*RO8Y2n85droWjX=aFsm?z1|f`HXIgS&HD!KLudUGQlH`jj^Ltj;~<5Ny7Wx)QPS z(rf{0g2a+7!BYR#bi6=H&ja93JxbMmtz^E9G#4gcg$fO+wSsm9jd^SDBwszIF~#iMm}1m`D&}_Yc0js(U`Jah}g7>oU03&Le^I{e=kRwxVQ>nboe*vZy5-g>Q;QPC%bCxN|9cRmePaK#qeK9ZhOz%J4&Se|-Hu{*d5575 znSORH}(RXD> zHhi_k+s77uS!IBEqPT?bcbnWN_8?ga`i~FLk%gL&9vs`MB~Dl?dL!=PYQ{RIXsaS> zWttHmR%OMyK&#N)X=8;8V7yRy{Ir#aLhjxChhI8VPNIvSD4*W9GyF!IKrILw$|3PV zk8qUXyUM#q&Tn+-okm=fD3;iuQ#Q|H(M>4LSpzuoL)vC#EB#+9)s!J&3Xw8F4ig3D36s z)%$rstM;ByH#wyd>M5bW4e07=_n3}gIY~IyxUCeAk%$0XQ!0{Aqiwi#RC2DQSg1B6 zIF)UTE*yU>qlhBus4T0hNM@-n2C=nV$tC=bTFS;I4;u=;A@lL$=Pkz$NlI-fM#YLL za$oGI0j+cd>PwH0KN!2^k1P~IMg15k%wsX)8QiVPEK58fDPhRej9JQ$l5H(I9iqyt zz0y=_UYZ4}yKKbOT+67X*{n3j;D%h9sI3=yJIK#u4-r+A^GcNxq0=KG<&k#Ay0k~$ z6kHR@1JvAeFwU{Ph74*EnH?`^BBulTNocxKk8)d4vDg;>0Xa`><bC+Mznj*!t0#gYywoy)tA!Rw z>Pk6O{SGWOXodLBOOHNep}qL{Yp9jhCQGU|dh9898*@~gfAit+bO;S&U+ERyOi_Br zdz-77ygt{9)qWnZryF12pM&+PX059|9pm4A>wOccm+cV!7^u>jO`VjAbn)>Jk)A;U zk+O~R1QG252V{K;=z7iUaBx4#Syj}yIbG%q;=Xa$>YlHeeTA+pE`HbPGbbLg{s^T% zU%7VWvr51|L?5zIUCE?EpsuR55Y;%-Ma`-8QaU%i+!$bOO}5!`5n6NhSqSo=aDo1v zd=)CVn1hGlVO(QV^jx=PHYNj@8+S6dzj-M@0^HSJ9O+h?F4)LqmuEz|VXLjAGV^}% zWx0jkTs>u_wQI0m237KIr_Ed}>Uc|C0mE>@p{y|QkIB(pSC zGEI}JzK}*KmSko`5L?E;WJOK%Su%AOGpiB%zl#gAZE(-rS(uDd6#st5AtCE7t%;jn zsOlh@o;GezlZh{iUS5oub{#Mi7#_8KF(_)81c0qQq;r@rZv6@ft-l03)C{7>`>(+M zqJG-(TdFR92FJ?SF)}nAGLgyY-|wGa?tTj%_ea7Xv~BT3=Bqoof6uSKHz#31y2SWa zpthp|^6qN|Iyuu18_?eIBdkQh4UAl1->~zT#b2I}_Tovte$21dOKiT?XH*N85B)y5 zh6CdK17eO}PKxwg!rUhmzA-m;rzm890=P{n8^}E>4<+tQ z0TcI&k?s@Z{?Ojn=v|rJ*>UXIJ%Q!1&mcS)DW?0p!r~t!`Zc90vMbMSV=-Qfmy9b@ zfh@>K^*i_%&P1WP*8+-(2771idjZ~?pbJ)!9~I;P@&-5~f7$&A<;?e^ z-rp?BcETw9c)9JJehy7m!6-%LN-BKtZKiav$$}`AM{-f^B>h#XN=h)!DZLqFqQqnBD5v8#wGmE z@|??-`IvbzBCB3TEImS2*M#v(j$5k5MYC|)QrW6iRCq@uq3b>yq^>49FPz9GRhkkd zmDDG%9-|Sy5Y)#Ne<4Dn0vc4+zpM(0_xrT_7bJW7(;%X$kyP0wmut#tf{V~^^-vt; z&yhUHczW|UKqP5L_F#^${P9vtKNFYz8yf>mD8WR1Ayg#;M%yC^7>%Nzy|*~f{eG*)N@QG0U%ss9K$}= z!{S8bS9FvW?&n5YUPl}u&6hz;n`82q(`2(RlelM<3aBiR**ZzR^k(h zv?0eBnSX+K4!u=_yLrI>HPqm) zO63y2Akb-fSXxS&DUQmnh&`^q%p?dtn;JgV8ccMTwfm#JS6Pg<9DUXZ%QktpCutW6 zFkA1~NB~8IRWhG_3O8df0(L-l)1^21DUMvdAfAc+sL)K`!mm2MFS+Mw?Tv38V}v>7 z-!*GAasgXnkDsz2Ep=#Ah_<_WfYLyNuurcO0OK+rm=C^LH;VWbXBK`mSq0Wis;fdJ zgQM2(hE5Fx;4QrM3BVnihJ#pQr^P46m6Gb`IcwUjp*JhNZHOjF^}6~_yMD+5Nzl}# z1V$X!u*K2wrWRT8cumGrZ}m7}s!7;Goqy!=h?>GAT|-quc`k0Cw_pDVxkbvKH6#%5 z1v4mc1s78OCt;L$Eafe}<)QA9_AinQVg5J$7;Z4GD)|{?BA$uL+&HcIlo23gHm8~; zdzgeapx_b@Rt@$dZ!ZBbhCELp&DqL9(58^nXsppOcvcKuuBQLdO~fIzV(+DC(lkx7 z{nKZaJ8i7ffH%m(y_>X;gh4C0oU~b4GIY%f>%5>GW2-R7b}qoSAk&0+rTVZ~=d>d= zcKH??XuL$|g7i4w+}l@*{LU?~&@8(kZ?!-$$EIwRo_|x2_M=QA1_6Q$H`thB7EQ zciq+1s+{44okt@Vt?+N;$Nw_XKL;^x%re$bI7_qyx2 zjx8uKADlJ&=*6}4Qy|;>>rHM)+2XmER$zYMGZ2EivZO{zUGP$iRMlJ3>QxHsR0T>U z;8!%`Wfjc+Omoelt&yrXLH3eYvC}yNiy08zoo|R-Hh?1oFt!8{V3#GJWX?ZRq*z{b z9xL7swf{FURYnJiW;sIzY2}tzSoDr|C{VZ3z@FgaDJ|ENx@+sR>v5^JF4&^{OL4_Z zm7VK)l|1=_B07t!!JxtwVp@n9lTUcPzMVP*2g954w|BA9Rynd~X1-mqD6`;FOKpA4 z8R}Nkb7G&6UQUcQX?c`xQ5Uyuoz6M(Zm)qZZjpb5zkw1Xjc-P2oo+<>MF2K*-p!7svp!s z)|M&Rkiu+>BC_HiuzF9Be6sm3aE&{8(#F!dqj}M%D#qXv`(I6NBjKAad@MDlNt$5L zb{P@O@y`;1wgUGbz}@^g6vW0R^AT=yyb+t(a`t%6a;pfRu6-*I8q?fPY8w`-Ie{CP7R@$Z>&RD?Ib+bjOfv8@%Ur!UC`4Q z0W>5P1ylWaF$1s!$pphwic`680|D%phT>kjDu&t+TU`kHFD@z1U{-oK*x$QyeZOaG zqW&zMQOF3ql((zyFjye$14p_w5L633^4i<=fG3sR2iyI3W3%-srlm@FLxy@m!;$r3 z9FW|E-txDBqfNy-D)70)20sDVdXZ>Hl7D>hC0d}~is;9sWWss`h$d=p9do@M&rK4O zaDs|b4|@3?DmfI8prjFw=upJAc|f`x`a3 z478V!ew@epj5yZDOhYZ*>#AH0vsnY6-09%sei}vbv?KKBHCr;3uJ2FB3$AlbCQ=AJ zP%z@>KE{aV;gfOP%JlNi7+n_B9&026fJZJW41q(fn7&RQLG%QHdUN3hh@5E&*f+O9 zO)wX&R-+3gqw9kv4mI--hZika%iPqIHf>ye)3ip?70)cJp_PaPC6tKxlgX zG$_j~REi2WT?7?hb!!`REJh|S7hiVK1Y~h&J@sr53)h@@4yuIRS2d7Wxo-tKm9_S0 z$xMkC9c<6g1)p_aEtm>Xt5WlLdsg zTuIJbf94w>J5HfJlsCO%R-Ds80I9Y)zs!l$546rT>y08>rwcL zW5!n%IAus(_MXigQeJ!*V=e_Q2CWGC<@O$=butuW-}gvVi0%Cl->f9%UK#4;fExY@ z%~VBj;kZ=$K<-d^uxezd%ERVqdtC9hi?isN1E)ue5aid) zxdPm%Cp$*sp^2VY+t{MUH6K(=dp6*!3B!$Fu6sG(~d%bw7ag%Q$X6K>;+d(7tezqeZNoiwmvjLY)i0SkkD5B-_$%kjo}?@b3rOBGMV9G=8=aMtj{4TMD84W zL?lm`c}ZN$O6FV3EH^{t#{!Ol=VahjtZumApVe;vt9G1gXyYM`*sz{={Lp-rENra*b6J+XuCBR}+}~ z=QzvegakvY^NhiBhz6C>(9l&xR1vlfajTdP)6R%;f>9g)qC8HGgt7EY!o;h}HwyV0I{m z!bJgssK|@uE@X*uvW21~zhZVWU>!DIJQB(8x?7oN#>h}qm8G0qPiB4&_kn*yuTL7$ zhgPoG09M!Wc8?9{@Ukhk$2+2?XZi4627J{ zf`!*XboJGHaGYaun?I}4xPNhK;3&?;oxO3qo8_LUveaSO7 zAWS90`MJJ4UT(@-A3feGddH*x@Ap<4RSE3YhOA2tQwiHV36^;7!)JO!O|v5W)XzHE zI?i#y2RNmC&iLV^X2k$vUq8(gcdO6>3Qmten0b-|B1OnES#DVfYi^ozhM2fPb~Agq zv~J~!n(*t8>bHX=x1Vq9`5f(Of9~vv=DX%eZ(A;AS5jRD4i4afVuauIb@W!z*&;-$ zTlG0Q?64nXot$aUEk-;m!}fN=Joh}P%jz%dCWlrl2mSJ~u=|M5AXDk@SvZq0rS_s8yep7dR+orew($Vc2Kiv zpq7&BGo+!&$Daayx8uX=?1eS62z|5xYFs@?hxmN9gSDgYO%W$R%5lgktpvg)%kA%8 zpl=9k;4|7ZUYapadnl{rf6aDYLnxK09_MjWr7Y)52+r7QrJUbuo{rcRwanp;7}!R# zmI%Z+dhz1{1(ylnDBVpXuKC3PBN|+{R}xGgREuyk_|%?Uz;><~9wD&bFtu-~yU?y?LKN4Zw#`X499Z#j1dx5q?`_OH$0Xekv(eDE&cOzy0d}z$G>D# z5|dA@mXJUZbE0y7OPfSrf>LGXqQgr3dj35FSq)8Qs$GtVKCR7)+KVpZ^s}5gYi)n4 zXt^((DP|GO<*HOm%i2wIXB<8PcNA|vczL#sLZiT7mk*5u9wT^o%m3~f<2pu5{Ia z(JH$_tN#(q3sdul&SP(b2pzwfbSBA%(<*hRWdCED_X1 zAF{{HA1hQw8^1$<(?p!h^N6Ee{JCa}K&L zY;Tbxvrwk5+752v=OITN=ubJ5x<76z3i$S`W1M7P!6vJWU}liA!p?||&7HP5jHpMyxaD?mTeL_-YNL;Nx;bi~v{^lpWWu$g!kJe2H7EGtbd+h-;7k1Qou6>l- z@egd|o_~-fh4=4iEtwn>7hSu`?4sHf6Tyb&?f@leT%~DcTjCh&Na`JlKQB16R?_BW zw|YbZ3CC1)kNO_QQ;O|IH;~_`=xK*Fi8jCwO*HHe?+D-7a7Hv<1y&%Ic%z=$7ip+KMG6 z0_}+yt%(rjXYC2-9L$axO@_+*Q%wfTtm>l*@~+gqGei2InWn~6Aih|20K)Cp>;bY} z`LMIhzF5IGX6}GkiAXC7aIYYNnuzM!F8ah-VtD&YR=`Po#ziPBImZ82BFfVFO-L_fptKo{7YA{Gm7~ zFC7D333VTbW2~W`X43PJONd@@xNZ%ZKkXJeyW?5R%6mFD;(kVdC7$kqx+^5-HsdiI z>}k;P%e)_nVWMsDzLAy@u-0MsMRQ7Bl7k*b2m~#eE96TF@V>OU0}t9FGx#TnukLme zZp=4X3&_KB%q93hLCuf?&UkF)f*yPYs;n;L^A;7!F;0XUnsE;Cofo^g+w8{<&W(JV z9Va;-zURUFyJBmb+27O7nG=Wz;Ux=R?YsE8^ulr8y7H$E&a6DyMOV??=1|1yn?yvs z-%&d+bM&tnWo9zI>1p${XvL_)NQ#)~qrt|I zna{t#5Ko+@?OFP0)zT9i>PDe>Xf#xnv;|(+TJE&IM#G6PCN=D0;=mSFHDBwY3>59^ z6!LvOX}nn2@UJ!6nzqVQ3(taMcxhe?VZ` z7W}Ss)fG*BH%n%HhK2}Mu5mR+W_nEBm&p;Pt$$2LFzqS-xSlksYyD;`x){$ zlNSB$-Cy9Pz^6+in_&0*f8hpF)5*D!8RZXbKI2dg3u|Cc>!Mh)fhscn5dMqWg6lw? zFB7I$ym`1IrlBR}YsR}tGxA12XO7=mfn$$2ptJ7>sY97}Q=`L|d_$@oR<`-H0`5tc zjgRj#$4<4hMz zoObfpg)K&~kBEjAVqVSaAyj--i71E)Sengd z3)z+P=5KD}ZIo6g0t+c)65FCr0gO`j`I3=S^PD^@K^HzhoNk2nyl%XIb8|jD^W|I( zJ9C*Dz>ktcQek$@3GD9mNlr1v+O9<39LS*2InagWwMnlQR>)4$;0p!il9|s^>k)IN zBOwnv=A__V+Bwl(C2JResHD?Kb}ofo0-iCKMI}!04zqId2YIX{YJ4YeRRKqi-s0!) ze-P&wI2brL9J4bAyb&=QZ|yi|+Ul=077}|-9g8~eCMZ7ni>NV#G>&c=<@)=A%23wh zzG@^yvG1s+(kqsJifpE3yb@2+KO^mw5G~RzO-`UM29 z@-SLCMD##PSIL=vA4_yvZT*)Qf<7Ai^_Mg!rWRHY(m_a7-h$&wWPzcK!m4SVeU;Ixw7pxeHgm0O2K`87B| zK357dak`#DXhLR|b*QyT(XXWmS#f!p(#8B&rE%_lcJ4ceOFWE)B-F(bi-&^6lM(h* zKJ1Od9JGda&@6}E8d&YuCzTeKI_v6e_okr%RVMDCcH$8tx*Lf zhFpar=e-E7x2KD!&YfpwxjPQ#!*plJ)|TOr5hKhr=$-{O!#cZe{(-yfCBkvs zv#*WJLw0OUR4BGL?KQFdl7a-&#t53D5V^_S=TM&bsJyeQW)VF}VWJA?qs`k{$m<6=Uw^T`-2^eggnJV@Xn^S}Gk+D|Wik7JfO=ha`pVu2q|!K44bh2L`OD zdm*U&;Lg^ly5?w;vVl1lf^Kx67b;uOd^Go3tnxQpz-&1`oJ}!V5g5tmgzf*`j@VkR z^(PsI9PCnV9`3|7QzdHQLf%2~C?w9?#qb)`uGZCw>8|+D3u8oFckC;au#>U;jV30(mKu_4z?3f}f zofl6LU_@+x`HK0wY1{(TTBs%CoVA_zQavs|4bUBiFj#+y5$RqIo{{s{vf$ zMjTa-3VDTRk`kxo;2SvWk>>mreWmGEDVu6}Z~JEllhAg)`!C7~h@m@LLd)&T zr;_u=gzH;}GX3x)ean02!J2-%#XBi)MXY)#?mx=~umUo2{rn%h#g>GDx4g^?AnMuK zWLi+x)u4TPX4{Ml@L7%ZUF}NIwR?6yXup5`Gnb0^U{&1p-|yk>>+6=dya$j^QT6pT zjGvvunV*}}G1A<~2{N13`c~2L$mM~0+d`C`rmu9T)06+xko@nbkmu$~D!$VC^(#W7 zEK%|d{IE=r4bZK8N~L*6PQyoAnNUn)YLlax{&~68!LD7Fh)(IBq^jVb_U?rA3F-`r zo`cw4)XBtso-jE42| zSU`WOlJ43pMmHP?#>0QcdNMVl7-TmNBk%U8-x~*3JHlDPy(T)s8jxqNKgFl? zv@;eiv-y~}*t04XZC;&xMD&YI`wdUAC)0SwdY6%vxpCf;T^JiDTTn4GH?$Oy8Q+M% zJrC_7h@c>-{bq2~JkZFNadkVb8=KWK(u?k{&9rg7;$iN6o)>@4#nT2t%j3RX(`;mQ zrU2?0CC%C3Ztc5JB(@HE1=(CZ>1-%1yNke|lws#vFfJ%NM`@iY+kR{L^=<@lRXY9^ z=8=mz>0N~^zxC# zU7v7n5?=Q`1DA|=EtPu)+Xx$zU#ak{Fe{0ii9D5<@yvMBoaMK`3gx~}PxCzPTSNB|>Jy&#s0y*GUDMBY;d_rfqTfkt2Cigd(?*H)i zPSKr3UB6~nv2EM7Z6_7mwv&o&+qP|+729_5k8|ofJ>E0=>oLx`>h7C8_P$zoYp=PU zXa430=K1EE4cK+FN#RE}N6D~Fk;`KJ2}^FaGZF7XM$|{O2^!_4TY?&4%!`A1z~bA_ zskpavnp*yq&**fJ5*eb;^#uDkh?I#b{E_MlY5sj&6JW{r$K9GqxUC` zCb(>-nxJ|}Mk92)F3VLkV^LZv2=uk^q24LEDUqpEEQ*HNq1(#Xdu(M>7PO;=>DJ2@1BaDScNB&8Ovw< zM$xyu?(!FTKs*u-@54Kv$=TR2ApSH_Tvl0CUJE0azPa{gy(LpJ4`O-dcTsF-r}i+Q zarsMZmwRjz98m10Tj8yYiYW46OYfo`eTm%(nb_K zbmTI92#{yGMDcC<{oQ19psjNMWxoEqRevAn#}-%r+}R#AK)fic=!p+7O!HjaB|6_2 z{z~EgqghxYQIsq<)IHZG+XTqlm$@%^<GG0dCE6Z0(3nJ{B9<;Qdr2 zT82IrNr_BPzMDiDx=wD(TdWY~L~3S0y|M5&t1+w7O3Q@JU(wL}Ck;y@|Q}}=fYm-7@>uyuk z7}IZbmzUm_GwVC5s7A2DCxiQxMuI4O23$3^Wjaz>ScRe58Fv`uL)NCyCyOnqbwA;gx;Y?8 zkcg{~$9SsmKCaS0AN$_570dc)gH_sWr5Xjwvcnf*oDHzamN(wqF9_KeaSH8IHF^%C z7uka~`~O-!@!ZpVbZ%p2o?=TGn~I7_a7~)ail$dpgE?!|h3YDuv@HuMgvd>Dq zYXnxHqil2Y!m?9~@94Q&F*Wobr%fsJ7|Bo3;HF0LFr*Qv#N%cBh~Tgq;q^m!QJf+y z;na!r;fnL1I#lbmEUFYWn>{zAT%@H*f&QlylWph_ui0)TJvhfXBWXg<{Yb*78jMTa zB71TGJR~~K86$Ow$|sf#It2FJ?ASBUh!m-xPn6sxd{GN>*#w6IeCMQKBHNiO&nSy+ zpALyum6B~p%oxQSQ+Tcw7=QA|5QNWZzIg)I*^P#`5PxY7oZlP;36vdDpi}zMJ{WcE zK-1A6M%Gl0D3w~(P?*T|9vj3i@;-ozJD3G;bfI{o!Hk3Ad3G=cBk0ft`)P75Y0+{o zGJVN%{@o)>{%}URY#`a!dC`*g{+>N&biFfllVXixx5b%Ze|O$pEY}hiTw1^E?SWlG=dl-2LwrXWAi7KE7nqDLMIc+q zPGBE^VV~U?Stbe=DM&9+7qfcmV3W?5$KzD6%H}J%(r=3-3l?4IMus~688skrIL9p8 zMUm2iLyY~)TqAyrViNsy@i$Y2RW(Hc5}ACn{E4_{B$+zsgs0O4P6;H&>CTc(R&yxQ z!BVuk&U$pxZDU60DAD$hR$b}@J9UYQMd30*$x8*Zmo_>H=Bw()>mnnOq@|8!GGg(S z4fkMjXrRZyk}QX@eT@n2c&EH{0|TP2?Yo%BH~~S4qk&ESMpzd7nc&ssp>=w&7=fp_K z=p&cf7!g2y!SA`mNR`!JDXy2csS^Yq!OPec0@p_WU41f%23ZtI_oZG0mJ zz)qT^3yP%F#5AL50v;23NcaC(|8GPE)El;t*KUtLA{Im^&x?!Ehl)sS;bjhe=79~5 zoAf8$8FhE4a4n<+|S&u^3sFIk7$#qJaNpga)28!d`enFqk1eWHr`0YeM#en zbcH)?gH`>AK$~@a2I6v=b^82Vy}`$RUS=V6@VhvEvGD)qCkXtzhcP@(vF*Y%Pb3F37y$LUR0qW$f@xH_ zB$F9{QlM=(XqNrn>c#bddvy*4XsZ&ftlb#33Qkmc~`~rf;ZK{&W)lv<*n9&vs(X* zxYt0+s~%1Fut%NJSI)s5p2sk+X;Ec+Ymr^=;&lg@Y@{ZrirUe%o^fM;<JE<%nET z(w-}NGW6C2u1idAK;R9{uS-Ul&pj92^lIyMG8cPg>ju*I$YARbFP~+#%d>^h3)X z+7HPOYyb0Xw4}Z~})n(|NZGpd7az_1iVKmDRN4UjI6>#Uq#48D6BGD%d z`$z6O>O70zT$#CmvL(42Bq3PdCP{^E)8NIIHi+Pmi-XRo<+UJpAG=?-{!_ilK{%Hd zGrUy`uCgVeW&xTPcNS&VxOx`;!{ViCC*H@GuZ+322CK?Tq$z^$?>IiJ71d@oQF$~(a%oP}CJax;Z8unQy(v!B>J(cHCNx2zhHX5k$6mE)5gn#UmMsLaI?aqvc|{tKT8beG!|eqF_5Yi7Ps`@x`BP^$b2z(iEtln z@Hz5a3A2j-8lcEd$En;CO-&BeUlaEfz=xAgl>Lh=apv-P_6c(4>2h^AKp$9FEG|4S zRiusO402L(KoP{<4~06TdNZunZAEtDyYlG^uSdYchP?AA@J8G&dPV#sH9ZqczjI8Y zx43x$BL@aA_71`|^6VL0Dw!+ptpEEsAPl8UJdv57!nL|=o*uyDu)MDfFU#?I@*9zS zL}`u3(n66eaf)S;9iK@qy$SpOgs^3xTorrETip;Vh2=j^sq2%KUn5`5a1L z>f3_tKfB`El5apH|6<#pHuMEArga+>3p>ff%XB))bF%JB$VI%U#hvm^)VeVwj5aR! z$`aMa8pf;)C`HqK3CCD+B!aQq2pP^M|El1oV2d!uDb)Qf5U$zm@3X0LP2doVzx*<*CxY=MZ6lA~g+mM(2w-7@N7Rx-uek}6Zp_P@Zj zUg-+6pE>@p?cu3ZqRDm0v1MhsfmjQxx%;<{BQi6YZBys{mQS66|m=y`GEU6%m9ayH`J0k1kBS$R~F_3etZXUVtf_#JH5-LGAAo zHNgJ{TFWoDY{@8PXBM5J;w|w5CBvE=%2BYHaLL}E8&#TOd{8K^&`p_r{IGI$563)` z=`x`FSPTY6aTZp}KkY^|h$j{{GZV~lfF&dj=j9(6d`2w(5@q4X=h7-3s_Z2EcClhe zVyz98{e+U9ixg-< zu2z3wv#=G*KCql2$m_0}?^_`G;JEXR#i*x+DtY|mh)sXpa6Pl0>fF1(58f||^+oeN?^?{&j^+jt(27`tP`j{9Z0XFbMg zb;p+W`4!&#qP57@P4xTGeGqCsIFA+LKs(#T_Mzpl*gBg#sCRDQvWP<0S`k3dRyB@e zNo77exSHBo#)3+-q5<|bNP}a%9o{NT^H~d~cmBjYPr*`v)J1$dN1lt2M~T2{FXpDo zLoqMl-Y1Mb@BwKaBg2fZBZA$+>#2HPO(cW)JKF1}a!LNj5yY2=oWfqdzkl0u&mV8C zf+|Oy#ndtQWI85vb*kVCJGcz`#kzQbe7i28H1`GYVf9Llpt(wngnTpUAw$%O_ zx33*kG*@ER{)GJH2rHb z#rC?&^tKOi!|~Tip%afYua!?*U4kEhg4@%9K7Rn~?sclr_0WU(u|bjA$*eFty(M$b ze~>eK>8+U-t`0C1zxttvu7^H72&nC^b!S*=l8_4!NDGfHz zJ%7<-zK1O%x%Z*HuP4G`Hj2#6Cy`2gwN@qxU~9Ijw#NuRAPtZ#mCptwA^>`yO{cMylM`CPTzG5WiWWl4MaWwLg@b7!Nyt-6NW z%DHqt+I+5hjjV#>3~%1yD|lbY&YQ1C_ZTb&FnsmISl|VUXSQB0(mm%>`rWHyG7T@k z>|&^=52f7Tq3z(|^k%AFA-z;B+#`(YLDGt1m0vNMfoVqdp8-~ZC1}i1kk@BBnttdM zU10U-`O|$ggMrhTnm+{(JS@6HRD;!2_)+kqeP;+w%as40B4=N0j+3Pp-J;Y+{xijc zY&UkVSh&a8jo;z4VQY39U0KD3CtxU>F;UBt#wJNJj&s4w>SLPz7?e)>++UYItKY(Nv{aIlNIuuPNmc z7&P1^RcL57M%*h>wxL|e*7}ZJUHHLKd$rN2`jOr$Rwrwpy% zH!WQYBcw{`DYQksF(0~gIZKi7hN&-(Iow-f52-C)=8;FjD=f#HCvP|k*$lsp2V{e; zP&;@1j^g`b{iV!^CjK&TL-~=c%#H%V#r{&s%PZ13Lc)F??w;fUjhh@j95p6QfFSzmOn{21b=Db(s*Co^N;%T(1DI58d zFqXvmm|DgEf$s)BKOJ^IoGkZMUL}GJtT>J|d@8Et0=VEp~d_p*s#b zIlv!wGi3xH@0F6h)_D9{az^`i6%>3tA0vA{S|6{@m07RzKM8JLy^a!jWqP7Bs+L-| zAWq-?Zs9)HrL%LZ&}Q#x?z`W=E|o*6^^JVF>~q#M3{*s!GJwMXN4Hiu{#$qc{NdTZ zyCA43Ul1oBcfz5eQ~#33;UcgjAus0=8VG+j@n=)Tyr;xzQd*79)~(J~C2O?UP=&MH zZ>;mFRpexv?T$Csh0l6%$VVgaOQHmVll4_6+w*S5Enx*q;5b*E>w7(LuOiLT%+_aSN7s57KSy1it_hq)i z_&o;|tObdRBo`s7@J!5YF%;RZ!7pEbPQj;Kid`&xg&;=o9A~A(JcdQK_%yx3d(LiP zAOF8ZV5RF2MiwarXht{MS*JOopft)^CyBH%!x|{VY>@g2fb%r?6{zpUGEU4(l=DD2 zCpRj8aoE9>qGRgOkDZ-8&V+X8z#Lm3A3M=Sg4E+Yp zLE!dK;}%;3`RGq0^Hd}oF+0c2y&QPv5AOgJ-1WHgC*|ONeB{l#8FS+`)q|NN0;5K5 zpAp{O>6e&cO0-#z0`5y8Q#n(I=CsLe7E~$BQep~(=8#y=lI!AdWkY`%cg#w|y|i(q zx=Gj0d!m-g#M`?ScBbq5cH)v1SpWM7M1HI$Yk6lH(tb{!x+ki*9itWP+G{_unR2xH z^+=~UKG=86yF1uvE+_L+I2Cg-%8>R18dE9@Ynn3D#|!)epUZ6_@ZLr~!$9U%#A;ls zu7T>PZ+7C(*tXTwYj>cf+tN>CaafUx(_oL@gmCj!Jqx2K*%pwWmM`G-*G_tuNn-b5 z_6Zz+xjbeHobOJ&p$z*lpZ0=`U#L6zpGQx7PnEKHey3bk9SRFkeG;Ra#Bju9pzg|j zOCd9BxC!l#E=|buz8UVqo~b{!seFW?FlU4})Db7Wln8fmoA9myC>%cFY#;V;&CDag zV1X?BL9$IX*9meqlf%hoIc(Z0d}?hJI1S(;_}XGKtHz)Ql%84-OP!d`Mr~!Gnc!2kjl~L9cgXoT7YW zIdtkz0e&|)7_qWrIb_C(FbKbA2hO$3Z&`R{sRl$kOnZ-XV0(y9uk(t=4dwt+Ywl^V zVD0oziew^p_(mMdQ{U7McYjm(o%8-8yK_H&^pJMQ&T}xmq(vwW;8CU!aI6B3%V}v z6dvCCW9mCxy$MCkr?3V*$4WjsSX|VVLT6hYx!lgT8kNj*FOT0cNcAO%7lsd(*N+Mk zM?3XHXCqhOcNx-ITw0B19wNKgBe?`w=1|cD<`@}d{kW8r5-mpv-9>SrsF#9n8|Io-vAXS-D&5a?l}gD|48ej z?^08X$LfQepB_O2x&ZXV;ET>&-1>9aNmyUkzs)#5_vRV%{CqYuB==_2=^uq%FnfA3 zJRK9&rk}4%xVf45cgyLeXeKjqE*$8_}1Uq&~&+yz?{4L_UsB-pN&Q zrj?^5BY^d-dXG<^C9seI9sjM!K>mYLX;W-ao+t~|o~yCar>p(LD_oUSwy=fK(A8fF zjJK;@DNJJmY%EiOt?Q9*?U|N>C~-7#|;AiH(i#Avxd02%F=d1_)FM7bj?lb z8utPHFQ=fPIj8(S_Sc#Up5&^0b>10q-F(hgrp?!z9l}NV-Tl*wd~)acEZYm7lKIiqy%7!LaEKRzw=cEb=E4I^7}YJ^}DLdb>jxy9oN1N zh$9t0K7|0e2K7XeIPA!ImZpl`^kDQ;(q1TC1N6LG| zXkiw}HCxU^5&Y}4y^{6m?2*PghM-5@>i4w;a>cq+d7^jVXLcuO&xg_c>*f-j!{pE% zvw2{h5tcuDc7~k9<8pam!G0>x8^98Bn!*FZI;+Ka*AW|0jf?G1n~<895+iP$cao8t zViu)_GUq&;W<%~o&FOEN64mmnH^tNgST}|=!KF`s@^G%HbkzeIAF){er6dX7wOAkG zb{)rNlNUP6!RR4P2SwsnV>ORssn4HnN3pfxy{tG3`Xl2 zosdGSe(N$7leKHaomWyHq+e8U=9xG2w`VfamTrNRICOwxU%v!u6BzS{8*hBL+v{aJ z+Q`pP5pGZXVFXF$WBG}iqyqYR`~Z}`aPu$3v6lVy9!EY7dMw=F*%lGExf{O(#1{~t z?26>dU^7W6aarnmbk28fn6Fw9`{FBd7{_p5T-YJ)PALO0d@phBF}9L6TuW}GY^P0~ zqBqh5s7qf|6HC~|lT@r$V>An1s!5>Q9=~`rvzYCYwyt6<>AqqtH31WEUWxWD#@M+H z-?i()QcskI0^Oc8);J?&ucNH#56l-K#oO;O=dykIF3LXH?zfr;A;;t9h1#nIB*F1- z3k|+LKUlx{?eaQ)qDMWV=~~-PPhFor8*T);s+*9|FwyIb;dlL0$B-ah6UBkbiy z{_$Ajb-xh%&o)P&lDQrwFzgt+*hRn=O5JkO4YJS_@j>3!mw7}gevC3Z+#~-k^URKa zC_zinKIpE0u08AFERV>r*LGi?YimbH`mM~=3g@dF-e34znWW(4jE_0wo~z8hqLoTM zUW68Qgey~*yEriaTbu7sUkgjHA%tBbFfH6(1h`zK8-AD0#<^bql-R^-f9^ht)6JPP zTT(ry{rR($dXi2^bcC80@CM$PlwMvzUGE4q@8!B5cssSBfjG z5R4T|UJL$c*rs@(Rplj|^mDp0>wCC49RtoC|%4jE%!xw`_ zG$#FMy}BJ#|0=e{GcxhomO`k+`R<}IHWjG3TIPHIJ(ci!_|*R~ZSrJZyA7@Sp7_Y> zJ5->2b@S%xSMcforw^oT_jO~t{l1jYf63`tx2>ZukTrrz6X@7p&+_qqJ%Y!(dC}lF z!TErAe7|rbaJif;II7cWypKC;Sicq+GfbgP_QB^ptD^^Sl#bPw_PPJB{PK@iv(5Fn zv(rm=cMXi&FmQ#zTzXk^hWacR%&UwSzv4#w_X6yN)Cb8$0GuT=k%f!Yswk1HOJ1bSa=0@&PH_Bjl*034aESC>6H5+mv=Rn+_l{WM`FsxefQMCjYI!T@!V zk)oaSCuUUx8^OKN^{qa1L6;w1D=IPZ^|G^AyjyaT2S~QbCFItje!e30_n|9xs#Gd; zvoZ*Mle>dSK$Mf;v$^rOoUk2FJ;?WdxZ5Od8Ms-E|Io-YymM7jysS7VGpxi?IBZV> z2QI>p!-+zV5G!ty5HESJ0H_8}CM<=}Zl0J4cA^FEmBKF;Ui2Gw3L+_WvJoneW)-t1 ziB3IQuoxc4T)MaPA|YN6_6G%hS$T-Bi3opWc!kj;OoZ5;{b_>PL33Z+0}NlTo*YIQ zs(VAv&tu?$?4K!CVgky{UYoALkz4QxAm=^-+&J;WhCpo-jgclX@(RFr=eNGTG((^m zdT$-ACHK=8N>&WQzaR)pG>ijRZKGMp)ZL1{lg&TvL1q=c#E{^NiQ=Iz~1HQp> z95o{&*x&?xb4xeVTVP2?LHlAAF1Ri*Y=C{ZrRTOQ^p29|>WFRgm zHUH?`_s7J#&n(cDkI^2&XwZZKWBS6+^Z9PkK>W|hSkg`m3EYh| zvKbOE#>6~XReDt7!>O9ESPaJ8`BAxf$;@6DutY0$lIcU(Qv@lvT$CupMsA%7Vdt&q zJP(CTw-ywBZdgdYWCThK5pwUm zf68G{x-YfgLj=N*#ZPGH=RyL{@{7Rk!cKfGX4_tHT3CACQ7-Hj{l}&xfBd|j^t_)J zK+>u`uv_&^AToLaW*r6@^&*0-Gv!$PqLP&?42Tp}6vp=3q`9|v(GmLKZzV&M1Nn1pSVw7bZ{1=iynvl^MT8Rr(ma+FhsT%V5mAEM8R)O zHBv1UQ#S9W#Z~R5BBtsGBP-~r4oh!zD~MI1i$^XCf#}n6`?Apd`XWjQ^Zq5v&S7A9 zMR%FOw;EVvAzbBTvl$!ET40hwB3x?wr)v7=hR+jAtbY_+^lRbqVn&bh_a9SHBhKPg zj#(?1!MzBu<>XNx}2le|f33|NaZ+RCJRcGMuag5!A+!+rADt@ZRCKGWTOlvO5Z8ch!!M z{8!Sg#lqNe3_A9Ht1sDLcqL_YeA?{HyYrO(c5&B$b$;dk+1iSQqT=O2n&0q&OWs11 zR2ZkGNmNc4Ooz_U%cTQQH=XPkb_S&7pLT`)s`V#7c1=Fqgb;ekbYky4M832xPO%D)m?=a%!8~<4zeTB&Gc|(xw9R&aoP{Ij{6_km zZ!!zlNjgggqjN%9Q0LtPf{{b#@`o+iEo}zvrYa?>P^6YTpRJaTb`ON0aO<~IIPz0e z66gm^qF%~s^U&cKInJ6O(?v)A4q4h+7|Fz8Zksm5v5Ql_I~*rH)t4e2mrH+Su)Ti^ zeQlP-S_`m%b>H!>`0O9(R{VmsJjCDm#rt^fJ%wQh={k@zt5m8l6=(~takzFFV$~Oc z`4#4~d=x)T@=l9OKvcy-6|qhBtgO$AMReiOcNQ==m&^bgQ0Ps#c2! z>0oPP*qoWxLv2c2?nzWwUk)w-v)}o&#kJ{yH~3B$_yxJd`z$O@AqS7s1Rz;LCjMZr*15Xwru$kK=L;n3 z`w3d4-GnZKQ>0|o^_`O_*el1%5W>9j$L~n{AS+0i4LKGKjq`}&N5A-%GUuIilNB#V zDCH?-k_0S@_v`<4Y2c@<{;QSlHccAxXCFh4$W$XVxD=Grq!Nmglga+goU$gVb%;%i zRh8saEmPwsOQDsM#;or%RGT}hF9>RO|3#+|@86*x0Z1c> z35vPj993*$NIF?%B|;_@fld!zcKIRnY=v9Ml|NpB7j3;)nnXt4+;YoqbnMY;5ch8M z+TFYiHf!eFd8Qg$%{KXyk14(L69MK!42)nQ4-E?=)tK)&D3>a#xDyl;n(o#xZ`H!r zFbl1L+L7ezVFnSup`lVG{+$P4agF?OVrHXI*%Y7GmCFh8f6Lg| z-F(Mtx~O5sQ9<^Tx8`^f&`NKb~hdwl^HlNoiu3W=a$iZPue_{6QK2(S1Vn z7mk=)x$>rQu*|ep{-%D^bD9tb5(#% zU~^`1TU%WyKAXR?BCe%Wa$j)x3)?8ft2n@N^1jxLBXK>m*iW8!vH?wJ3zIOp+U zZpp-{VgLt^& z(j8QPTX*~NUfEV6ZdVEE@;nAmUw_xS3*fb)816>N(K_Omfz=3_we5#Tu8kNk39XU; zOE_s&SCJ!A2v}fg$oiqCn$)=J2UcV15Sc*_e-2C@AWN7V7Xdz)7xoo&lg%Uv+~ChH zHjNGYI+#C0$8drW2<(YXakIdDlE3tl>lzG|H<^P#%=?$`d}#>|1IuY@SDSp>L~FP1 z6b8YjSG@!n`DT{#PQ|;%dPJfxWVQv(q9hyhWyjlxQkRlQIQM3&W$e5@} zQ^<>7@1JdD&5dPziV`SaI7IwFQY+zwS}8g3M0lxk+f>l9uswmoYW+4UGkHbboEx#x z6MqC<$^N=3kD4N#aX!^D-{c*5TB$BlOIITFhQ!BKnQZDCCU{v}&(yWvaG>(1UH*hb z$}S^aT!4!B%NxX-U8_`Ou1BZIj?=ME>IKS9p@0{yI2 zmiLouk{A{D_urW;sRO*4XvtA>FVyOv{D@CkQ5fMfINZ@=&guSiG%jw8ITDKGMZds- z6rdHxJmGb9Ri&b?{Ub%h3TLn7EyBEX@+k|~wAIG@Ym-PYz$l~1wuXtF2S%j&nameX zmjwT5%}uLE&v*^_(f6R9j%A}=XQhPa2t-X+_}qgG<^{GtS3Ezl`>U{&36BhqHH z$@Ylqs91fRt;!jWV2`<*-+H0E@{iEhACfK@+8J(pC)uv|HAqS*QxYa}g)*Fnp z>iACAnB=pf0WYc6+@~EgF9|*X$$G2Gm|tm`_d1ix=5&mC8Ft|q1*V?xCJv4wHWtNC zme!%8@_KFZKDlyyw9k%DPPuO=?9iH^KTCftMF!+KNlb$iljK#|+=;t3d#)?HUYe@b zdA6;(Y&g_$Q_4SA)aU+crR7^WLMhN7as^o)_vPej-~Dw#dlga00=6>1)q(56VI5%N zi^Ckv$#s!*!+z=rFsl=HP7>lAcf=YAB2(09XLADcZtkLgHkqp)I9I~|eU3{ct`&f? zy*HAHdd5yw*W{{+rr($>T&eH6bCFoOCSP8|dT*-0Ly)}3k@l9BRtqs8a0pjll;)oWV2(tV==?1C`jp%m|S zT6oAc^Kdv4SU}B==Iu!&S|aUs9|L#bu~y#VXT;bmd>uZtsiwuPq1jqp->jiQnz$m| zh0^h>d!b84(^~FopTi2;y4ypHf=Y|k)9yU=N4orn55-FTS@|rx<7zbfLy`m%p12(j zr}l$l*TGe;e^X+M9V+Z{0L8IgE6K5)o9w9DIILL5%|>B*eVs|3d)LOCV$J4*c|e;YP%}qOPZTc>SZ_cPzEDuy zms3Q%?kUTH(^{)M8Dx?Z%}VC*H{v3;kvj8RWf( z&~#Nb0K65-9VN|OQSjLF72LDv-&-YGa+$~Sm>b}&G2Piti*X9pa_TX2bnu+s+w|a< zwEmkrE-9ZirkiDdan3Z6 zMZH`B*N)@fYvvpvGT_HWWjIvUsfjOl|A#xV@=8uA$S*;OemiWSd{rv?K=huuETqXCDcn zJhu`vKnbtxsP- zZwcY!b?_-}_qVZtzqJ)-N@$$ z7`B%vIVZs7cD(T8Ut-cJePa?EaKwG4QGDs;Hiv|V-B(`tW@~q-fj^h{rSxP@a{F}5 zJOUf2sRP6E@j2aobVU+uc$r670-m6`3eJ&hOJ>O#ttIjQwq0(n?Rn&>4dJ&$!)75I zun2l+lPGK>;OSyBTN+#-T;Rnf`pSJzcEY7q=tkx3 zOM%*Xm9<$H|0&$niq_QIjlyc%)*UoOM7yBot)>?S`Nn8B+7FhCg6I0g^-zh$FQSt5 zqH&Us``v)q8<7SdrzT;}!!VIA7~-ikuoo*)Wxy)Hzq}`K5%g22Y-0=GN*563kz~#x zRUE58c{yk<$%0XD7zrVJhMh4MyxGFeU+Tnl$ISU)@ogg znbQuRg*7qB?-MN}ZnjzLeKoJr0B`xO-OuwSqdd;c;j?J1K`-zkB8zdJ3V%qrPC>O7 zmi$bo8IP#vNY5{;7RjZe`S?q5nNPkCKO;vNjkJKkUzCqfR32!M`~4{b4zJ-hy5WS6 zKWTe=Tm8ANYtQy*;mPb(penms&q1>g6kYAW`Ke8lm?4SmVNsK~?zRHz0k3nDQmElT z9-u(wNTfG?T7y-Z{g9ytq>xN(VeHsMvYFRS%ZwG^s4mlZy3B#S5v=o+`Fd^- zThne$r0i&e^-5{sX{&*rjG@o0`*@DckJ?{|Zv&~#QM^UwhDf3hszov40dalUKU*u1 zkKT$ey1%U~hH$alJr2S!*mPE!k8LsbYsh(Wo|A(Jjam0{DfPR&}!K?OUH@gh^ZMwkkH(;gu{10 z_LCpp|K=B&81ckEv!1t+AwpNmkKd`Z=H+>-VSoqBTc`RW}JzWWFQ002aQAEBRx zH$M9&@te~6bH#KLUame(qu;13{i7Lws)kG`-vBGz?XIsy+Wz^fnYQ)wljXN(6j1?! zYej9Oz*nPQaB*P9jLRh+oGa-cv%Wm|c*AWNde_O9jl0VRK>Yjpc4S!QK zcIn!lD5{*Lo;LG7VT|7Y)x72kMaqA^L z9E4Qn4zV%;lj2K{m!T|@ThvT3o(V$duM(Q#@wVlrf4`vPcoyZU3n(br{FaD(yX8R^ zaG+E3n7m!&7K6bM==*tfE^+Vq$tv>~_`H3;851}Rc)9abLK{#}@(8ncnYsN5*^cju5byuGGtVbdyw9|G`z_D&Ha60P_A$$N^%E9^ zU#9!7Kj_gYt!G#NwY3YMMIKErI^TWnTGHrM#o0nmdSwPauI(q`y+v_il@FipL}P=H z0&%_R3zqn6J1nd!DcPf$eJTK_r44S9SpHVMjTDyg`W8vkRtL4~#0LE9&!+1|U>3e5 zEug~O3H>Y1|FvwB)TR3o|D|JFJ;kVjImR`)@t0cnzxi!?)aKcW23;E_;(Mn>Zro?k znMrcBl$N9ANmNE_4Yz>XhcZ!fx>t{RnsoL%Q7;ZTse0W!!z^9^#2D~}fVzRrTyo?6 zW8P(%G{QnJ#5Ama?xG3-QadXj>l7S6@J@k#?poSgMG0sX-Au>8A}&)p2855m&qGD+ zKvz`xQ5R#*&+Ay(=TqL^7(k(;=r(-h=jmoh8~!6~Ox*WdKkq~$qIV1D@|@wLUdabn z^VZnt`{8MS}v$s7jwvY4Qbc?bY)9w_gz1r|B+(U;XWF>&#uy*SGf7E63R@ zhx|xmMQe1ZmI>)wAW|;G!V%~4ko`HmC-5`^;7^BV*fhj}zAGo3*T*#_w(qkdeJ_tL z|JOc(!sJGue_=I#+#WV%n#-=FIOT%gY|8?cYrXFu7xY71IDZXD61g3kGhD95}GPaQMSNf-%w zQW|yIp%)AQ~wtaYE6GX7O*|TGTEhVuJ;JD%DMeAyu_c~d~oeC zz^7oJgBkKo>rYa=fxZM%iHndH_(SkygZdxkZVoH_F>HL2NLz2K%MBacpC#_sy-kmK z`bx>mnua;binF39_QBx&+TxGNV9#9NUtrn+^H+#7f4%tbE?kfGQEUoePdamqlkM8< z(p6L!#jui}lzvCCG#Wj}nN@*)N<8A203o9=YImbR+F$B{4kXr-j?@qH);2ts%driZ zGeBL!>i_8-$c5b>cw%$>c-|!j>O@j6fy7@NKju_T1bPRmSlIViAT~j*72LoiZBEJR zau`GEW&fAE^H?w6)>GE73N#rWpXmUKX+?uz+2Rz!rc!nO+5RR-AT6yY^Dvdlr~zc1 ztR8$6j2ncG%t}z6_SlI(EjV~qlNK0XX8%cpW(;$o&2``2m(aP~8B5L_0I; ztWfkX$Da)_%!7MAT4@j%h&2cuRLV~~%Kk18;P%{hEnUoh*A>yZ`+o&2U&^LUyHX%*uzzJ+fY}n^ z2Qm=Ro3D+>AzXn{Ztp__6sQ!V1D(Z&u%+FNQy}_5@_g&wwH@!OA(}4S2KNO_F&|m1 zM0#%h530T?zLQ{SJNCvlH@1z9ZJQh0wr%sDjcwbuZQJ;O4ySr(!KGahr&~Yun!N}HB6}s5d*w-Q#~l+Z;12^QAjKOEs3=`iVctiN%As$@j*u#M>9u|J}H;^QWzojxB5bXa@pv2&tB&({wWvT0T?`EAe}p!MMY z@NBYWzt>F^Hn}wV91KSD9|bQIW=vIDYI2V9wq3t}1?&Av+@}T*JSK2`_E($uB8>E` z851_royDLQX*y?o#s%v1eaWLcOn+%(iy~?fGJ2&(G*hUT8^IKBR$!C;jh@>rf^`3B zMRBiVL>eQ<4gZb)rllb!x&^o(9-i_j)7rnXH&uVajrz6yq+_*4?RwuM}& zF0x#E&kGO)pnf6i)L)g+RC$Y=oTpsJY}R7tSzP#kv&qQJOM z(sh)9HuP4S4>OVJw7~Gv(H3d%V23wnOf8Yhl)|O{CVq)j({L0w;I^bw|3wNf$+^4Y z-gMNX32w;-ON9n-IHf>S7uj+&zsXcws1OV^2LNTVV2c1|3X(lQXXLDY`pRgUhx3{5 zG%H(Vh;YKo6AF0eE3zk>&eX%i9(n87XC6+Nvz0~z$w!0cl_tY$YpP6PX^e123w&yy`K^Q2HqYr|XlNyrRc_jtB}zA-&GgKuR92TJX#%?*&Kb{iS$dbU2|tZqw9HFIW8-fFQPw9!Q%SY|iIHJ10bgTPj7-?k zm?}khr{~X-OG*J&sT#^s+hz~SaD=7l9}VG_n%i7B zvN@y6v8|%0X93DB3k{nFFeB7tTBXgEPBnmnf_^|{6*w_I7p_c-_a*SE*WsLDQ#~+I zco)Eb_b<+-G++e=!UDjMND4X)QL`#36Ptcrm~!so*PKBT*P0{WpV?5^3x=R`lDQUIay;E0?((eMOL-Y6vk*L1Ub?Kq$;kozG4OFF%aydNK2 zXZd0;@hxI+V6FFCk4}y=8lN&aAHTNZRNu~`Qn)c;oDw>~p2u0cUvd4@&_6SU+f*qa zIk2Yeg>u42sV5eOn&ub>k@%$X5&pVl-S#5lK0N?84zYd)VsfO_dZk75$gfO;FE%ey z^ytEiVi8~kub&q_z1}{#%y!LlaUpg8awasM$$Dq&M7d1o{VkcX1O?-)Rrr7-4%eSU zwR4<7bwL5YbBQ0q{<(6g`~9{#-g(xMo9q>4gdDW<3|wh3BdgY^&6}6JV^uCv2i-97 zXyZtPFJN_@n7PcaV4G{LJqAexzm$uxL_e{APH^-j+3;HEnDEIfoNTG3)B~Q#WFItectJXY+Qs}^%Rr!`~<~+3%t^}`Xcfk z?jj(iE4V`c@(s6Jn@efa5oYlRX`ELTp@RmUkrTGmoE&7}4LTJXj+vbJoNWTZ`*}s$X>kYr1JhFGx0DQS! zKYXYbHqgm28q;7QD!DFxtN99}P+g%G7kJ)lM_8Ks069&6s(s~@8H}!yW*t4ZzupkM zP6LNP9>VPrQ(jT}2o%{GJFJh43Qqi!=5a*y#1EH+gxI})$`4zo@E9Gone^DSemn1P zqltu`lM;on$*K+7M33>@6|MB^d9kkR)g4abh! zX93NxN!P-0_Nk5OvxBf8iZNcF;GAYy)OLIFVs!TcD;Rg5C9rew*a~~abx-HW7hOGI zru8SpV%ZtgI$v-b$2$fa}KZ3s=79Q4{C_S@%U z)EMI4({MVTI@3b7y+v#4!l4N}Esb)MXyPE4zB#ypjo%YhJHgaCMy(v`2&pZEM3Oqq z8cqm?!nm)mclT)10LCisGO9(phB}-38$83FSEfAIShJ@P^?<#t_IOZ=agG(dEP9W)w zsm{P=nf!C*7`Iv3r3rk&=s3onGK3pPNlKr$=+v~{8g)uJ;Y2%F%3QOrnoNiln|6BR zu|#H`2Ir1!z`vtEL{9ag6(b*TGOc!X%l~0UX$+`kxBgwurDt2egV_*3ylHBhU^di_ z?;SRDrc9QLOvJ*HjWI)~rpKRnxpt%MiI2uv!!!}jMG(N7kMn#hc)~NNjMjaJ5Au7C z;<#O)lN?D+bpq3XZ-F(D5(4m(Cf#OqF5_KsU{;sycBwWlXTP05ROVKB)tWc(Si|2V~wA_j@Q@Nt8f0- zzZMr}jxcO4ru||lN~4OhTUU2k8NGJj$!<0sZB9QhmHLbr^LA0ot1Q55xc0DGp=*B8 z;4cVDF`F7m#Tg|LKIfTZ8>%?dARQVq{n8HY3HEZ;2o(u*N1&o3lYQZi=1RPOLoCVf}$y z9rg-jjmSlFRd5^Ex%p((%Kmr-8T?Az5_Zh$NQTEPMfpU@f|qSOR5);q-MzJjy|&Vd z2N&;}qk8#;c?K`I9Ufu7G#0@Bhu-?H7}I9iD(s<{8u$f(sR&ULTR#m()$i^^c{mSF z+oEoeo99@$23`j@k0dZ2#FM5TZ7_i#>C2%(79Z`}ENA=IG(?HN^XV#(YGrfIFN*ck z=9)o;ZXHjy-_-GH-1FmF9<-#QTZPMghQh0gvAP~K3|1yj>OEB6nawP?f^K`YKxwR1 z^+N}(Ff|I@6))MA&RimI9nY4{CK0NY4aBBiDQJVfG++=m`e ziHKV|%o3X=KN5(!(9~5EfxWtv;jNES`HQ)dDD>RNGD^-AFZh*KeFK7#Dc8V=^ITEs z!vT5{6oQtvvDi7EAg=q^`L>=2WrAE63biZZRcG2a=6kc+HwHr2egtC-vheSezK>jo z+)({ilj4WKnz(fcowaOdgO+Vx&ig4j%)$oVMR&Rs< zgRqyW6=c=(7qHH7${;J`|9GHWtc7g#9>4`zGFa?iGKyl0olM5pA13Ae-p8B z1QTmMT6a1u?#h5VG+cI7*l8O|!-09-IfP)1)=_2^IH#F-t&mTiUsc_Y2mGWLt-$=9J;EG{~7WH$7*u-tZ> zp!4Jdsq!R*bvZYxMGoM4XkQP)XEs+`juYBPaAb9PX`pGxyedS|gRKSlc44f~bx^}AmurR!j#hB56pqFV z$OJPy_6g##^HCGeO=ar2NLL{1mKA1a=i* zD^%gMN73~5&w{IV0NxBboQv&r73CxR=}FUN;i*N;$6_!oT3Ns_t}Fy!1J(P*gC;(y zwmyl-l5(~sBF8w$Ug#{rT?f;R8p z_=s=iqpph=FV7n^wjBlKdB1YTLiByDn!GvF{OeV^YrtQqZIIf$gnP&3WS8{YaLg)h z`{hL}T8|*K>_4DBH@M6YGlAv0o;FYz>SFQI3HAIJnY(~Vl7xc-MmD#6)=F76lQQbh zv8o@5eSMRvC4b52927|tIvF#W(P@Q{6>4iSLVMIVr5DS@oRfo&dpS`l-Q~{Yw=lw& z#-_=!+3m)@Bwm;>?Q{1yp0#mte$BmZq2L_W-#fL`QE!G9%7WSvXkTQj?|J=TM9V>9*nWLo z_TGSi^t_MSgC!dO61P%hIi&MO!8P-Y&>^HkHS1BHQrCtnHXh*7kbiUxYMg%X?d2jr z)DfK;A6NrvvX6&zP8YN`IxCsOwV)c0;7V|%-}KcC+1YHYhA(z)UD3kX<#og$Zgc5m z0hP!rrb?sqOZ2Rze~Z0|jDNpz28?FcY(!Y0nrphul%odeDoQHLvV>*Z*=l!Ef$R^4 zXTMH&=zZ707S|h`@gmM!`?8{Z(VC@w&EYGg!iXr-a9QtGZ!6*TpJ)%*>CN!XzpAw( zb;WhuwV(|bvKJP;SlbaIF$k4+)<*Gv<}*c~7@3-f%rZ_k;o;BH;7d!$J9``FyJidu zFm6Zf7QL$qP2YI9FUxCJe{-w1i0LCeGJVB~?ls;3`48=^7P_-jiMue6+Yed-URH{CEl8v9_y zN15qWnTLh7KrD9sz2@PPJ1q5Jr9LY8t#kedsMqtjS^i&x+q!3*Pjpv>FfSmtc{w#% z_N9qB+ zNQd6z_xNURE-e%6n7yI&YgM_1e-B5d9wga8hL$hh;ZRbzINQ8E2@x*wNW(swzRv?f zcD_V*zM{A8j884<&?!4gw5WqczhAeni{ixqY2+O-mRkgS75Vp^P=fONC4$J=CGCA__dTU%3DR&yaXgH?QjUArLCAXfm%IlxuUy?WM)EzFVB}D7VQ( z{1OAoEZgkdy*w!OuftZ}48SyzMdS2P{h2`fQRtyp)fo=<{=h zq(VhbCK*sLT)}au$LJfN9!odBSLJYpf0F%2xTe(b4QzeWezt!Px%GwDQ1 z)NhyQag5r0M?mMAIW^deIl7}CzVnHuG7?G`i(DC(gc-u~@5+8b^O~;2Q=R+JxMq2p zS^k!0%sO|Gbd%cm8UpqMCGK-*T-AqLuXsu)=0RvU`KNHgle1M9&e~J?S2UTb$OemU zhP_Csd`(J*eSYCx?{m)0p|KpiZ<1txq!9d1vz*D8)2?n!a@~EY)A8F}lU$J-lwMNB zu5Cz2@~o(H(LKK4Q`vL; zFUj{59@y9J(lD#t^Y*tr?^F_p``7&4#-wO1XNoX|R&mvrpNH6ZTqewns-0EpaS2@c zV=fLJhPHd00vk$CR!6pAQ(HB(G$-tzt*BmO;U=p^GLQz5*$rv-!{O%nauMcuF2cTK z8gIudhSzfPY-=qroCGfwAh6L6K&D?}xC(gK2VbeYHc^FUI*~o0unJ^iLi2TTM3Wq~ zUf&6Aj#Mrf=BHV~Jzt^zgyfswS{G-Kf!tNL+qrUz^vZQi+NGA?USCvJ&t`9=rMAtN z+M2wh?xkM|4_`}dhI@fnZjM^I7jV1#jCsywciiG^7?4gWx+YAX_j%Dtj_VIN!SPyq4z9YxY8rUz#w9T@eokFDN zyj5jeZ_H(72M|~Ad;k+Ql z+95)Q%2gGy_X&dh?IwdyxIWh6qPt_*Sx1Fj_}n`iaOorwUca66@YgXNF;ukOO%$OG zuFUzGlG+f76*etV-e&O;H))L~V5(ck(m0gOc48fzt~DM0hl{d!bVisANDc9+`tpP{d<+j}nV zdcG^HX|dTIWM{BJyTV6FlWxoQuZCQMc7gVc1N6S|_>*5ss0$Z$ShM0gh~nEhkqFzw zxVc95Ox_ zv(Ek;9nU@wd^l!<`Pp@CEGjE~<=6loMr$PqSad$9(jaPVl9$)ejyj<4AOSAj1n6TbFd%Z&-I&P2_L%#*e<+z~YLL?mUC$4&iakRPu3}pt&E8+Z z*5E~SAseIj-(^#rE<(r2g&>I$FH5VQ?QD#2W^!jl&IH}$;?X%T#Om?kQ%X~!*lZ-} zm*O@tDQiu%2n~27eA}lhFqaBy5if&twt^<}_msRjlF_Tz<721<{Y<|h{2+Lxyal|Q zJFWxpbv-u?SR9d&erw61MU?AJg*t@pYGHsXr0DaXoK48rOcb*xG-~T% zU(q4nr)DK5#DJhRd`z&97pMFAg=VY7k33nR0Yi}Z41{vc>%(bKn;cpI) zpR<=K`JNzXJh^T-WK%=vyuy}r5_3;NAdd_@#l>M3x`II;gYUoOtCVR><)s#hN zpM0SBm!9(C!~Y>0?=3dyidCLmwas9iE8=;b;UBUye?!%vQ|a26rDM6&L#s- zLM>MD#R|8PU|6x?asx82NT~)Uc^J-_wOD(>78%RgM&AX-n{CeCassk%yL^d??gjMS z>(iF=+E6rRne3Jfd|^Qr38Yu zLW|+1W2p)-r_yxEI?4AArm)vN@)&JE7Ms=JB+sAruZzIFW=%GJR)ziEcl9Qg%I7zN z^O@`dN)W}y#9N%tB4<@pZGt4z<`DL4<*UTj4aKe~R)eYY6T$HN9_(bHLC9P}`ob{4 z-u)`&0*@);-ssOq9;|!?II?$!AR5>>6ik*sl&mI7B4sN3C|fp8;D06O!62i6d9W#s znxc9$8DbzlIb6jN1ZI2vh4F8VBJ&WA4U4P-l;LW z{HgiT&piuYlH~6rW~^dAuASAmRtL>~VX+){$z1=84=a8QVynL;$=m%mlVzVw5JU}r z99(GIws+mkylp+9$^KYTXID7=2%nJTA5TwN&)TQPk056MQT$A(ZeQ4fHhYiqPR_=w zN&e_Q*>#TvGgBWO{(nU8koxfH_HPbRe=lH{I&^Sc#4sjXw#PTR)l`MVJqa<>K){%G}th~Sz{ z!G9or)IW&zI^KZ9OT}GDa_S$iI8wYir^d_weP8)8xMC#-6_36MG%x&_{<#)wI!K7w zZ)(my>gN+*3RZh?10-g9x2SPx)N)U^{p=JBq*jhEAkllUbn8DMW&VIRKN2|u5_L|- z|GNg!%-fYYFRYZaKPuRf&7|jMvp3D;Ct4Lh^7iUy-F{5E z^Ie<(iDcW00snsDMQ}EU#>#3|}>MwpDxky~mFomcvg-`%V9iYwzm^?klf4fW-GFvLfdHJ{;>xL&7cirayBBFu-*Hr_TcmmZ z{`fnjpGrFKtvM3sa6fc9SFyLMczfEHy>B}{u2i5@y{zq$NLS*)B9Eb^tDpy@cs2*y2ogAF4>19kDEUirbSQ(gG(^)v$ z+FWRBIBtx@`)osfhcXc?9fUz%K~Rk2!;4JXRZ^3>dxdG10imuy<@>Y2E8>EGznhw> z00;Ap6c?q}7%g&zRgqA~(pR6Q@O@r&W3KO+Yep8Yav5ta4U<=)s2gAgk;h!}bGlsi zc;2bEBr?djy{u%rxmdVYIX5&?KM!$Uct%b~c_;AebI>2_tiv%EYBUz0IgduNFFX2^ zTmE(tE0^ReT)mf4P=-BVF%w47RckFI~*Z}%Bi zoxfA%IoFg|jc;CVsjV2}>^`z5f*9jnETYP6x=Ls&Lo=bB%`<>Utuj*ym7H>$4fCJ) zJtj9O7T<@=A$mbKu{q3exm+7zYDN>DfqOsS>$eYS`Ldgr;E>(;u(VzYkif&>$*ru3 zX+gE?<7$T+(-XWqPW(p?7ooDeWnEhP02JMHBrz`QtNR4yJ#qAV6|N$+wM8>Otb#g` zt$OU2Q*EhRH}r~+43D)}MFg(xb|t5qu9}LA=YoG{bEe|FBzm0H&J}FIg00QhWVCN2 zU2zA|aERT#NDQW$iakG{`S7Lm7gblY5On$7ni=Kp(!*<`<55Ui4?)5VdeB(iF3UTL zZE?%m+ld>#>n6jkHJ?P`LX6RH{Ra#DCd)$y$AicOGkK#yIGVj!iw`PTJohbgP8h>( zLU5%fDRFMIfYK>c|2z?Odx1QUjfpdBqS>3x(bvwp9KKv$S4P$fdAKWb7|9jBhOV)v z!d+lL%2&&>F~M;xUpE`hxNig}`pAmMRRFuMHN~k-E6VsIZTYsUGR7o=2q3+=tMf~* z+e3RmB-slSmr^1d%IkNAdLn6Uf*rCuw3{5Jh{j%!k0~G~H+X6QrXcM->s`ZGtBV)9 zl5{uxx+36o*+nVXlo?)d;3V= zVRaAh4H0R9o1)+zxr`yI3_cs9!=7oJ?}_`Z&*^dkK5U=#LL`oo(_((aX@E@-I_%<` z^~e}g7^bCw-fn*)5|8udPY^z{YcNKF$}3YDj>eS^6-dz_VhApAvX-9>vm30?WFkCR zm&uEMU(l8#NW=|QyQnPU5MllYhbVGGdO#3cOf{(`{Stsegq+&$f@*AE!9-!4nDVdV zu;p+bE2wIfhhEsb$riACweXD$9EFBIoCeXUEA) za9(hAIk6nkS*~?&)Pz(5wlS!i8>}2t_oHn{hcKA3jKDi1-Yg+&Jj()IW&5g*h$x^8 zoaxUKF3P#uc1PfDFqkNHh=)bT{NEQ;YHv@-`#MTZ#aw@{<^6thWwi>Z zEOr=`)k)$jU121!y#bWHqSX}tEIQ_y;9m9(jRN&+w#Tj)GA5pb>6y{cun&1U0cr=% zhY&lYKJ}_D*6lu?Hq($FF{v4&sE1voJle5-x6n^@Yx_52)#|YEUl^Z+CG_IsuCX)n;{YHIv=)o}J{GfU2#=jg=bwIgeyTGN$;Cb(q(XxMhq1>P67MjMSrcjD1p0h!r=J-3j*2NkD3yv)Wr zM2}pUa}6XpZC2va?CaxVJ2k|`lO&O;lW?~3TvQQfk_Pnj^bLpi73{`a3^V*h@*3LM z4gdh$*l;7zFeG7(qBi57V`-nps>l=ulobIWQclFF)6A#-eh2?J z1#&Tl2{BZZm9dGVEw(_Wd}di&DHvIC8jUvdff4Y=`xYD1B>KmTMBXaexR5%z8n-B9 z47wL_<$D1Q#Y<3Vt4FNeY5sr83UWr-c6L`apu0Vh>x_+Z_2E46v(tfeY3X%c@7?V? zJNpO3(lN1)m{cR1%6n~_W)EHP>1?7oozTMF;vW&aw|!92F5A)}~F2L?PC78wIJ|&8Indw!C+K z34ths+idS zirS8N0?m6EajTtQ?I>F}Whuc8G+iNgh{VzG$j;t8^{&~=uhoipLXHFvgb*$Zgz5Q+ zOq&*oPxS9cuoYB_;jrrpOfr;Y+kI5H=&y59RlEF*c3oM#xMj2dJwHFQ&|kvCL=lSh>YYhaF@eo z=g}5CS>mDjp>8!vKZ@HSh-t+Qf4`cuHFW zQR6@fsA93vxx;7PtGlfHcO{29@C9Vq_49(ZIdtmKxnh|qfILE{;X2TBEk3m z$II#LX?@}_$4`qMJh(^S9G%#P=5a!w1wVEMDmyR%^_f&6N@}p_p5wPO)6C)5E{fVJ z-_b;bnFJyZGzu}kNMQJ$d*;x+z0xAXqXQ{JD=mALmIpdK&Vr&veZ)j6x39g)*VFrZ zGxF-65@6$K5Z%ZnhWmi|UCRos9b}wn6D}qvstLn40x^k1IXKgIWXli-(sAR;dvdXV za?2TT`*8lPy;{A)bi5_@m3V&(uZ)evG)-&8zw{~+Xmv<^pYf=^xu3kL=z7ORNZ#z` zYm@~@TLL0tkk;;l-aMkb%iz2~Wy!PaR>`>%FlUH-i)xl+ACaNBW+-4>h$K(46|gBn zY7kE?T5Uy;%&A1w;>6!Bzi*_zxJvKc#}7<;9=S(B-o+My=S6z!a0{tG<;e+3){HT9 za>h;O5&9{g()0l8zx)J2jy zO=jj;&s^Yx+2Bv!t)Y@id$MT4cTIm-3W<`~L>p&fI3FU^rS*Z?Mk+ZNEAK)>Xx9sx z?Tzpa|5om%$2GiwPv_qRP$EV*(+Zmi1WnZR7-@Sah2r;YXSDf0@;KxbgDY>CVT-9B3_ z`O`#j_|a|x9MFWp9N`BtaL-I@=-03o6eWZM>`a)FqtUy_J3&2zR8<<9#+sj2q2-D} zMXYVYG4FVQVc+a)j&=D0;q!?;?~6}OJ8zJg-gz5A9~VGXOxp8({Elit{**lYtGAYc zo|)+62K_qHp+&bL6g3IS5=u~SO0akKNKVRQsaQsxlxpH%dW>$X5=Qe%P~3Qs3gtZ( zOXZ|B`mgmL6gH>*JdZty8q* zF8Aq?h!^B4(?9P4Zbb0gn_sR4k9f-(5exX0Zn_l@(P0)7#e;mS#kGf7SLx4VXwbwS zO8scl6_kUzK5r0#Z_@EKMnT8le++j!y=h!s=oGny3c3NB&6D9e5~tQ*Hp=%~nA0$w zM^({4ZF8YAl|E>4x~Iyn@AvG1o7r}=2;1X93*?)>bDc%Tr4*cH>}ehCT8SYu8%N_j zLP58c;6o-dNma7PmbznEG4&4a69e>mc5x$DAtaM9M+83q89czbjgqCPzJA=!>TPFr zx%rIb{CNN-jEcmfAjr=aw0GbtUk$a9sVI;Ul>rZ0ELde}+JITpkkeutIRf-#$QxDp zfz>m}cxc+I2>81`q6MtcU6!kQxya%q0Z=k}Q@HkhPOVKI)ECyvpza8a9{4mXS*C?{ zG}*r0db<&T(5W-&!TU<46imQU{Q>Bofa)*5!dNxTKThdYTL1E^+?nw%hhj_Kl_ZGc z+0^;{4J`fjzQFRU#JFn;KO0 z6rD*ZU4Y|XW~m-G$=Wkuh{Y=VC=8D((+nm>YjMM7n^8meEoLV~0`xX%tGXo*yp$9| zt)ebL5Jm*&O*C?5E?I)y6xhP3tw<5lJLfTi`e$pvnbm+lse9nLBsz#_zyqR|IgfA^ z%zECZ=p0>~a)WsjrG*^R;~!XQq}A@-7ybAIeo;1_@2#cb!~YhyK7Kd!#XylI@q;rc zo1!ls@FJ>9nNYkc7I7Fjq@Ca zMsr#6o)b!))!)-aUF9wc@m0EKxYA*f%(KR7Ty|?E_Qqld(b$Cg1qk6m`D`kb!<-Qy zv|l58k==yYWyf6U=9-0;h`|Q{a88>GHN%!!yNme%#u#Xqsn%aFGtYM(0+perk^zGH z&q=2tF}e*jGBh6q>+Yt@1E9L*tx*SMtz*1 zI4$WKX7dR6eY`YS*EUW*TikS!B5=HxFjx=D8e*=_q1jQXDTXYhgoF2XR|9Sp2D>@%Zgektb1ToK({to_5&ao=xH!>zh+pQj%({+NeHaU_TA< zhLg!inkOAJgXJ`xifI+lD2T5@B$cmnY4y6xa zM{@{0D*cjs8AC+s)D;$bP#YkEUyb*o9Xg}_Tz^idu@zL5m#pGFv{v$SuD1_p(b&H= zIzQ)-x+QX-D`nqR|9O|scP*N4pEcMzuid=;=Q@fOXUW`qia>c8)cggEb_>|!l`K@C zruUy&1SmXVSntcRkRD8dN0CWS4Q&4{-F{(pDlKD6&DWRqnQtajl{fs#^Cw1?vGP{G zZO4VZIB9(gLnJzHL(x5!4?xRmpWjf3acPnZeXNUtx^N=@bx=%V`0YgF$Z+1nvfDG2 zG?6em_)7{np{eWyGDo4p84gnc$5@+gQa0py+x1>iMS?U!gbD1&d~L=-Ss7# z{k3{#!dIsFD;89l#)n_&Ya7)+S>69oqif$I-{k#;jDP)(+}}haKN;Y2G48HE43pLK zi}r;!_s?>)(0ZLcUjs>=e|t7fUt`MgyFURap4QiH3Z9mYu}Bjhm;jDyf7%A~=z=CD zxrNP%R@J4r&&SLGxs#V?yag1?Zft0|ApOu;k3$8NoUW^b4eIZ$}jr3l*#$PY`TVh=eguRL_WFQX*50|nGxYJq^6#JT)|9m||3$`N2m z{I--xz8LhBF4P2C0D5mX?H$nrK^SH}WcSFqzN%&0aFGWD3?f=q*bqddz=r)HU*1ko zj#L*WaCHmv!@H|HbA?}} zj%BZ3V82DCe0D!oX%AathCKn_A%wI$?U5;J6~iJD=IYC1u!Yq^>;GFJ{?19?rB%?a zE(eQ?Y*hQr*}sb`*K`}w=#k=)RxFFq+0d$G1v5qdVfu+Qb57jI5^7fWC{5LgR`Sf$og2 z`E7L7F#v`In=1xi3-cFDbf(?STK=jNSd5D1A3SVOlwYvlQX0iwS}YHvY=|Aud7m=| zAmuE&prUq8I!=03U2oYv3M1Xj8n?fVLvBE!VC2%9vL6wBWq>=b(1FDtKlOAes5{O( zc@{}YVh}bdNNq-GC%s*pG^xCz%s?ogFKGOP-!69$w4Th!#zbd_z9wcU4D#I~0@J?{ zZ`eP`FiYNT$N)|2#4M^Di?%Npzwz(hNY_U98Qe>(%dO-W#rVAgHCDP6V+Md$U99WW zS|OK}{z1&v^`tKwHp{82%nypGZ8^#guTtVMwyt12m}r~BJx+;Zuok&xZpdqB>An=3 z2_yX8*qwS^mfgC%cOZ*-DnDd$PRNIepVtv*w+R_QKVQLra6<=@CSmY^GUOcKUAnf>Fz=ppzZSHcd^T|B6N!~Zw*S{}U; zaD(jQM%?nh`GyFJ4`eD-aZTb63;kwX$`zl!Sb<3#3+;z6H{b(n4%`_?V{DPN*z5-o8XmPz6xKIB+iT*!Lt5BeUTevyC@GVz12w73)@TyenO!CSgA4 zxvoelOV`XNixeA`&KTn2uQ!^jabWLT-J)Fn(^g0Ank8oml~`Bcc* zJ}E{$Gd0SZ?(Q=N9hLe#DVi+m5^T3QQnWStnk{H>Z2S*^r-dCV50 z7-i2F7fgY-om+K~>rOsAFUI#{{Q7g+U5D=4S%c;ZN9GN5^?2&lHhRm5o+6`CuMRo^ zO-JVL!G7abt$S)b8O<-{wGmd(DAnLo<=oU;*l3PDc8w!TC5J)Nu&a5iqVKg{zy1%oU1O9Xw>h$6gkVRwDS~`+u_)IpU!D9`0-iB94Z)eBr^BaAyy$s*oG=T>klY=}|A_)MlmByzqB6!^2@0++?lhGuW? z#mlm#Y{=8LnVgdLg$`ENtF=k*FA|{vf#uB8YQ#}C(T-B)QK-^-$s8?+4k|g~U6>f7 zv}c*?$g0JucUENgERnYVs(k%l=wGzSY&a8|zTt>pS-i4o?Yz9GpF*%XLm%XIKUyCc zf5$~P9(D&asUv=13D?o;{if{l;O$LMyLakMHSzV=gx}GU#<${bN18dfz*XIucVwSw zPV+Q80{3;L2B^BtnP?V!<#gpz#C+GVbSI2sW*M~st*XXkvNNz{PO9x-DPdJ!K*>H{ z4rvFM#`(ITwN#2%N!(E+==qJv?Qw|G=y-K^{}rX6{&u2cCJHj&w4x5HrY(sm?^;~&Mp480ez}aaXGRbHr8b_77xwx zeQUlw{b+q~&U_=vd+m4*?_=(2itj{Bu;axji4B1Qxv?w-zLxgQKh;6q&Qd3*`@lZB z@9EnOpqZMo>nsdk>IK0*-JKvGeb&V3`un|Gp7OAN-(6n|YStLDJSeueHPXN`t90sc|g=mJX*=Ew}=jU^a-287dQRsA`5 z&{vGpx5B9S65IEsn;_x+Ku$)GF*vxbNS;G6iNiL?>NGVZ+ZZ{=gG7&6`<<#i+Eo~G zhZZ?HvqfH^tjweYA84j6Naiy+QgdO%I6Yt_6Q!fH;Ei3I7((D5)9qm3$OaxT9S1de_qONT9VgqV)MHB@y2T#7 zdUxzULL8fc_}O(VY~rYP_b^vZU*!ZDNdUyO1eIQ+V#Vkq6Uaq%cu^mo74Y~ERCQ6= zm*SbOkR#nDWs(fdGT2p*`5r`-ZZ)9KH)VH1VdoP#xwB1w>(v>07%OzK;Fk2}(A6YZ zor$)HQ^P9AEtq?|*el0r#biUJ`wkn>y;%>}JT8^$(bA+PaEsiWW?Zv5F;Vj^;qA0f zgVv?sQmV$u1=+PPR$*JN{;h%0#~ddkS!tS;jGHH{djiorp7r<>m^}o-Cit~=C9S}Z zs{^)w<=zRdzjoKBmbq9qMJ0Vp))5d`yM+^)i+i)^Y=}*QoV`6>$e6as+^D?0X@#4a z-Z6ek=do`W&*{(}8CU)S_0R5;{mXBToyxL|zH_0iqbmdVZBE{0hg9g66Sm5xw=R62 zEpSm@$<=x8+)-4;l}1#IWg$n;mFdvR6!u1}Pc~?P*W|-F&4wPQUm%4LjtMumB=Z_- zStM$3{JLpZ@Z^U5OH1jCU}#IVw)ORyDo779c*is~P`VcB4tj3L`cuR?Bb0)n5ryjW z!$`69YVguRXUrEgxODD!i)9FY^dJ;?PWwA1DEsC^J4K~l7YOxPkLnc{eN}t1fIx0h zG_gbbV`(ih!)$y-+$~3xb6Uy#_v_Wg#prAzLCiG%w}aQi^1j~G6smx4`G#qe*?W_9 z=#5ctrzQ8B?6lftjCs+l3Z)3T)P|wb$(%|7=r8d-5g6sWR}}p}w9kv8aC;-FCT)IT z7EcQY$d}!XN{Q8};te8{F;j;D)vBVJ)wXS!vvTPt}B0@XGydHr=E~5ztTka+%$2ji@<6J@dgh%|iJQ)3IRKoA}`Z}+k_I*Pt z{`Kc=XYH0;Y+5g?(XZlM(C6#$Wz>;5%l}>tag1-o0&h}DaBdK!|4bXXads|BFcA|c z=<-sb5i82DLJVHU!}w!_Pb*gjv?vjt=_m)-@&$O1aTEm5u3aTBSmQ>xb3`_s4D(Aq zxl}v_=tb&o{WdapMA}==&%MrXK(U9*RQF-=@9%3XBkk%?41V5Ibqp_U*e=|C1}JOE z28cF|um$3hAxx^8r;HPeN~+%nYG^hno2-}F(VF^w0Ld;ove_~}GY|1iTWq$4rD})X zbn{cDe^15XTmKJ!8>lv<OWLgihcP2D3- z1Zx#A{#-8qr-ae-HE#VFNz@S$ua=>KJ{QILp;pg>))=&wjh$#pFu>NJ;}7iXRESvsjV4WQJ~z$z^|^+}Agzp~CdBG0LiXZE0l0IA6Uc3%ST3>(rYq zBaYCFGJ7av&a&X|P+P@%QH=s3vGEc4hGcJ-U_ck?3ZrD1t;j0R%1mVQ;sEL(}h&g>s2 zow?$H?q;|HTdk`hRSZF;*jY`__OVpM9+D*PlOLY{TGvJ!?A>gw%<9005#<`? zH`+$sBfx>GR+m|+p76fIbt@$T&u8uAIYv`+GBVqVlGZd0L8ft>FcVuxQuYQ}VZ5y^ zuHMMniP9}(Rsq%%kcW@D6@f;OV^^7FOm6B*R(zg9@@DYxykjWbnO zn-zB|#6y|+4MtXe$gB{ZpZ(&xoWpXtz%ZKS7}qwLsy$gjYi;#2ew}ExR7_oMjIN#Wf{JobLI34Z4S82@ z(tP_Z>D7Hrku$8UKmdweC``}KaZ@N!B?@xbmuyoG^@$iS+^ef!O^tAdSG`{`2v`pq zeN|U2HSHMyHE1MQ~;{;(lvXcu@*FAN$^?zIRSOxSX?>Z%JS9ZK*e z;sh3~y431QV93A(aJ>*2TaX@9q8_3f8-FM+q3M!?oG2fIOul zyNPq@k{H~ig?s1eA&S*ms82%<>S`+KgOT3hCRTNgCE)AEHIbq>aB>k?Rju7fgd>#6;`z-RDFlC`&ezl_Q4kC1 zQbEIjxze@6z@pSk!Z;R=Ct}wUiO)sgMO3iJk0R!ZfcZ(_B~chsH=yQ7N*%r^l!HST zb-Z-#0m(JH1-6Q zzQbb2r%CMdfG2ShGS>}k>TKeD;-u%sav0fWAIM}F1ZuH7*f_TBu^o^}(bZ zbzW^S!!mS#Agw{J+7Z4N*hsO`K}O|Aa>?gwIcCC9md%IA`WZxH*&Y5_p4EFZ2i4!* zP_?t{u4L#fr%~6fggmrb+$-B*!b$seY~S*IE25r&02tBG4p?l(zGWqm2rWN`*e8NG zpqAw_OIo25Mv>2B89NE{!f>Pg)`zY)H{fhE=s}j8w%kdforC4&%PhYEs9Z=`%P+;% z6UeF}o!!dEm{cWU5+Kz&>97zgkJt$!5s1X)%yX?Mlu>L`$QQBA zuJN_*>k7AVx#qhnbMvnpRJkHia}nH7*I<(*ZJX)fm3N~-GjzsbG$txV4^ zN?38mWou})I4U~`s@7=!M!~CP>uFQ#4Z?XZ)o<&VWp5AsdI<0paj|Ra)HMbyz@TKg z(iR5{O(M~9)@NKpWO(>_HiEJCvQLL!Guy^~J>z|J>PQTVhF+f9QbB2Pq|1i*r~D_x zG@1CeasSb*PbM&qF{2O5CnPcq`%zKybh-6#l_jXm5&@cvOB0%_1%&SUO2X+3q(`Qx*b%_cPNdArrSli@oQF06!P!k7#!;nSD~fzK?@ z@u(&3z~xQ?@jS6TJFq2-gv&i)F((Oa?g$zW!uQANi2Ge13@^kx zL&Wa@@jKkExBA1{do3S{oEOq?@n4S!9cQCMVFf=XOcAw&xx7x8z0LNeieEAwkkA$y z?X%N)dqKTYM;<;Tmg_zss2HmLfC-Lh2rm%w!$(6E;8m*}UkxI6VCWrG3Mg!UOlx?d zAeSKYD>V8E-Ql$)_fY?L$onxYc)>gqWPR+l^`DIcbj+izv&j$``$6b%CvszpC*1X5 zZRkO8vt#MUBC_#=^EDiL1r_>*VHtEvVkaHvj7iql{9I zI@Gm14wD3K!XfTbCWV*iH@!XhxUTI46slXPg=-b?63)0E36TT7j+aIo@0PUf{jDlUnkSBY`V}6Y?rz(;8uMq-Id}3}ow= zcHp6I2Lu&G77JSKqM_8_LCw0Z8EZ!&Q&NDQU`+l@>DMt9(XlVY>{i?(?aC&BXD9H$ zIxHi9=7~0xZu9-X;Iu=;0M=uu41CmT;8NDoO$2Na?<}XXDTNu^(O8@Smb>5~AU5Vz^Ctn! zZ|?M8;o>YVXd`T-X|WJK%s^SpHc)WagJNwcqg4+^Pf=|RsRk@gg+*HdSKmT?OZ;Zc z3O$WI!AJlmu6YG+8S(m|69JV$ioycxIxo*;W@`BJ{34FJQ zg~e?wl2#)nxBDaA&U`42=1I0^_i20fAZc^NJCt$FpLvRSM-rY_@g8%1r{suow-f2n zD!!N~&d~Y$F`PO!3V@+E>pm4V!2|%>_5+#t3D^bB2gJBOwnnZH%(1y{^;xggLD`3% zZWW2}M35w=RqECld;wG(=vHpVN(c$UcMS%fnAX?|6Tz5njr=wT9U4`?WoQikzr8Ez zl^Zw0e`VnF94M0F;$vK#F7%#N!vt^8^S2|M%2FN}{CKuiGsrFrYs4LUF13 zs#ptEXpMt~`4zV+(^`uRxzxVe*VdFq?@Hv>ajLBVLW!kP@8F zanukiHp(P#@Xw#9b*g<;iau%?YHM9r#{pe>Z7qshNAUNi01iaW5Vq8yz_KZcN2$85 za3N?tGR}jpD+oVMWtC3k0b^CwYgX zw?qF#HUO=9ZFAs5&~pJlG|DQF*^{sJnp@w(QNlt8@vo>q`r1tIUg2&*&WcaX_ zbwdKomu*NCRcBZC&3+oVjekKMV&=TF-jyKG?9;0Ds(6)jPgOcV6vT=+j46QGz-O4;vSs5`@T4l zEGi{v$0#nsz50lJ(rVpFWIcf&n1UABrJS-BNhCRC=;h;W3J~NC%49e2H|?A~x*&xc z_-WDkipr7FVuD?O841R3$dl?g0&YN`G4mPa^E+`*ofiuYXbCjpK&Z0LLJp=l)`gG^ z9B0kBfFEm5%(!4a9~+(%?esab#T}Z1jcUPY%g6J`aGr+Ie2XTLW?6qfKR+YgIC%)^ z5hKDAk%qi*k2LyOh^-)^9e7m(KGQzW_g>>5>ePAElZuc-0>`{2(uGkeecV+_)Yc6OWGR#%RV`8&&Fyv-4T2*b0m#VRlFs7b8xZfledH2JiI` zXMudR*%GnjYj?=k4Cl%hOj(m}DJ);d?a@(=$7ct8CP4b2XDyI#c_ljGsV5jXmjw&0 z<>E)EZQ5BxI)#{XY~t|y=oF@6kbk9$_Ha|eJE?T%Nx(@SPnC!jzL$s>yyt!ZEUby= zV&Tdm7MM-r>NPVDc#0Og*u{ofzh<4Y(d=RzJBfY2DeU_tz3-Q{@sakbaawg)-|+HI zsr#c9P_!jlDRYzrrWd|zUtbIK-Nnmm29i&mO%$KZQ5%5 zY>@<@>Nv-sh(=V|oE}$m+}kMdWby9M(tu}?Cu(U}?Em6*+!F1=&ZX?^bnchzN+BH) zGEwc!T1#|yYL=_D#%~VvZ;0*m?8tVTRmL)VlKV4@IQmmjjy7#G3(|HvS72QX0KA`K zd^?xp`;A8Ia^Uft9Jt-LTxdb9ydSf2uKk<_+hc}pQXHKXypP@U=xp;~)+%St!Tt%{ zC%g}FChke?aZlY{%;)*t$_MQMARM&7`$G44b8(0aAP{F{lIrfo02XW9l71(C|2|ws zIpj2A?tK=QA>86J=C`@T?~4WcUz{d^oNh{`uLtKBCdQvYhp#*vWcg z(fomU=sW^)k5hMAcJA=JX_knZ40yTF+cmQJ?Y!lA%=S8pmZ+_~#3grVV$S7;CKmCI ze>kYIF}6fK35*a*M7xud1w-Kz%pZ~ z?*bG}r|30f6I_|&@!>73BN}ULsIo`;?gXphz;`WzZ1nGHLLhIiQB<*b*LR?A6lH-X zZt5%?-Pi8=jHtY zpZIPC>p@>NMV%D{zRS2s7%d;t)$Ee(ZO$7jtAmvf*8?eRe8{lb{{rv& zksPE9gb94EF~J`FPA5AGT#@K9J)WM3sK#l6ZK@4Ob!6yX&Ua zx>q69?zN}RUxifkx(cbTLMp?@lUE_tfmgZ;sh*I?RY-LeQXNDqS0PpZ`tG`X6;fS= zR97L@a1~Nrg;dP-RY>)4LC;l4^~CE5+^<5atB~p{q@veVNcH$@ucQ7dq`C^J8Xs37 z)m2D!6;fS=RI`MyLaP63A=SUq%k<&nPyfN6(D0AHe@<9U1sAvrwEddD{Ou*ZVy~~Q zt^Ri*v<=w8?fAI(-;U?QE8j37{-<;JYyKtt`{nm9t7&UHwET%%erlKKa(MmnM_kqn z&i=e=Z~r=r6dgTq{v&_=upaX%#QX^d@Z(;(YcHj|W}Ho|TVFrD&1QY-O00;nx zeKJJlP+@6uMqy)gZ*qAqYIARH>^y06+qjb7 zw`%_b#~-HTM0P~Umy(y+avW#JwQ=H2oT>LJPH7+#w7I584G%k>y!`j=#zhbWDaw|e z%)z9}5&?8K8hr!Mm;d|^$5|u3pVBN_d+MwWKJO3x>F(Ga?zsm(r7x!L;o(bfcaMy= z#(QHw7`_Pnt=;kTaIMeBPD2>?5kEW57ybuchw;3~5#q;Bef2WSNluT89L7XpeuMbp zB%YHSGL7h3*)PADQ*88-ILp(*%ae4CH-7D#hzLNqnI#3{3P_aEzJ&()N*gG8`1CXN zp$niXM~b$brZI_51u>FI)m|}~vDQ4fr18LL%#ERCswFq$-0&W0j_9l0*#z z!SYwunKkD6xRq1W&Y?L8(}(6y0WXHzI}H>yP$LIv)X0yTdPyKBFs*}>g0A@%rJ`3f z&KuRqs<#sG@%}$2uMQ72ph=N0*0Bd;fW^LCh4k9OgrJDMJWS%-@qu_Ao#(G8Jti?Z zr>UJGcQAabAn$|}*|#O_JCF#)k|;v0$n5OsN@%+^>266Zgg%()3P!x9@p*o6H+J0P zy4?#qy3VVETix%z*!>lveQ^(HSLLuRt0>`k%o&|jyzOlSZk67=o6xPw6k3=PEN~yI zValo*@^D(%BA1g@3FbLPFMc=v|Iw_Voef8En1>_^e>Y_P77SUHKz6oZ500=!G;c4H z_p;bsXY}AKd~k&KvSykB-M4q^&XPZ?Y_;$|%u-!Ysh>?;!E% z&m_BJUNgPPX*L=z$q6xNX=coeboIgIye0YX%7%N?+Xs^g8v9{n;}im^R~m;|&5W4AOy0?Jylop$E0Dh=++kap3U*ivWKV>v0S^5r|I<#uJy z0twB#3TQh|n2q=&uw#L=n7)v;-da+=eOcW`7c)zLmoflo5|KRov+@G}a6oH$O5%*L zRu=I-#l8E{V22L#3L_NIE}mdK)jdl3)OqN{HcTL{Eu+|6~MT%?VMyEGPWVR zHX4jZ)GUV)p{zVS+|6I8gGi(6nxZE zXM41}yEWL_RjOCa3bc<`^uJqF1nm<$PoorSdhf0t5kL`Lp-Czwt}C1Y(ybK;Yn z;E*q8U^`}Wu@k9)$h*20ObU^GSKX6pVt~xTzcLD5n16)qXfQ*r56)X=? zs$hAqt}w0CV%6u4vi z!l;gs!9_cr=2;h$;AJ&r8LT|kzBi03;dM!}I9btUMXjRTB*rUW(aI5!F61uFlsl5! znPvPeM!WuZhVx=6I7?Z$3jfQ~5M6k`wAEXgdQ^xG8Vx{aqL(H3jsjC(ph?#i;>QBI zO!T2O!z8n^ZQq69rBcwqHgng-R0Z{~KH z=MrqZ;|yyA;%4i2OrpLS+KEiQd)Z2eb1?B6`kDO>7v5lG$Pe@U%n4oaga~1{KPwBHNML*_E{fz$p+16ev$Y{ z;g_#{y`t#iS6t)zSheykgYi3vNe<>W(b2F^xjcK_l_Z+LGPOrb#5*&}!_-CRURtaqjrk3uh$Coac_aC#c5WKsoM( zIC%nH;v}aQO4*e94zxPqY*z60EQ~$ssG2{hqH_Tf3xei^u>*64KO#S;4mTD~06-5w z5l;_?fDM*y27R&|=oHQdq??n4{!-3C!^!?=)C&tKd*(?_qW8so9^Jq^2UoQCE&+llCD#Nd`m7m_93;m~NrWTb1{!*iKRD70I4|EG?;pLHygxkIf46`7 z_MLe&pUM2r9PqVaOzISyTO+420Me%?jWFn zJ8%cv0T~8_(1APLaosKA?u@;it-Y;ne+S-p<0bgXrjc0|y-xG-(VL^=566?&NB{fb z=;hJrzfjr-j~2&CE_(D>pY)J$%m;3Gzr(Mvu(-$8ZMv zN7E40Cz;apiaF8Dq2O?DoYBAm6)Ip2`wnL1Ov9qY1EwTkSR$oQTuGg`(@cU;Rz_zj zVgpvr=FcpRFb5b+2M1~+wWXI^@Ab7Z+XFE{PA3c_n6B04WvsbcYR;1PXk5^u4RmGK zX8G}xT$-eO*(yxsB1w~}WTHb~x7j#J_L1l@G zZ@@8K(I>#TONh6uOb`62l5(GCV|YN*&0cQWoe)k5=`4$K#> za+Ms`F|@7<){7#IduOEyZ2+tFFcCC1x&0Qnc_JDOdftN?-ie;0xP_v&#=+YnZy9Q| zcAn2o?Db6VRW6FOe8#8)6r|(*%OXw%PKCvyC0|1!7^Dj&@Y2w_b@vL}Ub(c9xxQa#rhMhMM|>8<=v|{Ds@+ zxr3;it^*(~ztbm*Pl-coSl=`^7kld!5+r7cute2UR4HmCAvy$RB%e#ldojIsWMWx^ zuwEG%27p82`(n%nGeiK(lS6Z=_>gJ1Nn)^U>aVQ-6f@q%%Ob1Ze4QzN>HxA3kYht0EHWgD(9f3+qSHv5)I&5IzN{Em40cR zUA?nwcGmi1NU9M0tzxMK z8l8nQ7t{xL03;!NwaV7M=cNU&lsQtW2d0dORUIgC5b0a#ohmYrk$|e)P)azj#mT%+ z)OA=FR@vbMfLP~=;+zIkBA%pZjWM+mrJzTSOWnP7=ZU`C!ocHuP`>{wvV6wsTp5V< zEV%-O@e8(J#n@zsjzC})6j3RA{9KS><1RjIt=Q7*%fkuAh`_Gpwv~|9$Xp5c)+^zf zD{*@!FUvXiwwxQ(sI78N)MN#Vjz7FVb*9wuaO2fSR+9KeZi7LLMdEXue}Wa<>oCKP zG4_}B<1h|ztB_V|xFs^Aj@6qpdY;mAW{z1s*-PLhP~ijcEaB^jpkv%afS4qAq7Wi7 zwy{leCk?a9hSfz2AziDg-83w*S~FHZ4Ox(;w){S-(Vv(~oYNc&!IBqA;QXq3{Aw)Dqd0U#r#D3YD16Fn$Sw>OO3(;t?JtWky}ON>WG?#tC~9hpa>FmZjBP%(FRpB zREOwFh^~pbffLYwqLIK?9EGo}$g3(oNTagDcN=O4M*>FD)pwctK-1+BQamIgPK4(`txE@aZxwS52#p zNOx%>8!9u+@~nw7)(%mYrHN$z9R0gb15!jv-T0ZruEJcGWlJ!ltSD&pJDv_?l_ZR( zh1!cHQ?N->@?mypOvWblZBwnMEpbvffeZ5EGfTT$wpaLM!H5pRx_gWLtBzF|Cjl7s z-|w^71Ov7(1z6~0ar2vl>^t)`^k`{8lT=zy)5qydmh2IJ$+{OI+FVeDPtE0zVyq<^>*H1izLM=yOh(U3AD*5~6G{ zi-?Ut!KP{agus=YJwXhsbyM}lZma;-7P_ftmD^e;o6lOtgw~1G9G(5ZkT%S<4QoC+ zgbyAc3ivU$3s^ZSw3QzpRhB|HKH=*4dDB_KkIq!`11=%#prf8Ae6tV&*iZ?7bf&Su z)1pj2nA%h~SC|VFQ+7C*75ZCUmrm{?yWJd#$j2ffckx|I_$~Rjv=isyl`;~-bKp@i zE(9}5vLcn$0A8>-iV+3o5%7tR<_&KPxooCwP?^6NW}cZiif_5GPz3`7*mT$Cpmn#o zz)jzmO)^Bh(TtknZde}N0n?{bw$w%5n0AMKq2VV}g0!zK3Zc=r(LkOp>eN$%o<&PG zS|+qv@6W1xc4ep;Ck>;!Bu2LrMkS+IEdYbIFTeMs67);`D2-}KVS}Rwi;v05uR?%+ z?K>CAHLK5wqnt&Cb(ka$!gHp}=P8MS+%(K@KoRFMn+*zZ^4E}-f(^_dz%zCEw<4*g zIHpotxT|JnY17CMt&4V6H8r>8IUhfj@i)^QV01=sN4lr@TC%#rh3c+?M8}})11HHj zwV%kw0*j(9ba2xI{`^A{Aa{D5@bTliHrl~6W6pDau^9ErZfw)%<~zv{W!TDXd-Sz9;u+vnUO z@2plOn|quHbL&kKB8>cV+u;N}5@1salyTKVz=v>v&&jGpF)S;qe>ukHqXMZnn!3f+ zNvRPkhrm@oWu+m4j-sC#J=uL$#S_7D*R-3Z93A5duzhk!R^_QFXjDg zM7bS^YV(XOM0InJ_$bTA(AGSq1*J_1qiyNAZ3hnSnjF;s2$5z1FOnkiwN1w9 z4cfrhYJX4mWS0-$B?TC3yrS86t}jCG0%H)+*co2I!b_cafe3eMb8!Sr+ie6DiG7m# zz=e=qOSu|4?BEz~X*1aoearJlVI_yqTm{CO^*BLoN>;5zucn9nx)!YKp{J$Ff{z*` zD?czsoVSyQ^wfT(q`QZVUvCBD8erTd!H8q;s5OePjdHRrV_a>FtBuhwdQ^s0uYsD! z6tI4jkt@7f-FIdMY2H%|dZgyP4wJ22X{;F~UH*E5^?rQ_Km7qZFe5QYF;ExD(hA>H zsNb99hplu?w(n8dCj=zftYKx28ne*swwk=2l7!}gt>&<5hxjqglJuYOz{Au?DX)Z29+-Z-nc0B+mKJW5u@b4UyAjD zqzWHaW@Xop^rIS*rTtQB?r2(hHN{bP)9>GcPQgIx7F3^fz1)JbTUkzP9%i|GB?jG# z(Oq~gg#l?ee27nr)t;=#Y)@`ww{;CK&$(0vnkNFkr6DfeOiv^IQOQ?kGfYzWj)Ulu zIbiwzCZY@{S7jvwMRfN7ygZ;8xpMCPs%nY3GShGK(K(x4f!7afh*ix2PKRE?Of ziF|GQngmn?q1K-qOmtc*{ zpN2WT)dfvhUF|LVtqDf7&%_*mPlvafF|%%>rP%+VU*i+E1lKp^&k^>j%Wvok)-}b+ zGj#6IG%b&*$mh-u6d%dQJi$FS0SVcs zzmQxzt#j>{{ntk?C#P=>uo&D|C275b`NK*uKX<}@_z8dJ21NfxJB4k=*i~F^E3T^T zyge?|LRnTrWJVW!v|m*M&aQ7>B*~@CsG$+i4Fc0}P8L!#C3s$`kiSwAL?pWabtg5l z?rQsW7|Ys!IbKf~3`=+vS8~{&G)3LeSYZ(KUzN1CXCGs7|EawwDR^8V#MKCK6;QX0 z5LYLpI%WYOhP?tps@9di5PEjhZd{MvSZ!;okr6aAE3+?-Hb1Hn=1GI2f?t)pl z_dF}N^Q>-VQ<%`P6yzGuWb&&l+>-Y3l{|@!$JF8=OlK;n@3TaOL|MYGo!+3`g9x8q zg-MaA`v6kqj$$!={@W^kq9q7#1BaZG5PxB&62Pt4;NkOx|B9VgfNrTDuKPT?d3-ba z%$UwsOa8JQy!ia+hBcJG6o*X>UU_n9jiuL}pTLY=_Wr-RckQv{HWEa?4>13su7HIl zSho3ocBJxI+rl4e?>o^q zG=BSV-rCjiFCTCGngApme0c7luaEia$Ut&`_2JA@@ZITgfbTw>m2OcrPr=8fh!$n- zg)o-2zpqgELX8i5q1WE{BP!G7Q=F~Q(S<*#6#Wr8`tHNAi@uQs{hWZ^55P?R_*r+1 z6X@Z*W&FWPA0B=Pwf9di?7HC3uFF3{j|kn9y8O{umnTEVEfU7y`SAIjA2lrh4AWkm zzKB0{ANbHQ{_H!yGJfil`-6_}*=P6tWdC|?<7{yZ@c^T_Mhe3iw)3*M(vP~I(O`b~ z(RwKP$-4aCaVQt5=b*RuVY&}=%j%zpDCQO)aIfgYfn#kgc0C>@s7Ju#5mu*LmIrLt zXC0%vAu$UQ_qz*OzBb1Ca9MBO6Z+}$%CnukD;ed@h04ypJ4 z{xjMZA`Ih>IV(9QYxKW7oDcKl)t`1ycEobP$V${VL(naQ1J=#~xl-feL1CQLh8_%d zU~#*)^urFDAX+y}?%Qh#Pf$hp^e{pg&z6(vr`tF_J3HcffeZipp5He9ZVoo6ezG#a zF94(Ml~WJkDM$I^rrn(@cXwLjUty%xr{CSOPS+}=4}5qE$$gb*ZDTiIeK;e4;pK_+ z4SxH(_BLSg)2}`Z4P2ZN=nl6?*N#w3G%v${{`tcnAE&(95`w^6s=y2PHLp$I5VEzr zdw)oic_F*UmMsD*u|Hxp=Gz7~ze8y-u$!OYmg-NMAHHj>-_`!%&uhm$%2t!@x6s+| z&fg(##Xc)21p(2h>S(SC$07LQ`M9_+vLD?rveS3Qk@0A{;oUH@M9EF_I<}Ul^f10- z5+=;cH7?5aB7i;*(Qj*$7z(y=cke09LdgLZGg{#khV^I>yWtB1E|g(qS3J#w3auyuuN`HEl@IXdf2|w$pJA&f9iHZZ+(0BGe~LXH-8pA(VlR@AcltUb zo`8L|oV_qOkao{6y7C$&EU$i_={WHXGjlnsCL`*9|L^Z)q(6eja|Z05Caxps!fanB zmiDu|FypMJ_H$UE`=67Ay8k&W*!>URoAF!f>vuo=;k8%W!n^RwO*um^&3q$w+#~^# z&&wCJ;O7r{u7#g6S$qyG_3hUPwp#Ht$VJk14g#_-B2-Fmzz8X~JkP^zD3Jb2SYv)m$ip zKv#LwhjH?5(wTpFP2*hE=8F??it$UkZG$W94CCXT+n`Zi$M+Vm1ug#=1#BOR)DQnt zPL=zo8ARH<&ub`QJzz*-M$OUiV+=LAtW*4duipRRH~Dp@n+NKRbdA!0N$>*>tzw4U zwR9?#DoD8Whgd2+|3MKk(Dg#M1=8csE6e(9%u-GBffop_x=6jI&=f0zH{Karj0qx( zNff1*XjMsZ3Mv)3#A$Y7l6DI7B8xRDXQ`bqdXe=`#2J`FAajTBXyu;HK9QTJK!0`Hd=VX8C;<3&o zLrfoE)LHGXzv^QQNjQs9=(z)7?2`Dd*jS@H56|TK>}m@2k?W1DuH$b5Q~N%+*?u_8 z*IvNLJ|g$3AAxL0U0752Jn#ir9Dz!aTTlQC`Iw__$kp6g4D}Wrk|{0RX80x_aVc!X zgJVLV20U~jd}pDyjZ8a8>f0Aukr!K$C#@W|tuBgz$$OP$R8yL?)g?IK@gb&Yb1}IH zW$hy81fPO2Mhdz3lC?1|&bSjdr(49pwJUhPPnodmog~At2ENq`j*&;#ON82us_lEn zwucKw>mh)2r7c0AG<;_0_k3z#E+3ZKycN%&*?(ufILq6*@j%#SWoneAc0vZ{ng5drE`2 ze7ZHa)N8y(VL6ny`>uF++e?f9q@mBc&Mx1(#YBEl+_ohGFBCw{m}h3Co{QC2@_)d4 zPb$@_|J1$FEr5saZj@8UekGV&t~@!-$I=?O;jWYQw);(YVN5+y?ogE;BLm++Rb}Kd zr{e}${cQv1Y5n(|jbOC?4}9z~jC{IYv-Une4VWVo9d&Voj{vaot8H2~Dtr<&TeZ(0 zet--C&GoOjazw&p#WhDL%*~HNLuf7~w|J4`2{PkB~{_`(?^H0Bd_z@n;`TgtMbiQ|B zNtg0!-rZ%fZa$~i*#l~>=)um6OXSJ&m1-aY(Fe*OCM z2MtsGHhrDn=i#W?1tNSnoWxlB9Az{4KN?!vEusI0p!^hn{bhIR`B5CRN9s}y`Mb5| zt_I@a+c)1*3f`ulqq2;K{#(rE2pn;NS)MyT6aK7<7A4$1THmC}{}#)!tA0xWf5?~J zE5_$I`@HJ9JFV_E|7x6k3`R=s3P?}|@KNEPf7 zq|T3luyg0j#Vxo)gWHXc*I)_9 zitV1tOVw(0MNK_;sD3!;a@{<*hzQ!hY{+PPqxVA2x?8vQP_U?N6_< z|C+<6AK~x&b0~f468?V7M}OMg7c`o7s%E3HM;YWrmf@ol!X`1LDMux>HdC6@WKtB# zS~<|UliAyj>EGg&5SOzD|csb+Xc8=_WvT*DL)MYxjf#@!xN~c*Z zSsQm;L|a&xi}D%t^pl!)Yesh@ z=p*mm{VDU!Mdi)g-{*(-7`&R^brO$mEoZlgaUEO^B-aK{4{N^!aj-CDKVy@>NX@|o`!$E93a3mjoR*zv*I#v1u zBzQ7I_yb7(+0TztfIsV$L!)%i9gnY3p6SodW(|K3k>3E)=?u_?xx*hi%!+4}{`IUC z{P_;!>Q4Lk%dTwyy)J-(Jo-7i$O0E1qDf}5i%KO~7sTw6ne~$WGEd5ZB?BLd(K^nc zeHi0|0~Wa01Z&xjy;n1F~8XgcC+srA-jh zIuPL!tRhf?;7M8RWCee=2L4L^mx2TZNTPt(Py^}&DU=hXU|Ez=L@9lMiHG;iuC8cx z`K>7EEfug2{G{Qxv=Unh@DCxfpnYjn%tX;8A7EB^tXRqe)CPg0r_wI`R6`G0$QfGD zF?s21Hd1m6v$r10r@TzTm8q2nw<|YPu9n2*ivV>{!I)}!kzAf-@oqAvmTMRum)or6 zB-{I1&b1uMW;2&oZWNc7XlAQt-^%^ek8~JGg#h2+@-#(dLMsR1$>jwsU*VQk9%CJ$ z41QXaYvoggV47(-X&t%TLtsTPU^eTDGpPjET+6wp%(W*F<&&|wwJ3|O<=zxEr4^T= z;uscyoM$asxvcL8wUlMvMs91rA(@iIqFTB0dx)j;$(7hz1h~1T%z9a5nAY;lib4a)8f5tYw!U$d zwto1nxIwwLpD(pX~#HU?-| z2ZNss%u=vQ01s19VOfCR_$GdWGN^UJ)m#sG>)FYZo(b}~;t@E5X?3Ew*ecHCE${Vs z^J%Vi#ZZ^Hc0{Ny_tt8tSzvF#-Q76zz^3iB*{AumJyew*RGu!(rq81GZf+lITSaJa zZkV=teFMbP`WZ&UZ^QaL(j>BboLi=bN*6}7`R;KbB2hrX-$*Yf>kz1k*CEi5l0<94 z?A=p$CQ#Qd=!%_GY}>YN+r|^ywo|cf+qP}nwkk>2xBDBtNAK>F-G@EiKd=th8gs5| z-V?H<`2(#+RZ&~aTPQbj*S?ga+8ECC!s5Umw_7T;?J3L7$B%vw6&OO9ww zU7W=BNKFu(e)aFlUsC`*fz~=lOKMXh8$l_10*v9kPy~mC74<rpd8pV)s~tBzBUS;qU$CYj<|S}4_EK?bt<-) zFwMNlF#JqJvoK@ACGpzed2VxQ`68<;0ks1fd9wmOp{R5TDr7_>Sn?@zO!nj;SZySF zuu0O6SvgGXLNTb8rH#v=YmcMPpf+-_gIX&mCEcy}GJTFBHx{4$k!#oz;2OS7 zT*qx(4$bjk!5q$z%+gdNWW1Ohz_C3V2f6;y%S?_?&ZgaW7jx$7-&o_C9j_$CnrSua(8Zqa1HCc}OYGN0Sj8veHIGnS{`1@rj(WjI8 zS7t{1DRhjW^@8T$0?va+h=>NJoG^jRqJ9hd0lk5n3@B%qv`$l2 z^s8v&Z=!#4$ku(DledAK2RA*oqfB383xmX9`MbD;k>veNZV1wccxC}| zVn=mHq}cWT{oLkd2rrMS7{K?DRH?%7t-}5gkl3JloMDmNUG@G4dA#=ErDtBQ!=`n$ zv|S);PWy=NYSt(TrS6WV#S+^-E$Zf|EHmWMLvF;Bkck{mSmJd|ug+Xk?} zthVMY zfd$YMN%t9vXev2qGCe4d{?)!u1G~h018DM_YMbL$Z0-a>OS=`J`si3qZ+dwLT1`cs z(2neuKC9E4Co|W1tAEYL+qKlF8M?E`;spr&d#_@Mla~PON7=lqwr~73amR(xMDL_( zlBA-GO(Ge_pI7UXBPfx+=7H8ajK462_zJ}&a}x}7#|u zc7ffS3EC7_x7oSU_@0n5$DU=9Rcman_GQPA!C+4W@yf7Od%LSCM;#fw6^Jsy0&~oz*)vNEr!aL7RRpa3gVr1 z3>9|Ysqf+IW^dz$DZfz92a?=h5jBhLieM^r*;6IcGtUmP+%&jz=Z8soEEUiK^4~V^ z%J2pYW7unJv71G?FX5QYHb)y^JcvXK?3DMKN#+p-c37^iW#W21)3Tr3@ESoTxUd@s zDb^bqonW?*y>xM#!+MAdFD!;mREeaNHqF`HpUQGb?J&!Z>0d87`_Wnj^l>cLUg)mH z(h%IQ;b}=tru1-qqtEHxhx(v&*5r z99UK>HWu_+*Pxt*6(kj69)X6JlC3H6fKO9+oeZ`ItR?-bP^qR5XXrk>j$gJ`G1Dw^ zg1f$?TbT{K{UKJW_bl!8~QmT6oXKwb$ z?;rPGF}_I9zYu)KA-r}^HNFt|;!k=$@Vz5~e)4%!T~zZ|HEwt)=k73`2R_}n{es!n zLHRw#yNc(*C+Gz0e^0Q)3eJ}J7us!+V(gV&nTCD4G%Bbj;^yC!o$s8k7u5eEKDyp< zR~+1k7$tw}=MTVpvQd+19B$QwBaFK>);9^kK5(exB2{*m@Z4pJwXgyRAppLH{7f%Q z37lk3aw!z!1br6lqQs2sqO2!wz6T3V9(1 zzaRx8PlwyD5{Q6zgv}X)X1~-8fEujIoVGoew$Y~45!nUkOu+mhmpn|ppt4=2wB4R` z@VaSjzHf_^{&xd77Vdg%6?XL19&z>>!2!Q_>#oXWFp44Ujt&F3a^e@1R!O`MdUJ}= zR_wTsp?H@NJ@BN`A_~0Cp2oqS7*)C{XjBh=m*SEDJ7p&^68$m3@DbO!yC^Ni5S`dr z+E&I=9$q3@3#)EH0$f6pZF}z}y!-CL?{8Hd=BQXVt6YsvYhhdJI9^<8=V}HXrloQr5vBIz33Q1P;XC`p zeP|a^75h{1kxBw<+sRl`fuCELkLcS!Ty zd@TWbY4CZ}blLq=WJT??)_gFoska-P|Ngy+WXTIljd8iY@Jw(ov%ZoGZX9`unf#(4 zue=JvP;--+TJnh&dDA0XUkRbC(_vTR+&u~C%ge$BXQZ$X7ENAzHZa=FRo;FB#S^?S zI2Wgmxz&odJ-?$=KHpPOax+%Yn%!ovJN~pQA2o+9jwJ*%V+Y0Zg2!Onv$=IgaYoe0 z^1!wGfMA!r>?wbVpwQ5X+~wwS?Y;T*RkHuBirabhm{Ar(9*n=yBwkJpCMQCpLUoEk z(pO;tE3_+PdDEp7Bl0g+l{SnhNiVpoZxZvP@3VO*U`}n>`Qz&Od`1Sq$eo>)s*T_{e`iu){x^!jbXBL#d; zsxLj+v)jfI{V5qOt~pClRlF2b^)-TXf|-Jo`hf+6ALZu$5i2chLpaWoDaz!kYgya} ze8{tmcA~{KJux%P94&C~g|XT`a=OyG_LDX-bxNJb(y{ z$>yP+WQx_;p+spB2_0V6VsP;ej)07tRC8GWL3H${Gn>qmX&xb+>WL*XSSd{>1p|3>rZO1RymKv(UWToa8y@Qu0SN+_d~_L#-o;!AsN7 z8TFI^PB}x$CSNf}NqI%uioHdN7pzvRQ+aC;@&FSY$0LMVe>CdSVm$C%HH51Y<4xB; zp`B&AddZBS@#99xT$P4FWW`7kEp6Ka!P=!{w`U|<8mh5>5f7!kx_ zH?+Hb5`o>wltlW25Pn%JR`Q;-HtuVtm)IJXH`-RlqJ@z^pSZC=y_`)SuCA-IU9cD+ zqG%TUmo;o7V-d}6dAzpb3E&K23RS6~3^2xC<|8 zWrsjRGBzgbiKd)W(v+*Gf%fgzZC8L~z!P1eD!tus1e%Sao5Y1BAwOPnZ&w_e^1{ll z#4^2I?w3MDm!MlfYJm<`)4R8;uz0u3S4k4`MJl@j|7z<)@Q*}YS177&z;$i+PGqpK)A3Sq%}?#~}ln-H8p2(=zlCk=J_M%Fc-2oebM7%=o3P~S6JSfSV3AYl5DIaN*_#vZwGzRt zd{gtD`%0-$`}#y82m7VW0h>fcR_-x}{MBd)Uj7IbUS+W6TkRwlrmm{vx523JDJnBYe+)S#Z~~(sE4{qGl#4=s3WNfh3sMZi^@kEA zil-OnbXQjh?{Y{u54PLlFP#VMc^&bl2wIP%7Zt37dYOY*?gK{8cVM24(K`&JY5k#Y zt8bW};<`Sn(9pA(F}u9ez@LFBa;?*AIB`3Y`fS909Ry{{w2~@qW8xenBY;<8Jqx{} zfxiI7v;K*nOUQs!x>DwkLp749e+Z0pPxWdV#1Cr6R3DpuZi+Y&?k4owUyMzQr|?$? zlML|{OGWE>+P|dfpAV@=SbmHJaYf!HJnl$$M@!kBH)RXc@guDY8$H<1{?RBq z<1O8TpV9%{73C^B(7ELEO*blLc^0kR)AGbO{k5jg!L-Z4F1%g(+PO(vTDw|Gi}fxx zv)ZM&?iF@h6X&MKPlE_y@Qwo+Az1A!cp^Km|C!6;~j>fXqO1gCL;LHA3o#Nq}w>--q_$~ zk23AYHx#W6ZSN#QvV{{BS4U`4niQ+ZWp@ED#LC&5)-*ZfyAviMs7W)udy#%aWwcdTZvkp~GgVISG_Q3!yD7Lvmg z3?MG6W8fkb>vU9&#`S%+KO^=XOd-PqpnGzlT4WATkw$HtVvVgzZ$liflhh)988eM`O0gN)`2$)Tp z;b!iPaE&n*FC?wqsG%O`EU+2s+Jn1B!zH581lGQE+I5m?i^oJ`m`js{au>@4JrjiT zlMv>b8O9ChA`HD8bYUKFIC+c|UNw=1{}>c|bZg?U7nQ)d=|6zAHa#tkQtU z9v$D;@VZrd?Zp<%jIt1KEpyL2NNXO&N|Peo`xeT_O5jKudh9QvH=bjQKUK&3XABad z=5?#O?9<5GQ)$EbsUQ}1h0PuX(vB!qW;=wW*64&e$Zv82R)XK`WTO7gremV1l9n zU&(EfgpDFA%mjn098i#inIg$VlelF7*b=4Kfg-@MeZhIqDr21Gj#OQ$v`;ujt9qbi za^@O}NYG!6r(dNQ;QTNwI=a7cEx_(I>RAxYhlzw2pQ1?2$Rm0ZX=+Q|s+31mff_29Y|C2hD$4NmS*HQGUaf*{~n>b{{aUi6n1fY)2 zKPna0j9y}7Q>gtq!L}18uhTjkM-DB4wW|CL9{y`LeVzJN(=MJ1;{d!u|NTpYXj1&m zi(1?;%k|wy!kB~tppr?mE5@5tUL9?L?EBLi4>Zfq$+nOtc z$tC}yO!43vuHnArXvEXA73kWj`ol8`qXuXzJtmdaJAI9KIV#D#7JG5j;YDVbaCsey zc?Os#N2+c%k@U;^Qb^!LxMEYt;nyyQ9?<3yaDam&G zP=0DExGHFOvz3;;v@JuP{GiNVN@6pv`ko7F5{;%#-lbW@L$er;wG*;yREA5L@KG%4 z{}JQwC)@QhHE-lONiOC~`7MkyYE671Uv=!o?Q@)G5_72O1m?;X`Zg4~Ic-58b`uQ1fzoclC$*tN+If*|qk5;55!AVt%DnkeuzaHF>8Smr7h_4J9T^iFajTtdrY6tMu&! zoDUd0LYc$KT=UD54~gevj>VA~f29G_d9!_YepsoljV4J>_gpr~F%SMn<^u9j_p6ra z=s{+Je-qAS7DsjIHFRl!iIQLoZrIR0bme zMucC!fkq3a&KsqpOz~OGJ#N1UCQX-6?6yH07=Bg6t-l59+ey{8$(`VcT~W<4dcF0d z8yC?X?73xNyp=B3ywTC`>Rruvmi)2$Ez|u^0%CLdlJa$ly-G! zKXTa`vam{;l7Jn9X8AOKBJiiV(%QRuMrmRdL5SUuD*q-=IIK95%BJH;l4k+(KJmxl zEOO4eBCema!_(qw{C=m?LWh>Z@`ITa=2u6MoFKWH$I>a+Fm2^Gd`2H`!O;9CeW^(4 z0wV~$;g{I?q?21Ry6kt)gPRohyR<2_pC#HOnY``lOWSk37sB@;EhA&77xx>xwYxG59s)05Z%c<#7ez zH@$*Ka$QA1x~3fIMJ-neS;a``X8m~+%-k-jmY74ZsfP=Ic$3Y(|C_38y)C?oHI{hW7$M&q+7M7y41@exSWnlS{G0mO#}Ep40!^U|?y z&iTIGV5n{!YAAJO0vq6{Q`f%!>o@Y5+DN(+{XR-%5mV$$;v&vw>CgpDHXFM%NFI6A z_me=T5`m|pw5XrD%<7@rz|nJ+dDuAtw86Mkvbl`Og-w<@>@L_myCgojBDDP~N@8o2 zswFUW+(Fx>%sz%t6n-Pq>j%iE$vjcf6x0|TiZb#j`XSXxx0$HhGC>sufZ-d1BJp9s zXk4rq?`l46G9f_}zZ$7gURtmi_*M>>j}V%IYlxglLWiH8!K?AHq6~6lily^`km?|Qk%o~K5l5`~n_%=(3io-$~k zt`u_Rl?Z6Guc)sf#XX~qL=`EAPYli6-p|`LO%;!r!NC}(x$znQ7P3#r;-Q(Ha&k++ zn%MXwE|!Q0zLE!P3MrtotZ0{t4{o^K4@165>RdUFTT40TUCdTX?wS_IvGQ4SIRmGn z176Q~`=K&`E|eCv-jSX)$3&?@&_Jbk(~B=mB4&$yn($n+;zFQlSCCV}-7mmQRdFW7 z-wpfe6b=e|t>n-RgLq2OsM}$%{+j}6zX0EuV8*|DPM=$1yP(#D%gSc2O<}hJYbobp z?%rgTH{$>;k{15+^)7m|UIr^+Dr7cmXC!}w=csJ7{VZ8dDlObR%U^fqZrs0U`EE56 zR%h{-DwT1Z(g70$cQngRmtB+28hgfy5Al-yviK(D#?NRWr+a-*m;@)Gmf9p1_3Hy( ztO`mlB6aDI$!)mlt^HgbQ{yO;A7 z4)p7|Y!~eWsZ;RnN^&kr6_AYiZ#a~hj<;pDgH!$3-xMBBWMksDknA>pq8h*#j78IuA^b!j4Ha{q-nvGv^E5I}2$zh&=9DFUWimDDauW}D?mbwQv zkZ8ZM(mVFoK1^`u60{2bVW^p+rjJ~O8wN0c#XfTPDw9iF>T*QGgd&+tLwBuFRe3kV z^qu24Ob%!s1h>4m)K&q!gJ~&sk<>tOROFG_2-2u=SuT%1yF%dsn-?Zxwo$%ip~LBq z;eV!y$29o7Jq7whH7w6K}8bla!_>1{Tzm>(T7cwdNcZ5TiSO@$dxM zlvs}_1CXnf@=qyFj_zy^g4HRNP8I;<%c|_m;LgG5htJ2fI_a2)e+!w7|4RN<%f@VC z@GyH|U?!7^n}w|%nR&T!#kpl-8I27fbk>qepN)DD-N#g9!KR<21g#;TrVdhHLzH43~ElvO2sx zuu%Dd5?vv(;@#?nu1Wr0mg!}ri|uW$9Uidz30(C%~LFgT6lI=;_!Q_jeQDNBi0qtTne zKA|DbvFNAGw&|_S3RlP-(k)jK3sF}K=&i{b@{K9YV{$ZG^|=X?wruN<&) zS7&+0Cn4s1b9T|NnQT2X^>kFL+^h_jC0y~EVZOHvC5JLOCxQZL58kEeGFjVEhXg&ggY%JZ7dOHt>9nOC#B#u7?2dSz|44Y~{3k zme|ASn=vO> zrHXr}1(P(;BVeK3pt1|Uw4_D6*%Lc!d$a0NHcC~#P`9JPN%k=%C|E4wo%611zpuH( z6IdV?i*;nQ=?#%pcHFZCw;U{x4(%x;#-^C#B3|Wn%D2z=JcbX%#lpTcC1^`-Q`tK( zrkR`z>uM)Fy zTp`wscC}LsJo-Sg=n^BF{qwfQ%68;4lfL!@s1UtS;WkV$c+8b=t%lsgLxnX8tu~>G z6MxJlE2;5|rp3}^vsuO2j#HZp=4-|P3iCt^k+%`;mG2z;UfY~r^rmw7^02XEA;lBx zY|D292Q+jxu*UIM)t~I0M*Lgb)GT6MF|55uFBzyUECEMTA4K*F4z+KrA{b6A@%rAMV-A;$-5Slff@m|H=atVN(_>NUJ1uxwe!Vt16GkLmd^(U(onf&x7aU z!SYQ$MxJ&N;u=f?=3*L=J~$~#a)y-d5TJuftJ2RwdFUllD+R*3=XaX@f1hs`cVzOt z7q-WjVjvEct<2LZ##Qwr8)r0sgZ z+o7y`6+?&bX-MjSZElO*z3mczHoX>o{azpuAMgUr=f&Mq4!>>3zt`kBKM%<+N@l}EhwaQ_pJ}_r&ibk;E!76r(elHKV#gvw!`4zQ^H1*tDMrC)qKNh!R_j8f^tx)t(?Ze7m*uo!esI)n}7#@%_rf^=FQI?Z#L`%?;CLk8(G&P3pVZ&2-8umarGx2Yz3VNcv=yM@3d3ebmKV|j}jg8>#}!V z&_c2h2HM&=*FDFaiL0H>S6ot#RfH>cDTR0GJ0tA^=dyZc9i?$Eb&6p|*-8n%g&Y-8 zjG?66$A$M*U8T5=vYwcu(aV|Db?O5(NSUralpWdUlU2lOo>OsBIAI4zm*JnyY+H*E zF4tXyDUMZ#&zDeAyt`dyVa;UJFR=SEI5#`o|Mn$6f{+;gn_hq}O576WDh5*8Bp6CJ z86zs0CAnCyt;zvu#$zrKk=2gly!HZh!1a_O+G^T7JMhm$Q^&;Ooev+F=>3y(wrS6g z(NqHdH@XX$V&q^#0`7F_hGs?e;ca3t{Evgm#);vvBwlhRHvd^pwNqDay$`)%7q{>} zjlS(`l9Kbry}7iP{xi75ilJD$5Kq+vJ~`#8yvA!F17FBql{a%Z?E^Zet_J_1SHyu9 zOKY5B1<85=2Jw;U{#wci1ZB_yW7L>~HAXq_h|`!YD$g}MM?)QTDq|Kp^p6t#^Iu@C zmrH9y>ajdnGxvjRq4TyDC!Njq{FVz#Vtq!I&eS{=af*Dn#umX9cQG_b0c$plJ0|@!WpGwNLRshLs#=6;>Ga{%b}won_y&z$#;(e+v*ye9Xd? zn>`d!OO{aqv#7U6rhIKZKzF4lHX>08cg%(rlc6@l&mCXI?w&AFk94Zvf?fZGOMITIaY?3!P>Ak5KZPKeHA6v(+m&kSHX@%7+_|tr9ejZ--E3{6NTk-P>aHNtHqW+M z0=hJ$c`kj~<{R$LZhTu@l_Khc=RM%aZMIZ!iTSK{ya-b-sE3Qga_v>mf^L8QmF)|R zD!%0W9z_uaf_Jx*UI*Dugd7RQ`;O`DVWvIO2%eXQtvmE$P0)(2?}XpPB2CbM$}hU4 zq|6(8FA?hX+8nDPbI~TG+Tt8~@umT!-^L=BY6EIV81s?xn{65BKobXT2k={6mdAy- z1SWV->K*={Og{;xb#^%x#7i=Y-MHjQCCUR9+=a^;)ee(S!do);aM+n~zr?oN%8YiF zTr0%@&NbA~rf%P1iU?>EaI>EdS(EIIL$KG{1Qak#lH?%4`=^|oDEswA!zK(==&%V= zoS{e!8Rpl=3C0oaS(B}eIVnmLT^Okc!0t{2x2c-6(kfEZ2Ih1IQE9MnWMSBdbXU1L(CQ70ESr+XVxE$NVel52}hZSO&D=k~$tvc3FI$f9JB3K?5 z>*ZKs8G9wT}u5EdI1ir1okdf zOqZtdhFX)CqLG$RdA~AH50>bXP!^lqJN|tum2wFkE(eaHX>sBy;h{j<`kZjWRd)0p z2b61lxVj+tf=s7rKrW|!4pDoBC`6~OHNS>Np?!WIdp;vQ|8se{1*@};Vh-NdRDzz= zwhA@Zr_$Hh)vni<&0lIGNd_Nik(*i;sp0d(BF+CT@_Z9){yh>PqWJ=l`vhy$Zaj>Oik)x+u1_K58K8kC}f zs7d2B%RSkuz$qd2nZGv+Q-fEF-WzxoQV3M?=w^$jWMtFV#x|7_9e9guwRWKGia61s zyP?k>MUp132MZy_#PBUcb*V|S68R8o;GtxzRx1~R7cXe#kjgPzWVF>R&h;nD>$$IB$|0lu2E88Bkt1}X=u;un%DP=A8O>MhWze3K;5uPE0 zzy;IGUvfz@W4XDjZoJP2xn(eOagaHoGGi2|p*o1ePbjhZc%ijI5aN;SlEg5vM%j=x zdeD;bR6?eB+$Ygg*LLZYZoR@CiGUZznjcb9T1_@D5i^Fa-REt~S^i(CT~A&~cp@k| zXz495`78kkoVN*Av&EXS0h8b192vaqP9VNpGk|vSbBE7OhHaapM0YmqccEZlwV)6h zGH2bE*5VDs!D>m#RV7n2&LB(5@%p2&gZyP^y~5_A?_kSU9;S2&0iG{@8!4V*-`1Xh zRI|%orE^`ko;IRdn}iak6pjNWBB-NA!eO8?Q(e5+p|p7=<)3%oygW!QBK#UVQybe2 zFYMW&Uo0DENqFjdD$l>cLtq>tp;p#EmdC+8Ot@VB2dgtH(~id$@0&;8C=#x;XpY9| zF#6ZL#TT>0a;e^TuE83>cEQ|&tX$>d7$76HCbR+UKZ*4#b6UyD#aBh-gUesnVGyT4 zU@?b^82(`-wOq6GqB-xG+;)Sl99-IyYdNIdp2wH72c3K>76%Bq{DzV;jbeDz3Dk_* zTnw%jAoM^xS5<}5cK^g7%iMXv2o=YoJK29kX}J{fOXpPN@pk(!D%U?E+UenHd(Uif zSTW`3un3w!LCbcU*XJEtd}$6cC9_W`6jRxzDbf>&~>C7enp)c-L zDJ}C~MlKFwbDhilRq?-g98C+{A8gW2dap0jA!^bk&xR}bEBp5N)ou;fTaJ!uTjD^H z2yy`?w?8sQIj1b-#Eu#d2{9Udd)drO5TEZ{f|nVBxlPO@;J?RmE_ne{aJmOyQctf{3y zsW7x(Lk8d$j2xjkY0LFIJgL_nyh81KvsS;J8BIdJQny>Mn)j9w@p?gdo6IGQIiWJB zjyBw;dQsyvmxOEKg(EggtuLz%za4G`Rc*zo$usGv8s+2KB;@2e_Ww40UmRCCis|*b zu2(;tkvu~S;@+gQq-x1{n;`Lfy)-a}Hjkf$!$mZ6 z89MwTK#(&$RqA!g?8v{{Mh*nu=&!FB%dYqN;WaVUy|;+!hD}EX60HxO0~}|JT}Yy{ zH>CLgh1@u;w{kYV+(ru?*vVBpFr%nu{6sqxCZ{DQ?eOAH44$yhgeK<}L)_TsLwJf| zsvj|R=h!FpR&T)y&nkPl#W*q7^&`Zb^=|lxh`(Z3j8rZFCNJ#sW1P2ncNe`#w|xRb zoyHDQ|ITC}-SH7gp)YI;psRA-)*&;sEr|N(;jX>K&{OZq&e51o?FJ8*MSPaLx;%Wg z%V;+=?a~-G`BHSpkSURTDk0Joy=?!dbn8k`dC@d>_2k5DWIp$v+5&zZ(p#l1k5hDE zF?yszBrU&gGIv^1^Kx&m+iRzXrZ^cG-rA=Qoy>uWci z#nEVG&|bi|3XytjYmEBVYv+A+0Vmry{qu#)mlEWp{0`-SRq-Bu18hF;GyfYY{*_Oz@iV_We6!vcLeEhD&s>fh zgmY*f<1k#DB7K)%>!UaiWAu(K#7Y^0)B6|}Z!NcFN9OEYK|LL=Huv)zC_f%n(pOcQ zS(IHP)&N~uEP|2d2B8kZ&wQrjt+t-<=NYH2s2cyhe!3^-7*66lxs=M$V#jX;(ht}q z3u1)|uygH7XF`XsrBpmq7^8f~H-jMaz zpM44@`yNUFqvSP9v0?vp)KS8q56csPzH+L6JLh7b$vK&IWIyK>+_d<5E@A!k(1?lv^S3-RsMF3OsMhc?cn}mTU^f0PVww8C@Xz zt2gOx46QO`d>f`wS-^iLG!i_??0e;JdR8ci?+R7xm6@kZpleIghjF)nJ zb}O4Qhw<`SI}ck*m*~Dh|FL!ZUHZd&lCax-7joNU*TiBGUJ}ZMUr;`-W%Or}?H5kG z>AB;r?*a0>S%Hk+;fjDKmC;Kr{3z=-Lb+aC)xwqtXgYkgLN^NB3FO#H2M+h3EBiCB zuiAv}%fIT&y(EVAn=y>4UvJ(N;D%vtutd2pd;6IUc__BKZ(DmGw2y?4GFd62+KbJo z@ty2&b*a~xvlXAAB)Zz^gEgq~GY=nRu+y)*DGHZ{8vPoxDK!wBpG(iB{b>iDV#T~m zi%ZYHqANd7iqCsO3OenSuP*vgQg1S;b#EQ97${Cd1!19a3>8UTdDGTjPgU6YewTf< zmg85m^jL{@6c3il6bC6wZpR1$c-?mUQf_;T@p2iHxI&ATZDF}yFj#E+*0-MNPDnb~ zLR$V2HbYAUzGZol{sYa?#-!R&|Iag@+*6)?U1ms_if)|p9ui!0jU5fD6D-o6G7D(2 zT?N2hr&6@YU5D5^eVxdnjN+SyR$(vt9-GI!H^x-!|AVK&m8AUd=rm^;;&&~rm#>jw z!!3Cuo(WGeL)v0IlWX=9hS|EKwxw0bH;t}GCrBMEOBl(Lb()0wOC{>+u;Mo7n&QQ( zD;=J}vy{3phiofvTc4<}xbi9Q9$+bBYT3TPlL3u7Wo{_NF9)5BO$xyYx_>=sy_YYl zsQlR|^Q|LKG$5KB6zM^YiB2W!$tGq3gD-ikW5{O$ZAtvOB1z=_6G& zD$p4Pz(f_aX`Vg#x=Q`UYWl%AxtHxqW{)%u=SuQH7Va+NA(Zl|p1wdyHNfHKo~#Ag zt_)ZTdX%$AgE9eB{za5f>{6?~t4bGwtLZ{&gek=@R@&!E16QUY^Qu`vEHVJ9<`6Lt zDOpYW>g_eDXOu3>YdHr5;&5{e`y_&3iaLVDPM*g%rkM}RMl@C?M zE$CH){NJEyuNOgSwgWymn8eGSBk|xL{ux{@g{^)e55^;prP= z4dj!KX{kyzvtav<>-L;_0U<1&sq;Jg1t{cNO`_X`<&~z=6b}!4S~8N_e#EN1T|O_u z4jGA^ebS0_a2wuyo%w}&CBDiNP|uUtWx1Ey9s_<1PNQ`Lv~^$2sTy$v(sKk5X9x8z zi3oFoyvC!gSv;|Z(l_sK7z3I+ORqZc)=hB&4CuhQG zD6i!fIA9fd6=tOkz0lR2sMbCY%k{anKtIVIZvdI-P!t^#!A@M+9)dPkq=#Ak^2s&S zbUEY~H{K#Q^AtwEEP(w_G!&Iwn-{T4MG$l|kAFj%6}l+1ubvz;y`7=Fi}ybDO$kuj z5qm*rcp!lE#*&B=#SQ?tmPaZ|pmw ze_J$z5?X-HHZc*Wo*9w@&)+*)*$yc0MN_V2M;5w70)T+?m;BOymQkUpO{HwUN1LTk z_CI0PMW=#(Cg9NZ$nmoy_Vzb)GFmnHHM^vP&|#_H>{`B`$j z`nj5v6<2$drP#cB5uRt6-S+sY!SQ3fH+XSWI?MMEoc=VF-tJ#u7)ba@UH0P_UrkmC zUcAxUz&Y>pZho)1E(fhy9l>q8=gIZQQ1Z8V9Cy@U$fAGD_A^J5+n_p~16Nsy@{4aA zGbryjcUHdWPHHc$7`~YWBL*pVkvoL-+aN6Fym+^-zN3{SyExNsXuvv;vTZx}L^X{q zAC$vlSpyY!yXb0jR28|xevmf(_aKw;JWhx zm&s%tR;)SB=;+djQqI>DkD~o5v3KDWnJCic$3*8~4GhUfI&-0zEnnw6M_eWIL30nT zI48-EG;^Z-EywqDCac6lNvs2@44agb){jZ%2$vS|CGLPEeG~YSvk<1bX@)JR+q_9v zB@D2Cuo$57V1e2XEF#xt*p*GQqYO0A8rMWvOCW}iS8H5Gi9|_WaoWq_Mf<9n?bYug zRd(t!!tS|;hBBPNRzaAXDYUCKhw(UoC;*yUiUXI>%!7jqK7I%L(s5bhQILt*$noU( z>)NJ?P2O2DHgI{0yQs)%7HJU7zjf{`h0cdhvmuAB_V};F9X&}+Kl<xHGQe}4|Ui15vHotcGahJRW)Fla%u%u!8 zIU{pK-siK&?y$}7(Dp{Vx)4LF07LZSzbKmA-Ke672NN_+*fQ=0SPNhLl+dV39))RW z2%TJBFE&j~C*&|UQ1IY%j<6mK>xqYWeWWLeSgJYovXwF9xMY zS7-LwNNrlJv*KA`!5|{@M3LF4B_jt>x zAVeAP?ISO^`VkIiQZfYJ;(5A24CCfg)8nCfEJX^nDcpXxXVHcHTOe|>4n%+|NiRb& zV;=~gF%hZTiY;EIaM8TpO|Cp|==JqHo(^z@U)d0w5Vj#MP25nZxwCBjzbP~Hj-{59 zu*(8|3isYk`Fz-H@=r<>4{i|}9$QXEJbhci&g}}noMW&`maWBy1hU%4PZ2N2#c5Y! zFV32r2<)N`uY-|~rbemZ3LCA2y;44fKk&BRClucngP1p$h+*|8lo9nDK)tdNzS%pZ!TO0vczhn>TYt(}5+ zn!cL%v%9c7(lQ6S-Pb17k9au@y87tf9CyvD-2C)^YM&r}Ze`cHM__XKTL3+`YYiBq zCDcQzhb)kYR+(02*25X}mP)car^)#=!{ksI zr`JzC8l4dtM)!dgIWga2d{W= z_LZt!pnRSdkXq+k_;lRfIT1zXr~l4foc*`BA(@{w$|I4y)yi!RNiPid>3;!cK-N)n z*Sb4UfQ=xMot{^9!oNz*%v5LNgm^;l#reya@-*yTkjFgxKKUF2hPlUGE*tud%@C5@ z)KX9{Ne4TTi&Vf?GGn-#J>2^;w(-kFHLJIk+W36#k^tsyU4D<*g1mjNa%X_8sn#u{-=A~tD^kAqn-m+46RDv6dN(SAJ3Zy5Yqe-(-JsZT0 z=%ggkd{`u>`DpzMZ*q4-x`R>_m?z|m7d-gz2w2a|Ru>hWGb>rQG1rUUoT(&0kSs8? zs%c0!em>?qkGR>p_R& z04D=WX&zb}A}vq2dtz+h2>Lv19ISf42#CNwEX%I`aTot}B9vI$Evb0|ZiJ1w=;w@r z=%8^tZ;%o$ks6~6@7ABLz3q7kQ?2x|bQrsmWZn~>nWF3k6SigPqt;9oR#5{&oTlx| zIyYQbOr&;GJd!9Q#R?gH;pR1a`nx>-vxJj`S6US}{DqqW0_v8&DQZ!AzZ34`F*F#? zdhwn+8u5gpey43;!w)6Gem;)zw>jkVfY@1UYKN%)xbw zEs8eI%k4g9t8qFDNjgj}XLpQnjK`Q_oYOpYb`k^PEC*0$)_x+8WaWM>J7!x6P=$&C z53VnrQ{AA%;q<52WQb28V4GbCPTi*|yWq=@CnE^`(kna(xxlo!>K~80-Iox($E5elCZaChXMYRBd=Wa!bE55_YI>soo-8~t~UDw8iCjADhJY@Sq zYchJjH@hhJg(hWuIgDi{RoG*Kso$av3&?@^*noNbGW`G`<3~f!o zLL`%%Xu=FFb-uDxN7-j=Q|3Bb_mixC^6}-fn+l z3gZ+%8}m^9p!H%ZFJzoKF)W?Y(9_$@oz=C)t@Y47u3ZqC(q_r6k2q#6!ZYM`a?|My zW0W@e@~!oQ##e3&1{fVL%wY2en~^~IjKNRdg z6zo3~>^~IjKNRf$*Ay%_mHm;N-{+0}FEp5+_wzKc{yk7Hu&Ms(tDk#g*I?`S!o+vh zZjaaV$^QY3KytquD3e&i<)8fNU4DDs9zJdm6qjge)sMP15+P&VELQn)i=NY)s^v`&YHa2_{>Kg z-@Er|dYylf^ApCVE{yF@ufBN?TK^Nq=057!{`}^3djIOFqto{qosl1PbS3BiCw&84 z?I~nw?nRbHf7HR%W%rBcjM3g}jP~PB;P3N$eCG)xa~DSTb^7*Oz}Bbh7(aik428$% z>!Z&;`|Jr=`M3-zy?%}Fyn6y#{G|zh`!;>p5b)XZ;hV3TCUE<3KfXfnBpL`$paGoa zC(Nw-xH`gD@AKE+iYE*;-fJPdkEKuhPFZ(pZ5pF`fN_Yc4M)7Mje`#;Oye|S&beWJt(rXOJ( zBRo@jx0|}pFF*@zq_1Di-1b$NfBU=ZP-}G#HKF*K=%Tt;dzI&%US>O&A*pqS{{EOh zT*l)HX6voK^zifl{J@<(hOqwmpVR9S40hV&R#_OCw^0f)7G82x^z&mHMyan;#N&*Vt0`eUH2ee(zU1HbWo>YDX>V>)Wn*P& zc4cxdYIARH>|E<}+%}T`epUBBaP?ttbdhAfANDzQBWbizonpIW#kozCngU5sVwpqE zk{sJg*8lr;g8&J>Ml&PHaW*%$C6WLd-9PjT4UT{N_kUBAJragFEsDM8%AWek@gjGs z9-p0_nR;ZL9ouJ=%rw{VPP{WC@^ss`T>Z@R_YSJDehlM&#%o3St@;Iz<8-+yi>9U3 z%6pVFPf2ohx1>0;VB(Bb&z02ah!C2byG0FzX5)X!h8o5lPEz zadJ!I^gJAyom1Fl@_R(4X}HW_%;sW?%U|jddqqh~`u(Z|?MUMC4hN=Lx+HhRPiRBA zrW#~vQRb_l%yLdy$kV740Sb4EY=v4Ck))svnN74Uq@QTm8_FBEL8w}uw}2DPHwS6W z@@&BwF1v1xX--ZnX;8*lx*Hm8 zUD^c%uCoIJ1};3I8OpbTX`P_#=CxS`FgR~R6PH#q+_15%%+t9#{-?p z7J>B=3W6Muvpie8A;EhZb_nmXKI@%-Ey823&~lXz1;#B_XaJueA@SmZMrHPa<|DW~ zAZkC1xsWcC?5^dzcUZ1}0SDX9xOM?zz1}{yx;_aIBZ==WXspe!*Jy?IwJ61KmbnWQ ze>BB-9J%I?o~Cc(cjix!itjl8qovz%oo-*!fW{C}evHf8uPmq}JlH)vPy3?eXhBFDD5{W8LsU8Y+nB`AH8kuhkuNqm!ExeflF=C>&% z>n({avQ=8PciODOb~aUGoKv)=OXmNc(gPH?B&V;V-^IQ2xgYG>pTrRjEXr6keEe1U zgTe9V3sa+T(D2V!ZQE3?ds5w!lEsK{o8|GfU!mnyi`JJ9Dg#`VqbxlReh-3fcfG)0 z6`{Q{Cuu=g>vyEM#op>CQwu#mpfs>GovI;?bcbrX6**4i>OS$qD71V}j||Q9J=Lbf z42Wk2)bT_rWYLRBp|1{5U;LgitO$A_D6_q`Oopl0mx{g?S>RT6zmLQ&rvtl0Dl{| z5cE#$z_d0e|L#|kmhlR0rp#9qA6Nc(kK{L!R|V0|&OAq*+8P+YuLV=hbPaQA8j%&w zOa$%t^z_&|IccU-Kb;sx1cDnU{;{fSu4$k6USPSA9=bClj7;4P{S)^@6GJpr)%0e# z5$L+@xf(bNn?$x}dd|!`GhKV?TBnYo*^Xrdk*)7Z&NE#tPFX2=LDRC4b+5>h;2h(M zSgXi0BI?^AEQ1#qk!FStESo_L&9ful7Y=hlOA?Zj;E><0!NV<gDRrso?LC}DU zpW&(sfb~riz8C=>ir9FJTI?ZvC4xOFd;LBiY)%H>aoCDXRRicyY1MAq-F21*>}Pld_YoZ>ik6O?{e18jwcU6ym(Ros=)en{K^)^1?!qpCdxsJ)=| zl>xgk5A)5#?W!!>%ptgx(d}-IPsU0;ZTO$@VxP$}2s5z=? z6B2=FR26LVK2Wg7#(eO@q+ur7ODGPDo=jslR)prTXCuXL9p>z;ebPzI!|hi(dU-;v zZlN&Xf_8!7%d`8n`iuc~tJ8_(c!Ah|77lME?~lc&Lxa<-jDw1WHzY3= zUCAQ&5vNLdOO+qNHk8TP)%W|#;kOE!wepRE=Aukqzu8w%Cl^a(TUq8=05U6Aw{fA= z+cdZaB$ioP#IP(%l;sMm^M8ob8#ckkPs##@ksGRzG*rU4DD&7~mDny#$2gbeMAkt) zuwPM0TGhV@GIK@p8(NCT6)VNF%7C6-);x8+AFSy`4C+ae6OfYCFP>wq6lr82#{x1jUJs-x+C|7aKzqJQk!f93 zv3CxRaJl4Q{`?C=H(TWat-%#2GJA*!v^=W{1{^)!sbT^nBDq-*rQj7srK&-`xV}!| zZ%u>O9F*VSAy!s}5h!I=lH~1bxlHaR`wIP3*`R`E0}52G^0ZJU+FAco_q42MP{Ss_-rmu4(#Nmh=gRFn&RjVm&Wze_(O9@Uvum7-~Cc`hqU9{H{OT zCkaUd2;)MMweybyfdz&djDl@B4wT0Nha^e%5!tL~$Udg>1jUlgxFzqPk2xgtlMWTm zpChb+mDwm?m+zBj?@Br@5;u4E!bpefB?BS zh86R+m~d2oO~cV0NB31ba7f^*p5bbt9y+=n`GKc9q2;Q98@j5lTbfRF&-8rXAt4RT zNV7e!tH1XJ?v5fqd#1d7bNauB7m(Ma1wA|up(T!Dnm<>*KfeO5*Q@$snL!?Oea)i# zvkP)Z^Pgy*JsUQtx_!pWeT*p>{Ne$$S_1ZI-4~5F9Z@?2J^=nc1N8p8$_bUn$Ok#e zC&~)1)0$>qJ8+slq_ykfsmF5VCvl*}iv?!rzzxzDwoy5|UKgBO3Nck_rr)hqSAC%X z44Te_1^f=G6J>F$l(Z;Q$XP3j!j<(%ikh-Cd#5jMV_ry%fm!y+h#LAh8M!(+LXI6( zLN}##E~dOx49C(m-7;0>KNXE??#Os~L%X(%s3_dqNvz92C%HT*Ni7|>PWU4k40d#V zFw}sD(Q*UVf%ft8;K=$|plaK%6%s!={l_ZK>7-3ZdHE7m=b!&n2A;DQ6PS^od^bIR zH9tR{zj}Q&2c^Piaw>!$W<4*t@=ut2btJ$Kv*nkS;!l{AT?!ozIxNYwgrwMMKymSd z+6v8!;^wGm=^B27mO=;iipde|XuwR!VkvrkZm2D?kokBeOOrdS8cc?fZKgu>aQ+Is z*RL-AKEIkx8`Q+e`M_*dCMX>y*V%_`I0v;BwiS8kIRY<3U5Dl2qWYk=w&w0AC(hP6 zB)F#w_psP1YPfCb0Fjq&={euoMoD>`8SC`XQZ_i+(el|V7sF;zu4y(QpuZ?$G1bKGs zIqb;VeYxp%RzU76JF(%Ovh^+EwuZJfv#XH^jR_=1nkz*rxfVF={SUfDA{V*feo)yD9zDQ z*M->T=pbvF0b!i;LOiJ?=>=cZpnBER!-|NT5)}kB>rDTA8XU_X%)KjoX3EuQ}CWm}7fkO@c%I~1<}5cqQnn+B39G>LC;LoozX zJ^9A20N`o+B8kn-1Z{<^$-tsWJUmv2YK4fym$F1`2Z8}o`4}g-p@(j;7mJh?s$i64 zAB+2CLPAGXrC?kjhTo7tCl}N6@7D-|7eoGP#G+dMrTy~N+AzUhcalYImqr>=Bk=&X z%(tL1hp;b2_j{OvFFQ=)lqzX<7^ir3NQ#0k{Nzp=DIT@R;isNYc@DWS+8weoX-jmV z=<2>K*5@^VwO`Dd+!vh1Vt3MP<=dA{68?>1s7grgipud`%+9V}znfjYWxEZwuv0MF zO&xICHsn-}we)I&Rc5#UATz-W1Z%W#N&m^`mW~^YN#eZ5@Ka1MiR?SteCY`^`})y+N!*D{KMOeL+wbbG@@JP z`u3%IWF4v8V@TDZBWdy<3Yt%sOOS#crJZDH6yJ1;L^an+pXqkhWsq8}dQz2@_~TM^6#oKMSoHre_=wR1giov z1)fcb2Ec`3#_?(K!PTozHK*VqLg8!<(fKoQ*-@V&eQg9+F}S5<2?-L5txRkd0I?p( zit4}$IJ6MA4oFoX6XSSrG`u(C52$e{`aJ!bXKx7mPDI033*?H&pDtemt@kulZnFgQ zwvV@&@-bT_Awt6HXxL4Xp+6M~$r3d84c_52>@kHW1sl(C7EYAlY5kExk8X~5c@mh4 z^DxhrOVGoVeWyjaAq6``VzcKoL51unM%Ovxx=lpEs8P-XzQO@X59Ut&E4oJU8|Q)) zc=VL=Hs)S%1Ja~vgGA0#4DKu&slNZ!aI-{3LF&sqE3+U=l!!8*Il?R>SRd&7alUfq ztOxLze~8iXurSX!F0ut+3evPDL4gGFU7bVxA+e)p6gH)6^{oT`ny8M)>=05@w59M_%a)BjOO=Z0Lpd+H@y9~XN4TOgV}GJoZ?#r6U)hhdOJL?lkA z6hPB9lLOh-@8_ULEkugEK4pSIJnqL>kayPzyJNHj=L{Hw`H}Qad3*Kxa&}rXI}w<( z+5jXib^5es$MuB~ufe+|#oIE=X}BAJqbl2dscZ;4WOmMzULgXgC~TGDkhvXnF6?E$ z;-(nD?16q+HbE>ZU$i)B&T2Z-jEc+$JXq@H#g3Bciv`^>lDr?~U7CWDc&)srnY;lsvQK4nP|)&w;!dO;OYQ?IuCY12 z8Q1_0+eFv<2~mWti0%VSvFY$D3`h!p!O#|RNBBwu$kmq=e5w+c?4@2Df-gQ`{{i!> zs(ZE1x+4EHI7x^q|L-g5w4xP7x7Ih70=>oSNg-0XOrk8X^IEw zBE2tY+N+;6rny~S+N+Xnl;@AyN~qbILru#HJvB5n%d&l+*oN%~rm5Px6B?>U1Jl() zs@YMbnvow`x@s6kU<7t#Jf^LTA2)qb!`b4T>R&kRc)B#9HwjG8hLFEt&NTZ7R6FJN zq>$W?OEv{phF|3&6O6tsRc-fenTxHH3-k-~4Hi9x(0AX$%c9E}MMwTkh1fD> zcq&OcdBT>$yiSul<>M_)g=bDF4U4LTRIC=X70B>y7gRY>)WFw=tM3{F2_==$6s(dU zT>b`uPFS5V^|cYH7wN_ltnNA1_~BKJC769cFPYT41)NO-N#Ib`(SyiPZBunM;?giO ziSF6~F^w>U?z(9hYNUI*5qfrHLOk(8BeE^SHBDz-AnAUwng6GE;>)nr|7mDzs-~;9 zYO0oQn69c>Hogz9S&pr$s;lCEX=qjL5cAZ?)eKjKzty#C7@i9hu-(->pn;h3g1Dnhg{K&17R$)3qE+mD)7j(V*4xvDNi)em19W+L|APwn{AxXu%9B@(ToX zmECD@r;EGD1R+e#^h|0+@Y95!)Ql|rZCj=ZbU;QQXxHNbcdeSs1-@0oV=}`GTJ?`W ze|QRTqXaI<=z-jLO_;nwwgB$%H^rw6JIm}+(Eu33&>TR@G7&3~m0_kC5yJ{4?u>CY z&4zy_;u41Px_F4VisPzh;-{;+mg~T5dbOI7E01EcLf(!ofsLa*!&2GP2(fhmQmIX^ zR^PP%ExuY3N1AT8IjSfbAi3S81iX5>X93qHUJ1@CnF;$Du%EQjHN*yghp_r^=Odc1 z5NtLLHAmH9IW>l#8>rQ4)@?8gZ!;{t)25r2Xmf&Yn-lRi%Zs{g8pS94&I}#t&T%Op z=a~V&Le61yWJJ_vE7P$uwQFUnX+Q&V4>=`kGybo=Yw2+$x50m9G3Pz#{g`8J0RklV zAP7_?2?#LR33hf5K`{S4A1TT8vfcKy)0b2?+Agysif>XP+GR-|a>i_wmo+P$ykw~+ zWj#TYC}q+yHK><6s9~N`heDClWab7=`*sBxCIn{y-59ac)KkNtjM%SW=A1H_S&K1!)&yRzq!2@Mg*sa)ZvLLj!^>D)%}~g`_M&dGvzsWz;sCI_MUw!0R8cZ#XNDPeq~<$yWNTtVRyClJY1ry>*fDvk2)} z-5fj`kwxo0W$))3iXXX6Cr9<&`*Du?DwuIaHR4zWVb*iryea7!<={@shjG2?G_C4= zOe-+Ci&nf+DS0K3N0Ty0wo#ds0aU6cnFP|P!zWZOP|`s=M5QiE6&Dm$3gkzTbSCMY zs8b=fD`aA>r%-Egy>-X_DdsR%6%@xC`bzYUB~GKhv#oZw$de>h6YFDg=oSAWhl+eD zUBPelMqyur!p~6g=Q3txKmh^VxIp8m5OA}L&f`xxDihz34N;e-z(vxMVL+!&ASKSz z#MM%#bXP}vs#}?M-BxIH2SZ$-GNr1N>(cjIZHtIeEOb$nH@ws6yDfMl=+LYq5xh+( zQ*5_ut56;2+<4ZdU9}pq{Wc5)msLi3B~IWa#80m?NvqvrRu9Hset0S_~Ly@*3^4=B>rGt2`{iQrF_U@RXG_Yo6SW1MD&(^T`!p#p@z;S zD+(pcQG7YC)VND0nHjH&MqZ)nO|SHjVo(s`;*~3UULcpNzPD688agK1TPTSf39k8L zaPY-+@x_?zOMNlUaYSyvmeGZS(mjf(- zI-%xwrrNEw)9^Maa8!fjk*fK`fq17%R7&ba;G=K&X3_A?V!;<$yz4?uktxP zuPxq^=!7V+J@cPT3IV)F)_HQRb}{{Q-xEfnoN>U$+WKz0zG&TmcCwH0V!fjGyVGpI z0*nay37a)#m(!sWu*+gAIV8KqJ*3;RRWOTGF?4TvbS`Q6jDBh-08zJH?>#)ZY**Cw zTDOH|VIYmmyt-Xq^ZGEy&H8rHVzf;Ikgeg*Z__rb`2p`5Ha)|zww5rP3YrzIzqSOj zuI@d9@rqhT2g%D90?t3sr^7L}H;R0E3(A?B+Tv;bFg36c@0~)~>o4JZN4P^_?=WN?G z9?!Pj*|rn^A8k8&%I~MoKmCV30zi-JrQRKGv>|}?2lmpa?*rEVGZrvOkOm)5{=I^a z?%YM#{)w7~{^bQvefu9h@9ool_URwCf#Of;-(P?KZ6$;b2js5}^3%A*x6`-Z{zyVn z#s>5A>c*g-q_TXC#jp3CM)>&%{xm^;@B(#2WhT%U51rY{t@8 zGcc0B_x~0DG;V(X`7I8^M{&4*zR44u%2#n3?MHFCexAt_oT?j~_J@%?!KwdPPRB!y zp5Rr#jMw<_yskqJkGapQc@eM3Zy&|$`l&HbaB3grv|aqIkLHn_e#U^6e}CRcgTDg? zS%C2V(Q zP)h>@6aWAK2mpwEGFFe2GnT|8008j#001BW003cfVrg`8b!{(FWp`n6WOGDmb98cP zVs&(HaxQ9fZ*J^8Yjf1NmfyE(|ARMMHI;@CEWb^Fy%55^)SbCAHN)QBDw67wZ8>=9 z*KNB4VT%90=SY4?vh41LkO2k_L(-DY(RrUES#Ey+_kXjj1Da)PR+a}3tONU97Dq7& z-N^H!Cw@Ynle7G(pGOXf+$0RsAPBP94!pC2BLSNf0QU-ix2)gA59lryt4&pQBg$w! zqhjj?oxQwXFl?FrGVjjzT6NjOKhLDBLJTj*LHp~;}I2G!|nmcCgn0p=wlHK>YR zu|@UeD+#H8k?k&%+t3pQ!GP?(D4Nn4E#_0UTBfhREW+mW-M(av*)_7sBzxG=o;#y8 zAWd6mnO2&&EH{+_aNn?)Zx(4)EEhLGUPWiqaYxXSn95HC(Gq*Kb3HZuSFlX<{KJkAEAlc^^dE9 zz5O&z7$lKFDk=*sPd`Z#;|2JDBtE+2{w$K1(Xvi=Q?(NQ7*`NvCk9cV5T@y7U4Ci|`PyXh1@L9i!E~AbxzsQq4p?ix z`Yws#?c1(W_y$tD$m%@7Cv-*^>7OiWe*t_cswk%`ww}Ia?9F#QShvepgJe^J2KX`5 zpDtnC3}5^2M~`l5;eK}G6ZR8rgYJq=bEq0<_1y@p+vQ8rz}Nxi7eMJ}(SS)3=I3-D zBaJVzYQY}@(LuGQi<0uuztQqF&bHq%-}guuWwuSyzzZEO$m5)nkR(xLvmkaEbBLb> zndb&k>_vH;1Sz95v0aB|c3ssRtXay6RRuU}89~;C4~xxgR?~Qpua|SNrtjwNQ=dG4 z7Cv{K@Qj?L-dVt&Q1^-L#l(x#rw&c&GpAt>A87*dY4zmeAN;EPzrbfJfQB?d)0_6w+M4C4CdITd59v7m$7Y_eH4OP~7dz9-8{@A z_cVEGgX4R_X%eS?lsj2;=4QF)L|Jkgoe~8@wOkdc7TGPt7Nvf|2=iIOKxuxG5ibvk z=Y$zyk(aw!X1l~o?L15zCx(d$m@-YHG)&zjc6=?w4~GgVbWsRhIbnHX2wnQsh+%}p z&hm&jzGDY*O6=IrLEkY$hQFR>9wd`EL z8nK_XiaABaJO{-*f6^)DiKLi1PcJs}XKXcFUeDR0>Q+7|m$UQ*)-sLc^4QH;5@bni z$ElkWFAEtbGeh$fWzA9#HeSYu&K3%bO3C;>1&JXP4=$N>7 zVZywqj%h-vpW5vF;KR}R!Hh00H}sP6iN7spMFw@q`2mcGN=aaY`UHM?1;2@+tNqYb zN*qD$#2g+AB;Kjsnc`zr58%TEbZg}hpV6JXtB}%lDC7i*Z0^;-xVT!;BbVR2P=+-I z>LONU0C!31;_WoP@JHk22N*+`FXXA(og)>7U(fjLLJ)h@&mjkK=jU@^mTvBR4)pE) zo85FM?$-?KuG5nOr(dCwytAFWkLNU7i9J^BZpM7J#ZBSFDD>$TOH{c)nd>y~ywund zpPT7d7iPB2@d9TXIOkVHc3~f{b&T;Y#&3o3Pt|ry#cgODck4T{tWerM-QI;#V^&pH z-JVB3mQw95!!GpRwq$pf*;Ez#fb`nw@}+^#7WdQ@+q(c?qMQ{{rRT(7BCR(dO$E)){(M_8u>a6^7m{yVus1@3%5(R0_1kAyd5rm0v%9TkI@$x1 z5=pj+uzdjdRf}&|R?Qot8(HQPSyd_Roxc3xp%#HMc9kvDbAG(^1~%Y)4s>#$IjdeT zajWy-_YX(%VHUxU=&5~J?A->8pP{Nlfs_JVoSIQ2>?K`ava0D8Po~QIzp}S!>ayjEG_J_{-nHsyA|5G}Cn=KdFQY5)qk*w*uVD;h;rqk0Wr++(}KK=FV z$=}a@olZG`eje-+H*iDObz}I?f!}@C6TgY|nu9=rG`X%=y381!CUSJeDi_KG3H?}r zvgzy;*yHC85AdK9aV%Hh>c#u!_>e8Igw5&+Fuva4N!0_#wsH2F&FN}YOYzkO7wdAf zPFX9}t>UX^2`bJH?%%h5`{mjH-utmgA?>hxFESV@@`9}&SbzQH$9wLveQ&wG2buyB z&ljsTy_{34tPdwoL1HzyCcf`-XR7Evo*6C(_#jNLyS?yY2cGi5Eq3kjX!m)M5 z4&5VnVzGHqqEVIzPB-8r>ju79U{P~q(FOQ5th)F=hLdJO8P-oPUW!%k+!sF^vaLR& zR#938{;l5u3=hxwftRJ7XCBt!&%%6jWVN4o4Kk@&m!QQ-+F{*^O#yk49T|qiF{5cj zIwmv?cgK8UOeUyBfydDlX#1bDv%g!9tkAk+MS*AAhPkUv0+O}5&EAQ5g0$;sX4G!i z%IneN254e{f2btiGhKb~F=<^urg>U{u^jRTTE}g%W!>jyGyxmJpC=MrXEXpe zt>ht1F}-ogFnVJx$s8Vrl^ArWadOOO9ZnSNHQ-cH4K@W9XBZWXtraZHnwOWyC0k@{ zEzel9e{G62I}|bbP%Jh%2IF2YA?nm=^9Ybq0~Rlp%c%XgwI zvaphYb*s&KQCclBMVVrBS2dbep6ZAEKtWTO8SO^sxwdcAmk>xTkGlWoys^c@>UB|0 z6oqw|rdboG5tEAf-hewbSo)(n3du>7WntbxD3Pa?1)$*gVZJV3Aa2|NGyo&}AQ&Ey z&=0E-&uah{U>Oa7tucq`whgfbp8!7|S`Pladsnp@Y%;QrlDoadu@!mW!X9=Q`p6p~ zS%yH8^}`Q6NkV^RMu1HV-LG0oFRZ(dR0Gn9#`eKtGpHgy3i|*IwnNo&@ARbu_A!}Q z_eXGaqA?O~=u6g&zR@R-a5$gh0!#U!)~}cv=P-@TaR2xrFA!HA}!aX z9I1s6`hW+{`e7JX<~L; ziO>wgKL@!hXuE4UV8xcB!>F6HUr;mFoXwZ(Yim^*ITG3f!vy7CA8P2Z;qqGdL|+y; zT2;qYX+3--E6?cKwcru&9+9e62^Ypai}WA|yr?dIaLs*8v)gURB9TnhU^F9}yAJcv z4z63Uo*-3NJJfi47`3|Ew`0i$n>prusutd8i4*hf8FG8bec0Jv!|`}@ZIXf1^%2pv za}nTia4TiDd}Dl)R4Dwh;m5dLXz=Xj&)8I7#x^xLvgkKCF*c(EV^e6{+oDb8yCbcm zga|!q5P0tRY_oV%;zrbz2Wk%Gq)Sh1-^ihp;BZro(#a zPCwvR+=(X>Q&hla>YwOB#Aa)K;|0#ZwX~t_@_x>OHext*lc%hg8>rYM!?*T2zUfUKfvt%W^^ex)C9ekRCPrVwru!SV z9>M)h7wk55W0ohWhl}mTZtFHlabe?bY1rk*0|lPxo1PGu0{VE_Io0pLi78UZ*{yU` z^02Xh)X(Dd^QF(0)u+n2vif8~nvTw)uMJdAn%ZfIUfhLC)=|h$C|)&$U7TnuDNuYF z-5V7d>|T*z>sKY%hO#{$>%?Lj9xPF?DMB9zu?jQF!x*!OB(ukc66@(j!AUgjjKt&4 zdUn_dn5rnLCT>a4^P5q}8gA8c4iCGfa0?+0O0meFj3ixsoyWbCXVrj*;2z2*Fwsbx z4m!<`(fZVX)NqaE zxB=OJ7*k=>)DmL+6kkGmr}r#CQu4+4d45;L$}qcFA2!*T3`M36re!@P!AaIsEVM#J zPDDImoEWhv*;dKJ^8BF+1^^^>v?wbcH`G^Gy8NgpOs4Wkw-60qowAJ2fQCzAyw`PG zW$_-zs)`=J*T&y#;}K>Cyj4Nd*G*3^3eNAf@%P&Jdu{x^Hda1=uZ{cddu{yH)W-W3 zh+TcC7lr#>ha4&pF-hrN!n&m$ zxfp2@YOinmEk`7`pOeNPM6jf_h(b3raP+jsDpe}^dc$0FVjxtHaU7>X4nt(yX2#e&@4Ub4A{o+)$ipI*o4sUnj8V! z&{Y@ykduR&DK$GAhtPek?{4_Un8DfZ-?x57M9Vy{U*kc?YhENO7DZLiS@FI(MreIg z{uYMr)r#)Ar1_~~^P<2mmn`Mi4m!j#3!Dvnh3*YYQ~Jii7d82ddRda@2_aeFr$I`? zEN~N=P|wK|Cnt{Mcwxi`qAX$&i9_3V9hT=lvt5tbaZ(u2k?3(Q%ktu;%FRROe#8&Zuy55?0S!VKW& zbXJbj67>Pg>v^)A4TE7-w79GzeILB{8pY`P!-9CeUd~%#2x~mDZb~?GHe0?$GTRlF zZx`|c<%+MkC+*EEH5!(h$SXSAuu&Roe8SUT>K0LdAryH{B+}PsV&Yik*Z6AxnM7^Apca(=1PeD06HUrIa|C?T3z^CqYUGOvN;aCyX)()yZZ0QiEIHNHobRnpY9NKz2A+y2=b4$tdGDed&bvZ_AKk((gZk3)>k z4^7@W2qBJ!_Y4{85e|1ZU}zADeA?GXW;hh$7~87o=I{$3~G~nIeH*PO;c|dR5UuaT`+qmf6D* zY%I>ng|@-0wDi^wldz?z*c9EhMIk_2IS(Bu7_Fx*H2(4Y<+uqA6dJqMYvY+OPJKdi zmP1~PoHVpEJBmW$1YTe}%#D2NCsx`;R}~zAk3WI(!E# zyf<&95%)VC3>)G-M8x>+%RA${FUrPP9Plw3en5BF7I>y`4fx)huwZ*P_+YH}s7Cu-JAh&yvd)G#^kEcx)JuG* zQFH1Ck(~w*+}w zccTY(WCylq`;O~HHt_@guO|@Vhk=d%NgT@Ds!bpCLvISljl3hVAN(XFCsod;*P*}YQ7^oa)DzK1wQD4 z_??_6^+Pukl5&~&O-M}qC*ZN4V;NOkhfqIZ$%`c?7j`vz_0j!;c473kc zV8j2wfyP?|)FB5N$8qdLz&DJAF$muGHC#U8ib({5fWL93gERTO5HfJ)#rUr(K=#FX zHte4Q*X6hf%n>%>+Of}I>*T8P<2(^Q6F=L?z2hO@T)V(EaM{AfC<~*^xoks_JCWoL ztlqHPNtCv7cO0j+MF3Vkfn(>hyr8vepgM9Q40TL31q@B6I=zaR~u!`$$+#vqQ2G z+{B36>2MpQ;DE_#Qa~MoCI|Qq2#LYwY6+tmLL7{{!c^S)tvFiC!pnWf{pd;y7XT3W$w>yI0C~Iy>6(l>xLleF!zNNAo7MvFJB?9d%Y;g96x8GmxiJ@fJhNXQ7n4X zx)*>W7Ue>YB&+2J!ls_xU|_CJ4RJ8jWv&=^Y92^H8UC{oqStfk-kf9!C|>jib+6+< zUy`SyHv(I%y`Z)=z?!2+`Vg&z6=T$hZ4tvTy)}Kn6#+v8D{SH5Z?FQiP{0o0VeJPl zLW-EzVDjKM=xbI1$k6A1OYmt}k2#4i(;~d3p$DPdxWNKcsPR0M*AO&Pr$-}jk|*k{ z#5Zu_?81qF&pP-Z$m%hV`O++m9ugeGzXK=2&k$j{S$2Px?d6bnS%-_i%hVVhdL+p9JB9V^~nG1|Fbr}z4e ziDzzrL^LBH^+X>N8H?$-)m7@ag?6Q(+IvGkO9UprXtZv zk!^*tsoSRo`3XB?VQmFG=+RpfjQMIDGFE^+Cz~Q@gy8Sc2=RCt@OZlHb;>Ns9X1z> zC)uHy0CxsZq07CNd1HBkz5&kQcNar6ES;2-L5AD{?3p+AsC078t-KBli+Dk=e;E8S<`F^f2<^p1y8Z# zTCQ_U8^zBR={E9;XeK9;!G$isUqs#pm1qRgNs>C1LU~(nn6Bte(uml8qYI$Q7fQA>ZdETV@BEp!C*>vuIp?@EV`IJ&LAUzQiMk{7inFN{`qON zgtBH*F)VW8F3@6_9!rZE|E*tWfr=baMm1`-aH!Ay)X0x3ei&M1u=n|?V{8YhqjFLD zcOhmZn7V@Gku9JHFLuV1S_)eqVk1|Iy-K6m{=pUBG!-w$&|FeSR(@5s;8Itik}-i+ zJ!(`kR0)@&=xujX%?JZ>2=|?K+8;eq9Eoz5wa&)qdc-%O zG5lWeEkcYsOoQL97F~g8mJzM=v7q|}L<0kLX>KYpE{ud@a9zCQu2^ZRF{Bx9bmbMw zp1nag0)p*$gLWic&$7ZjR-C`euG9K%`FD!{H(PiAVE+4s|E5@+j@MF&N+87)U3in% zSiD~B4rA}!%4JH(5^duux}^11qyhKi1@X+g0QG|d6J%!30sF>hLCt;o+^1UlZ?)V>!kVJ!E(6ZMSR#ftz^%?8w z;(ug~z_PyRXVzsZ8#b01ptr$&!Stq85sqr$eOX!>Pi2u9^t3bf1_yc!k|qk@9Ib7* zj4rw?ick zF7r$sNreS85Je`^h-ExJOQ@A=k9yif&JM6{-;#}jQE?PvWyuiT`jhq#+$wG*$EFpO zDTuLn#UT67I3~H#W^l})UZ`Z*WeW}t+l(EydY-K-t!yJ#hFuF9hHOEx4j?_z1pNWT z-5O&+zue5%u}1r4r4}Vml82Aq>NbT{*3J^v_uV4nzT3eEn|(9jo1Mmx zBvcK-hsmXZ4qX>&uqnm?XFg2Ot@gp|Ak>sPbjIb-M}yxVCbku`X3uNupd3Ir?}?V} zpV`LJir>IEmr*GulfBUDJ|ly~d#TuBR=6Ey^7(mPs$9eC%P6t7hnIcW;ZDSe?xKHw z6Jo?g|0}C#7Y~+v`Zyxui|k{>{FNTd6G^42@S|Ndj2L0=NO|luOF7WV%$l+0^TN&4 zQH)_`8%XVhFSWNT+nHw;DDEVLQgfuCI^r6AgC_2XmOIRw((-EmGWC!3FOzNj%Nd)u z-+NHPlhm_wy9u;tFS`jrKIc zvT8Z0cKtiATJoriq>&w*w0EYa7nb!vUHno|S&eC4|C^EI)=}28hp3Nc@2c4k@$&40 zny<$)*xMIgY&udq9fD zUF=EGGKLh7S|B0^;#Yz5z>@koSXydI;cg=!2Si5OZrmp8eF} zT^9{lv>of#;@tl_E(TXjKN7dlNL>>bBSjw(7sC(kSi!3~6&DL3=iO)5$HhR#@y`|) zRJ~((Wx>)g8fTJBY}>YNO>8FBe(LF6jZ*je zu~v6gbx4e$K(Zd0!qKj2kk3_hWK0koqQC0O`$r*37|K7c(!eXLi(x7znBoKwiCA!y z_g)K5_Ns<{_SFG_k%m*AA%KyV9AGN+LGPzpv| zEO&$5o@xI4;hXDCDwrPg(BRp#7T9d#4Ri9u4YO=K?G1C_B;pOT)Fy?vBd6AIx7f`q zvtgE|GMDYH5zZXdXIMS@4KvGOG$`9}H~ts=zbBI4ID)UhrX%474HMUi&0>2>l$RW}OVF4{R7*xBtl`=3rk5*Cm3! z1mC9ryuwP*&@80ggGFlh&k)tWI0=(!+wvkG=UZ#?2RzD&8wFnw#~Hd=Ne21-(OFXK z?C&&Mk3qFnLG<$;Bd1C}9_-ob==B57iu*7@oZ|luRTTio0L|3nLwIE%jjW#5^#JfF z*WwThQ%O8)Fbsx)@W>~tYB<1aaiJNbz9c63d;dsKe8R~XXY27k>Js?-RG2vs? zzQD@L_!IoG>d^z(cAELw@BJkq6?;y9*EL#oNH&N=$>4WWViSX=o{6Jmu*kurNIs#) zPWYm8GvJb4LQ{WyuWxb4_Ipf!`1x#Q&PX2lwR1GtKtyNpBD6l|Wm1cg#YHOU?*s0a zLMlf|dbguNi+M33YbLR1EBtiUfE!?%4x#fYyyxhnZ(v3z6=6xG0P~00g zpE{Ikk|!%5bE?F z4)SA{U+e}4&Cdc|Z`T_E*I4lWpC@Vq*_fU^8hPhw_pdca&%wa1lzQJxjAS^5om&sj z-~<1F=lyu3o8*b>sr!WMhnJ!%NfU_JH6g3oK0HQ$=y`kRyQEy@R=pK+=y!I8AGtI*IRDsB*|##!33y>$ zD$d*=Ooi9TLZ*-YtF-3=MbhUV@OuAZX7$r8N733)`2GHj88T--p7(%R;GGa=y|3$G zJN$Z9=IzZVJO}@4y6a*1?zaje`;YO9N(ZOR<<=FzH{p_+k`jKUl8#ye?)S8Af9~$9 zzEI7nlkG=&V^zTpHOI%pdhSN4)Dws=zc=Rp+XHH;i(5XG4-71J2OJFJ|H?n&;O6>2 zIY%!1tbeabrEWh(rGNFzL>T;I92BM{3*K@{Qyi|XKzmxPXt3l>(}_n`7f#H z@wofS#|tc@kL6y_qZ;#*@7oqA{A7 zv2-d{Mk3!7ig(ti-QmV@q9cY0wtsVa9*Qfza0mWwqm{|Yru{en z!^8p-i(A)v=U{Nf!>MXl%1bK%P;JAwSaD(R61D;4Z0{ln*`$}rbGn_Ig8WFvKC4)$ zjtes=xySg9eHJtJAXl}D;_iI9{`)xJg-^R;;%p$;zHIb5r-|n6!h)l%U>Mf#%xqS=`I+$+w=X zGUzXqsH>Cy{MD*9UCj0aZ#S`prUYKF2utoB67)AFaG@R}3qC%D43nc5YIa#ysg_Z%`8ADG_D~Pqr zu&VWeeOXHlQ&I!BIBbg6{Kt9z0e6gB=}m%BK%sVMhX4> z^ZtrE_0-(Gn{SOM-xiG9hf53KF8n=!S(}c?q6X&73zrJyETz|c>)c^-+#-c)UNC|@ zuP!Vf0%TrtET28(Ntb8oSSvYlaoNr+U9i{4bgSs|Zvr&jlA=E6Pa&)26E?Yj5{$b@ zgIMi4zC;n$uE7hj1V>&Ybv{*@xaW8sLQzxKu0qPI`yt8Sz5RZCL?#NKW&KmXe|flh zl@V$;NlfRRJb2x3T;GQ&8Gz|-w=N+fa@Y9019Ylc-i;5$HTsyDnK!h(sFh~TT`Q5C z3YW$_*l^0fF}N&QyQj9|AFX+548wT>I-05fIIfSwyTP{|9$+e_3O9IXX=xl|muy!e zm+T*gVKy|en_Jj5=SDb4?I>9LFS=77pM8@b8yiDB9(35x$}+ZLojyHF{1I&fOzqw% zV=RQcKtxP!S1oaHvVw0bk$iGXnt7c%xLkMwxYP+uNWA*bbc4HR&pzh%`%ajV44jloqjn%3kb$Q?g&m+MsHFdQw(Wb7 zmvDHb^fB+7m|GKLgeOa9K4_i#TR)j{%9M7F4wC{ajLsD8fRa%yGcEXzZo)JX+x)M@ zDEtrd3=LK-KVNSEFL3?5LSrt@p@zvB7<8XrM4OPL%Mx7?Q{mDI8F$+)B>}}bzp#j1 z`hL;94`}WX%MYrRG^wAlZQegDDyhhKuxuQki&YlwqD%4q^;0tqP@_w}Fu&I>QpjV=cu83GBwhq%z^-}n0wQufYa{(0*mMWUH(bsGm<;F>g3}v_L_RgJd`R?_}{85trKGotE2d%3D z-EPGGotjyUC@B5{-IyEbPv71Uezs^|UjEY`ZHb(})4RG9>ULw&Vy@YjFJc!m$UW1! zJZj#Ks{<5sO}}3sP(NFon|>750oovJGF`nIP5EXBaca~&{#0IF{-}XNyi(>A7Iz*~ zJt2rAMoGO#@~8>IIn%p{4rS5#qO4pStFW;T7e(qL$gJF}YtkcDhkYF}fgUPCqGxU8 znC0iZk4F#H$lM94mE)&#{O#A^3U}sM?aB;iM|?K!gY@l*;z(Hv?=VlCca7Ke_p&!w zRg2Uv$vo21-FBWgl4ZP^wxen0F!M^|6uO|AQ|-G|36@;zJ@9sx5%?UO}|wK$PAR>!l1BcVRv!f})) zKkr6NyHVc#VX!T&(~C^tCEos;knLoe5h0Q1e5>%|hLeTyFTEB$+%W8b8STVjn<<8-)u zS6Ea{kWimd>YdQ~`D2EA88~93V*-5!_WE@agp)!QD4&=u?(Rj^iK|anOwL_?SrI^t ziYl)Ypl2Ztbt7mZy{cV_uR^-DOmIW_MM8Ux9KEGOFY-_4g?POXSbm^QrOFJlU zoaYn=!=9dTi~4xG*f0pt!tKq~(gU8P4$k|9-8^YtxQ{K2Rngiv)ySStvA24axihU8 zJHBNsT93IsGiqPJ?g0Iyp^EOWBd>8Ca4J zRLu#1-cW8Cx)-vS8sJ+@Yd;vgHL~x{(Ix#Omj%A*P^~(e%U)UA^%G&@)&z6_f2t8=JOoC)u$*c{3#dNd`VSRHt?f?I>G-rS_(F$ z2h#=?+tW4`K&(C~zCTY!v+oc7T(byP+&1XkUdzesAF|Z)XWpB6RlE%SrjE}f$Z+LI z@T47>8?9+!WnOpcw$r#FcJ(*8 zg7A8}S*h#gCJWn0_(fP)$m@B3<;%dgm1KrGmqlwHY1a#LFSx0u^4fPZ(5H@x(}*ch zsfO#c$!1RH4?lPT*J-Yn{K&y3)934fm;-$mEL$;HQ_NUbJ=wglVF)g_pH3 z26(qtJ(AoGL%HL_7cZt5BaSR4_nLXJhF@myObU~>jG4W?Yl!lDC#*Q;jYGsh>pAcokE9P!I#tXGi*y_;?L{jlR0T6 zeqYx$P5{2%a`_~d(K27>`1AV&7H|97oVoAi+IM8z@P@oju-k8>9s@C#q0?X8(!#z+ zV8}g>-=IR7_Pv7ME*CV_?&(?5rif;w$g8*!%5*$$&d_4t7wnx#d%-%T6v4FhC6pLbnq`@GBCb98|@{U$AP}cs->fK9nT%A4!^E7!UC=?|DE5j=h!0V z5n74Kw%EwJA5C`AL4JHAXw_%*K&bS%f&Zx7>9hNXEALS9(hWgM>qo?I=iITMi2MaxbPp7OEg7Saxdny`EG*4c>9l0S2uv}`8u_q zqDL59<}Zo5W7qt`$`YtG zj=QGf4sOmRQm=?uw*0mraU$tAMeeN21*u2* zH%0*GM{}FLdK$T4YST&Bm{8t#rrrl52d1W&-4v+q2L0zZR2y=5hC1ja*|nh*p<|c> zqMK>fc>fm@oq&40pE-$I%H|Vdz^F@0vbk}C+_%g7aH_>yXbxzUQ<$sMeh-M*FgpQ6 zh}6rsfJ)RLlX!Dr3*qw^u-%r6V`H&c2ud6B0;ug$GU>zI;}iEYVixSvWAo`_1NO=j z|M83Gm{8~kWH;$MPUhz-pg9FQx109@5Uri`^t0oN4YV6`>}Avklw@#|0GLoCVPT&_ z>~XQ1v*7t0v$k^a;qwAc>-Un)R3fY|i9BJMN$W$tr8e4a3Quhlzxx@}ZJ@j2<(`d_2q9U^OB_v^IWMd6lx`o967xvNC>8&R@XdGM zdK0r>>tvzAV}U7sU)v<=(mfy6PY{Vfy2xlAy9i}c&CRtD6mCa#;F0dsnEH8rut_>1 zkC*h0Wgz8ye|ZKgUX#U{Jn<%^5gha;B|2YCsKMyjbArO1Vgoezm?Cuj*}B2Fxu^mo z^zbbebKd_H!p!Ct$;&W;jGaop@m99v;+zc;bA-=+K-xXPEyW;jjC~JI%Ugg?} z+ysv@*6<;*VU_>N=Gv!A!yQCH+ow`HWQ%A57JRH5>@*f~K*Swho_rTUl>P=gL*`|f zEbDuV1SP$tMlxeMW%?rS^xSV`{MW|xy+3+ucMow`a)74){A=4gI|-l}!8&uWUw zFSAqwIQt8vPFFP4X&J?@(VywLRqeLd_C+na8GnP%WqLTBk8gBaKcR*3NvL{YwWoxn zs6(yrj=cQ-vR#mE6Nw1;T`T>|L%V){6VVIIj%0 z1W>M2X*iOwv_@FAmvsR6E5KCaOxEs7KD?B?xJXkEjcB$Fle~$#SIevz1bYENtV!Gg zPfZ_kgQcic%ymltl_2Zoi&FADb=1$Na^e-HR52?O9Nv+1B+kx?+<}{uQy=kWuI6_x zoY??aGHW!hruAPOUcJnaxNbn|T|33G!$#iLdm9^&5DT=T9Q1J#B(-&=xlQmew#{nPw}h_lS_xnG!@>Q$$%@e<_h z93Q+5N_BSJw6u<|J-LeBLw0U=pz4Up-U|0nD6aC#LGi{>gGF|o*+@ME3>j0k^M)&P ztx^Y5*@{kTXvbK#xyn?zz?p>!2tU5WpP56MfRcZf(ma(8m1#soWJTf?K!I*N zdOn)cM~Nhx$kPo?2PBkb6R)`*7!BitCpov)O(u`-6Z=gEkpS#?XT2ve?3EQwhqndt zoodRNXW#G;HIk`=f{x&Hc)Zq_&kFq)hEOCs#b4g3xNCO#!Xk)tP{fpqh`HXJ_odi@ zC+MD7!UC^{?EwP1902>K5&FW3i;afQBPJcJ6NCj9CCRZ^$jKc5MOLUe3 ztC~T1qdz~E!4&B2v$06y+rT&GLVoPPDf|Lvd4M6M@YtyGi!?6XA+Bzr`h`!GF*q_i zyBYkxI77i`*BY~fjm9#(!R0ES%!7y;QlzQ2WahqIS~KvOEyHN7FLUg<|6b?nqCP=9 z*W*fJJ4pq=Mvqw%wQrZVnoB#@bn`-&yxLHG0dDVQvR03z87hf-?KR26;_@i`a_=UU z_0jL=7EB{NbWE`P=Cc_Ok0{jngGI>iZw0~w6@WH?cmV0(xj7@$-M^N2) z2WC5SXL$PZ#nomXHHJwTK5c1{7MV>~!Sf0))SP;s*+M868eK3Za;GSXmsuJwcXTE*2MXAs5e37%Ac|-r~?7+eUI#&pr zxWUlFNPSMX2*2{*MeJ0>Z1@?_AaEONvPr&?oW0Y#3o~0Z^KcC;ska3#w|n8?^v^F& zp2D%Yk76h9CPY984Onr==3oiJEJD;AtswJ_Q|Ih5u0Gtx#7Z|=TUL#SIfu|kizn(O z({RbmkL5U4|LXu9bFU*qJ&E^W@>eS)wj?tg)D|j3e55=JVu)3w=r>#WmuFTg!Ci-Z ze>PLC?m6m(`?Uq5@fG$E=3Hn&qHBoaj1%4N`9oI+&()0$6sFVTIeUZ#(cZ3hLVM|2 z0d(G0dzR^3`LSF{i2$S!#CfyVnB0GTwwnCe8N^%AS(XZ%o&7|1VaA+UANLrbH|i0Y zwCQI7Vm#WH%VEo{ujk4Df48Y+r-~?)Dm$=nv#3;1IwR2p2+^9vjVK-h=Yre_pTNvs zTp3GPY#*xV@X#A|)8l7s?z%k_X7a}uznI1G_QRKtyXpX+(I=2wEkd+om3tlbHbVWjcdsL-8XUjlcpI}1zdQZvs9Ldy`YIxIA zeT1Cefnxz1S&4;008=H5(uE3matkO67VV}v2}{*bE+hS2IuL7BZl_a1KkWlFw2k5AZB{ycAwCwtPu9iG0A`)7+M z4nA*O)+GMf#BS06i}OJ#$6rf=0+*#iD0x7}(lG8gTxtax#)m$LxUqQm>ICb)vhb2q z{gb&#p#mAh14CtNAX+% zqnFRg4A#&V{~z7fYwJWLmHA&a)L+wJW?wX!3209p)IX-z153&lBVt$B^>k=GNj=4^ zG^qqM%Vm;+i;^rErsn95P!l3vIb= z=@k75(HNdmaC6hfTZmO>_o$V$pMn{|<5sjT$tTcqP_OIIFHa#HYyxyR6f5kttC3Da zVedE$o1kt4uQg-8y!y7_T&C)Ex~2lv*6kbLs+|RK?E-L6bp?5THXcsKOCfzbdDVhy zus8WQ8+9=DDbo``apyPkY}bf^p2eF+#j*1{<-E7OshmKSFFlK+i<@R%Et^zdvk*c) z<(muqclX1f%D#PHs7II>-7Ik?o1%43#o2nT8_Y9HWGz`t~mg6kCdU z%DzTsIU60DX1aXQBN3LbUDP068^jq>AW<3$21R=xN;le@+ukhKUm=r<-n~iTh$L6s zBA&Fdm|;2SSzHbqz!fU;Uf2_61L7j1Qc9KL449sM4ZW&+v5$U^Z+N-WDODFxsPE*; zVnU=rH4pr6MeQ{1qp`gOpBqr%>C_5@iWRl{X3I21BH`=Mf7r; z#Xe~CHGx4DOb3FQaAXLgW%MewdE!8@% zAq8h9kQO%HI!=Z=Ou;-G9h@^lj#bB#B+F#x`8%k)r%;s+sAT>;97bHkYb$904RIcF z)of&wV3mzx@R!IpT1{*JZ$Nb;_cK1hhqYvBS~)nByR7CIDslocL7;>3o@aZube0#( z{Ev3HkP?+4If{P`bfnf2g=~rHl9$*iQ%%rPw^vyCVa@6!zC zrm=P7k&8|O=BLN?zww1yhzg`8<%tG02P#5Ybtp9Q=~SfzqS5+#?Byj3cp|oNnbA{9 zDl6qk;r>|-VUU_j@{%;-^=tYie*&F~lt{0PN0Hi|2qJ~7Zim7-iZffhjVHZsg8tzQ zu*ChuJy2jvl1-%<(ovTz0&`c7E^^YRQ;E`!meEL&lfopRU{G5XkuM=QR_E( z{y1-dMiLDEXkQJ+)wgfflJh`HBkEK~n8r5lx<92;rua2eRg{FVMCKW7!J5KU3+^q_ z2~*oV5yU4bl;%5Ei3<3Zc*Wn+^7M_rtmd2cJ7U+m(SE$XA0)D|v(m~r_MGm5v}c?e%Xl6aBr z4cyNUsHk9RpGOr$Vu^kDU!PbR{(qrcu-XmWejUoi_8<}p!y`ARh@?FA@l_%)e-|`nfB03#X*NO&;>~M z%*1VOPg`Ghb){Dqt!@E9#l+uzAgJhzV`Cx*;0Ch-zeTBCbCRQKm}d`D!S;GEj3H2w zJx_h0fd!MG_6h|5RQ_ESaub{Gkk|T~C*n2o#YhUuS6x&#Nd%$kd+HDujtQ$o7lE(A zpbV3Y0{fpF&|Y$K%y%1bZD^2_8r61vpkEwYsbmlJbC(24;y@rL8n>Wa1r71j-tA27U z^4P7;@zU5?ah380}9OU((FePKPPu{h!={);x_O+Cqk!@2oBBH?Br!Y@OrU=sZy z+52YeZ$ds%qyKyPgRbZ){+i>~e=yjqdt3NQtL)u5TK%&o{jK{wo1>u3?L9SGlbDB5 za3nfUn(oOTHK}-$nXY3q>AOzdX9{`Ye3f`^hmov?jIQR0R3yk!mDSbof*_6m zp=bwyU(eGvIW_I;ONRsB_}40%;#MA8o{dQbM7eP1#iotRPaaZ~R4n7el%E-B8bjD7 z6-klB|^1EEWoQ%$7{xM0)&Zx4s+&Wi{Ph)?AGj9gf4cR>bSPc?@klBRS7ZN3Wtt!*ySr!58j2 z_63S*N-{c=Dmq(g-Vp~s{6muwL8=iL*j)f+B??m;FJ^5Ay`HQk<$z0{tkP?0r>AU_ zHwxYfm)f%**-Q2_@a;Rrm;*cZ23L&Om*N>$O!^8JdXL90U|!v1wLpXjQcJBNIsyQL z+_Ug~xtSB878D0>obZfuVha>ob3x8VoPNRD^*Kx z`i<4J3kyMH$5KRh`I=CS>Bo|da1-cgj&k4GYRZ{cy2IS+#kyFKUP0-#Y{+WHF6FG7 z!9iCe!!D(kXhn=29vJt8JU$QRr?V_&NbWH!wqc3fe-pO=tb0&bOU|@@wS)@ z+i5>qq8fg1*Ly3eM)Yo@XBbJtVB|igM@LuVds3P%&B0*w&{$Ik^{H!+6C}!UFgEfy z&;%i{v|k=MmXan)pIyvdCZ6fO>s!hlbsp4EE|zg<-7J8e^0}4_>ti#jHop@!XA({? z?S_>mcx?^1>!|LY8N?W|I~_&~cD`PUtorwSMpYjy<^?_z5v@2L@^JjvYHEd!qaNA3<2m=D zYn+50XNke>VV6jOdSGkplc1Ur++VgFwHt3Q89rvtsUI$P6in5vF_kC*`2fJO@;Ia% zdf3=)Gd7YHxI5&Bm1h+TR)yvbD~2MWmk!ZO1Yi{QGlac5azw3pyep_Wp0+}K(Hz3PkMW?S4FBpgbNsjoFogIz#wg?`umsp>jKzd= zqeq3*coJXF^l!V&!`i~X3(IFFx5O8a0?2cQWXf#--;eC_U}jOty@9K%dPLMxTQ9BX z6E1y+tdzjcMJ)Vb-DxG(PM1~^!!X?$vv`HSS!h@#87I`vCIEA&d4@-L7qHl}7m0NF zia2n*iVzh_Gu(+ULVsw7qCII`V)!)-*=E6f1s}0EpmfcW;ksQ-?FYT?M}Outq@>bR zx`#W*xsd!{v*c##sE0)ZvmoI z6;6`>_&=~nP|IG{rM0I0ORXg)p&gcjof=-&jSz5FHLZIUt$Uwl@J1;vW|J~zjTfcm zTnzZis_dJIssiqhWCTN1brzp1p_Wa+UqJaMei;2cp_i=EoZgiTDq`Wk_F0BxDdeW{#H4^=vVz0{o54o zR);}U5=p+VgElCO-B93iYqX`;Ei0?eH9wRu zr@}4P-cM=_9M#)b1~szFiJ(M%0Ekq3WKU5jfvJq4AznDH!naRqA;qZgAEzZ5&0uO= zfh$FVGbO^eUHG{riy(jA;=~~;O`95fOfz_3NLaLsHq4kAFtJQ@EhIg84O9sCrk<)7 zxw=0kuGHf(n#T`SZn2Zl)^Dk@C_<}w%mXy`AtH5{^^vmYmoA4fq6etRaq zW(n3YEdY;G%wB)ATn4MC!)FFJUDBM5lg&Fs(blZFoz`v=l;%;KSCBqWyh#ujEH#_d z#G4e5NWqIE*4>k`k{%k0Yr&$!6+uq}Z-&s=G-I|d0~g#IrTkn|R0G%6C&t=C<4I!p9)Foa;7Nv_313Z_^Mk-?iH0xVfGQM=vEBB9;?(pm;EP7G zFu`djI@0a?UR)N>dkc^_2zGXN21VFiip;t2Vfajl{VmgrUM1X#=v6cnW5)WX>hyVF z-0@h`N`KLJN;T-L@+Yn%#!_Lk&SC@E#0|FFySXJdT_5RkLQxZq+N<2mX>M%|#wwB* z0*|CTh9X<6DdLxYh#6V0E`{ji}r2jUL%H4Zp2Uk7c%+i+7d{M$}G zJFifYo(v(TP|!)U9yV>k`T+sQJYtNY*{?Cttfq#v&6;Obj%V&{;9ddR(&8M!kE5}K zhd#7HA6=>@pUJI7QrIxb$9om8oxj^$ZV~rG>&PRSQ&s%{Tu- zHf}S9#I4-mj86=o!-U6pBB_gS1Rc~n!&?;9Qo9aN9{QHqeOQk>FbWdcn7qz5WEV1j zs8wVuhqZ3lf0a@s&QX*LB8Vh4a&Q)JzV|(+3obXda9V6-z#Zc^I813IQEDyl}p6xo| z{_*}1{5NApuZ+jkKkl!rjX$DY06Qdt?`{J6qYm?W5W4|0=S^u|rI~}O`Av!M2Y7dd zZKmtCKCU{JVivuNK)1t>C@@ma2m4_Ez+m!Y>Xss-p*QO=FHvU#U}(-(h8&}fS6I#m z37N+%oHAB;ytPjw0*kDI{4a9OT)66%r`G`}T%;(pbOpVFlI`uJs z^_qu*iv^tP)kfr8@wR`;G)8{PRb!*o-UEE9)x-0hs~IdnNc03NA{;to6%zC)$T5F!hfUqG{6;i=4N&zyu@zLMa2^4IAssxVtMt(PMhNhScDCAO# zvK``Qf?`z}Lb9sQG~fBJr~=6I0tF3=C507E%L^if#wf-P`AEMX(NF6WHB?k$gTQ1I zh(q_vrbS$#F1bD7o+E!;$r0D@bo7naIA~|BWa$6Ms8LPaNH1dS2jQMO5&}-WbgVmQ z;_d|R>M0TicR=NEr#|&x9VDmnFp~7NxY$27CrC(v|@5gIS z?`NyXYb=wN0oh>jMXGUooSg1uvE>0_!#pHZt5Xwmv1!bT`{+d8C==fI5_GrU5#+t-L zHyOt;+QQ8aA2jaKwSE|ViARoqiQg^%9q5-i*S*Q{vQmX8dl2C8tE!wo zWhPs98WvC^F*#jac@o67QXp6sOkAQCri7+Ki*}$6KzvR8RFl4Do^ShH*WeZE=E0$- zSts}Hc$C7m^qpEy+a*~4+FPUJcd>*QSSt|paQBt>^KK!^k7E2H;9o8H$=hdMPSUS` z_*1$qG126T1Ie-#t(jUnVSzY-_LuDTJ`9?;8^IK}u5llYnA`44Zh6j^wG?XkzyR#^ zNgSCrL)TI3yxipsal~WuUq<{`2i!d_K&86*Yc(C=n3i00=*^JWYsIx`1Gn_oR-7LY zd+$OhWINGN`b{}j=HOwaD%x`0i-f?DBPn`5B)& zg}Gb{^7)k_Hmt9XUv7MIGK3Oh;JNq_LAhZ5VYr{B#j|bcj~9+y#L|~4VDW4B$Z_4? z$zm!fJ+fi>0ugNEx6&qlU`3jPRY&^lInF!8)%j9XV+M1Tb~o z@J{3TDrOmLw%vq633PJv%0@%x$-UhBs;qPk9020K#6j%|~96s*5eRN^2gW=q%xlXBu-2y!ZrF z7mL_Wf>as?LboAlTG#bt4fG*tA1yi(U;V2f@z-p5O8hwn*Gq^S*O+ zuv6>h;fCunApy_pTj+_cnKaC&H!1di%zvIT6n=0(6Vtf3(ebKVerdNv0jJ}+P5r=WrH_pBt(z_bIREH#J z=P~}nwTu$*hb!VoqQuUPLW^NWVJq`&sbMqWu(7|{2zH3`KkGJ}HNBv4&%-;|oG!f?&|sLL4!2OcbB4W53A(ykN~vEid_;OL0okP~V&r~=KOUWZ zqks9zMCFu-s)|U?WC>nb1@8?$S5|Phh}HNtduHb2gZlI?=&0(r6-!YkfXLJ{S+~@&BD#Zno{PAeZ_01^Q zHpH6Iay7-hiIS$LVQ7`?T8ro>%cX{+09Ey={!+syTL+9>0+hiqV=5DpXeB$0TgUFEah^h{j?Vb~>Jb zAKx}K4JrNgbO08PJ(A?FeyCwr=zG{4S5baO9Cs_%Qyoip*O6X#2p3$&eV+x-71sb$ zuVtHdOTt=Pc?oYtxk?YHVDU+>q7vOS??f`fEs3e)Pp1u6 zuNj-Whe#&-p5av~;=Pr(c?NW4$InIg-}%P)%ZmImhCdpyk&;GK*51~3+=JT5=86O8 z&WXA0$~wkM)bB#QjKZ$0_3vW+YYGIm&3<*@QCVn?ur*r@oYc$gjh=Kc2t2qedvMOi zbVQsXs&8-)ioZ-C+L90mozFg2Io49^fcaRw6>k*^&8V|>tHuP}(bvuDE>WmYtJ+cm zt)8X4TFnV|6@0?zjx>eSGUYM;*~Fr+N7&ntA9^5K7Q)^hX3Ye>3WNkQyC#t6TCpt6 zevOMP&wkCD#;*~nGkz#B9G*Vqe_{`@Em_9@oR6Su@d6vI7ZLsj0Q}TwmMnxD_aW*) z*8Bc(Y*Jl-!;OhZVT~n{l#x0Odq;wbg?2*nukWdBQ1Qd?Ht;p-fPG~dcgNpp%<>Ss zL7(!Ef^~KI8DpVgm5C=P-}>we!4aAOZ{Z-NT@IL-#GEG?{hL+3&!6o+P@E-Sf@oG< zKWt-0tc|fiB+q=$cgrtmt8H6tNEa>U{U73=FmC`~_(ouy=AA_V?7Q&h+1ClqNPKn+ zs-@uB@)|k+RC;Dk#vSnuJDk?%9E;(3Sq$Gfjmc>bFu59O04y+NY4aKbFHxq+dVbDc zy;;F(y98dqep1^x|E4!Kp-0B^Gv*OxdUg*Jsr57KSX;=M`m$lfSrE8qSGTc}O#YS8 z$hLb}t9Fr|U0?r89Ix!}@cu~j$_ zH6y|4?@r&ilSR49ffxH@$h_61a?tB&PZvLv{JnPeAIz&GxPG0#vo5sHD?1Ep_>A}* z@b_6Un}4V*lCPB~KQQkVned*wpOIdcvej0bhXfkYVsE$K9Yd>{;C>u^2VFZH`aT#( z08pUh`QBrNw@8dzDrwuAz_os~2t(nG4Ia-Xxv11+$aSl)c}I{E1olu`X>C&~9B&g_qSNm8U3v+w$+_1f+jdzIKrtYS??J^tCW zlwLiJ@09K;hBkYxXB?NgR2JE0R!eQ6o}Tj4r{rkR5k+|$Geazxgo&}NHkgh5n<}67 z+;wN8U)dJI;sY-F+vYPw--le)16MbiP3KwW-{aTV(St+aLG>NB%92g!{HQlm`IL?8 zFaDak@Wv&Z`!2-YPC|ZmBIq03p~-Z)zGv>p;u}AjFB4xvsX3GL4rWy@mRV))Tb_F( z1zEpfQ+c%&or%)X>_yd3OD~-v%73PjyrH<|2Rw-OLxZ6?`Fp@rd5E`_Fv{eB{3RWZ zS`0JY1ni5Od>Vl&x<&Rni;a$I%N}MEPy#z6wqI%Y2_}*guhbStUm1VCv^4Q|Xnx{1 zB=e0Eaa8LK{`&40{V`*We8%Gwnn=0OP{hd?Djfp@(`SQ&Q;n=9x661EU6M`y3a|4G z-V}_52!f~}hdEl4d&W`#`38V& zBu*%BHmn;>r)|c#sHcN&xm4L)z}R3Ysi3HU;bl3N0VK4zCkzkiBKs&pwQN@ycA ztD`_3w$xU5#~F)DaCxc_&MBs-=$!n^@Lg(*tj9{kr+pOKS?7zn4C0+SQ789U&PsSN z9&Oi22gB;ws-07?C3VR5ie$)%4s`M{Hr-Jg1cp4a12qbJP}vk)LEG1J z$p?9*XgLrpvO(OX))us)6Kp=XmSs#+OAZ<@d2X~NtdwnYcjkT|pmOV~M25~BPkS)9 za*A2-n&JSiG?EIKu^26K|1V$*NkxDLD6SJ=trFvhn{~a^3ym%OmmX9G4W%=m*{o(U zpPfA}-7fj+7%A&M+B4Xs<$ziOMnHATyANNTt^Yvo};OQ0;9(W1w*nT1h< z4FL}i2$wJdaf$EQ@YTs(vHcBVOc*={((>c}-nFapD$~s8XIG`tlO@Pjg#nO!;?5@n zISvrrugy%5luY`N(ZjJ8=7`gwK9+UXLGtqj}7Pa^E-#PvVvg#}!<1%m@q#X!srfs?^Yb4u2C`fQk zJ}A}`#DsJh#C72cq*!LUgin<3fA}eZrUKL_xdJj;`~x&2YsH|&`X5{V7r|dPXL-h^ z{qK5Px{)Kg?SY1mF@uzDU;#0B5CJ_6mYtY(84Vx~H4*|wi(13Bpy!j=k09;g|3oi< zqCB^*sVUy;^;0~}h&xzxNG`-K46DW%5513O4J#(xTMb3=dNF?cp8+bkJ|1?mY}8ve zs<>~9UUj<+j4nC=c6@)|?;9#io*q?A{!~=lxfl#~f33BDA^&e2D;QX$ADbp9boKxJ z{aSLV=`YySHm~TSQf6WMpJyL}X-S*Z z`tnwfK2^n{9Ay=Jd5^#0&8V2wWjd;>jh%OOR?gDN!!ke4)~jNoONnyXtVWm{8_B`m z*OLUGpIGnpy)U`DT^tUSX5b=bWRH>c9zb@Nj~F$FY@{wr`tW6 zNt6?d50bn}nAXYrqZx8SIv$r<1-LGbC;2GJr_)899#0sZax;P66tl@C|4c^dESVPL z{NxgF2gU?CB%LaUf0MlCf@kS`4t#{YQphwmG(69!ng8#9|3CiU|Lgzx&;R&8|MNfo zxBvW)|NB4x<9{MGvFZY-e)r3-5+XiyC4tUWbvmn)$1nG{4|iWYPqvb;lW}@k5hO|P zl&Cn#n9ApXzo0V=TQbkeycjQQ;Mw-yhWk4|Ztp)H9=`bN&hrCkY4FwNa?JMjcOLB? zFlvMT?c0NIyh?%+by262gT;J4x!mLeQy?Lr*pUUd9>_XfSxHd;#feizQW>f=KmNP{oQUBFzSwf6yyqRN|PzqjN zaiG9fV-8`RPcs3q}w<_^(^m2jzuAuLpwN3M=gW%5`A8xT5036teSqHo~G0xU~MXGuC56^mKjOO7vr z_s7}0DB}iR=^khXFk0F4@j8TQJ6lYTVFm+cO&GPFKmhJhW1FpML35}DCEVdts8r5} zl_(GtDGc$s+eI#$f%*Z-naztTuhk49+=a5~X?DWC?T+<}bc$5&ZknKe1obm6(~Fyc z^&Gl;a>it|=Q>b#Dm>hF}2A3$NMe>G0R?I=t*?Oz=TY zSB#u*CVBF0u+jBNHao4)pun9w76SO>CrKw%=~ezZ`NNj%Rj1$eYEo?>&tFAAyoP=N z!Lm)is!$y3^F?(Q!=UTb`=Eb*@Wf?Ofn7L3%VI4<8*4VYch!mHmY+l(1yoo3LeyH zS*rn78l|{v?Yy7AyCu>PZ|M+9lVe_opjpA~e)ntA|v5`i{Qe2b* zR-HrUH@d2UhSWBe+nFKZ3;=hOskzzE>2G!IKby7h+n|K0>T=fY+XD1$CH5a@Fapzj zmXYN;2Xm`b%7|7IGpYEJv_j30CdWALLRV;bgjw8IUF?ISg_B6R-+b zMZGquutiubsNuQDCllx}7|}IIazKT}<1`2BA26AwSZZB2I8V!TDrG*YFZvsC#I8Jl za)@Azd1F*k^rUL)7nBDkq3V(bX{{@Z(Ks|dV^K+;vve$Igl~BfMje(AHhhNMLxMkK zV7n;FHD9{QO!JiH59V0?`#jGsT<$S=m_G#=d1k0_U`yL{c_mPJZ7?PZTf5R$()R?b zAXwk1Xb3(KbWidUn1sd%Bvw_^k`zd3*~zlKQ2?b^77}a8;PtvOS+>mC9mcKW0_aAO zeV)COxT1W{N3bCMDJzQ=u{378S*MLx!b2Cj=wpok6CSY-$^V>AcYL9%hn zCja3>RGu3I-D(?{%KoihFH90tfsP?c>)gT*+9#ErAijL$8 zuLm5l^68{VWQ`zeT}OmmU5I!~p^q*>t|3EwWPcYR>hYWvrWo-l_qz;{f3}h#!;3Pn zGflv_T_QNwFy;fIVQ5g8jUr8+0Ot*v<@Q!HNbJtrFdiiR z*WA%S4l|0LLD3A1wXxF`gnI~J*`>5SN3#L#pY&5VizMWBj6gaWTuv&a^sRuW&rdo@}#ga;)vNBom4pm-TX2r4mJA z~9#-i|c37sf>I8ahv~G4@ z)UaK)_+-=EabJ5hV`v5hSvTPIT;L|^@g?swBc~ASfIg~0FCpolTKi)|E0N$X|fV$$ttUHm0}P< z0ZU?f8%H-NLe&^l=#f1%EDoE*n!H9YXk{ETu&%O5wy`0H0ALbyKdSlSU>rwm^NJRQ#(??jKy)Ar?h!E? zAYkN9H%b>=Uc&DbbVOYg$vDdl6U?Y>+H01VzYU2H&Ve+{Y*NsCQ6zj27*|gS7z0S+ zV9OW-q;yao;1gOV_mhabEq7PR_-Lye9v3~ z1$xQxqSk(e87xl8LV)6AfT~zSj6@_&bezH8lL>q~x+UwuQuY>yO;YryYmW}cBKSoP zE=OVb7Kg^~z1h7+3sV;~R@Nw=xDkVBY9O^fHjC+kp0`h#0X_&TP$1&Bv4E2?C!>J^ ztE!$8rxS7y$pD~FN6)o(^j!Oe=&3@Yu0+sDc2Ya;gH^mEY81x*zNqSKd?=Nf9b(~# zC9|V4u%SV^*uY;$`!X{Ey0)p`F*9FKWx0QV3zA7@;Ea;?4=PTGu?&b-2H^`r5d|fJ zpz`X+GZ^Ygj$LH-=mvaeN4H3Wh-Ht8skqQ}k8atuT%#+FkZ{3>wIr-9y-?&JLTD>b z)7hnR;V^DZc-Z^s#~i!$sRVQNI(CJ^{~MvgH!3!JJsi12^f!sdZ}A4v{^x;`q#nG{`)pzdI#J{X>(5j2Kz(|GJf znD*nePP=l(ucKY(NXGOyU(aR;9aZc>HpwVRRvZbcMQ34T`2(_Nk8wBFP@z#2_#~fw zmUIvci9C9AlAnL3hQ}E;OrLw)jc&IgqR|&W?Z+SzPy8Dk8oLla&R`*B^nm%r9a6~0 zB87YmQpo2Mj63}A7N4y9(DTmWout?=JP$|buAb1(%TIV9FL#gG87P>?+&P%<$u&^O}+rG!@nohdjfv$W2v?nv`f zZ#7sk;pPUFva&@LOVb7rO>`VP2`!v`fBU5qRJE- zrIpy=y`*!3<7_@DF0(QDo@cVudb^oTUWQLIvp)|{Y!`#@gjHu@or!AJrip63Xqc!( z>)5m-Ao~0Yo_JN}cH%I%@xf*Y!#7_Yn3FB?QeG zpzv%r6C^S91Zcy1*u*c&dJY0%&ci|h#xv>?-cCNpU;a)TIUS~taHOpc6NZFzNGD~{(Aq*KL+tS$+BnZ zEInO<_Y<=i7i>6d8+b)jgx_)o=(CsT@ddiu&Fho5z`gjn{n1+jrVdJRYz^-!fxyjc zj5e9myby6ExYhKADgP!pnWU%5G(SD7(RD;8RL;|ULMO%Z87-dYXITl0CrJj0h_ZZ# zbvB*%H=Dl7ASD(j)+a??KH!3#c|_t&?@!B9ePjyvdr9#9KnN@Dm@dR!N50X1L-V|! zC7PI_fs3?QF@%Sl41v|8=Bij_#p=nHi0cI&z57R9z+m=7A2jpL56K^G0=Ys_T(W*7 zj7xhAkWG;shDxE|t1R?I4TBDrT)>STONa!z3+sis#AKzW&4w%tWYeyQYNi9vXxwwI zvz74h5HR?N!8Nt51(6;H&26h7qHFb%&vCND3-n#$o6iG7^u*+8qs=8lWgxr?c3z_b zN%204tTppO!n=vGdQ3@XsLe+Jx(e>CDXR{fVu5eBq}qa7_yT>&XCR8>RsI00WKmc; zzh}h^k4#u~XrrGy)xt5cwp?UKR;!X~adMK6@@!^A{sGCg=y-zxs+LXPaOn)3-Mjm8ZLDdDSGaQ2R{HKhv z{DB!oUS^WNBDRl2E=Ng=Y#`*J1__KQTb}O8s13(Ot9`ReB@cnxG~*@p3Le&eMcClM!a1VM4Rm$T{^fyuvFr5F~>az%OlLFXvLql z$a5#EiAa2%Ny~OjJ}FA!Mzh;i?j_|MTs3PU7g`22m~pVV%98AcfYdlUNf%(FRkL@* zDrlxCo}@fTQ(*Q~TPZEb$sOI-eufrx+NBzFYoWM(IUhqycnqL@J;rb^D-V&o4?wYI zI+b8Mx2pshN^y7vC|Z*UaOlI?UlC2Wn>2TK$C{y?=@QRO*#OiGy|?D-f8AV;Lg<&k zhZa8e_+1@4n_aJjVr3iv{>`PE49p>k#3xNR*)S{qE2f+LI9+TW?AVkFNYFA;bR~K? zNVnz(yYWb-PKV4VSystyt-vRJeC@w-hR-FLJf8remh^&-FlXbw_ht})C-(F|K}Yy6 zbFJ?K9g;O4Xw3~?2$XQ583H9Rz9I0MSIqhYyVy_I8ulwRCoUEJHFXX3No-BMwIXKS z;47z>Mo}+>DI9i$4<|*%&KfVHDO8o&Pg@br3ILzqlc!qB|6eG1>PX3xmRSn$aS!e^ zNgJ;9-mRPrjh3U>4TI=Oy50~%;y8ks0JR>ClAluKV4U zZOh7(?C0m76^P(*ZP}e6>Ct41^=WcP^?0+P{6Lf+=<;qlFYSAkj&=Km-!XRbbleH# zXEwq|p#4BZ(ROTE*IlPWW1{JmVeKOs&`I*e) zRmF&(;^S8=Lwsa^7a;2KJo3NiRQ?Du#C9Ru@qjmJpD0+Z#Y>aZSRD4hsMgAYx`xlq3D>1KttxAqx#qVo zaHAWvrr?cJ)#nPLv;F$UZ9S~zuxAp>ZidfqN`$W}S_sM4&C|6lkdWw!Y7;NVRCJ~L z3uNdwmbkWrunDs~q53EQ^k#CZw}pJ&9Q|R~pFT&w#3Q+4Ms?=5n80e0c|@{KbVJe^ zwbio!w=-R?$Bawo@e;{tS z#`k)h?PuLviT{?Y%v*}t>+z?*Lc0-3*$ONdf=-PCA+Y%TV)sv22-%-qCJPPXRk=#+ zZ2x`(MY3$2`Y~^yFc;s9zHcXaaU%q)%|#OSp;)AIF9ftltM;1QU1c4)Lw)|rAhzZO)^@r$S$y@ZaWN^V)7 zrtf+bPtvtIjE@qtf}=xsABbUc=YHt!1H)!&zWX2+EFA$Bq^3_oRoVU&TFAA#ctNrJ z3O6sTbf<^@p+;hCoo&zxLLPPqZHHMR8*}VBP|OLi1b!zl+%XK2riN^s?u3dOSb2*x zN%>gY)})T70mjcUT@&^w1`nZ!bq+F;-OVPCUR)%YL+P!sU06{d$sI>3bvjW+Bzn5$ z&mmifgoM)TuqNq-Qq?oMc(Ozy87QRA$)GdHqGx;rU8c2l)CyxL21l)0-Rb2wO&9F! zH*k>lB!J}IUs#&aXt~jIVvVe$ErNrhi;#v0At{iPNJTpsth}U$#-vyp(bmGx9=-?0 z>-45yQz^3M>1I#jupQgvooDEc*S>skTk$7Dt0o%KGlw-u6}q*?+=y*+5lg1;sW&jL~L$n5N-z-HldqeRBwlJ z1WlqM)oF%~(#gn~V?Hc=c*cdl0dj_gA1l*uRffA5Dd4b-UnmsNCgvjQe*QC1W{I0j zh#NKCBn3l|JeeU&JB4k3wkxNW&h3D}Y#hsF{yjA|gQk!Dz(;Sy)Q7-e8Sa^&R@72C zB#;FqZE29c>lnx7ZUo=Hhi`=Q1GogZ|Awp|9#Iz+ zK^OhfV?{a|g@KT)BB5)j?i?M+$(XAIZwDzBwRV9NGpI33=hazJYk2hRvcp52Fs4{Z z3{pJ0g&>NP}vGFprplxk( z*fIW}%EXEq|$zcL{Qk2`13BjqBcvEFg?6AL!ng|?oY4TxM#MXd)b-I$X zqphQ3H77@-gG0iIyRU(o}A4Z$)z%pPM$B@o6%f@o8f^bGhZ_vn*jFa&Nk=_ z$_5{lk+z3D4YhP$VSyQB|f?>fz;ze4Xnt=3YW8yhe+fZUK|b=2-g3 zPMFG&jPSGcJWI-jYX^nzcy>Lhx=YvHq>S4)HV4`Swzrw|uF$F>WBtZ(F?=XIHx>hQ zm2&~jMu~muN^LZ)W}d|GZFP;b-StmpsQ7}`zgk(vfCa6T5QIS#LR&YTZ7ug%E=NMp z!&0tEG+P%vx08R(2o7!>!NIBsDghma*#08pPPm7_N8z#QMsG7#&Xks7I>bsbP6{gi z=0RFvj6!2$M*oIoR%8gATZsd_Wndtii@^T1L$z`X1CvvfqLGB8!VzR>D9i(ruX+Z@2=@XsELA3aWm5 z!lmWwfV{M$mD0LSM`tt)hXr43B&zlr(EJeYehhPm?+8LLu29l=E7+~27S7V3l`t?n zc;b3-D`A>7;E{a1=oNFiI2EmF+2;Ccn`uuEtc@;c$0V)o|k`0gjsD$DZNy@+tscro z=+P}EmFR7yG7??r+UDg5__)$8j*@^a??wJL@sfrIQNp{Urs?c5v2km{!_a#Tdw6#J zb{^S&qcipw+qQ49t?cCbyV|UE*w0^f34B&scHt8kB2m&vb+%O1-G~IS0HH)ow%Umk z`FQi1ptwE$xU`dv-w};RsOSqLADAPTBx#P7wib>AmMVrLA$pc2EF%1tzf}gYfxa_y zj&ALh#d$tfK|_hWYc6(+ONbx5-4Y;NfL^U+vhzI&rbLypkkX+t_98G)W>c!SQ4-rr4xe0ggp73&h}EIJWJ%aO z5Kv{A7wdRgn$)Y#eC3M@tHlT`RJ?}|Z(Wlb9?8yc1e*(4ib zzG!jtPAxhMBg-F<9ea$sp`z+}o77}?>%*oF`Q^Vs78>Y`a?nbxUjkCBf zP}`3|B(?T$aA@p8_&9@wl+gp`7k5Y@ABz<7F-RewUufKA_R{u4Ud>s8{?-Oq3}?z6 zHm08J&?lRJADXTkJH_~z8S3thr+2@jA4Pes>&KwL3+UoMviTgABD3U?Y%8JDUJ2XB z|Z-K1lnU?R{(4s!1@`yY6j8SgEt8@wj@@kRkH{v=vl)4kJw(eQ1+n0$SA zKsS=Xzx&xJ%g;lXf~^K}F!=IIf{A}z6X>GOC-A$xoY%!^naRP_r4z7y%toMa%BPBOw*g_@YR>s0ys_UvyB6g5|4mSt_6v2OsF;<7mMRbwgdBR z{BMhF5x7@w1)$q3k*);;Cj;1D*Mfmd&+@8h7?W++oNe-gJ4&Q{JNZkxsLzTrc_tGT z&{dlI#bojbBw*4xtLu4ne`DhmMBd^UWb2fIbAQBWX|sidON2!6R6Ht0cn;+oZaz>THV6yedDPacti)-xY_$o8Xay(=!mNuxeOP zhK0o>tJW3lLp&*hs-6wE&(nOuHx1&2hbX`Atq<|r z#?ed>Q&CutF%nzweJ^1#0soTx=_QH@dx;~J`GqM`rEXu~wZ(}$w<(0koA3|$_TtAd zzH-UH)uo)FYQm(j3h*?e&tk?M8eRx4Dep#>mrTiP_8x9Oefr{Xc=-3do$t2~zE8|+ zlaFpa#A`M5Ry-I8^P);8yW<|d`i6q;U`luO!YbCz&fgAqovD zpzH@$QLw?x$Vv%%orwh|;{wGj-AZb9k%tupE>O>FO;ct>WP`!xU~SC8KRU|+0n`8` zsQ_U!pDZSdu}KfW(}kvC81W}p~+ zAAuq&rhKQurBtx^rwHUntlke9!=fa?9Rv^qVYRc(i&pw#fNr%&i3EF8OBnnajf(zz6ZG_AQc32~NULbyB5)&xKrgK<~c61>cDKeRn zbDb?Kk?u9NVB2?77Hy!^oe0#mu%l9JBQ!1Vo(Qq z0qKcWLQ0`_#(9PFVvK`g&ixbxT{*_70plZW(XP{7(ViJde6G0&+H+XZ) z<;|u2J;*?b?y~i}Cd{j97oApkS4XII(W z^sn60uY|A2>?=%+-I)?hI5u=Rdr^|iH=6A6T0vk(SK82mNU(;Kp+*fJ*>O%%(`pff z&}1PFXpO)k$At^J()P*f+@6j1$l?UDE2^YbB3F~6v6Oa$C~pB>tbRSS^rx>@*t z*k$p-kzQ{=Q2F?-Qu*QKL4LX%f?U@j1gF(*^7GG4olly&+p4Ow9BYOEtbtB2k9|$P zZ8>Ws%4;OaqEiLGcADpcW_?S{g%UQ&g~Cb*O8FYaQHjo*Li6a>fLu2#p?L;MMy_)- zuByu6nYK%loKB3v&+%f!q8MvSeYyYiQNqseaq!I~zmzMzDtT3}L#JrzowkJ#1$t!+L6>zpofO2D>3dH4TXhjv$J526&T+{g@vk(gMrDC3 z5m{oE)fYwiwi2UC`e>S^GqJdYwNX)`X%0$EnD4q}jck2^cg1z^FY!?|C{gGdv;ufW zN0e3WGMw2s-8kTodUi6wWn)xKm=o0BD>D+K@{IF0$8-^%e?|$KO8UE+i*6B^ZO%00 z0!nnvVI|)nxM>&_yV)-MCEjf!Ru1xD-`1s5A$Dri!eo8N_nLi(f|jndcAy{GjyDgq zBqp8b#5gZmTO;E3vwU4S#L>W4ys@%ybGd7IZ&h2Ly0<&C z@rr%jGYl8Cwe+wA_4;|G*DLpv;n6KLV8vanPyw5(*=(g|3a<4amCgF#nS8C$}q^KU{gi0 zcV>NP>~kxZpVuAo9Bf7r-mPr=(s0QG(ZLLjqh^bon@80R}eYCorCGNc5_GsW&}?anKRLHpwxsjo$F?*qeC&EZi1F;01-!P%y(CR?G zbBU$e$FkJewa*?1y44*I1gV8bPVb}o;FugMk0cFZe8@m!rm#LTw-)5;+}JHZBH-XjcNDZ* zpA}=Va2iu87{e(yjSbJ4+|vri-`dNX|0H-8M4w?L{Uo z<7f!Qb=SH#Oqd?;Z*tm5ybzBHrnS>zbezXbCgoRLCQ*!`3HxAHcfklHvrIz=A|*fi z>d)Q*FqT}BAC;n8%_ImNCQ#DQ+(MFPcZ3SZ>t^Ysi?4INLk4;+AhozqnaA0rxX=no zX-fC>LDR$s``ucYH?36l(v~RRF?}IjyCD^(%HWI;PlhXA*gI+Y3_hBE1uhhh#rGjA zOm7_c13Y_W0^_|h3Cau`!ABBv z3$<)@7GUdj@sbLF__!mK%;Rj5UUs_1r%ex>u@+>=vN8u^xwUouK>sSkekNdMdscb0 zw$0KK3%dzA!J-C)ote&j4QfGrtodty^2HQBo@Byj2I7~+&#TuCW4Ta6k_#Uqg!4{z z*L&@VHhkQAHFs0F{=;39cU0J@W( zTt0%5`&k96jgD$sx7M@B;&`gXKM`jAz9`=rxFuTVr>DS)4eMN66nt#nBXHts z029>5=fIUi%C5s-vO&!~ewa|G4nAIJ*rGann2z2WJ7gBixjcu@2m6&DLAHdKNCL0S zN|xNd7AH|zK|HJA)%b}@DWdrWKOtAqaddZxX<5_>vxHlAG|AGk;|}^NBdk;#@9k;L zbe|HURLNp)du(x`Q}*CD#WGOXxCr_^&iF{cnvP9Ko~0$gfD)tpDZI9PJtz|6%uV7c}N{yEF zA6%nZ4i)Y##>(uxo6|N;V-aSUw$^t_+n_62-im#fS>Cc!4K!NS5Ovm&>M&Q7x0M^s zbx22c5N={`Pq!)Ca&{>^KkM>6zDUP)wBvFT=&~PuhvieyP@J|}m2%RxAE%cr5jq5B z?_ONd;VWs*8?0NFhiKC$g~G?ggX;FwHVS##uS^Rab-SD@x@_C6Ad6(aH(ko$gwN7> zEc8oLmeINa+Ny}=Rfw#Eygv%HSDenjjDito3#An7x*q6r=eL`s#ke8n%B*lh0?$5X zu$(7iHLuGiSDBu_MJ}^H<71q{_P*g`aAUXtKC$E8y?B-2@VJjZQ10VyX9{%@yRXNt zBIH=OXyCQ;>YDTJiZgFjA*@!|2#6*UJ3rMro03%OfPE^4CkZ%Qr6&RyYFx|Fs^vJ# zctR$Z8Q}wS2UfVM)pIL=iI4e)77Ze1MqKD)CX>)BPbmP_lb14<%r)Lyt;rEACRJ#$ z7Oy^XppET)wymz!R@{wjqYQVCaaLdb{A;k#zW|@Kvlmz6BIPc)ZlHtbknuMsIqutz zdLU*&rVyt&Czr}EVoOO$U%?eyp;fAEJr=m^icNfs=(^?!Btqj15E=-bQ{Z!tMkX}R ziAoL{$z(p-hFPbZvsXa)ghSOW*oL=Zl~zLZ`4CW5Tx+S|*vG&VI{l2v15=(mMQPe~ zICl#Qy(^D%D5kuf>v-Z9rWtVg#aSkfplScJI$o_>#8YV)C@oJ{i@XOQduB#mJdaJM z^m@r8e~ZaUvYC)DsY-W%5(~f?XwnudCvDJ&^YR%6mTHvLtl_ic_(3F_#!l}@bn4^+ z&k5s}tT@Q5P*b=cUnbMM!i?Wa1{nwIa*jVVPncJ@<9iwIC#odt=m{ugQR9E4fHG3T3(MC^zhE-9+_aQh+dp7y!lT?v zc*~OW7A|GVZP^o%je^fkT7(mxe|eqvdh(+<_>To9MLIT5L*(wRuZ zAxF4cK&xqGa9v#67@InVa1VuqieU=b3D#cFQYxvu07mAkwPI$y7{?cEZb_e$eC6mf zRYc!OK3ckd;*W7t+r9Kkr{thS>=od?!N{J9Lw?MTK$E;;e)%Uu0A9#=U zXc-lL!5osoZkib-cO+>jx0um0K#ue|n9BE(f_6o#o>+YepzBB1Pk?A6h<1UI9Pxc@ z8nfk?jTs-zz)|5wJFqXz4pp5F!0~}Lfi1xh(>a?hrev$4bIQ{9r$Eulv@f1mS*Ew4 zJE_c5pk$4c=MMpgwx&}CPHTou|1*$1_9^9N-On;jpEQoP9weN)1{S(l*4t5S$m@sY z19|;qld;jTJ*W@J=ZAi8zn3yGFhAE z@3Jvk-bc3RwSen$g-edxx5yMC79(57$TOeu8Ne+Vjh-O;>Ze#F{o{H>mI!V$I;-`z zJE~sVBI%*A2GiQjmuRRfKbQ7&n}YR)|r>#k^J+)!7%LHyG1xDzx=l>0sM}y%F z+YcSG+iZ)&%NJ?5Y=13>Xh97xaoDOc|5$^}9@{@y!|ACa(@*2(?{o(iMo6T4=6%jR9YZu&bIi zFGcumEo4o~wOzlSTU&TA9Hnso6OQRDc~AGy2oj51$Y|Xwmat#SLSNq zxZdUQk_LZ1oi1vT>6q{C;!-0cF|DXU1-1k3SNf1_Sp}NZC0KD|xs7U&P-XrjIG&ZjRAHpeVYD$r*J|dJszu&{_5(Iv^-p#Y%r+5`8%<}p^ z{Hfc54h;G*d?m2QyqNJd7y=ZZQ5y9BNZmBMMqM%S;5}#6vVHx45R?=b!=NAQs-B;~ z)K+rL9A=>XR7=W=`+}W;?F8#BUH$C~c}}@;MAmLW5=FRmUL!8=j#60;F4stP7ML6D zJ0v<{4Bom-ctm4Q>~xGLhxxJ!F?eIPWg2>B5aAkqgXXW&9Zn`jiZrS9xerWml$Fy8 z8Q4i>cc0U1O)ddybm}$tSh44g9}DVO=E5OPy#qqF<2H5M=PSJaI4~qj$@+-0@LFWm z?CuFO6^|Ac#coWRs<+R}c|7e;H-6b)*OF(#bA`G!)0e#jLs!;~de4E@dK{JiYl>h> zwAGLW?LBDk7<%#v}9x_QfBtn^F_c=*RWD%y7KUvPC_di!7ND)>#Q- z9Qo_xi%>jlr&*nj>FU8IhD3!UnH>Hch(AmDt{m{7C6%6NN!>U8_UFX%>BYc(Jwo#~ zSj%OlmO7{$X-vn}6;%%mIGFiM^o}Wf6+K1DPZ30L-ZRb$>m$N(IaOVxbJLRUzgXB^ z7|;tXeq>6yk$Ds&4*wWBZ3wTZFchuZO?za5Wm(+@+9ZdiByzI{fn;}}UhULxmv!ZzG8D8sPOtO|$Yen~g5<2+}BT@KMDeq;;K+&JIx~92UIRbi{;YVReWj zrUAy80)@PGJz(hke{4F-qcB?fI1u2EmIwX15cBHCv%JnGc!`qsoHY9>f|DcQ#c74W zSZZ!9XNIRp^{eSz4shM6MrCnvBlAN+!)d~}%M)g3CzxAc@N;nYo8&l8&2wSmZ8a(8 z*(Sz&|F6l~ScDpFBxB>6aikaSO4XrLXUCJbRGZc<{8{Z;8mhv!Z(7cuI!mW3i8bKq z(W)jkn^k8yhO1wSgu!YrcWgs9W zedZn_IEsv$!m>?awTs%Ourfhg7Pi!~3>Dr;2tizU(y|Lijn?xb;*2k9oZ|xaIIZ~h zb(vJG;#?~i8Li_uSAq_VM-h(U(opOSLv`~R|4TPOGU^DV)9oJ3B+7|3v>5zpM?k1W zvU?r?A(f<^F(OH1W5k%vDTY2@${CI8ObYVNYc6;OD=bO~M8cJkX>4eCu8&Gdz88f? z7}uGCta|)%fBSIv#q(q<`8pY=mlYu<>6#L?CK*!`!)CZpGt9mHokzO|40O=HeS7fD zrd=Tyl+#t7ZU1e!zw_hv{^Q}{i@)wXKftPADeN~kRM2fTdx!3cx3~aTLlL?pF>u0O z&0c{qcXJ=4@n-8fyj}AopXJqA`&t;E&w)JXL~dV?G2F{aT4Nl5?LwIWqV)q=0whQa zmz}hn#j$9D!j3=hk!1o_k!iA}rl)zIKKK58# z9Xp%#u7o1{LoMuhpstQpWe#)%8%&@ElqpUmg$?{zSKw)Pz4Sf4 zw6f{rg;DxC?70b})?5tW9yPYvnig`)U>POc;Zvwo&WDvK5S-Tx@%g9eVzcmzO{su1 zEF(o%qKAWY6xC*J;gOEva7>VNG)ZW7bdj2g=DG%72>;Bc2}-$`ZUEME!!Hy#O=v-m ze`Y!a&Kz=+{N8T(5xQQ*_RuG2nEx6Xr)!iui|oNb6w;7F*0M1pNh55Z7G*s#`{QUx=Krg z4>Oi@BUQ&aT*49XMm4BsVrT-qYrc<^k&T8ACkUDI81GA;V%8>H_sqeTEtS}$Rn$ys zAv~uBVo4t4VL_$g;bDh|#us(UAWcs48J*G_i>fHhFx`Ni8TBGpS0sXL091G)PIFlG z047s1<=1tCbPiZb5t5zsw>BHOg{~#5^zfXes&%PN0Yl z)iC?z-Ewn)9V8pKZ1NyJMCG|b(51$V z$Uj$-A@*|D-sZna`$WNNEnb=yxU4#^Y_xRxJ@|N2BFAka;uH`#FOf$!F!e>hj`k_U z%B!N{!@y_V2GqNWmevDZ!{_FN>r$Lnm9@=W^V=7=QD?F#c;i&{xx#R0$>+vxJ*?%h zXJP{K+yK8N5x%NuAtYZnPuI45ox_$Wz_w-6wr$(CZQHhO+qO?;p0sV-wr%5`dtX(f zIyFZ8K=dN^UTaPPp(651*)VidJ##D#pHk|w%0xzj0?05h{5vM?V&n`p;hT}XC7gTG z8d^e|fi;Ey+vqF?m{WIS70&}khZhcU(JZAkX^swY+3%J0L@^mWuA5&pi^-iG?tlke zzlGHI*|J2(M0zsN>h3a@MOallz0;O42)!wGGz&7xtw3JIY$pA>U@+ibJocJubHSrG zl)=`*ChHc8=4<5`kVLem#HP39?Q0?9doe%iqWHA1L;u^cwPoZ}JGy?eQQnC4ORJgL ziqg1xDDNNYMx4}us*$K~MU6loAfM5nCNP5d97fvbEL*f7F#2=Gq+tP2JE3UQcx0)! zYzx=74NE?fq)lhUKV}&-5P<>lF-j>+iWKDMsM;}YLxs$TR*I@aTuX&4dJiPQqrl|W z5##_5NHe>2%~=D;@G%}Kw>nnaBKDkKR`iIW_WJ+!LXAGW%a9Z(j&Y7D#S8X-KyQSl zCbS%F!;Wog*4lS_9FMQ@7tom-QeMoe}#_M0q zi2nLo2q)HCYzgUfSRKC+l~G+oft97=I+&)ol3~se@I~Bu@T$b(>8cdJ8Tw}RT+Wk~ zbbCj|BNYXi|8Hw_4Tvn_c*+hl#niw`OT;laeIqu+Kr{gK4`z}~QNuT7lT0$MU%*eQ zVQQWUm2c#{YqEKmR`kXm1!!6`_H8|uFf+keM@?5SWJ?9dHEF)?z$cO8NMK-8I@~y{ zcb==Njguy1iIyx=Y*LQxN9+zE%oOjo`jTIls=bQ>DC8Vtpb0hPl&WVCL7zph{KPJK zDK}*}(eDrxvXYvnEfd#BIF_=uy!JU4b}YhGks%K&m-}J$$Hu6}sgbIb=k)hCg*XvDY4IkA6rS4^zTf08o?9x4{78*_)UloBgF_n`nHM zt-_o^51=k6k#fi`DRN>nD35~sgUEDWunx>=I`vH7YNl=Bi9m3pZ=pJafcT84w>FYe zAQLqAnoyR+kd%-ZKu3}=iffeC_Oxw6R_8--5|bl|Iww}D#LN~SYw$i#BhtPQFsa^_ z5;`Q|CG`a*v``D~xWMluGITxzn`{OIYfhppNGrFKv7rpRVt3cxZ(?tJ0n!1l_G2G= zh^~r=F7x!jdMU7RVy52`=sAB~($@Yrkjv5HnOZ4>Gx{wd3j(yBz0!hK&uXBbUeg3& z*9o9!d%xLsm&$O!4Jp{yalqtBJF4bi=%U#75bYAAdH)v77*G|tu?xHFk2;u+g8-#5 zcA@jH43D{HkRal4bKq=?jhUb3=H%>6y)p4NbbY*^3S;Jz6=UYJfia_F*M3hk$%-}i zM#EZk54qm**2GwLuQ^?yh7u?EIFwk8SaH|yhuYYbINQ{vW7v&uLdz;VFxg|eb;Z1E zHMKHiA&p~@sMRvAg}JZMGZ#yD>W5s_4)$IH;Pth7<}+afLzJ9>BACfr-o zQ1a26A@n-D8=>+}F&AIQ1}}&qLfG_dx~^uLUusHX#Yf|v1#&XB)N);-#2gfiE$&c9 z6(nU7M(9>I%N4-5N2EYH$P2;;6%VV|g%(zp14kQb9+7I4gQ7Az9o#g45jrvgqX9Qr zJ%(UV;Y@s-Yw#ZCOYM_&)c77^i9o;G6N<$03SeK_i!O7|FzWj{O{GH|~`@S*)Ft5Y-UT(GRi0sx>Ba zVyaQb1ZUUM3`1|>Fs`x0)T-N0WTXPa5mnpN!WfMS+rfAsHU3UOBSMUrh~}`-mgY$Z zbT7qA4lLTIdvN0Wxvb#(7k7EpkFc^Tg+QI?Gb(+rZHA;t1&5o{vkuj*8vKe`SnE)9 z!Gn!V15-tQ3k%%=7NgZS-9um|p|1iu5g*<7R{_HYN7;yTVx+G>U?GW|oOuFOjw&-J z&C@MtS}|^_6*Y{H@Z8KemuUi(_S#NmVQZHtBmp`pwe8$rRg-UsLgQ<3kFgQdvvXOk z*Rk+9nsZ!Rl>YC)*e&is#y($4zbcE3oJ3{}XlBKwob)@$h){|Qo63tou^dOjhZtEZ zC`718!?Io2_^7db(80^w;es5SpEwI%VG+NzkHO4SQb}UFRLc--=z!DWir%OYAB%9h z>!G&m(wM+*CXsmS%ftZ>{w2j^2Srlj*V9zDrRopv0r>1OUhk5%+ zKX#HHjmR3gyheUc`@AA0MKmNjyib-X`cq_YwGkyq5I5(m8+!O&&c@Q5=1ICPZAnb9fokf&>U+<7ysMGWzbtCVXb`hGUX!6GGW75~hKb#-Tsfq@P#> z7iYfNEfo-K$OWO!P&CEo+wyyJ0dG4yTX`82k9W`WdHufe|L3SSpVhzm-u&s`pTzh3 z+T8t3#ETzUA3xXpxwR)>)MWfM*IbT%jCN1we+GBI^}Rn<*Y|%c=f);dW@R&b@e1dt zW8x;i(L043=$kd9GF1aIz78$l$OSm8s$toZKeBByrU7wT*`rq83!awT9nYpsV=Sn1 z?QOFkcVYbFtP?c=br>D%EeV;0>iTVT(=@UcpRZJ`ACS6I2zEo_KL66b>I!HdKPp46 zkYbvJLoa8*HQ*IC2HK&B-U0!1H25@E68I)PYVj^N@LC~C<=k^cYX(xKp{2V1gwbJ% zfS37*VmyhgAoe51gdg1%I8E&HF{(u)p z1>5||3P6>vA<*o-Euq}_UR379%uq@uDzzyfv~{FgC-`wIcXrQ3Acz7Zpq>VDi8yyr zeFf8V?kEj%yOV6k9uOCxoGZ(vfaCWMyYh-DNYw=dI%J6f4G+r*WSEXO)Yvs}G zcDwT})N+-ct=6V;LqQgw9y0}8`4}494~{P2nz&lb%)=0cG-SSwIJRJdVB`^K(9FSx z-36^%-s3w@ZWMDHt4rkr(d5wT3k|$Hz`i8}(DOY&WIBtGCpJ8{Ll^C%Xzxlbpoip0 ziY?$(h=yvlTB&8?;|K)Nun4n4fqIMtdat{{3VB{KwZO>LYEo5kuGrxWIu{zcvS(#1 zsHFQxbjv~^kCHfBLWMRgCp5^1l1nWvnST)fHTkgOo(I)^X-g(~x5c9V!~Bo$Px|DB zq~8NiA;y>E>?8a)$i$7)q93{8UfDfq8Kje3@*%MjVmI)X|3kn*aKNtZ$1S1-cwrB4 z#VrT4qDv(vq$eGtbzSdj%ybjiIUg6>8N0R^|E5~jJRbfUi`*eu;fEZ3wXA~-JA*{e zH(UGXae6jn=>8mkpY>0|9yAG4M6;xp z@yLO^qhs7iyR7BQpEmW)mOqsAaJH&1W;I)wj(%V>2Lb6?3vvTSLDp?hzHZ~5EA6YD z;d*n2Q3BcOmva+1>f9K~p%^8N((g$2M~IjRAO<$dpj*s}=VrL~<$H$5k&kLl{5Mx$ zsAgmA`o8nG!1DgxmL!@9ZRlq$B3<+iSG0C)Dh5?Xco&mLcQ%S@hbSH;{`df0JU&ah zD+e=;+rW;i)A>InrGi~=`!6?(g^H&)3s^6oKi3QK|q%6w`4>B48IKlora39vng>B-PU<2uP|G?5L@ltz(6!hZI2?KNa zhEIKIni6m{=?l4_vDOqZ}RsE7O`(18-{RW2Ow+7(ZM3QLF>P^t6JT?uy*p-}pd zVYh|qGbV%r@OrkSe#TZq)Xd*=YVave#=B@Pj8tT(G#t<@J|S_EJHIKd6nq_TGJF6a zBUE@M!SZkX-o;gQfk)PYV$d|lwH`n<0wEwu4E(7u8!d?^4^)zIaqR%CN4ku(?aGC! z`~**f95)c4uS&8}jUnZi=2%X60>M_cC%J|d6c(UWV0d9C+YN^5!mmB4?{8~|{@^)N zO^R)?^vv9Y0g04Hv!VMDhF73et2(`X-vl-|8^OS#AyN_eQo=^XskYG7^V}%SL~+$g zTAsC;L@62Z(k=RJVS+TQnK7ELQ?KdsSFnw7M1@80pV787M(+M{tegd9mDQfE4 z1U9gDB4wm)P+7Zm=E`LS4iRp#3Y`^%>rcOVv?)~#Cv^%!dTqLj;NCa*{oLtq!itGM zVK7MjT9176v-whFzy5YX3HgnP69bj)i2^3Cj}Xm{m`c%r<_u+7a+C+p;q6$?nsn$KoXF6p{AW*RMWAa6N1H{45Q zF-+``#D_YHi$-h5roJfHDqpR1cW&(dybU*AZ=VhZ=XTp_VE3-=subU`VaG1C0@OIW zSi@5m!?!x1DZf``HR>d7mlw!BTZggbez49g+>_*+>UN*JC@g%kbAK{yhKKv_Zod0{ z?tPj_N9X=@);83FuX9X;xyOT#`hR>JMc?loRsD3=ev+?`7x16?dnWDhN-kFOw|y=f z+=+6%UC0;L_Pm`$(~s)+XV2$vC?|R;cottBe%idg-!!JrhRM7CULW5aZV&bno4?xc z_LN_6aie7=OT3T6R-PyYo0iHoR69*z;AAi1Lu0hz;dc#0f}Bt(6a&mNCN7HU=>8tGB_Rl*d7ceLeT8Xj9(%6%H)SM+ zam^ltg6R=D-``6-#URQsB!L~LZW4MYEUz(9!YQ~Fv|U`D+qm2;TXSNC`mOhIdTEr< z#MlLYh=Swk%(sxNn=P&izES_>R0#r^YHX-Rm33C^D3q=g;dSqQ-U3x!a`4PCgqwq^zJN*W^kLw=j8I9xo!% zrC{sKzacdrHi_Ak0w9#G@*#2~scHr~i&a+iHlg0w)rtc^N))U$VPYVN> zI=iCfWaz`<&Sk_sGxF|(CoTw#-X#Jm$P|xm7}AxPUob~H;^c0XBOhiAyM~DPdyI!2 z<3gcd)T8w`aGg*n0}<)8tq&s*l@|%kUG0v9!ybY{GMrr`-+(duW{QjkTD!PZpmq*b zRop$K)q8$Q2{l(%kF{%SvgcDs*Td=xXBVa-+#o{V6j@6s-j|U%rbFO3tR{9GaH_@H zpaEN|fZW0IZN2-D&-TNZ&F^4$Ett%m^6uWLjqLWiZCL4u@)>Ao6+(8{3hD+r|8S zxL~y9JHghI2hp^;H7B&qPO$g3Cg1G2Mn_X2i_ZDaR^s%;iVHVxXp)eqks$!Vdbw}( z8EXnPFMPmp6k&LZ&2{%SqD~8-0^)~_|DbsO_lC6NC{0232dZ>Mo{AZ+k)(-U{FocqwCOD9 zE~r|@keqSZE&nIh}AGR|BMuoYvnW#Z196CpkaF{Zh@DgZQ>zXm9&mTKi5YBMJK zzjPH6ej?f3#~Hwf&))O$!DHo2YUM80cZ`=Cp470h8==K~Fi+m|n)w-W=}SXbp}UMHt&y6_Pba4gx~hm%Veouyt-%gbRo`sXF*?9 zFx8k29~=>F||cZ5dT(S8m|; zOrH(8lJC@L5*uG%AjnyseT)L&pd}252nojaHud)E#4)T4#*-#^ z7Dh;xgQ8MKe4}LU3o8|dp|NMXC1#@O0g$QV8I~D*HI#sp2^E8B+PzMoWpYv-7JDlvoLUdDxfFXf*hWKH1_r+(Ve6q6`N+@Y{Adq_aDI)zLWeX+(Jo& z;s|!{Jt)9qNE=Kr#x547+A^mU#!u7MVuvYoB3256(qJh3rNA0(834>vF>3&c$|(g% zZ$69drXFv^rNsDM`**zVFYZ1vQg8bA^?wi?9mB+X+UuC7{MK6t`Kg z<2dM@jzEz--w?C(-Al6f=w)YkZT3!3;`!ScXS3Ps5`)+xT`~2c{}K@RvcOKG#so83 z!3s4SAu_%hs7yhQ8t%`3$;e2+Ijb}XoG}%4bI>_yIaoxP&N0j1nZ|V_>JK4FwAefj z6QGIDeWX5qO?iTJ(0PZ6m`fDiPJ*8gR~uBeN;5lA^lQl2CPq)5+G~< z80UGcm1{W9%lh zu%;R`&U{k{jhdZS1h{By@-8$so4OA1G+x!UF7Bdf)41zz!W8?n)b#{zYJoHd3|nYD z&X?X{;T~nqFf$~ID+rD=aWA>Dv2Bl?U^(HK!{qf&{ z$n#v3o{55XN{R#+5)GA0G;&MIU&!I5UBoQVI(a6YYHQaq&!Z7A)bEQz4AB8y$z(SF zZKt>pNCFM5l~-LR|4j}A^4Dp>x12iZs}v!3#7OcP07$1A-rkHODle;B_Mdd8$0jD& z6c~77fd+#bZNQ8;!FI+B2~5s8*?8gAO52ynR!0QDHX8- z%*Jx=Dg3kTPz4BUyE81FmdyaR{OTMr!M;)62c9S1&?rmpGpK88VB>@`K8rijw=D@dXBqEXVgllPYf$Y3PT&mcOMy>uJ}wC&h>^b`Ap{J}w#{{Gj0`(c1VAnufjUI+{+gpI7;pNizwq{u(_x3mN%^A^+?Q zh88j-TbXA+7#!%n1nS0hh3HB0cC+6lBleyuahRrj5aHAvIVyeNufYK-ofVl4E3Dt^ z1(E!I)i$p*mP;4q>Z4|lbyjT8C@{XNxR(LaXIz?Jm9&-)1u*!80V@R&2DW*GkhSb9 zi=L^03MPi?z-koSb#TZ{3m=zLyIax{l0RZLJdK zxJ<@lg9h~?SF@8@hb?T8Ev#J~?Pp6{&(=*c1%>2uU22Kfo6~PQ>7Oaf@`f@EC27=V zpx&^o%wwvi-s-158ryJh{rKD3v0HYk`17Fx{Iv3*>59kR43QOu>%)+^v95tX{FgP9 zJu_hUxX9vz{%^+7n_RyJd8o+b^BtF-&Ef1^G1nxuGbIAGMG$?j;Zz?H*-XLv@5_sYgwx3`^xXW$(&th=*l zT-W5I4sRy(c?rJ0oKeoE`#3&>TToAd+CfWsQC{|BigoWNl zv~OoN&-fTjjj;y9u(A2KsFme9poZVP2KxyL>Oe;a1`Z1Z;;`674Xb;`^S!EhY0Nhv@lvO-J{E+*^e6%JPEO1TFv0bb9 z7-R&|e%`(9WwiZ4EWR}{>mvqj!^>Yd2TgRMqOwSPwwT*0?jOCLFR+cTA>oQxwpexu z+>h`<3oa!!OI0=;!Kh>99-sWvFy!6TB0;X&KZ-}M*b%6imwP%~q$GIb6m&f!a>_Y7 z(#BBzfle;zm35L~In*#TABuW&XFG>hO(5oE$@ zv!zgGW`otX(`SazH-gW@sp55a^Q$4 zsWsZgjK&~M?*M(pvnk=SQ`m}@OkBKqsDwv;rp4by)8t}t69){5AM{dVA5`zJ3uZX{ z$@`=6T_!!-cAKt#Y2&Pas0#$k(*;w#wHrFHu^U>`rnpZ=jX;QYC8$0gO2ngLEUZ!> z`Q_K!YVnol;^5QeQfsl$6{@zQ>vboKVEjZ2Bzn&l(5ibVK^WtYK*y&6u8a|{J2b$J z`NnbG9eRS$sJfvI-E{hj$&Q!d(C_D*$SSGbRZOn|hhHCk!4@?e-tt}c(nf3XG_tYC z|E;U9xtkBL($n6ZL?mk;-k?M5@o;#JBw=%3BaHgoQZ(E>zAs}U8tiEcR#;@2eSB)> zP_rf7o9MwUjb`c4!D_D(Q$rui0%iN`DRLqo2BMwU2b|dkWp1~yz!bUJ3@3bP`kQtR zJlD`S&3CSblYt5z7-g3dlFeefDV_CFC+$rmqS>(&I)&^{^ur11K2PttD=@zYmyQt? zzR70K&@Em|fCh_dM6T?}Kx)W<7l2w01;qntKK& zrxpf!RqLT)x(a(>ox+xqvI(X&K?K;VEnwHRY^J$J)tPwCQ=;v++nkYH2}b!ciJD=P zvA{AS7M32!*gAoiyxteOJ3ioXx_P%yiH{9#0rQHc%3J|-q=m0`WS?H26%c&=D0kE; z-Kys@Ry|khsOmiqGbl;q@&Q;e$OqV5lZM@+6V^awK#kpo+D?eOjg{68>0>UH~tmdOR>G`S-Aev$G>G_sozc z(u~KG>{Rb{ce3kprrbWs*`54pXS)QZ>k+sg)=COL$0oEUq%}UdpemNvhTDI0b9>j* zM!(~vtS}sr;bB%gNw9nu+9S+3_2}Oa%iR6;vVVJYm}S}=*U=oXjPEM4_dbdq10}WI z&jk$BeUxgG*JoCquJDMszI;3Ny=0m^Wmx`DOyt_2Di54ga}M`eOe+MuDG~eVP=^G;LX7Vw z#u?xLq&=P+cstx4*+UezyT`e_up~!zABi@JJ4{@IiOG%%fZ6=e_TGqkTrzYmJLK)%xHA3X1n3Qu70 zR@-%4QBIPCurY)_%676}IJXK631NBA0v3OLp$OD~ks_k&7%*7==edRP&^t{x!@{F) z#YZ`e3rCE7y#YXL?a-K+04~yuzp<#1C-M<4unlan?anUAK5Z=npw0RuSm-uE3RqM- z=$Jx7QS+=m%9zKorpoFPWwbID(3{*2m>VJM_)|VDp7P8)3e!^-WkpZ|;GagX z7}L!7seLe08l6}{QdK@=AQIUIMTl7a@e)G}xf#H3>asD|CP~rF&CxNVxJHM>LVb`us)g#pZ_(4;UY^jke{a0|0=SL>XLXz@Z~)zdYG?# z!00lQ`SOpzc-Mgk>C{3Z%nkh8PYqM{T{~S@FHW-S*{A$dHwBYKI#cSh(9S zDCYR2NRKgGv{y&ELPzyPJ5UUQH@&8oQ`rHxFEeaW8)fS|{7Xhkfrw5n$Rc$Yg)kjThZ`2#AJrGL~1;#^c(yh^1?LL zywt$zokI+9C~QA;Mw6Zs19ksjL%(QkK8c#iI{3>~gH-EzMABp+u_X<;Aeo;0hIgJ|)Saxb@?Wi` zcM!ky^v4bk+Qs+v<1j$!reK-(1N?%7C-n91-X%|1r5S=Mk9hQ?AVulg%KvT`CCd7j zct&i(Jl46t`n3ACJ+wltN~1quqO0PQw5 zc?~TeXz(p;I8uhiQ@HDrIxS@yQ-g0+F#i+8Or$?e{JiP2;?{2(QB;C;$L@Jq>BM}b zosfa88@cU$Cd=MivUHdR-MK~!SK&@goJJF;%W&7>^j}9jft>16Enklt5oN6GX#`{7 zC`}+~D-Kc*C*>%`A&^Uq>;;{es&7nSv2Wp{o?jrl4)|)?w{r5s6$V~W&rQfTWvT~a z(LkC@hrEBQ)42^pPk!p_)a~O`F^IoYW1rwFWUT42NUs~WlV zUw2;VcdvwJom6AqS+A846n77~SY~BpxYFhB@n)tAW(LG_L6m~_Rdsm8?)+Sre{yfe z|MK}fxp=>3KD}zw{s`2#L>r*IXdAJWU?~=2`^h3SdKqz6@TNEMl^CsunPi?U z!&72_$zw+R(OMteMSMGx+$=^D7ApgU_Wt<-&11pf+g$&bTgesZg>TrvQ1aH=H(o?a z-zz;F0wJJ*1vOWCu~UA?Tq}$?kVcaUA}C^E86@BAln*`(UJyMBaBm2~YNf*{i5!lzw^q{Gdt#QXkfU4UW`)SbvHAf8M)YQ??%FCbhfnv*FWEI zoIGl}?&M7gc31S;mL2+Dy2u8~@jy$;P5gxxkBYWXnfM5A!|lGx#S2ybT1F-Zt%ebb0OE4wrWi| zT*eofjqTaJ+z=cYIN=I6?LGq;|7a{jSjx!=X)?8HO3O7Di*5`a(Bw^ubu&ItmiVt8 zkN?N({{GAhGq;k#8QVZuMMog=QV))Zvs6Z+6e zlj1!p@X!$?8tVIE!*)rpunJ4IxF-}1#faFJ3Ag-Pyc;|I?eB2xNW`5TQJ&PtSU2>) z!7@dVnbG|>`Pgj^F3`Jh@UN};_&n?D>M!ARs0UW-gxMWv2WG|NY0+YJ6&Z?f-LXYw zG*DRNL2#f9(6lnr$h7Jpi%8GLw) zVcv{XA$;;1lJi4C9Dt?;A61UWR=LugainY>6}W@;tLTkXPtK1^Bu0BO07hsZ z9a~gnzWPy-yFxT2Mb?ybEHh^L8l(4%BLhTj|DsaSI|#QAQg?=b@5bcY@cVEv=cjXoA@6RIIZhx6^b9J5_QLMB(}al)j<*pAyc|)0T%956RJyDvK^xmbzqk;3d0?EyYtKY%Uy5u)ttS8@kA_FdN{ZNN^s>aAwD!~l*^NcO#tPu9@^(QE1ASIIc?e@ASk5`N$JXqlzVrXG}d6-G+`pI`k=aBo`}>ml79VRg=!aE(=Az>AG4N;giQ7{XWn z8oj?Q9$}m3mjb5DLh5`y@PS7jiA`?B*u%h|_te7{-35O0`TA(cDDL*Ns?fBh;x~Tl zp`fRk=ndSYS#LT%@pbHcY=1*s3zG>RStd2Zz*pn}&IvOMh9k_Z(lOX_vd3D&7vSWe zh!K4AT0IhU%Z}^3XxV+Du(_kC;;M88CMPHUX*xzgzDEC*0PkKH5?`lr2023qb8VF$ zPk~woTB-y!b+YWvfWK-ZHa3bPbnD2*t%>_nk`=Xzy!iUx zh2Xm>XW~@W$a;I{yL2j2!UZxa4Zzu>BV@DlQfne@wkU=?SuTgYmz< z){~c2YfI`hQQB5U?ZR|TzZUSPCMpx+qG3vtK-u*wMGFK<{Tw%X@WAq&e%rJVh`Xp_ z4?}@1{570y#>hjFV|D$ZXm!li%|W;C`{*M&KQZfHz3LzYqZFd&h+u|oR)w+id%~`#k@) z)mB#6(d|yj4-q6IH(_!0F8>Hvw)YfRFo^9a=_e&Vx6~8}M^{H;Dd>kP5)feDDQVb{ zAp90X3yudbn>8RRqMA`o=t=f{ZyShIC$4Mjh{B=}x&{NOkBZ8qjk=0y@;L;j(wLEf zYQvs_FcVtR;B~+rB6qCagToSJp-q8&!-(?LmU-E@`K>cm6 z8&thJU(5OEBZs*Q$#$dtmBXfD& zF@Q>B+$A(XeHJUAT}8-@S%2~fx$L7@Uoms&`kfiQPJ4XH%^8YVy=FTg?wsXu-h00 zb28^ja;!YvKr51lZ|D2SS6}VjRY2|@a-4#X%njPvE<#?ra6LeTBD&s@Sl^ltjL2&b3mm-YP_0n8$){H4sej+C`+(OG3a!LZWj!VCoQA>JoVapiZB) zjWi8fxtzFO0x7eDjs$58;pZbwvuMcma?0S=Bry~@f8E8L>xJm0Xpws<&7(gy+(1E} zj%_r9e4l3P3~{9fY1G^iG3WGl?=T|UM+k!9mTYjNe(<8R0GHXxhEI6ema&5M6}%7Z z#LY_bRycOF;N%>@rvwk-m!h3b1YH4|OnH#pgFAxx?qwFM+z;*$OZ1AB=XTHBnD+rTblaa6KFFtU?#Xg2fH1|wwj)obURw@NaeRdoad@wH9le-*aKRzq5f-G>bKv9L2oWzhnM8+$%$IC z$MFxrz&i5XOEs)AND7xe=b1W+8F5M|&q zeg{PodUCeTw)V|n_-hvoU6iWR*chybT;RGMXiWC^wH|>(r#8Tcz}7N5nCtS9P{(VJ zEY*`oY(BEzx0*ub@dlH$`G(qp)<0Go=uDuOgam2NO;?qQJSX7-p2fszNXy~BjfI8} z)q+fnSM5B8g2|Xvz}e)CZr||YK|2=H)gW1RA zzk}J|`3KWWbdP?zF6O8%SJ?(RpchHwMb5Cp!eF9D!DC zy4&y81I`dA@GsDci{9+)Z1On!>j~8J(8#Jt102vt;~B-HvVGg8h=;+S(_)uy4@~b4 zk7`RtN(7c&z3aB9k#~arIdV0}0{(9#yik$K%NISN{$_a);M(N0EjabaJ71J1_LMmFOZ&G-@jSX;ktxLh2gT)g;~!MI5}S=8_5nONG{{QKO0dR8{)sL|gKs-uxg_kO3(GxPe6goe-k!J|cGQ-7@VPwG@*8uJ$}bSSk` z=V*($$x>!g)m1smX|=YYMoZ$hpifP`q4CxcU6^h(1d24qB8Zx*O%ze_8*4c*S?Jl* zhC3(CC?^Aqj5T0K%LipUEz*hbQwp_#%5#Gg#~)lE`j4gU85AXx;K0_KO&Sm!SSt^@Yk0`xk3x`ZM( z+c1sKTwZS%=l-2;{hnT}g>Qj}Z-uuFQ+&mWP(uPVMcx7gE1x`gG*>ikJbgvZM?d(a zzV}_UnHum|o-HD+A921wGK{UU905DGV8B+KaK`EQ8+<)od@ZikkCL&SO_$p?b?Mx7 zXPV;&wwV_|{6`b&k+(Bl-k_Adp9ZyPHxa%z20rZOAU&}fN-A+*73E}Z<`7gTcO~Ww zCW5#kvaEqur6Oh}?=Kw=4##bjppVv;n+4zL`tqoEd3nDy{Iob#&52ShW{s@fZKPmS z82k9Bl1HE485Jo6nzOt(TE(3vfyKPva!Mf320!q2L7h$M|vKx-$w_<2I zhdS@DQ$`e^$sG}H;j6ic4LBjy9zSWYgUNw?W6{jci2`DGai1CzFq5gUA0h>dj~A(^ zh^FCE{LYtN(>;|1ljx_%aa8HI8~kpsXJcbCuvFbFC&R!wJxLlwz^$Ii5*8rUZeJMX zos5dpknE|Q?Yf46j(j7QSwYToPZ6}5gTWC4meoIhUSl;MLTFFq!GqW;_L7g;)WFDbPCa_E$wAoo?5mqL##4Pk#SBoX>EG)ycIati$e@^qENpe&H%n#Gpt8&)6 zh`@-YucsHLPf+NU=1rrwqS}(uR(2|Woc%^A{S!Oq+>NJ5N$r4N=L|uj`RH@Su8ZEj zG_B-n2*cLtUxm_=3vfDokQplzIP#wEw$$lW7iPi#CDQ9HePcxF#MiA8*vvaSz0Yvu)sPiTBN!VeTfd8gh<}8JKNI6wID0ce6Sd*j1T)IW^{5h87Wm5f+Y=kv_t7 zV8Qz4EI5nEW6mxjh<2cxDZG&)$=3CTDz>PlekU>yNZ9zd4g+hKtENrFM{vEV@G<1;)o6edD2iPTz=b*LQisvAoRlC)OJc8<&D&za_LHzBX9C#op-8T ztW#m$v&5%}hytG#WL|#8OI5<3+vB@#Ux}uq8=a^d;F>K?KI03c@gkjdGgOd~b2Udo zY%1`|yz7Lzx5%9M1aA}hjh12JZ4D(JlO@pX@pSsVyRY040QBY21U%or1@Os5erN(O zAlMTTr*)I9DX!UyQ=dg96svDH(sdD`8F9mcMQDKe;VP#&d2>M{4Bh|k9!#d&MRdZ| zS9@*8Y|s)xvyMLug>qhz+9-Q$n#^RQE>pEljoz*68TNXyL8FLT@`=xUvX;%x- z?iQYVv1xLc*l(^y#BN{mH~x`ln6vTZD4->z^iXZYzso9VllV1<;#Q{N-S@_MQyL-S zxGY21gL!E1*@Ag2V((3df_pr&fwz^8ZjF3@sWaybssOW^6u|pi>PRBp3sc!i_`m;E zPYsemdW^W!Tsq>Q$3}H6{vQBaK%~FeN5w{uoY7H(kDK8&R^WFkk$4s%0 z@Fev%TU37)uWs#~niExXsTroKH9(R@o8=Khv?7wXpx_;0oq4iFg_`6G@VOfa6X9jI zCUQp(iTo1Km0J)zZbyS`C4Q~|2)~s==GqHkWJK{%w^qa}#^jJkcyUSWIo)V4k8yb- zL`?_?TE>OT8#)x)U#ul#;Sf*_bxD~C90%(L@`}$2t^k3&4wK;wW;oD95BXYS_EK1Qf3t24@w)G$2!#7v$4;16-42;1hCI@d=EUsuFk?YPzytS*w`V zc2CHdwNOGgpG!BZpT?Q8*Jf*NGgsh2In0;&Ta@fOvRc2Te77=vUpbk&72ysDwsrfU zCAC6GHHCq2K&PY%xP&bXy6qF;6SCZf(^(~zb+(a z=Q^2KSESs$w^H7(R}7A^veh84=&U zN(X}bq4WI5VLqM)Qw1`%J8=^U{fL=J0Q|-tcI(@b+0U>kZ)I+!0#T-M?ljR4s<(m{ zLb@yA=y>t1W5vP?23eJ&tGga7L_#Jg5G=rCNHzpLj4}dU-q_#dAA8mj4Tch0X>cT7 zs4elYA?cs=T7);Y_(YZ__TC@uzds7>Gd3^7+OTa(It@p?d`FB|9Wh?D#8}bSy9QZM zWc5=FcNBVQ>ZD0anzmD7(snCyCfO8^G7m9eDQaZDsr3B8qW_#M3f}2_{`_W4C{sRs zB{SMbqqK&0az!k9PRizNz2o&eXYKeF7Lq2ohh;Zz?`YZI@VOl>$0x+;_ykVJNF-<@Hw7Fj$^;jHlo=^Z7Iz3Sgs z*O$%ryN8=^w)^efr#4FwznwT*V)!q}M)pF9mEEz5jC8r4tdzZJmioaL(b3p`0J~*%AP&> z!fE2dSs=NHn@#c89gRbvdTu0Gw2^hwEb6b6YSH-ltHb(raafo6FmwPb+QLYU{cV{{hj+&LMw!0ARi^mpyRu-X(hu&~}f4xOrux0mObJf%Z*f@xg2#>0o}_G_xJf|(`5m{^+NWOjOr84isFUc>l4VpdA^0V_=|3>)m z>tvJ;KEuzImp{}%tK^DGz>916;}QNb7^M|<9q|G*@2>}lBu3TCy2l03x1s@re|uV2 z$wBS*fXFM@dI*OnAsj6BTL25iHx4H1eKRi4ZW9;HvJNu(Lo+tdZxb7qUmFn?Ap-~G zbJ2uu#1^Iht_r*{U06nLtiwtxhQ$3}Ki-?9V?h6fAWQPU???Cq5&U>>h>5!MDILwF zN@FA)?IZJ0}S#q6cqhUqK^s|I)Cvs*s&Z`RG z^(Y0O$U>W(l=(?kaijS-Jrg*hXYzu6BSjv9a#%m14)*}>P}hZm;U0Xs-|a3oO!uk5 zbUFolOXhb4$!xTVKNs+jM#W9jX8*YVcIol*>QYfIVG`DI(G1$Q^TT-fZqKL?4iEhC ztK>DoXCf9!~EHDQW*#H@&nHt+N`b-WOM!nEth-shBW0+A&tA@z&A0Rus1>aF! zB`M%jqZ^lUl+6k1812rCVo+4 zJ<#pG#Sei+b39J&a)ri4Xw9$0#^*c4th9MBh}%2Oi3Wl6%df-B07Rs+*xtg4=20Ac zgMe39+GIqIs)Po8t-(^-vf?=&rI5ED0*p`jqGLCmLlhMH#CBs`oN_1%df zUGk~alc^mv8huNn;nQ$ehn@qCt$|VMvCnI(p)4I6FlH7%nP(8kHwWgjtXXsnUYU17^ynsbetJ zhFKHuMvxK76prjIi!?zFvW35N{1kp6z~?rYHPiOGLg;POc)22 zX}x8f19tx(|45vE8OHppJ2!WdM6-#vwA$Oan0)K^4CTfw2_se8-q*vs+p#&7*&R6? z^8OyBGxfbTw7plZhn!~ZEKnIge3B9#G3bsg6j$-5yvTPY&X6Y8jaLGM)Y#SPgUlO49#6Mm7@52s!x?1HA;@_?)5l3kF)d)R)V4~E3OB{)_tnObsh+JJSj*$wUHzVgC zJ$)L#<1M-FPs{8AN?)%BzJ5kG=(K}KUAxP`sDM8M{HtpZvZ_DCiE`)aI$26ScOM`X zR)FF`aQI+pa9*IA^RYRFkZ9&Jv;xSqZDuLZjNilS{nIyjvcAu^z_#G*471nysgP?O;bZN>dN1~7?$rPd=^>L; zNWzKLRsJ^222x_+&o%L9Dc_ZAsvQG`)t)}F&MIr!IvKTN<>6On0mfOK;_{q#Q)E)5 zxMe1{aCatjsADzxGa&K+(ON0jk{5ss{#acp&3%&;Ma;?!&cJ$_bl4m02p(tW{&H8V zx+^A3$%;V10DR&B)}yl+Xj$)e8G#Oj{dVIn@^1Vwq|qTgq~<%fD9Lv*j=#11%89{k zk9TlL-sRvI&c;9EbmKM$hN;c}z0n~3z6VE*2M)+!2NGU}~tBT|9nD%DJm0Yx4y2_GGbt1w^}=FEL!0 z=Y#FIsgKTGr;o7v*MR}n1<_gSh>};bBoMUIzqTqzMg|&sfIvhGwAXX>`1;}X<10M+ z@Od6j$>kD&!dcKkKRNZ(DB?dY7Ri1rE?{(uue*qQ{_@zbJF+1aQaQ>`R*Gph`Fl2< zW}|$vq!H79olz}Z-(A@;QFQ_~i#n@r40u-OBaCN2AjaaGg#PxChk6i)>(HZC70La@}lRRn`%soV`ldBxt zbd@9$Q>Hxqw`Lfs{_E}Cy>~mi0>awr>T0<4X<1B*Djn_4##x!x1+LFN;xvDC3WJu` zAabjZ{w=iF%Y2>mFU*jBO`VPzeI;LhycaA>kUB9)0Xlb{bZI+V(8JJXv>zS_)bP#E zMS&y!Ivb_e9Tho4rUct9^I_Ien!!KC6I$F|dx{$@c=&}#xW<>YH@Cl^m3c9|Ed-Lw zEc+ZkTvKKB5zt3X1}E7i{$6B9AL)xxZIk#SoKaqV)Qk26pL<0;P6ydH!2+2BH|N0Xx2TPVcl)E&AB_jPmn zmkO;0?ucAS{3CGvUX+V?qj=>3t_C- zp;b{(q1)AR_!PM;8<|svfxdr*Ztd%K|4zE6hf zHJh_CyG+Yrm83M;8f7WQP$N}DpA428t-$GX6a>6P^hR?k2c zon@23H9BvDe6%jE{~6{dqiZlhGZ>)}g}7ZORX)x~DeCiNYX)=G`&F_nt0%8F_atKw zLCgT&U+8oMj~@l=vDF4Ui|-wN`tV6vaSYj`TIp!Szd)rkOQ1&zPAzD#i%bwL5YQ|B zRDJ=CG=oHNScG1+27tBR6eVd80>e@7P!hki1|zwp&mr(OB*jYfG3gW&7>UzN-E-Um zzBKtk_{tv;@XJj8-Oz&amqZIZbT%pFaGD^97vj;@2vWhsGXo59a#~B8;=lAE3|BFY zHAJYXTtE>3ywD-);)#Y|WY3KH0j|Xxtf6?>0_q4{1H@=(qNF?n1cW81m$>RH4!2R6M~8!eBy&~Fo^4D2f~TNHd8Omn=hxXBf!wW2$>k_=YITdQ+!}h3 zNHJyEM@GOFkOKun81D$S$B?t;*AYdIfR3WMnL_ zAc`Y%=#w+!*kCqKfC=#C^iKOauQ|(%*Z64a(?!tT2kyjiG2~xVR*G8(y$ix~dVN6V z&jT+*Bi;9GEgPV|miGu|3qm%L4*}k+>vVALfr}i72#~@ZvRegbh^ze_?K>3t0HUcA@a0lbIWd<&Jg`0N#QL zSX*0Xrprb<^laD-XojDL1%x5g1)5KzNUtjP-F2H97faAFqa`um=cNpNUUZl!{Fw{b z9%O$u;X{gvK1@6=hBQ^96L=kG)q%aDY-aFcU-9P$i=di!MzqjS&8|%A$bkA+%e^=Z6IspzhXR`inoDd4e5Q?T6 z)9?0`tczoum`F9SYlP1t$B@+Oqw1!V2jv3H?WU>`mMR6Y36E_@$}~O$e$gHsS71%F z0>UgCh++q5WVI^-iU}+^35tliL&jEjsO`YJ;v+Z1y>br?gnN2`p_x4h2n2M(ktdV; z8GQxI_!K}WWgo>W9@vZwl0|7YqyJj8Dp1iW%uM>yaRjX1T;M1Q?hv0T&6bf5H0nFX##7E5BLz3w#~h>#sgo z$bafC_f?uSK|KMxYsf(W38MvPCVZPMSPb>BfhO_TVh>CcX}|cd_;{R}LP(5z0*H%w zIOy1EU(vyMZvryr$d&Z={6B3#9>&JQQv z(59Hp?V@L&8%vWZ#lac|-R+)Py`5bpSI9t^{Goulx}Y~fMdkG1rlwid(*@#&K-+ZFC_&DoVk$ci(MRf+CRw1xO6NN7CIs=3Iw^$ zvSDUUZceW7@m_WX*i}xldeeQ&L>fc~A;`xz88*EQG5^jG z^W<0B#w{)={~AjGxqRv5np}+@?G7Z9VzQ)z2Jv)?b5)|`eI8e2^6zNKY$mr$nj+2A z_=MyLe0W7`vES)!h@lPF>aLPq+Yv!lGDCnm=5l^_nftyYs@R^4Abg1L`?gEcs*&w0 zvk`l6gKbFX*ordhnEMqHG;6OukDNn*o{KC_>ESZ)fGYa4b8Dn8W#P^n&aZ5M`M(k3@3k1D*6N}1m z*X1`dUDUeV?v~`WY}ouEbpfjrVFpQj#NQrgizLKS^fFinD9zRWz+Od=_LMn0b=KCz0S8T(8lD3k#jG^8k_$QV(& zzWO{HSJ_B~coAt%<$17SbV|j5)HK7To7~)&DQ!Zti6|Wr!fRs&8zrC}U2tdAbo!=( zLmE2Qb3z{cP7X80ESQ1nuGyu{m@-PyF_jS(Hy+bp%#DC=FsMBLQ2{q!HC#NC?X*7u zEes7CIct?w0q1o@6;X=;B%(+(`Kl^iQ4IV}n>zCJjnw_?Ugsu8S<;xIR7Fh+Hy&b)Q30LP;MJOCiTNTEc`cGY(CCJ}((82i-?OU5EdLlz z&DSOmli`f==n?^Ji4f33`)D*Aw5Ua847M^R7Q|sz+?CmVCdfR_(k_y}7r@FpJOJUP zXs*#5)8IN~k(h=CR1eaL)K+u=OUNwrJG8iBV@eemTPQylMS&s75pK;afavCE)Ctqh z>Bwr&lGAx()!yBS`oDq2B99Lgg#=?zLLaU#8uQxKB95boFtT`(jZyq{#~ zARJfyD}aEmm5cJM?`XoE)ydhYIFU+lmFL`p!E8LkEZsw)AZ%!X_IM^G!7@SRd~q-< zOVkTwyOH4F{D?;7s}Q!sY*eQTE*`ZvH7^C8Wf@Y8ZU#ZEgKGuD9IuDSFdmCeWlXY+ z^SEc&E$}mkjjw_nFt|mGjsyg2$K=? zTjYf)%S(<%8~76o)SQIvx?kgq{mNXa32x+vhgy#`?HE^C$%j6~!3;7i*=af(DeeN* zQyZ7PMAZlNM$G)9TG?2%_rlk1S!44`hpDacJY2xyi00esbLuCpyM(&QD-KQFlu1jZ z_t)sGExhZXz?yvt(~wbZrXjB{$#oQqhM+jPd1Ei?29$i01?h+fOa3XSh={hLAr`!C z3Jz7Ad4!C2;tQdU3rJUvw>8pAd$$|Vc!3(40nFaw^JSsVd&Xa$aKURu3{=D^$c~70 zU1np~pNeDJ1`Yuq#5l-?%2FwBRGX_v6J9&eFqlDgxeZ_8yZ(bN{L-dZ7Y5|C=EYN7 z;5JIGm?6l%8JxFzg^$xzU}nQ!xo*`RFP`hVryeYkBH%F?&4XM-JW_)LT6?2LojU>Q z`S+*!B(Kh!UHmKU;$MLfauxVHAbdtsmY09k(#!XyW?^-4#p>cJpf2WMEQSB79j^X# z+1e7+s~~m)@|L%WO6x$dzVgOKU06WFs~g+hqiJ8wD7vC=)C?`S-Ti%v&e`ibJiPxa zlH>bFYrRDL@lNEVTP!mVk$r_BtRVYN@M0%EBX0oxCRu=-p2^JSi#1|($bl4W>Cx(( zdnZ-40EYlyac`wbMa3}lz&N}m()+9cFa4i7ufd{miG+)YFKCkn8DDwgUQ0={#f(Z< z3G{O5(W+dm&nGmc0o^sm1Fh+Vz5^)}fMbKEF-*?W3z%-o!?eQ;Z}UK8u$g=e_Nywm zJw0_A6l1V{HBVNlwOLIEWx=9fLecDkSM08-G>26oMqSZ8!`mR$|baV19n=DRh=DIT#i80mu2Pc$}0$L51g4e-lp&i^hA)574@aC6r1 zUR*b}y9>TWg-7&*ZDR<04SMu?WqiFfIjyOA@Y(+xG^K1jpBPQEkZj=rwrK$@hfaps z_hEKHqpU}FkX}~_-sGK@KPO=2_J*`YklH+%q|9Q0YZu>at zJV~yha@Ae7Q&T7sP=<<#hU+CF&5|%m*5dV7EGaObH1X78YX^w<4u z<6hpagYC_u?f%=nt-rXRc6RaOq4>ym-G@HE-{soSC*$+G?Smh;38Z77`EVu?DI31x zux1lkp#9pT=VB4puwQb$)AgeSynP(B0GyLNH4h$$x77%AD0$`oJ6Rg4NZeuVv}fJj zN^ed^pQ)am!3qCad64{~h8zVGCmY-2G;US5$w3bU;J41G_Kq;Q(7{{X` z4z01%QfCez4?rM95kG+6DO+$EV&%cgS3SC+=(GLv_U_T4qRUr2n!ffqc#VW~OjTBZ zvbe}`R^(DjECV>N$q{s4sw41%LyYgH3K2ogeGIViniJdC(kq;E*j{06BWvO);o1;I z>M8m*Ewc;$Eei88Wq19X4gJ>M?%~nF`>mtBgWDZ_NiQ!s4^e78SO_C^%kU>7t)TNI z6>gZKnVaT=6seJU1b+3;^Gana;-k+?FB34o`Pl@=7Ry*_0*&Q6hKrtz^5BwOUamTV zc}6h1uWD^mOp2^!r6x0~0>KH7Mk__Ix!R zJbgYGF4&rM7}~Y^Zu@BS_2$v0-~7{)r`g)$Kb`u`Z;6c_+U>`NjqMGgZbWNB>}?Rj zrff+M$VlK|l$xexI%WWUWa;D>uVOvsH(I1pBW%D5Ey)1a$U-+bNw=Md0^LzfRJnP>lVP1SvhF~P=-+$@Ew5P(Cc`& z_j>0I%mQxN?^uyyTxKed$Js0`hgyK22lPcB#I~Q|Yb(D-w74$%C|p#Q=+mBI637!W zDJBxfI+8EMfw5tsX|2(_t;rW=na1)4;M?YfdCVY%CpiQ^Wb?=E+hquG3AP$K;R&c~ zvuPQH7G4@k8&_txDi5<~TyvueYs;(4tEvLCiCbP~S5L$x+gw&H{<`^W`}Ga7*_!+! zbbH@$to$WsXjQIq87Fwy!rZ)R!*nRSVYR;^CHO$Z#>vPFHf8S*c9OB>1gvO-Dt8Z) zBPt8F9{jV@tOgek>%rV^+36%zfN#;0?RJ=+7;j$j4hn5PJSu1_(>UMv-G-%fKi>O~ zSyo=tR1>rSonKNNw4;pebp^RMq4EInAHl=)B7V?Vs_aP8cbEIB+qP_~-B;&z@Vs`< zwa{I+8l$%iyx@F6V&i!bI`Sw=i8wbS;qN!IN^HfGSDSA)cel1z_I}yjKDZlgwBpVu zc=7Mek>FKaGgVF=u5J{UxO7_!wvFUgG-eNq{nneCq`YRvHj#FB&vW5lR!*a`updlH zz>W&&2G-jWOI;ChHoI6*+><~?`~WD+4T61+(=NHSA`Vv>b(CNe%)L`ruBC#uq*{^D zl4p{ifH==pSlA2paj{Q;TSeFmVY-qW_X)9Mql@$$ozs$ieyU2)auz`PdsY^bV9N|G zt;AeaaEw_*ti!`>c1RvdKDkIo`7l6IruwGbHv~#vo)3; z%wUOj(aizI`M{w5pz=iDv+a?2!60%qT%!KB(yNJ5t(*J%2YWwnzWr^qsyJddR0F(- zHr*6=+Xq%*nl$cu7k|N6H zqT~%+T28d>xV$Izb@zh;>Qnme^b0*g$-LeBacAp}G|M4~28>RbrKhKPIc^XW_C{zN zEsK#)hWQ}HJx&$sJ&CHO6~|)DCL@G#tmjtBa>?ltiklc_MuYd6^S_(SE4WA2F}cWX zlEgvC&M{*P%$Sg!<1Th~_l~w-KzaBmzF(HO{m+pG+dKQ+2GFwSUPlY7LbOt5Jo&Vtx#B0@YpIh3y$D@D08V+tq&_wp{7%NT?I@W7%o9{@ z!J3kGI$%n2-09vrT4FQ~#tt^g#E5^Z54lX11-l_HkC4w{R4Rc}IY{3FyYeR(P zX)md~j3a>Sey?nt{_&4U3r<%LEpwWV^v8&W!Zi^|KLZq>h!w>GhTZ{nAmKIeIVqbhf5fL4=LaudZ zbw7PKB{@3S+&z4=eUQ9)zq^HjkN(siVaz%%|YRWM5)sHD$e7X60)+`|&GE2ZM$$>}5za zN*Oso^@STw5^HwDSadh^gyZkXj`YOj#&rv|`zVB(eFYOamplE#LyAKM72-TPXU4IZ zOT>nM>NpRg?uNo9T0?dt(Pgn-^IS3xriIHPn+dGiJN-b1!^1Q5l3R84T3~+IdaxFp z9tQY9gKpucTxGLbvpy?Ud%c04_Ol|v(&6b4vAQ{vbDA;db+~zMO?#|X$?N8fPr%=r z#kCzSz_&tN`_g}Dnj6(ccww@k3a&xTwJHnG@mz5?Pih3B`Us0&;C)@V5qE*DCe4gQ zBL2{PV1?7j&@{p}Ppfz$SR^bif@&qxLGgYwN~?2P5C9t28L_*u6{)I; zwbQ^Y4qj9fH2=0ZW78?x(jV;z9ZlpmTJo;6Us&JWkB_4Q-B!Rd>m8t_Ht-1uoTeFn@{FT!_nif$3m? z;{_PQDCZrqNlm8-v z_NZbP?0h%0PxIT0qIaVA&c)GdF)WcE?`h{Ka1uGMWN@>ZKBx?HZRd6?E4&gnh8b*u zw+N2%jCQ#IZ9J@7fr#}m1NY!uL0KgcQfJ%}Gu;=!Q*qLOWKUdXM&bkDkeTR`R*W!4 znPkZVX%_W7it7oQ#C)USq|u)I-jIs9SGP}ozZ12i`yT3 zXi1(ZPwu-+b>D8NhR!<2@d=}4j~T6{czZ(GV|sNBW5I`dgwLJ@bA}-yWC2`UZiR+Q zEfGyaR^kEm8pMe!zDR7a@EuQFQ%D#f@7y^cpD*^SFTk4^fZVZ|q|DL^W|;B5;b$|M z#XOwvOO(}!gEUNviQ5G=yjgiah<)Q#XfZQqJ^~?-pw8n*J=s%W>QRvnMbFGIU-S7g zpPc%qx6Xg}VJ3Jm?JmPicGRIa8RR-pBCC~O&bb=^nScV#C5WBZ$&U1I67|+qjeMx7 zQVmP-GvO?}3>-QtWdi($5khn#Yj^W)@(%u5dG-Ea_f7|}bx0uRgG5`%dQhx3HUtD( zL4DEa>z(1-yb6S0M?xbR4Y@F8<6uV-s`hGLccbM`nLyZSj3WuL97f|(8xG&m$GuYm z@`_V4Htua=fraB1@z6kAcub|&l1>D<Pb5s*y7=_Lf)c(Z@CK;{D7@3 zT9eijLH#iZ2{E?;yysN6tgo2egnj}K5mRC4(m`gk+}AL2%u+r)n~}s30N^7`0P9_I zt_J^&)+2PDRyt%&<4&}{$t*C!CXSTj^hT+AN=%ZEMpD>mY$(^F^d09+l*AwmWe3gT zLc49!)^nDMtWP?=G&duMkVuzlC3Ci&&b$yIx^BE3f6rOaX{5HtE>T9~USihQMwrHC%SyGzBt0J?BH&`Ug?&0LjX>P*?7MhRG4E^dD zO}lK^tYR+$hSkkosvGipV;5}btOGVY8zc(iO^gCd8EDfAaf_VzupHhk&1ht>a|YJ8 zM?C|m>A&Qbb8NKZGO^wK?ezGYa>)XUsLE(xo^h#QLu6DL9fu5Gz8uRla%A;mEQKpkz?viic$x8-Lt1M z$^ueJq0077t?PbmqF50<1|V+0weummF6!H8e}=GgvbaPV5zJ|``r{9)_iI+T0t!`iBRK7|07$;j|E<|5;YREXez z3d6UOLs*&KRct&J6(5>V%_)(jf zRqm5twzvO+2~U#CEc;xoH-BHM*OIaCYMoMqNXgT_o*Ofgc(&K{G7hbk)q%=ar1aWhTtO$I0o=pr|-mmyF z48B<)3oh9*ZHa0@p7n`EAi;<_q+(^<@57gtJR2j5o9YL%>NL^dfaF--TqKh2E|GO1xB9y*?Q6EDMBo}-a+JHt+I2{e>iZxc;74aG7s5Y;I z6=naDP4WI%UK1pltTB9+vdq`c-E7#nCN;8p^3u&Vg#rFX8Nm+G>(7w3%aRa&y%pst ztj8*2ztCnFkRAv!%Uo6t&P!f~EO*EKi{Ed}IPrcPW#;x9%Bp_*_2%>&E31BMNN&F! zoLlwVV~~R^9de)(twvUON@Ips5X%(c;syi5M=)wTq{oANCz-4=1^0n?Q(l5F1D)!_ zaJqpo_IBU?mG>~I;+ywJ?+>PVyOy^Zh$YEV?-=Cc28~G+@2EXsC-x~W2r`R4%r%Q@R!c7 z$h0q#)gB{2f7S59;Y&GOVm1@@TOd2MTyd3;p%kVdM>v=*pF?u1 zF3C%k^4`_hstWpmv+m;p%V~Z#E5$vPm;*bzN(VTRpyj@tGGwtkDdNo{gBa+cNfFm_ zQMdZqupwGQdbwg=dw>Jz>d%)pp}kSHL3fOq-~$Ov<$OSF@VN0^Hof>7F~)v1CkRMhzsM26 z6t4|WVxlAA^&@gt)O=1r>3?2W27~TL%!DeC_N$n;C1;7&YBxT>XuDupthUi`oznfE z;3n7kD5*Clcz2nu)oN;K8$*m>ag3ju3W)guusM9oGRn(B_fiY<>48QQX_`Q^kTeZl zWq_T^iB1mbkB&JXS~6#at_E`DURP#SXG|~MstZYe3)u}!H`{8u`PwVSJv6nW#VB4? z#K9U$Utt0!Q!tLM(TbNBG0}werOmT+nIHS~gKR|p zkq^%R_Rv}fiRj83&qR%emaK&ba`Sgs9i(*VNL=c~myM~*F6U}Gd~9FE8G@!Mu(x>8 zX4$6geEnrxA{o={0FjE3+@!;VZ(#pZb?y=PoMb2r)~1TX(_#rJzAzAELNr@1kh}Ce zrdD$sP{f+hjoL~W8^CNh;`Lo$bKt{UJZkeaY1-xi2V!mA9nOa08wOyf|2zVbn```n zbKQaF{U*IPESKht>cMy%u`eKQL?dlPlR<(hQ~Ue_ zd7Hm~lAYpppd0SCKR*0QeUoJ$3NozE!9=SAI_32enpLt5C!(Bg7SOVoQ2$@gN#^sNWP*K86y3vZJL3~Gz*@z{>ILdxKp zNTwU3#A?shX7~c*#umL?}9zC$(H>|Kzo2SZp~mqPRw z!QD6A5H(z;T@Hq&Fc0dHG%sUY*gi&%3aHpsrPjKL4|rfo@H z;x5+xUB^rTm1mQob(Y($A5@M2YKsR_kW=b#DyHtfwE$ZVkFPscmHOyes?NQ!`>VMA zSi7$LiuA>B#%G-Zp;B!fQX5dRtL~PmKvztLm9j?$LY)$c4@AQ?11x~|rvrUy|0Ix~ z9!hNLNGlAMc-(CL^yqu^Z&P2*07x(J=r@)V`(Z=$c{+RcYfD_yZWBR6M|jo(U% z2gk^z0_`5%t}K`sM|hc2{Lm1Il}AF)-0}~Ki3$1#Z}tYn5D^m43g2hXZHN#9aqWFF zPOt9UPQ$~8LPA`}S*bj6?#L>^$MO2^`LNbPXig5hvJs}J@vn2zMv7ce^!aUeYKmT^TC~N+jxFq6^q{WQq0VY=)oUfX^e#(97T%W_KMR2sGk97=FWpF@{ zG<|>%$s}g-z>9z*fgs0`)UJ9(Xhm5y@)C!e$zsS^aE(@pl}{aKt+r|P)Z$OQUTUL= zzMOTQim;+H%i$>*Eq_Xh4T^wh>~ny3PE zf~UnmT)-h5Q|1LFN!U6E<$4G6gtx?BU(tUl9#;yKQ3!06*zA7I@vNAT<+>o>4EL?@ zlTk?~5YhqQA&eYb(Z`k<8*WP&4H1q-KNKGAZ-Pd7GwI|gI$RBLVvWT66w|h-2958h zp;+OyN6*8t!qEONGK7~li$G%)v$Jyo1GSb;Kqz@^+*_$|zX#DnYXOJ^BQ-+7d`?`0 z?B|enEfL^D?%u;>4gI@E>wddVTmV%5L=go)Y={8~A|r^2#a)!5v4w)rgx``E7HP+P z$v@?E7@BKxapYN8xsPa_G;Z{DHivkHY9%M9q$ZMMr2vkZ`zVhl!r3g-Gh7r93IumL z8}8(yTqQ;6ZluUk=Hbt}kbSjqPiv!|C_slv%~Gy-DeR&B@H{4-Up>6Y+amtO7*6A? zOEBN8=*Rr*K>HNg7do5Me6TljPt4$RlfZB!6ovrP4<`aRAWL@=0f~=1&TM#s4h(m% zR{Z0zMw~O+Z;w(CAv)-hOKj{=q;6=mrBqw!XdaC?HqG7Hj4T_~?Rz!{EdbS|gWd^` zz>?p>N&}aQ(?-cTALKY@4cnlT-hspNE;AI;W^JgX7s+{DPpcOzD`(&_&Q6v=FRlET zUw}^|T%EXXde2*)mzd(F4sVt^{(?TPgPL-#n)#C(QRZoMeL(v`6wY%%w}Y0ZkXGom^Yc$_$+R4CjH@nK7l1^HnC!4-U7l zyAyz$J0z`C?f(Q1rCHbiP8=5f!!la4b_NTOv)7VsA2`{tQtqe%>Z|WjOJ`d9(d!Wu z8L8D|{<%|XQ#2D|++n|VUK^gk52j1sWak-+wFo}QD6VDKD2ckn4@Q>Y zC~TdV4fBR>&y@WZ4Z4d%u~r?r^0SUGA7(r>Qe zl?83p7*w2fT4FA!`RY^a&L-{Y=_(VxuR%jv(!%J6q`jh?0R0-<4{1y_@h46B-G%{+ zbU?@&651U{XK?8Uav6aDXmu)2N_K4UR%Hh>)2arg*hAf7gT)b#=wyX@NX5@XT>rVk zCrySNB$?(DJbZXs;H^#P@ctCDKbCZCP^_{Md|zpZRok@YzV{T8FuFr?Uc!yuy2juV zxTMN|bx`N7@F7LiAV9mamg|!k5bQyK+G3sK7PSqZzE|@cJ;BiQ@)n*Pp91{dG`I7;X1(Z`?gz;HwwR%`KjGhe{@iky+Aag3*7uneEbkbC=jHx@MvS1?A2UZ6Kge?*0k znJ>Efdb4)zUH{OP532q2q(VpJP7ydw!DhrUpdq|P1R?<-k@pW9(uohV-xRf_2GqtG z`1ArZI}?2~f>ukMQQZxVp|^fqj0=gc`2d%@uLDo5?{i{!D1rS=D&pOgN`~=yTg2mZ za3zcX5*=G_S8pvb1AM$$8^uW=Y_hqz6^^rN#^YGEGCEZpW(`rxU-i zoqD~wcgH~{+O@%{(e}>%()VkR=&1L3TAiza5P3lEew7T1aVoEyruz{eKa!?OWek74 z_il4%mq_;0=HX8;(&qiV&@B1)f)zzbLNk zI@+ntgp)e zH2dIzP%IBr^LrpgWj@UK25=nbVG76`Z^3+Hxhh7-YN#sn<}CKy6*NPR3fz6gSZawB z$JufkV~o5~L%*!5Qz|xMq6&+NHe^BkyO?BEHab;RgoZTy8|RKQjZS2eqh!EvEo5C8 zZnI$s#s>v3FoRJQ%&Ta?0;)P-{zMtyR``SRV^-UD$)i70$;EpP{1KdZtSj?+lz4An zwpUR8Mhl9rC#R4$_ggIoTXe_ZjOQMD2t8O zA3h~GRZY(_5lgFx#atoFda{j@A=cpes!&|dNgE{>@-#jV!x_TfXX8$5NVqmin@ z2XAFcHp>4#bb>$XhHw;o{1q936ZPR?==WjfPQ!2CRI7A2qpcc?uRNgo{GIRwsOdL( zS=Gz|<~1OW6p8lQGKyN1H$%o_xOH3r&Olk{?&7WqV~f|A=Yw3NlW&jjs)^vs`S`8I z&=DgyqD5_gTOB^lrc?Ul_RuJKd7h6l+(yNcFBw=+Bmf)^48h~lOS0OMtcGzINTorR zk9ury(AHo&-_sFhU^IbhoRm@+Ok>)Bn+|P94WukMq4K&ydBW65pcJYeRH;d2W!%LYcX)Ap2kedXjKjlvT4u%Fsy3( zgIvTTPUF|%1Z$|z7%VQqF&tdPQxTn^dj;%D+UE``Kq2{Des?zZ{RjRO%Eax6HW%C* zp%`g+FXaV4?(=6${zWSvbVbW=41;(P1hE>_8}gAp6R`ZD(P;_?`Q<#Vb=QxIU&_4B z1TEctM+wU#0G>$R2qG5lgoTM;q_H!gk~Z;xCr(e(aRzcczNt6Uf2uQ{diAs+$H5q6n9+}$vB-{Cu$Jy`ISRt4NAU? zU2Dl#72}ex2Ch+(15)f%RBB_rg>(z9u!JQj-OiuBr?i!AUCT+NW)8K}~WS+km z4+j5m36d{eRievX&N@1s|Q|FxLW@pU@hUS?_;moCG(hL6y!Jxs3q z_lLXphr8#vd&E3^|2X_NK)m0?>(jT<*BIvTowyqP5AW{}@9+2Q{Sl)Rr_zLfi#Cil z1=uz}jfA z)N}`f&$`_f1wnf8N~K^~p4w9AT0RVXmqSk%6xg4QpQa!w(owM5PZ-M9iX?#;HG^Mz zVt7^5S!3J7{0wHit=ipBF?O;87W(7W+MnP*t7{+c_1sbI8QqDrttO`w1cd>v8%Z|6 z;3=SghcW5_<0S~JYY9xqQ_)~7Z`T>3kN1A2u=ee0P!^XjURc8O0yH~CXX(H!(-E1E z1CbmR00(M)P&j>h`0!?k5TM17a1RQCU*-vQ3k(zqR3gPF7LNW>y$-7{_}{(%_5ab2 z9{+n!24z+&zm#}$*Kk|x?Y%1VlMK!5y%))^Tv!wb>jLlY;r{LZ>;GJO3ua?dWlK9l z_>iCGS@|M)w{!GyG6k1>oF)JwALjLSvby|ydF?UT!+bm~${OgPn;+#TWm@K0wel{l z&#~c;_tt|YJq%+7b9wrwTH*YBZ43XH&dypx#trXsfx>FsRh^F$pe6ODN~Y;GU2I)u zmuWeaH)WmWc$vnuC@}FHhSU}lnPG*(4O7ftUDBOr85A9|-Nq7hb6MxC$SS(a3>_%? z7n5-&j5-48bU{@}l#>uENP8l6hp;mFcs#4=I^qlCNK3R(|3aSmuz`z$m_N20VIXq< z1m7#?2~8nxLMzu%#|ytdAWaM^?E7SxURM;BBFUE$QAQaP4ey#Z6Vqg6UJU0ofHSLu z?O!$zUiXjo{<6JG;kwUSV77m-y|r`5sI9F&c(C?dRhkobi||AMD*UOVZfTBoz+KzV z%5CHHSR{TGtIOKl-8W!8tA<)_@W7*G+i5vb{SozHCN4?{`p28GPGIE~cS^xCX9JtY zOrFGHoR*()_^dcA5pT|L^fbp^EVlv~*8Oh+rt9(HT{d;H3kaQFa}xn?kK(F@>;)El zD5r5$n3ZW&&7Ol#*V2dH5wk&e--!WJJjYbQD7NxKVdS#T^)!r#);1hgHT z$;&<(5V&r#5rx{x-B~&%H1QzJUoDiP^1-X@oa!?lfdwxacokjL8m9apmK6p=qEcPT zC{y#`n&p!Vc-pYf*{UfwvRqrBs{_DKpwmhnCt^q(_tMoi>@ZCe;3M;Wq)hy@91qbU zrX>gkIjJs8XJkZ-tvJ%E7Sn@*$|03IqUyWY_0A9U?Mo3&rqpoEo#tzcA*P@F?cYNO-A4-xY+N2o1ewChPM>5U0(YkdgR_k{g z94$jy&VxrYh8D080h1sP`H}fXP9fF-U#bSnApHwwpDM;BZwfJbt+_>`B-uv4L1G4^ zqup_A<-^bxDZ3>O)6u8B(@tQl|E0N$X|fP!$tsI+m0}P<0ZU`{5{F4{QH828sL)&; z8Id(Mi8XnRUN}x2yMXq#i(;8Y4$;KWlcD!sn;6CoO1>1Qw>cc&Zb{0Q{nqKW{upu= z`XEG66k^?8a_&Hvz!cA$eFx=2Q7#z%f}D`hDjy!E;0!9A^b}Q2PFr>`yEhnt`OlaM z%KT1cb|HAvXvlbLMkHB|lS7*zMG(%Bd(^=C3PaNL`A}Y^VN;2-WJ+>}!ni%XW3UKm zpbcZZa1f%~lpWEFo4|&c}nS4B68UT5B(eONJx+OMl#ljX&?)ITG&Puvt%CiNx*#r-BTbR=<*0SciqLA-J zjk43)nRPBQsg_)m4*z>r)!Fb!Y9f2tqTv*@Itdo1hz@6o_pa`a7 zztnZz_$;3{V+e_vy9^`y!Qa^kBBUb3FDc)>N1_~&BSuT z5yCKJKsm;NeUM_r#RH!v*(H7AFNXYgk@iJG7!%#{(6M9)%9 zazNxqH=~|aNcJKyaAs4gw^0(?>jFNx>IfO@BCxw;+;AHX36$g@sLL1tBUP89s5`is zm{haD02=FYWR0Be4bwX9N{L?{q@z(Zyaun-JIqEI?QDsF0eO=jj4XdZ_LO(|X+WV- z6!@SA)IlsH@|0QcAOE0+hZ)5a;pZNAquXuRCGgcx`!R@Y0{#;Yja>*IXRwemdcgeR z4k_egkwQMsJWuP}mAC12R{mF37AxWC67?NiSn`H%8o%@E{o&iCwdFPB zKsSu%<;Lpr)8$pNA}ZQt*=QWE4HBCj$hBL={UJBu&ToI03tPTHO&URkt5k2oDj2oCh4U?i)#>uRlUW@@{%Qyo2vrF&Pnbl7BR^c z;r!Z0VXm%>&LjY-1OF!x=`O2+%snfoMLACKzL#rYNf4fsYpzpyZBEncQIR6LX)*u{ zT8xF*$qyJ3jRX_KvCyzm^cg_Q43yAtQ{c2DH^8c5Rs#J=@KV-MFn}NNf&wVyeLiRVKOsr)I;g-WwD=LW71NMmPKJk@xKoCSi>aeU@QTv z%kx4UfWTNQnYz&Eg4a?yOsBxI`}m74F2FysnnKi}x*)RD(kZ5uUQS?^xtxf2tR&6L zVOd~IRf3d;H)m<3gS5(QgskW=g`@m&%xHGD_RM5UsZ>#aqCT;h&i^QwK!<9;3y#dP zhS&(@@aXIVwFqQ*NdmTVI1Q0C6GO7JVn`1M0pb=9FXUI}oSG6vS77dqPE`(U2^CB^ zS2&@f%{j8741?>Wl@LcYX)!>DR7Hdn1G4Vb<^Wc%IGdalC>Tf!SFNRNoYf10d3 zvw!wP5KCq^mfepsyXMFcC(7JAITL-C#sQQ^Dtl0}pr$rs!IXS(4t+;O0#n!RpWk7W z03f!6e}>2S_F0uGs*$x+rMbttWAtsok!V~fdiJE-MABkb8#EQ_4ph2N$R352fd>U7 z7+v?!iiqpyz=QxnZ=E80CTc;osu=LAX@Nl$f14FG@|eU^n}MFPLDKNyCI@Nzu5>Et z2#qvXQY#Fz5pw6XN1LznS!TA=B~=mzfuz%^snlpJPO~ zb|z@T$>pFKZcpPfMFv6O)3T_G0n9W`Ga|B}Zms9;5p(Wab5`6`0x&EuayrR@#+>k_ z%W#IcEN8ZX-H}vxcnwL9mtMcgvZ|TS9Ktu)Zkkjn+BDnaMxGU&c#}zG3da6TmNf`9 zj<|4^?^i}(w_t0RuS}5>J#LQYT6-33oE5a3H*nTm@Donce3Th>a$;lXdsDxaGLDLc zVP8)uvaig&I5O(%P3`E7Y$E7kpl*(r+h0>+^zGLQ(~hJzExUqOqP(N{Eb5!mTG8!1 ztq$v=%!W6kU6fC0zTQYS#I!G*S&2XJB_AxJoYX)obm+#_S>==K>r}8QbBEB*TMG{z zv+cAJ?XIZsl|5!>>Ra^rfZeul)@}6p%1lK=pUrS@P!2L^yBx9BAmmn9Im;vju0rLO z*~ldYye}{F%DuKMuMU}YBu{@Omqw8n&hPExe;^s*<~@-9<$xB1W+iisnDD!+K<2zs z6w&KJ;=HNHjp99Up${ZhXJBbK`Ahl~Qz7w;Gk%_&`BS;D6u5d$_CrdCEbgO3jo}>| z2nqkeeB>t8mhmVFbjt50hREbKC!mKac;E!f2kbh*Q_5A4haC!hF_`b^@I+2y8)pe) z0lASigzPmjLu?#xV+>p!{4=+;xE5;giDXwte?L&N`g`cFz~&aZ{I$#A0+aI2m%#%o z+OqAya<#wioLu6a>-ppYCKGJm6hS$6LN1RkTCQ$(BL`PCdIP_!(pt>s4z-rqxI|_y za?zre;k<{}wrp=1&o>*3QaR85-fs#ojt^qs){1nf0bh4rN{h>4?x45&)W);^S`Lox zrF?64Zod`tuWFj_%$9m>0DPN#;@VwexMfNR$XuSJ>Kdc1kdecDa%PklWD1a=i3`8XHvAAEQ4ooV*ZD_NfX_f zQDg)$A7lsA<(p~#HX6MECGz)dIt5cbS<*^f|8<5dof8aHUfKDP{w{9pmr!~QD6j{O z{+DPp*^*81J;KRs3jIJm`ega}@@f~8K!h>qhU~%r!)zVyCjauvtj%X2HPUxw z`(SJB*;6x{1?81`z_;}7C}Sc9@K@RP7Z}7cLyg77`fi!G$nC^OH; zyv|NDq^R-g5Mw>Eq4n-RX4%YovCT(z%J|%Tp;+BRVH3Z*ici;TPcMoEM zMs?kq@s%VFK1!Jj0Oc^zSE!Ui851T$_mjBo5d7jnnNPJ}Y|Nk*p|aqDIb;^4IzDx8 z)@&yDqq$khMPJqI1#L@VPpg`e!eH_l(#e%-T>;pI!Y`6zjJXGma4g0p5zt~ld70}1<`ibd7mE#0c-=sRKM$U`$c9+@KG}DcxqpDb- z#o!oWz#eTsHRUDYacilZ?2+^IUIPai3qHt+JV77jr5LqjsiD z5hec_;5}Oy;esC3EFaPI0?UDw!kbe$Wg84WqJcRjU25vn4$w%)zT)j7FY6hMs9G=) zJ@r<_7U_)eFmJ6tXf4y(sD1%{!~wAo2FTiJq1pya`ZVoA;sz8 zuLE(V)fe)GvBG6aQA?G~zJ+o|>FqJ1ZJebPx~3XFAy*ZBPYQQ>ze5f<$p0mJKP9+O ztW63+s!BLVmk@qx51sXq&QyGg z39cf6jvz;_CxV4i%I+d*u>sSQi{jt^HY>{6cmqoG#MSV}zN$N-%dC(ZkM!lIfJ0^K zKkVKygA0IIavDB{&Y$AOyofroD1{eoZ=R*dpuGfd=6-|G*^lro0g?lOknFxW5^alAinOSRCi?Y-Xa*cpm$L4o@w3KNe0015;5p>Z7|!;S}hFFA#+Zo2 zcQ{Q03!PbNm(7G&9U*R?s5PA#=&_VtV&leJmIsa!PHRI8fm4(L(`fVYCB6#4%_?Imlwc(#bw7E*&vF#6w~ zm7ZV@f>f^d_MAiYZqFh%4@q1zfpbR%!*^=`^NfN>(b&8a zIFAU8%XyM8`b&U9-U6IV$7Qa=-5wPkok?sM`@~heoTe9pBTepN0r8T(?Xx>z#9yGQX z0dT_VICfqE!j*Getoqg2llsC7#&cY;>^GQ!SyNSW9_BG=m_J)?!|>(}imkG8#=w#x z(uaS}GiiC`Ie`>YYxcCS;#$m}bOlwjL*dlgAXM`ATSXaRkv*@TjMN`l+R{&@pXv+{K33Z@?`r=j-B-?bq?lmOr`iM-5d17Mv$w za$!5DyR6NY`5Z6oZ#&fG>LPE<++Ih}Mja5$w)@?&EhV*tCqh9?Oz)H!B(sf{x(&H- z+d}@*hFg%)c3n|8MS2QwDV$Br`Gnq_3_Y*l7Ad}<&u}Z_F{`9|DVB%^<@K~K&dPLp z4y~v-h6cU4DC4@fhuw&R{QjnQh20YI7G&nzCH8N?_O~)}H{tznI`Fp;@y20elo7A` zRzYu1-JmxYiEd-mn-#>iRgA~Q#5jRUd&9bf~fWg=%DBA}Vv$XqYqxeU*8@;b9Gr*vaBL~ZkCPxG1? zS>69y7xG*CI2&=cTBLQd)*iV}iP#*+wFA{l+|iTeK&R*xg$o+_#%>dV=kz@@LyfYF zyqHxY&$j*m)3jG}Ri~VgqB;`ScABYjXsl_!)taf!ovgbn7IRa5w!?5PX6`0O3d#ys zH+iwkT9k;dbYW^%p>W$Sz1&LgXvHq6)RGZbiKaW^=dLM4>^Vi=GkA2`+Ez8o0Mz)p+t~Dp#is zD)dM+5{w8uJI7|PMcO2Ugcb5ZK215PMXH)bEanaFkzO4QFKOP&h$>a#ixB9FqRJ*w zJZ07PqLg}vgo zUj0izx*zX#yZXxPPQDD(SiL%Z^f-N%JzJyARe4IxI0VFbECY5$oSnh2A-c{Pcf+JW z3i~mE*%xu7*;~=FPFUM@L6TnZ!AW-qP2}Z7Le)ujG=O|a)puUYJx^wUlZ+;O0*^8q zy7kyT9$D@NZ`91MOS7jjI^G$oxB#<{{%%A}|(^LXF>I8$;2NpZQYsIhkSs^69< znHZUh#Yp%3Pfku#sdaOA28u6<$le4~O+fKK{LwIXdZU8K)L`hMDnV|<1(ZVNXaxl^ zuNt+&E4*TAj%ujL|4|Tct|U5`&HHA0g7BQjL?1pGe>EwLlfl}bz8^fldxb$aczs*7 zQ6-z;PL^fLM_SXIVw~_jhP7hwazvBho-c*60)vRP9U7)F^+D{>6JQT*@iEjeYoV`f z9I+3#e1|IQt61))y320#78ICqItRnc+ zh{7Ftpx|>pSza?-&iPm@;(LnfAt$rWYu4&ZP$1bYCQEN-lQRm*qkQtop$L2KiQs)8 z`&ginC=5R;hxIVaRA4lik7}9r>$BOIf}*!~_7CwjHuf>(!y28GE-c~|b7AdO07Q3C zj7IEQQ_OpGDkRS4M5csoLZ0WgUtNz+icu5;{(QSQyr1N#Z{VFcQ>}S0>AXMK>C)oo zF`>FMJZ7Au7}8g$r6&5KUVD^pMH&t6y#vvU9Jr2Qu!z{*Y|3{aY= z<#<#{(rY;;N^NF=*0Qa`8MN4CSW5B{j!(%~!zG8h@YWi5Nmjab-ZCs%iop7^UTe_r zKFiB8TVYODRURk2QeP#<>2yjr%MzyJbV7+sK}6;-KjY8W(xxL1e{mtE`&u@3>)pU* zb3WezoT~fOg@VEyoBhK@Mc@_MUaP9ikKMI<_ogT}N3Hv)>_4Y4mAJIjOnN0>ObPLD zm+0;BeYHpz)kR`Luy?A^rMmOh8(VCGnppn-?S1QZ+enh;|2b#g0joZzin2)xq^_1N z_oyVft=aNrEmhU@*lrUfK?!Y=U;(5q<NTb$`K zMIdjH5s_a+Mn>|rvBK;v;uKZ&yn0eYTDj-1V-vx2;0Ohr`wz@V+hT`E}fT@M9 zXCaYsM#kp}wf#`Je9s%RubK$>8zx;5{cM^qLlgF|COWGLNqD{M3#+7iFS=kBKIeHP zBQ%o!cz%rz)yV*E$;u>2;f*+5C(MO=#}B5o7bsri-D;4oq!>MMpcn!kl`iK65v9};h>)8Z%>m4+x)f{K1Pi?tN#k?rKA#+(x0_rQ> zU@C4gQ<-Ee_#Yep_A-oGcj(?l1RaAQil@9^AZd&)j9?NV&#I>AWc@AvS4g>7DJL=u zHPnnYuTMvTNmEg~Y&PO~3G}YwhDV+Y;=it#&^{FTUxYpRhp<#2EH-j+SwtQ`PnM75Y)5p^LZ8CIb0E=3zo~?X2|1z72oN5f6qxC*TEw7GOd~tRZAZNH zrc1X20!H!if&dU6SO%S+I2GamxFbcr2PuFtz8a(7PHtn$ZX++K_UITioz8XSr89Ug zP%oTVNV>B^G#LUqfy@EaF$F#O$Y_{E_hvSP_0;PIbQ8?)Tfi$2>*`m(<;7^aHWB&@ z=mR>?ISOK#?~RC$XN#n(EKOq6Lt_pDN`q7OlL`WmSYVztiQ%;~AZb2jNkm!R)P9=^ z`QhU=YF_Ao2!>J9xk>(6#@?Cy!o7%<%U1O;C$xVNA73VAjl9%)T)+a@!Ljb6G!F84 zHV6Ku*<|c|ksP&%Peh}&6`6vY!(65y|HSx)P32LSl(SuCn`DycLB0_$@R=ymGhe0& zRYua1QE+r*ZhSAvDTO$viBdCW3?QjiiYm<#Ux@Rf6)!FS+8imc5-lbq5wIj=K{41o zzm+wO=5l0Cz>8p!etDxzP{G3N6lvIvsnb4tCu7G zG(DS1SAZH;(fH*_s4D$_Upx3?uh9QjCiElgU`H#1Aw+iT zAuhu6tsIP;0G~0{L$FXZNW78?Tg~$nW-?x<+4UD#*~s)kWg!YZEb2hGqz9mzj!1%Zqo@#PuLL?h==z#C8LfQl;OYzk2)T-R1G?OP#^!2tKAT z2AHpkE$VzJYIrz)4h8`bGN;dp*Rp=fr0^rk3!f5 z8h(yx3o(p^lcO$wm52iA%Ko=oTw4w2=`i^0JAWC6F|>g0T0Sb%4}D(m$T02WGS!L4(ciQ@7eH1s!8E9K zPVeGRuR~08G7Nmmr3zAur{Ln?H-AgIXpHOArMpqq>?W$@ge7W*k`i4Plp<3NbGHXE zGpoqjuDLW(r?3YMDmm(Kc2gQ2_z_Yl-59Am-=Fe}#i^{{`I8~Q8gjehI3(2g9$k_G z!E_EO7#=rXN4#d-`hjDlDe5Tb)1iaom?n{;v=S#Mu1Grj0tbmBe*h-KD94Fm5ogjm zIM{g)f8oC$WdbD;;D~MYLc@^=^z1>anAkC#&{WrDf+}=m(l&#h!>f=lz{INB+peqc z?o}0HFo3u#Sre)*tAc_fSQ9ZruMFA?Sl}Tg1FrQp;XK zab*aFoB~+pK5mZv=~f@a|H{YHb=_fjwbgc8Pqy4ATflRZ2A%F~NK6tpWDgqS@OJC{ zkG>aSl7Ptnm;=0}UOWVm?|GQjl86=#bIgMTSM+dOMz|&Qdf*9X9BLR|%8LB80mh=9 zh-^%JKvh-q<((??7rgQ8L7?^wjpUe{xZJ=Cn8C3bgj-+@-rzMWt=5**Z-_6cEh2l| zyq=DRe}eHgpjd-8rs4*#GjW5o4=*fnV*;ujbkX}c?>OQeP2j8#Mlga>buv?dVPr_y z%|dA?K||q*3=guJ8nV-7QwHZhKN5xO&W8Hz1DbkCZo`oEAVbtvk8sD0SrD$*TORTv%6azj_Ua#*ykpY|PS&q`WUy6R#@_m)%s zA=p*sl%h9z_xRMa=irSSL(Kc>bntf&%wts*C`$}(px*^Z705SADN-+4`yr)(Me?h< z^vVW09vCu5+;I1dAXP_MV?$_p)m?t#L(;>rk#wY(pd5DFeu9J%M~gS-TsKkVIh}j|HRX+*%*xc2CN>9 zt6>N{*|_ndfI??TGXG4N2-C+Nfx2jNcGo|_S5Cx?`VPy|@A!wZu-&CO;vM;P{%8uuGrxX0ki;zUBKi?$&#USNg=FuiZppslcgVI zW-XhiKs+=@#_z0gg3ZRh%2cWfaZ1SuRhWasi*$^Hr)t{Di?!TWF;SrrD}e!B zH?%INn5z?>i!L;CDg#xRRku=abi@Lm)7cexOV8axJ)rRfjbL3|BNp>w)j*n&{jgPP z3DutzkBLF2c}=}8^oMGW75DE+e`rdts7Q*Ap;fG4768&LgXG~+wz*;SNmQAFrHRpU z-+0M85|l|mRr=?lMsFmLD#I5)3I_K`@OPBk0(UhosS?HEs$JdGx7Lv&(KQ2G%=#Vl zh-`KoxV@MIFR0GaP$T81u~aNZV@a)&t4@sJR;o%;Gr;2Udzy$9^*{-Ex17e(V#x$T z`urCbN1Zdrnh$ms^MOhfR8}MxPh(0N6D?WDV`99&Gl~2PbMf`0a`8--7D!2-Z!eOU zAqR4EYhs(x@YxV^q3Z~DIn*vOZFi-!unMGB6Je0udv>5C_WiD0_x&cqDuvH^{Izi*_#al8+q}^V}Tj+i;%A4+RWq%-K?GX}MSc zm84fN@wg%+R6Mp28JZw40yIPJ7C5~Vq#;5izjF^p-ClYk3${(kc7YZc}V^#hM|dO zy#Bzk+$q9+Vt%hJ5>cbE6{U5KYz6~C!14E>KC*(EaPwOVs-39Kfm~@(GX(5w$PryK zw3-}!U9M1sla&;aV-6KIVG4sAT%l?BM(;obe+~NE);>xqbf#&@o^ZkH|h@W(-m(y|DAqJBLTk2yX^A#<`g-Ddq;2h}w4BT%kAX=^9g|4V9D6JfiBw z{IXi$7iv%cZn~zxFPX<7)0TC(C~ZTrBEm2M&K`nt;dSwLUs{nwx=FRyPs;{0gm>fM z^?+LEJ(3yfWF{vgrUp45qaul=onNj4=1`a!+=jjKaa$FS$*9eFst-9-XOW>w@J|-a zDW3QdR~3rrbB~k@hbZzbD^4HQF7qjBSjxP8{N{CjCKp^+f(FGuy752Y@7{;c;`b8FHgMjozvhdzyzunGI60yA<8Lp_NT)qzJCj(fXk8eQf_SMkmJo=Gi-HKnh znDgvs#7C!!g>g;5SufN=)9Wa_rOwt8gCUSmjP?+&(JN^6nFX6-=ml8!DRyrha`lH! zpJI-#wW;qY>{8r9ddN9V5zhIrK@)~M7gRte%ukwYr5of4D&MTgeYRrj7fUq!ef&M| ztEAdavBmuJV$x}Wawa6pqx)dtiBb4Qe|MhswzQPZk__~{KLGvLviUf=tPX5suEPE zlLt{Zn3BR2v+6VDk=%k^7!V(GngC(J!O}J}ZbK#FV=xs`S{{R!BVzRpOUG5f+0q2} zad#aZ05TgeEDaQGp-~E^wV@Ze1G`bg>i!tkVo2Dz}*j8jJ^rZ;4 zsVDSc)~TYdKhgfjz1@s*ls$=_=Kmh2e#hqI@}`q~yP+GMl{ z?nZYrYK}~`!qkK}13Gkw0eRB1&`iHwor5CM?g(@>sDacS_pa@3<~SzeIVE;-OWa@y zq;t)!7nR(DlEr=u{0JMzU@m5=n>yx3k8{@2T;!qHs^)Iit=9K%yHNhIF#fSH{%2Yk z(~Ch=;YyI)G?gMDTELTZd8W%zR%Pf04cRtLATDY=R33WKRN9@BQ3P+`HPm#Jc8BnI zLwDnWb%HpC!rGz}b%^Gj8xWNE8cgekURA)xANIkH^>KNb`oo-bIhNUA+wPMCJf%Zl zxE+IK*Sz#6ud%p^7tQyam0vB}Fuymk^PT*m=HBfOR{NOqE>Hk8Lf>jKJw**W|NObr z-UX!b7?e>Cvn*PvN-<9~k8@UHoV*!s7tinRf#h+dK3SiMES-z53A%FXJ^%U zSw`{%3m4rav$O;Xmug$wjU*6+9-_bzbnulo3MBHVZ8o7=odAm$QGStjIRIBDVRfQa zMkGzlDulZdcg_n5CeDP)bN=dMZvc!>aOXj(MX3?507A^VXcOJji}c{_oD0_I@33%tO<8rB6t5iw2h9bH`#kiXD-7R#sS;c+iE(VoU%ZO&U9K zgW;2jxD2G#G@DE`e?D;T!&xLZRa9fKff02V>tfR>mJPfry4D4~MBz39N5F#xah$mwi@9=04x77j0mAhMXtck8NV})I`+H~m+q?V6JG*Y{^z_BqllF_9 zy}g6h4{i52yRBZ@O1elHNNE;I+Q&gGWT+<7MX0f>jcru~cRjfqx>C7Ji04O!S}C*# zrJKMfuc{u|>Vq#FyR3yF(zztUn-)q0;Z!_}_%(u&7}MRG}D z!^aVpPhF<^kO>vo(qv;@RW^yj{*15I0i&!Jg7(G)pd2;8$1=mQFMR`~N~SsIq+#7^ z-Ugq8t-r@$Ax4wl*74i(Kf$k`u;lxW{MON)z<<7Y^Sbfw?TI5&D|oTGybu@d){|Dg z1@T3)S0P{ITY(8SnI9ar-A==ZZQ7KjwTV4=!B`lG&|RAH#OpqWYV`De9wvh^SlsJ| zH^y=zCSPCvf+tLUx@7sShpC0}EcA!F){}ynKK$@uyxsn=QRks8mf6zG0}}fGIo~Kp zKq=0tVrFq(<>vJ?4DL*!6g-j-26_0ZS2Er%pjQ)5l5025Ms%K@P`Bce&nQRvA7U}nvc*N;!|JRIzf*OHxW%Ie$&YY*)MEn1Pu5f!2qLD z0n*l~RWLS1<`@-srV=^nEbCLVZ^1P7hl3`@CsM9_c-iMDmt+APZ$k{Er;3YK{d+FO z!wbx;NHV!bFC2A)F^>bYoN6Hu=uyc>$E0E+Do=JORz$=wE0z|CG-1YSUp}QI=;xh> zO@^@)oa-mlh)E7=6|<3ze7!F)AkQ|KTa)zbNG8tLNIy&GcR#qoKw;V76rI~bM`EZY zF)XzNJw^6XdI7D?T>4cf~I8at`a(&o(gxU@C%d{b`1OlTqYT!j?jZtvt_vu`bT)IHTo_M`$ zKc5FU-ZdDFW>ZlS9jI0r6DaRkYHr0r6}`gajxdHCv&Y7fxxS!f5#!@cW%lVFZ6Bq3 z5e$+|z?bor+9Q-psf_Z{z5R4@eDd<_^wa5^SI6hCKV6)?J$`q5`R1Ki?&KNu;({kH zvE2EoC?Ji#;sTd1&o7=ztTm@&FOM(q_1DL*&Ys%7{PWqni}N?H7r%e`*SBX>=&441 ziY55Ms3MM#uctubIo%jK41N=~dX`T>t*PJvp2vbM+>!6e<*tJrko!g~qLc^8T-sDw zyG8d;(h z&fOs64dvHJ+am+*(&HLdwrRRblBIqYgv=I{E#{R)OoE^|QB1#vpAQ?Xa8GGU%1>-W);D{@TLT`n*i5U8wuBtp(&tCnjSgt2nC^D69h2dOzAavwTo92 zHK~I^Kj+o7?t~(ry0c)|KTX1+nj~D^=wvIdjZtgP&FFW@Gi_q}7ug zY~gtM3kT_s)iK|tRydR|*0t|h)P(u?ku%_{CJoQH77g;mh;?Q#!!ukw_P#`v()eJJ z!DA%_s}R9&cI+gMHC)j+*o%|d0!Y|7Vuyp`nnbfr=LLGw?>vO$*(JNv=}0SH{igga zY%PHxrEH;E?p&+#_%UzVeg!z(ygx?hcj3dJi?r*B!a$zkWmqq$ke45P=S0?^uM5{q z1Ak;Tir6C|_ceHYd9gr5mqKNhrp8=1)SQD{`Eta4O#8s{G-$&8v=;BvD?j=?^xsBd zIQZr+s8nAT`Jocdrpwf^Aw2dd@|v09eIPg7igOwHggV1P^6-%}#Rt;=z%NK?m7BwT z;aUl2e8NboBoT7Z3rAZfF}6n3WCLq{|IglychQT2iQM78XN#8dn^U59&|Bym{&g0B zg+E142^q`MfrVO-FXHAts|)FLf^^5b2?Ny<<%*6yK!Z99K(hez{UQ8(qz&s$; zrbKIuNu$}kVb=&#lIN&LL+v6(sK5loi``3}F=+0GIUV1}PIeN^xCh;aK`{){q^hJR zh7>*fVH`Y4EEb4vct=edN68Gn*3O3_C?+!ddrk+((2=Y+QFqFre@QveJju@3TU8?m zws4+oXm#4*B?5a~$C`<&b^cVDsG&{@8`o)LuK^ubIIFa5lEaBciJ70Td7A_OCVGo) z32aeP1H099&cM)B70O9wHX%v#J-kX#{0`ID2u853#YA_$+Cq+;8Kn?~vcVvA@B5F^ zcA^0r``OS#{TKGVcvm5v&R*zns1Xlh)1=l!^;{9aQmlU=usIQDd`(OC3lBgB#m|ou z+qcP~Mz^G9s8JeJ7?r?YkTmP| z31g=IxfK>0!8H2g!*Lm=D-z<2SupNX35?+lCbK#HJ%WBOxDQB87}pEbasHir{tuaU*rl}mDEVMOMEYE?=t{DV$uCN*)%jQy2~UNVmpj_PwdY-LutYJNs*>N3ev49XIK zO#q)^HER8&RB5Y7zg6WL7XV^5Nei+WX9@y8zH%NoS=B6e(8VPA0b^dE`bdL4j0b^# zc=kOYMwb_c=jRUZd6apW?5K(cUVV8GCDLx@o*xqyj!r>Ldcmps^@Iw)uX`du47)?# z{bU8rMYXd#P}A6|I2LdAIWSP^nIYiH@*==Qh>vzl*P+%aAB~uvBz>HxV`y-9*&Qm` zH(^I~-|U>?W&fn6%LAVLO^88RPq# zo)N}@`Hr;P)vW2dnX^P%jJd0TWoI zAJ=SP@-Ki*mn0$5PEjI96{&uxE~p!CZfkL!U3Wk8Iw9jxZ&xh2==C6CG? z7BLYHA6$ve+>`ncS{AUhm?^ycC@eRC0ZR5Su~Tl=M}|XuPc<|A(u4?_iC-C|XyQDb zOXDAA=Iii1N#L0+)$s+BGPD8NB${gDk5RCjLL`k4JRbrp#@}Qu&{L3PhDtl;DqpK# z#gRx+SfhH1WUcbe7i2r5xg4tavekXB$3VkHxjHK+?%NfC-3CVJm%E~LVn(!ajQhx@ z18OIKo<#L32{E*jAV3dslT=*22YE)Yea%jz1*30nMnnyrPL%35ya$MHHx@s2x}f1f z!YuCDKR?$hYUb<|f?`CCo@5}VpB0u+eB`ud2+}`7DH9wvHq~N00VzR~$q_iJN7+_Q z5#or_=}IBsQeKPnQwa)M`Rwi$anK;ETJ57vdUpzqd*5%J1%$ss$vStJG7JCoQ0}{>@PE}jzHju8w?0MZwapB1=u>% zElT%2-O#%9Byf+CXpKAUc=kCxyp~s2wbVFt8S{PRd*TJZMv;e|^=WR9_C2qOYZ(id zKuI?OS6M+SUCgOpPgYDY8w8TaOvz)X@}x+BpVqYZ&irf_ma+O_R|! zq&tJxQ-D_u`V<|jwv}EKaJ|%ede}<^dcT$Qpn<)aA{bK=aNUi^BKg6?o)w&G zHY^$}XJA1ck&V6lq(x=6eXlW38aAJyi>#$ElcL?GNr@qD{iXdEi=I)1Ra(CAw=xxS z1;lXV5zoz|b92D@NCQtI`0{QB?SVy+itc^_3P9XO1&hQP;#v5vD6?8ClUM>oxe{U5 z9L-@9tw7BXmYDkY=v$)a^AkAfLNVKteZs_=&B2rCeOYvW6~B(I@oqj{bMA4fG=`RwnA(YK>Vz;_!`g^MPwSxU8>X2JuB4)8(q}5LJnqXP-;AH%`ref-x^HnmE7TrI&PY#G#li)Y zq63i;@UM-pZ%Mv!Jl!Yz*%;_YyiMbUhDP}9;<3*wBatSFvod<(SRC>;s(6t;jTOJ9)F=K_b zO~X;|PT$;4kG)>m7s^p5J$?p=NDSkwBiezu#&DV&sEZdfehe4}L}LourcjG554;T9 zyJ|VTdGI51mPVg)S?5(E>%x3GCy*Xv^VGz+a0i+DsNM@E=-m=; zxNUp*4Oxl5%xt__xmwi>nxlQu#-Xl{!h$o86YL6wPUTb*d5LdHN7rY=x| z;*?AnRHJ|f;o!b9|6&vcdGL3}4$e?a2y1_`7}^4#T!!mS+9?t`krz3RMWjqD@E2EO zxl+*#r~McMnI|1PgN!g9Y zCUX=H@CEiAq`1`cWh0ygUNFOo=+e^%e3t#O;sw1f(fcx*DDh^kF@DVSVx=q!i2BWL z#G};U+C)eMC2FRhx(bWX!l<8)p_tE61n3bNbmy7kTb%@vp<2CwH8Bya17focA&UEW zg%fRf9}{FLb9pcmENm}Ee`vx{oG-S#ld>ou@9)Fe&U?V=b}C@G^{@i z-QDdkq`kfEyE0en>ylbnS}mq-{UI)mc4`YO=UGktMbQcr7}0CQ z5K*>wP&O#U3Z} zwFgKYQUHy zVrRBaJ_~NUvFFdjnZ_X_aj7@m4HbishgdlWTfbj)?HWYa zRK`@F5Erm}@e#V8-J4elR%~`UF(OKT>jE<-Q;w)aYM12B;laU)!FI7b?r3}H$#I^KeOHTA0V_1|>f$Hs9d+913Tjb(Nl|X? z-(X{!ctUi>BISXaO}Z9H2gWfT?v{arY9K<}%jutKSXd*1rjHaPLN6$w;z#+3H9+T? zY;nR6Hf`ar6RN~JKTZn!~YcS0R$`BsZiSkJ(ap>WsAWg{%Os&j4-V7Ae%9N zKW#3o$tmsn1!>GH_FVrDF^FnZj0G*&YIxK&xT;us4nsErs(#{(!KvqP3gVkhJlPnq zf>*8?F%x`o%qsNB$OO%u8inCX1{l35a@p9uLx;Nuziw!)AlAUD-0MOW$gpq?flURJ zN067~#rFgGXA4<+C4+pp;#OA(L=~v9a7y`OzGxPIPwv}?4X$oot%10en zjdb$dfUj~QZ*KjRtnw}X=cz9T;SSm@0A~J|)^=jws(_%K?J;_>x$c!3^Jhv_1m%8> z%|#>(Kz19rpeyO@J&#n0yBLl(fFzID|z=nmiZLn z`4|Li?%7=K%H@;UH4fRwd#&_9G|3B>b_>aVCqv6M{BvN4yFzk81UaFKjKz~!%MzM@ z(eMFep0wcMSCA|%E*kuifo$O2UjnHe4@T(WNAOMFLWu$*TLd{9H5J!PFe6GSheyI5 zJ1;$>V_8eKQP`y;>!P?pPnB;z?jCKkYGhY1k_>769; zEt!8a^#}t5bmLsS4zkTw-UVg;rR8If`YQNU*`;a`P(csWfIyM2cBdFAAm^F7gkufz z5k=yrJMYGOoF#tV!&!Wo&q;^ZLu@2zkYbY%m9wx>bfpV->MIH*@>C)4AjDw=$>@%< zOLHBPptKj-q}vfsOPk0!p`8Enfn%lkVq z;r-22Hr<0CP4VJ(+?wvmS2u9gDjvLX)d6otFl$}kVm@zZZ7(3d7=OZU!5aBcRzC%{ zKDG0CM$78Wk<96TEhDdQWIeisw%S&Rol@pgt^VP~zPPH3TyDD(Mq3RNBE1~d|Dd~9 zIp?(6N!Pq--@yPB-8EArnQwYBzLn}%MWaq{Er&0fn5WjYY-yuyVm({Bb&l3neb-;Q zR{7XgJ!@rGrE<_HP!(AtlT`)%@pbB~hPxwEQ06+RxqLeJdQOvL=IqOpvw5vf?fSIh z_$yoFNqthEU?8QFT!U+7u750~==Es5&w2ktS#z6pH12ymPsoUGc?od&;__$dk(1s$ zVL0vb-f>c{nEF@0TDSZU=ee>4M|H@cO2fqRAMKK7*eIuR8Ck=QOrF`{Srv_%jjwC0 zOq_0oavt|amYdg;(Gw~a=61i}-ToOTZ>X`GVRGfZs({A{;Wi4_03OkowpiRR-!ve} zCRL7i583Z-_9sbHz{YP@KXC&B&nLQmk$hNSG(WgnFo(>kHzt{%{%>jY?~GwiDq!FS z5)rySB+yZ-W8fm-oW>=?GNY!@9>wCRrOZ&J>oC6^A_RDgY6pj*R|7UO&?}Ct7{}>-iZD%jtw?*DVa3Ft| z;bahw^ptVOQaXHtZ{6L2CrDbX@b^PJ^+J7JMpUO|c2m+Knd@56MRhwtgX{b@x74l0 zR=O-{UnPuq^?Zo2_<#pX(N``l&m^Urs3}=VIWJ}4G4!dpM^2IqXd>L*MT7`Gx%1k> z4VOhwoEU*wE{9m%>F_R5`n?}~9P$twOI_L&FFU;dK0@k%8?SVlXO5ss&0OuzAeOMQqef#o5m@c*bA18{d z_Lc6v^@p&o2+mC!576D0bq|v+z}i`xHrkWeE4P&H27N0~nq1o`-EAQ&?fWo1C1QIaLfTz;rlQqR z+?pP8kD?Y$Zu{ovOHY%AZHtt9@)EoYXAjT{(+ONBA;8h=RY8Ce8Y{bF)17O?i*Ly^ zl}QbQr&QV<@Z}_Kym;`4ggVj(sC(Nq3cwIiN4k{naB60 z>uiFGzE%qoZ(EHJZ%Z2}+*mf5zmjPzXu4BHmKPer3dt63djqPoH2FTezb(Yyw^){;IchAY64-ILZ5Ae_#U z`f}@7aeZ&Pb3in9=vt2x@A;?67OTsrucP3I?UmjUNCn5_R#DeUB3e!D7Q{+P97b) zAO;LeC?yIg=GSM`#*zBg9vxjk2BotS3?nGkd?C$K*v04ZMCx836-&Tm7Y~xpWAPX{ z0+oli^Ek5v^v;jv@5z!W1bj5E*W>U162B^n#KYrgxSg9vNhSYgb5(x#Cw_U7!qO?9 zwA$1W?c2?x5#)9 zubJE{`8p$krB^<8NPJo&`6v>PR=`kqs<-exb%J)#=5B2cOU1ZUg3w+Ek+s(A7`L|k z3r+b)#VhJ8(^zJHH-Z_tgKsLE*bg&U-;$uyFNyzl;qBMmsG|ifrKGx>PHWb6p=F@J zO7%$z|0;}+-(kC_Gw~RS>N6VcSqif75n&p6q;fi(> z5}VCm5ld@iLE1*8Q6YT*3a;~iP?;kDs$^<*&iyo-8=7yViy@<%_Ntv2$^vnvLPtiw zQmI|uVm=~bTBF0D$_=}g)q+8{)HwV%NUoLcPpiaT6A7#-+-`~1xISvO+tsei+98f! zsS`#eUEAn?Eb4i4<;;Wy=Amm-B?p>tW9a-ZhKHwD>V;8>qR>UY+iZA5ErElblqp8@3hFU0IoFI%m0n|;LpiQ`HWs*JfL zj2-q$cj!#66ydXaT;xN&-!kR1$O>bPSfwwMt@@SmBH z7E3iLcA>*#Fx3P5NIu zE#Zr2k3|2mLoJFGh|bZ3$EA)&TM(P^f}z2 z{~N2m(|=;M1x&F5N6>$!co*Q>st#JA?SH-sG|K<^DjH`U8nz*@tl+9A2An_Sgdt0a0x+g{?y^U^*6b$h z*n~w&pgX{rE;RxZR$WTxuBG-+C}FAum9&mL2T{hLuM|-={L|}`nnJ93WGvj193q25 zmh(uf@3D*`RYRV`p{fK$wI+}U*>i}Rd4<}C-v-X(5!dqw^kST4@Ccd(d9}Xg2doqj zY9Wbrb8+e76ILCp=5UA^SGY}Q;B-h2*|V{#L5S3#yfoHmm=gsyGIx}S#9)YNj+jZpSo@UX}Q!NM!$cgj5pJ}&&a))n68 zwN3Y&gJ8;o;%Zn~gwX56{y>7537R=D*C}C~Gxd0X${ zS+{G=iV%()K7&~cRXO+)NVwYuPjoV}vFLC4iS_vDc*!~QaZ7{+=I3(S&C~bE6o$Di zRP{rnBc6KLn!S!BEtvJlf9M|o0x9plSb^?lgu3Q~;;Bh$s8gVv-PfUYNiAS}jhXGw z{50yzcrN=q`i@tPQ#u)+ql`3GP5`V}Q?RICPBs-sd-bdF zWT3q=S5UX{gn)`Cz5O$ew{75&2aKP5RfrwsYZAL89K_NxIQK(9`&YQxFDL zl0H+<@sNm!anOPd*Q-11z_8Qk6`O5Hw(eyu-f)=@e7>VI7qALuL`>DaesqcNgxBVw zK{dF}f2eLYkGBTT)-n7B3>sditEg?Gt1C+>nySykR63y-cAqQj-7C^a9744q74y9$ zJ!wlz#ZgZRpiN_;G|+-5cAh1u65h6yS-bDCATrwCFB~ zegmMn?1Sj!2j?OL{|H^fUnX9T>dy9dA+6jI;_>Qs>Ks?kAAP&@F^e`g{1QZcr1QFNrv}o<| zh4-?F!9XQ}G?>JN@LdMBKeD|T)hp(r<<9izEr{7KkTcOuC1T_pnpfd7zuPgNzuMYK zUdZdq#CL}z4u&A;!0Nf|ms}y?T*Iqy-G46{o6;93*M9NVu>~5uyI*L~1$mk22HBQ` z&2zw3rhlTl|qqGiVM$IXJRrS@4JMn%Yqv$JX@{)BPcFlFf+_VYlK%w!X+iIi*=D7!=XiOd}cSH!P@I+`Jf*jN+NKjXSH)U+X)1m2Gm0soF5f;czv}-q(?{>UtiRs`3PYuA+6dAIX|e@ zD~)`t_oZjyI-^E4xkf}b_lfI~_tEK#=+=o6hryeJ#c{x`gIwWhV8(9Y4ah2-?K-L~ zBB)_6k#P)~5*0WTSK4fPB+?%40aT`Qxl3s=YJQ*}>= z(9osIGmks4wmEb1hO;N0FkOt%w!x$*8uoy3U}&s(>IVIo+D{ay_*w2p>-B=mL1og(l-AaY{Ax}cjCZTstkyZHr@*Fqo#?njx9ZX%V>$H}uSqF-tQ zLvkHh5rUxH@r(wQM}TXT*c~I|#YmpJDYxg<2HXpD%J!NCO3B6HxC)}+(vfeKFBF%S z0OvKOn!AhfEV&TyD8=|(UXda@p1gWYSjQD^`WP^IOQI=sDO4vrSz7m-UXJ{FFJ)!=YIfz|n-B9EX1`NR_rmqeGtyYcXWbo|9(ELc{iW zMUWd*U;*Nz3BkgqOw)}gym_{uK^*uChxpJQ9T2-UdRuiTMA>xdAi>8tyA+fo+0nq& z$j!wLd-CCJud%KYJ(-ytS0#F$PlPc` zKZKJ0jEG0E^7b6LmTk}I@@-gWYzKaAZi9VawPhLZxuy%+9!cxB_i9QX);<+B3*gkb znoee9PX#qu*rBK%M84)a&=t@mXTrZ+^V=B;ZRK=6hhPbz(>O?TTIpE@EFgGegC994 z<%l=gr8`?)uaSt&4)ZxH*|*OAI&ty9TIvK7wXx+MJg}IYrPy<99L`p{Tog?i_j zn1oD`3I9`h<#;~AkrO^hK*@!Wj#}kw#}dCk*KA2AdvuGWW(<(t5sZZ=5S}?8YN&1# zLihbTzQ0WP!c^c0%N?y;O@BK&uFy-1KKF))CYqE0i;hyPofrQWb)QB>FvL z1ty(43o8U{*GGmNf&yA6>BeuU5}G~AX@Hi1iB#iF@Y6)9^6VJ#4Sf^?<+O<~EhgI6 zzadIh67_oe95KGf3?u&eb4>t&F+&{DG8{CUT&1TRVPIQ zv)ES#E`DoUau;^kQD!u5yfbdvr+CZKky7csXK$x0dnB@1qma=*<}B6%7!7pS`9K z{w)gGRckRAbq^@(JtH`60sl(AR`j`GXRN4#snbqdmeZu|HGBA_9RQovYHQH|l}1rZ zPpJ!Yx4zznY7%{XRa_>OfUTh;G#L8!`H*3wKBr(9Q>b`Cigr6Vj9<*&0+JdmY%krzMh^hu+Ulxsl<0@Nx6d)jZ86Y4mK(CRLv89WXt1Y93sj!oa zl9RoMCxex5*^HxB7#dvGB4dBZLgghs8~q;NbG#RKHh=l8NqAC>3#(?z!CEY6H5-{da1W^yt~`>aMt zJMwymS`d@snTtMYma(uhF~)<=u}Zze8)5AWezCplo8%LPiB((LB)(B?wqnK`!7){4 z_xWy&k#G+J5yF9dg<^G1!S>NxBN%e_U~JO4rPZC;&G#x3(u3P&N#IBI^He zGxW%b^f48Sx%YSCx$P#EmP77kvFe1@#`~$Tr^27@syj3H(vWk1W5BNM-pej)rDg9! z9QK>9b{$raQ+EmyN2`z)bFsVT+%h~NL0ruHYEvFpvT3K|m<{3&?98F%WOVamsDiv% z^8^dz-ms{S3^Ghb$z4!If;WNMXcWt|tZnsCR97`@v*)-dyEU+RSy@kOSooPS-?hgk z?a33_!ct?1)X{A2y1B|f6Tj>#6V$kDK4Y2#n!kjwXowV(P|dc4|--(sohi6&I~UZPTOS_&vIodcFv1+_@z0VCdS@v6r;Z|Q3;Qk zYD-$8)?BbXqbH0n*U#xbE!{&5-E`Q79PTmu+AVeInatMTNOo^cHIq(6A)ZU4Cl;A- zS22^BY&E%_Grh6}$5^&5@~3`dcT@X}HtMD7p>u@j@l3F)dhMVW^hjIi@9Big3iO0d zF=wbBF!^`66Xwng0@C_}LmT{V=>$%mh(HwT-lyHpJmz~>+eZT%{N)vtuj62rBV=4MlXg!~_l7(zfod60;!_xunz1CIVBfz&MOWx^e}fsvnlFKSL2A{N ze_+PTWo`x^t}8k6VG#dxtL8Nr*Dju4u@o;4Ay>r0$N*`HtfoCKH|eT{G!@PiwFs(} zCx5U>MfWc%T!3_Zh6ps>)5pa}Q%u#>j?B-}kDgF8)8B3nAI(SNvpnMrQZ|1%R7Xvp zo;a}C|C+gYh!%~&Eo{b#V!)rF5Jc?u*HeV;7B{c^+?=kOL+<+d{z@*Q+`;ej|2%&^ zWgM&9?kfY&3RQHnEKX4|yCvT>kVU^C=@CF6Rq>w>>t+CfU@fRJGZkGDCS{~ys>c-s zb|ixAXETEvR-RqAQu$htv`^;|L=cArdUzN?%fN^se&mzev{|vdn&wq8=}A8^su;;R zKQ|+Fy^ZeR&1f$^0}+g@*dN$vQ+=(aX!6>o$Rp^Yz;ewn)J^X8o%d@2FGmYn5$yeYf5zLb93eC=GYg?y)3i}>pE90++(w_r zN1Q%ETdVHD@7l>h(aUD&cPd}hxlcW}wi=NEE8e#Uj5zgLnfgy_ikF`A&316CqYjJL zABWax!kCuQChdJpQ|#mZH8!6Z)(_-|E&59_TfH&Gdw8Yo-_#2psKndA^o2tc0}H+> z6faWn`0s*17w$LPTVg1bb?DWsQZAEUQm&CFPNthBRg6_Kk59da1Y%Xy=VpTSG=5)F zm;`&D4||EjD9yDUTo5!J5B1!<(le9?mJd)l&|d_b-v?vy;eB`V?-@YlfE81Y>!Ui z%}Zcw$#UrFThh9}ad&Ii`i<_7Suk<39P>VTw4XQB&X9i@4mQsQDScfUi3t5D3Qi>F zqt9vUw2wha+)+N*4wTT;2@jp(;Bv!Mfpd9+fC9-;1e)HI@alO~aG;G+N6{Xyoivhq zDG*ywdMzyCwJQw|Ni@b0>Y`l(s2X?i7Ny-L&Ya5>1{M11hk6nuijH?*Md2oQzC;iV z;d3Xn7!u;Quxg=KNj;N`AOR$Ng7s^qjaVnyRkgMMiF7SE016H0X2Hyb!()aRkW)Pg zycZeI8}0s~KS$Ks_xdGAJ?`?v>d?y(*cdp}22DEuGsM+BG*zN#sbFWI6+IIUrhx50 z@!ZQ+!G2k%G3h|b!r5B?*p^EpJ%!yd9D5~ki@E7+5NuV4wUrs(h?l>>$VZub(FPAp zZBJ?Z>y?{8Stx@8*YXcX`0de}YZHXSm4x+K(lDo0&N%`)Lxj$ex>b#%({g1xy+k3%ZU$5_F zc|R9@KhJ_QC*o9!3RQjnSc;`jm;NX6U0fd?es{13A~d!(nOnHTal!_;QT}qkt8gVD zcpzWSl++$jEol0Zy=SRI5jQ!IMbE1?aO3iTa|K-?SI9>4vr9U2{T&666&s}Ob69}# z`0qxnwq+ZizzsO|q={|=IasNr=rxLEDv7(Gh^j-uB;P`3Mr8M7WfIP4kX-?qsB+eb zvW|-`)77N&TcqETy6~M~wJYoAz<1t}Xj#K6scr3vq05K(xB*J+L&NcmwJy5{bEBb* z8=g)-%KK5qdAW!ve(ta~hmJsakO&DKu1T+hhHJ(DOe&E;H`2T1Mz8!_14`o%98CRi zJ1fm0G$!S1@5CQ(xnhCJM!tXRbr}<;<@4f`p|6m*87x>w6Y(eU6l&4mxJo`b^>OFi zJUkLDki^_$tF_XP^N3BKc@XaIo#7A_tD5|6oO#1o*oU#~_I$qlH5T+H&rP(zSxgtA z^FPaMEZ4mVp40sN@h{_c^VO}AWB*ohWyY&#cD90&5s>%knBTd4}I7{<}w z=rhpM1~Y^*$Pnkq7VHcOHaVO=043;}fTvYYWowkcqbS~TDynq}!as&5+%eLGl}s^> zu%Z3?<7jL6Gnvr}@w`V(3wy;L%uMMMrAdJ`GY;pU)(H2jIhUE-C}`z_i?YQi@D5Mo zZ(%@b)WHrPvdEy-mF9(GOe!mOv9O*)9g=YNBK8(BVs@_fC~I*^jKQ=}+f<hp9^u>Ja?I;o&%^&D=sJF{^2_+Xu^(sLT zD3-r-jx{{=6VJCie6{wM^|rw56HBZ(w|6x>nzD9}UMahBJh(Y!yTdLRhoaraTEcE+ z;Co(R1mnPx#D1@FL{;i3H(x%WX{PgJaNKGy8Z}vdd)gqyp8C=xdz3Ju_Rt@Ned`2p z@!M>(NmmAtyc5}M2FOSljCni?1elu6@XrT%E+802r{BsnjDoImtdop!@3Ltng{yAf z54!5O{-y@Pp7A2&7K`U--ShyCjg!f+#;uDGZBJof3Huxy-y^M@z@k-&vf5fUNvJ^s+)C^k1tgR8fnyg`qg#-J0|i6u82zi z%@5PP5bQ6}7I5yCAF=ilq25otA92ZR_b)NeuI?@Evf1^h8q=#OT)c}Ww-{Osb{cI$ zQHU?1g_po{6c5RBK*h+f)c!Up;^%x7VF6I{B1eezQf6S2R$SJKLS|?aDvWTwVHWNH zDb@r$lTJF;lzk+AbCAz1BsNnJtUWGC^o3x}!Yg&oztRE~uuJUH6oIs;smArc9;>b91QogC3x%^NGePF(u}3_>#X(W4vv_AG-H^s^~HHZIJhwy!wI6PTY(9 zvG9kMhTs{x!Wjp(?Dr>!FV z)=KtLs0q*Wu*#>w2zSm!p?!|R!rh4FZ@&okE&@NfZN3XBJNN_nT|dux0Ir87Ewqj0 z+%Km_B1pV^i;%X6U%1VkEab7NL}_AzOiH-VxgQxXo;esCJ_@D>G*(Jv~>F= z&m?8|+hMRxl@e^7ZeM{uUAGanh>CEA|A^v=KI+2CyN7v7j$%h(5Gm&`Go7U4(O?cD z|J>TF>@ksQLskJp&|sWGdVoUdDw*Or0P{ssu`5p#-B34GC-%3MPNo|_2UQ0@xj5IJ z;MN492dRbzV9$M?Sl9il?!gCS^5-)5WvD9tEWl(0UxhhMR_USddXo?HxHYTL#=iBR ztC`PPIP?=W3<9|q%N`I}pXBpC!kBSu;kN)WKq4gT%%zISL)WJcx~qbc)~^NH6}zNI z7Ki|oRHzaY(X+s(pzGM*IEvbOW?+J>1$=XYl}#EtPdmr3-Si84XdC*$2t%ex+ouej zgS1YH{{A zqDG7*>&dLhCLQC)em;6N)ybmK$d&0`HxzW-sw#N4@4O}P=^6yTPy9W$rGBre)MymJ z+8_FRjA{`aF?**9JW)q_zS7D6Mmk}O&TFDOVVhYnzhhFgIQgW@QjY%CM*1Zj7z-pj3f29OlM{hPNSy`!{}^g1U_G>FbgB!4cj{bV2?UO4xD%F@Ms zcjh#^Fou<*g1O7qXXUVKY|U-Or5pa|nN??Pg{Zfj3?H9KHXo?`gT;~fxr%40hcaeCL(gIdmfL zG^Ls6^0yFeF>f_`^pk{;{ermj4fy?XP1lCL#{SWtscX-_o!h5}h5K}&REu>;H6p}qTvEF;uL~$BoX)NUu zwHXp|ag=+e6XZK>9OW5p8~0%euX2MwLW{;B?%<5wZ(cktESVpvndbdY&um1Dz0n3t zIQ*2eALKLwK=WhhFCfkZOkLRLUE{VD5BAm;Ld z!Bnn&-+Wv$vg%orw^ESVKqrbF6|6R=hMUDS=r4=_H9Pr2Q(){mCW?~=mKZf=PRtp; zCT^koYbhiyp(1XYU2H^Rc^>Y_pp9lujkCOfJb zUyyd$?c+kK*8HM^$_V@Q>-jK#s7~NkH6HEksc*PDyV{YfKbcj_rj(tuq1y?Az39#B zIY&n>`XVDU4L)|hGJP_Q>#2%p95uBHjZOAbtT7u1O-7mmOH3lS^f`6dqEtp%`}}|$ zE~;tdcV%i?5$r2i^cuPtzE3;eTl~Ic$QL}$6vYu~A`G(BFa0=yoL_OJ#(pgrnlhZ9 z9q9@z>FRoM`J+=FaO~-}{Uf;TEY515w;1a#W~7-?toZZ49Y_lQ=CFE<<5XxsmgjG0 z-#eaJo4q3;`7D?xG3ct&$uEWV9fu^->X*mQwPdVbu^r$pv`{jIDchl)C$uikb6E2K zUtE1tkSM{HZR@mc+qP}nwr$(CZQHhO+kM*hJ8$lM%uK|Nim1$;74@01u$P|=Qtg(H z=T&QUY*h=^)sa{mG?nan=!Gx*MkBiDQ!79Xtcwj;Gw?2aiEEWJbV%yo=LkwN!#2px zs3qF)k3y_AmQ9~Zl+l?1OgPADg3ai#tespDOdxF9Dc1ti%QnGQ8UkFnZG5~6xNm5M z=cs1{FQ#XAGzK>@u#RwES|*T|F4y?fi&SRrQTdc=Mjvg z#AB&ZrWgr>;3sU~GnJ06+%4^}~-D@*4EKzjBRwsppf0&4iMzN@u-SDu;^o6%W!`g7O?YZ;)9(DbCy;%~jc$eVzPUo8@$}K+(e*WOq z;Wmo>3>m(|-+>j-o<)_kXF}MSw7K&%QGB6W?*AIMlBbrqd0aHE&SpWuUuLDXpwAD! zRA73lpUJ4^+8+Bbx3sg_ibC2o$d(~pTzu;>(D69?+-l80dl|!XRu*;@Wnm0e#?I+| zpT8_zt;W!(b_LaF8TtlSzpBpW=({X7tjO;eJ3nRhjz$l>U<=WC_Hj@LNnYLj9)pv_Qs)6Y@*t9<_dh?-S@NdDMiKB(r>*2kj)NcJE}`Gz`=j^ zohGJSz9+Gb7SY1$y4SlY*0g(MZ>E$2Ml0$U)^jW&_aGe#ouk{2XGlQZ# zLn@2vgd|Qh-k$S*XHsk~uuzsAP^wxZTVm9d;&Q5jG^u0R5wyA2Tl3Mm2*4$6p^wvs z*L!Jj4fBr!D)}s<#oa+T1f1@losIcQIcF0n`WwrA^b&srU_8SMf+r?M{JQG3Zgw6- zzj@w+Ls%6!a5@^>7%>fsEJWDvXytFq;T#vmW(}=Cd!WxKNk1- zhOrVur$_eWYP+}Pgcm97?@!y>!fXa)wy;PIY3=(i1;q$g&%+wk6mx#GF{Py9Y$HCT zQ_3VUR7jm-iQ$A3COk<*-mn3o3UT^_2yF$vL;QPkm@7tAnsw&!sGv*HQB05XHusHdO_G7hFYu>Z*kdomFYDO`{_0HRnd^+JxgT3n zj#?ia(Fy2dfnmD3&-_{ekVlam6(|_}_T_%I2y^6Jeo=I=^mp(Gagm0w1#GTt5p}o^ zhFOE$z*0pagxn%CV#cJq>>x4V@AVDz#-ruRXe7r8+D8N4$2Oe#`H{mGzCQPh1U%v% z88)F*+Nnl7==`kNe4r4{@*o-F2O(+2oVcLisI-T)cV_&s9C*YX&wO*bbbVOd8us$? zKge3@PSc4XR888b(!-xx9IQ?;v4&gfvBJW0jUOJS)T8HhKySZn<;Yh zp8X+!R6ao3zeU0K@B3mfJ{y1hFn-<~q8>ew0T6qBb4zG4@tqKKCr05^J5a(RI63(| zh*rTcNXwD?pAN`L=pRkTViEu3Xck7wQP0$KRcf^u9vrR@EZ1Xm>Si>OQdj^{hZL~?|ZRvSYph)^9>iCiGoRW%kk z>Z8gB+bX;yUXhDoqf;jSSv%3j70xtb503ro3Kt;hy_!-jHA$3+3 z6_68YsR8NQh+`J)HX z$@xPA$0`iEOz13q47-opJItGLIA#I-^tz0%wTBeVqVhT3>lqo@SW&jXwYdH2w=SyErgY|NGojvX1B4W)a@1b%@m?g187U2_?*I;=X9*}1=fKD z_~t0b@K#W~`IO=VO2N@4#2S#nF0}dy zKo;5J^+ZSU4()EI@>|7fN~4Cj@c~my&bMn&h*sBo7JC zF*)-!RYI9qdaGTH%9B~!F_KOs04-n)3rmPJ#CTMz8R1|*cgLk~$WZalBgWQH&I0~R zOlK6iUP+>rkY-i$+>N)lL5e1yPx%9JwZ2!qeV`YutGQ&-D3u1rd8_7Jp?f4o&mgo7 z9F$Q*6p)Z?726M^wS~8)iLAMdU6jwo=%B8^rrbsl|1YR0!kmCVx|nd4+e2zmvla6U zSoJ!S>MiQIiX6C)vG1OT#MHR|t?IA-ghQ0kTq=jMMD=I>56GF~f-ecwgCL(iUb`@j0L z`WL$|Jncmmu;DH^0cYIQeG^xwQ(?!2ipy1i?Mej`vc)5nIGX!{Z+@Ei3NqF! zZxI?MvPZ9?$*YH6l|_L@a~^DH7!ylP!*{LDBX-@Rk0uD&LgCpQ(e+Az^+LhNjT}eq ztnrFx4vZQ#XN-sE&)uf($T?u-wc-oB&4xtt&cm73i{*5y`L-wJl`o0xQPe54e&5qE z{6&ojtUNwv1W?zH>Y%RDT@po7wr~cGUxR)e>VQ1Ww8(e1pmoKP-%9_5)54l z(PqmQU1=fGp$usK&dy|qFXCYwhi%0bn7Lvf*g7SE?Rfhq{IN`Jao)v&hiO-EtDaP> z+vPu#rSA~jk7`+hL0M^aj?xTMl^vtz-zx_(@#Qbu^5++a-HPslJ(Zo;h}8&zZ>U|~ zZ@&L6w)%)KD)#&biB(XJaC5Vd!Y!_}`K%9xEp-w#20K z1pwlQGQJ-IiCJj{>K#j$7Y|3#o8>FDx)$FQMUwNWJJ6Y=_iNK0OHa-o1jFl8C#G*(ud8^+k>MuTSV6F*82B zSr}$|0=IDs)2JEmZ`)p>c}sh#d9zoNZoPr4k(jL8Vy?n{qs8wl({Bjyv#1egFctfd z*cqR*P9EDnDi!zLu4gH`hFB1@{i-pSsL!q;@FpVPUxPzm?E5!IrnajILtkOHzOZLG z-BSM|l3Zux%MaB`QTuQN&;|dqfv*hHA zW5%X{kfxF*TgNWYYz2w^D0`+o>9T~eCdZESKbe7PUn%)^ebc*+sXYaD)*qssX`y|@ z6{Queb?FVKQmPSQR^Ix%wR*h1P{mZgT^;jMQ1!a9@TRgFETZG?@1n`%WDkm_WD|dqy8xurvJQbNxsmM9M)1jZ{wJ2 zX0>o#l{9&r`77ndrDJVo+iOdnSA(kb32XK*r?=#^WXdGLs*r}xLeqFw!_BSr=kjA233sa;xeA#SYZdt-!2HX0N z(Pw~%Be?nPEJ|+SrhrYHjZH2Q1lR{;vMO3Rm6jzDogmTX*96*Bx~^g`{KCG%Q9OSL zs|VUl`9Ze?5c0YU%-Wv5^~Tqs<#s8bF6+ogKR0QX=e?=qJ~rUyw#``EAO%-H186e7 z_B6a;pMoNmJzK$VsLhakz!3R5iact#wxRF8K_rx1h zMmlb2<_`gR*&ic?{A4}@gLUM1WIHyhHtg7uRiU7J-;>p=iLY-;XtvPZ*2F=8cQfO9?D({W}Zkb*Q@Q(L!5Jj5aI{y9yBIx^=CFRb zKbcP_lD>hu+R-Bp5-3U&#;jX!$vMF;V#C4pH6=qH&_Bervb2`LZ{Ri)Xecj_ke4DL zAM5xvhSVLja}1(MTo2UuXj@UCRa-NN=#E!2j=hrH+Hr-qfemuAZE~$?$g4y5*Moh$ zJYlt5h@6L?BEjoZ%J+{MhjN?N*9T^FMDS;8TewVaTVnPqw5bIg8U7*TQ0|{fgTek$ zWpZ8lZ{Tlrc4;@j{&srNE_?iN>2U9xx=#e8CXT+q#5b)%$1I_SP~@|>trKPwGb2dL zqa@|N*aW=r-dWrs4&S?R5m~j{1d?q0;OL!fC3B+kHv#JFkY0SE`Rjnj75H0TbbF}nL27$bA7S|lBqILun ztI%xGqPTRqYE8QyV^iEYDSCYXi|oAbK(rDMc>NPd$5)OLNpk^M-2`b;i=z7UPn%f? zXMkHxqF&^1kwDpE5kd7-;?Q!4(f-Gb5A&nhaP(}bp6EB0+Y8@-&p%d~drN#8FZm`z zK;K{C4&M^f?^j|@)7fMH7>uE2xA|C$-28{T4|b*RRT*V15_BWG>(z!+AE&LMlpl5x zzsq!VmkYTJyIQNH_IR z(lxd-8dWXr(1y9q=oN05%1z8avcS(SHAk3ZwGPcJv9MzcKkfQK?E5As9tSTgB6N^F znFRmrsy+VY+;$N&#!pQIwv-?EBXH6zQBuodj@xys{@fN- zR+{E}@{T&q0NblOc>zwhtku7*Hz2>UOv9U4QZ%nFnKhiYHD@9mm?`*}m&MoY5s_4Z*5j4*=v|L-BcYp>H&j_YP&T(b~T5uv^W< z>=nXfMK+VWB&2duF(U{jQYVETSL<(13@Xkx4O$LN4n7E;nCPO)S`m>mBx+b5!Ith7 zJd!(@&D!zft~+2^zh3W6RLKWJG_6WrSIjiGyOlhQXLNShBKpW|%FYd3^XKEwZ!Hr@-y?%~|;@uDnG z&%Kk2?ai9TK3?3oRx@QebPgJ)bEvBEnmcppvc@-mzY5(OF$5I*Dq2Skhfm~F3)xvRpk$SO= zDlR$RR@cx}TMR4?7N5j$7*!y2Y+th=(8;|oq)skSW}3kXQJztpREF5R#M2+)Ypa~~ z7~E@>FboH=4!l=Jpd=;%0XNpCDiqfU*ADijq;O`a1^)`R8tG6?mjA1Ud z<9pIUR`R5*pexw^a;IznM}jJBb{}if?UMEYeY-EY&aF#8imvmpNboZB0ZcuAa55=~ z7v`~yU}?Y%rXhfl4W?}lFDQo zfVX$)n4iPu?a`C+vtl2?J?Ih;9n!n_=ek7KFS82SSd6O#Bqzo{_CST94k0dhPqTXOlql&Q=nw@7#7Nczvcs+P!F;?OMQ5s#^`H*pj@z;whEEKg`}}4q?ludQ_{rp zrx6%ewQAQoihkR=l4gGomY3wVz+Z~%kz4u~!PE0qYNLd=h$H&3GoB-Ql|uxFbWB%e zI@y}9kRy5i5(jArkSSkR?AU*Xa(R7~zen=mOyNQVO9I%D(<=_-jn434^L<3HA*JwP zBeUWNp?J~A29ZJujMdkEM-GGrgFf!r{5qb>bijZ6?6bvvwm%e3-+hjR4Q%M3uCE~P z^vh%KCY`?!RA<4y6;cb&;yPG?Y8bqlmQ3U1_BA!~`5C$F-^XtsZHMSA9OApK9RKF50FLRY zgSCA}dv;lkulce8GL)2@fw)xG(;Z{hK`pl?RxF0KCwzawZoBtT!As#_)_lBcMN)z` zg1LuJ7DxgRcn_cY`te(o0OF0bM7iU)B7VcPlw`|~5MXT2|1v*U`QBD!8iP3ic=OqT z@aW?${iIYVAM8ds`QiaqhjwS~Uw{Kb5Ss6XM8~*dFRFM7BaOhy?Dx5w4zLMdRG0>& zE~C_lhDN^{i(|zN`)bV)nd@*2hHQ-dDW;j8)P*AzkF(AC#33mp`pK?>zgH0Ig|YfB zoGQB>lT*Rr&%V((am3>zJ##37rMOVUesa)x`5JoEGN8wQC4df1aDXm4f}ZmhywDf_ z{Aoc022ZKPg==i%qvvHrqIY`{H641Rubk~0P(A96jNd$eqI9sbN!;qpBukSNI z^Tqi~y-9>wH~iWdERAtGzI_Nw8RcM(t!6MsVs|33!0)7Mrkb8eKQxpwBYgblHLv6K z06lMAbY#FgZ;9bIz!mh-C!Xd~Uike{oJoJugX5S){6ez!VI$Tgf1H zjsSSyOCm^ae$y@zpkl&)hCWfkp-=A(=eK*fMOseHg!j%%%JO@~J{9_CNRcPlsOO7w z5Mg>N7jNp>A1~`=%t(u&n5dBen_5!5?xxX^9PhjnYmJL}3^;8Pwqw~*yl3OrVn3Rr z8YXxOXT6+l74}ukX5c$}IcG`!hW2C^dWBP=k>o1(0H0fROF3F7n5vGzJ@CZXCsoDY zsAaAZzeS%a%9E-)uP{utjH)2d?bD+CFzbi;C9Ob^aNzM98`IY$i^^Li{h%?FF2nUr zvZG)9Q9C?Rk~B=aw8obtOnXwbFV%*Y0Ffk_pHSF@O)u^WHc?s5O-M$=g-<5rr+4Mv z80s4LWtwH^87=Beb5m>E$STL_V&^P1wtb+ZB(4}2jEG7^`@~>nYyVK^(>O3R64TsM z4f?9Cxl^j>W+kSOlx^o+CYo0aB^DJzSzdy9~MREg64LQYrgxMrhXH)EF+#9h#ASo zJQ(~<$}C;FWHvk*11*wa5}kTX<%XRl)eI96{8$|D9bA5M(PF0hgrpradO|8_tcG4D z->o!6KjTE6s|+Kpq&c792B!)D)Z=T&f6%Wyic0tShd+N4pB={@?0gCE)$UUK&bi-* z7(y0oJI)V#CQA-%TP$(kxqnBW567PGZU5%qF82T5rTJS1eDm+bh5skQCNGYCoLR|# z-u^Xk?&F?bECIT$P5nE5{9g%ceeek=BeSb7A z#@0s$(f5Zb*HK99+lTVs?GK^yR#UGOkx$YS1n-3#=)kf^J@fU3s!7Ls zbMF*+i)#-%2rs55Qt#nd;p-j_?-%cXqgF}i>|6f10040-zyO&47qt?zb2V|awR8M0 zUDsb83#B9R)IB!CUm;oqB$%G$dmCvR8|tvCto2UN^W0q-KJqbV|Md*?Ov|Jo^Q(inp>z&W2w_$xqL~Fb-#e)Xv|PSeV<70Rb#=^&*VQ3 zZAamo4mbnEV*ImzEAYKXwDfBZqfpbrJ~TC~cW_ zVXQxpST*vcbFiuON=NbpgU!gYiET5@<#h12$jx9^R9%cHs_plR+m9_Xq|Z!KcWl#> zy-7`)v>|pTXQC~PbU&~vQmFL#%@k1O@1j60DuX#SQISd43eg&{EyJE=%h0oRICl0| zsL!gWHZJY zk}7NRu9!P9_`r7QWb_6;OAUOPnDUmm3c+g9f}D+Tj90MbqA1(htt_Laf<;}tILGyh-IM}m`{j?Dx(ks3!;YBrZs~~jSYdIuOYqT~{ef#Nt=wY5%;i@4PeY9tbdB|L&+P7^;F=Zs~O!uTiw`|Ym{Oahd>xtINSf=Oc5GF_rXF7@Bz;A$^zmbmE{mDauPFs2Ty0L(@a5e{ zqy4g=M8$kql^W)MAi0n^@jUNUgLx+dJN(>g3a%gL_{V$(oUCh-0dKGmitL^$d`&0e z(@fSza!X419dZUW9f=k#aTEqHa2SC$*{;G?hxhdW&0L?vTt-ylOfj^@mfB$(s5l(F z6K*F<^k^;-?y}ZyV~M?`Dc|Te-B)f!xmWp;>DE(2ZbKB6+HhEzj;K)BbcAT|(b2+- zkG56xf<-6~tr1aNbO@RK48!!+kx;;okANIb4Y#a4mD0%&uG~F~OMaZ6VLwG`#^&+L z9SBv914kyr>D*etFCmmCo=``8byyr*6|k^M68KIFUXgMEj^7Z)S$wKk{X9wtb9rQYF4r+L&*E1H)+$EmlhovGi1<)7A@;U+`QfLCteJw`PotuVJ;~iNgYaD@2O^z%;hwM<=@a(X_(Y5=90-W zPm|#t?_cEr9lI3W*_bS74Umpft<>*ISiD?C@EaDbM=8@2&SG9Zi{ukKfoY#?Ry~5- zs}v}Y#{kkG(YqO6!>HcKm+opPE)7L{VEj{Jz94F@Ww_z|>IjhiS+pE}BD zYWa@Q(+DKhKhVDj$~FO?&fb>iULj!Xcbz+XY@R);eJks1W7F1gm^7TWESsQJZKI$z z%o=8X&3vWb_r6_QHuJDHSUIRyZI{c|D_Rd&#z0rp0O^U=_V0I5NSm$14px6VlmeQT zFxz4|V_wO6UTaM4=F!ow1=4U9R}Ff0?3zDE6_PNYiYwZedVl3R?}JXXT*%(}MnDw+ zN-K7C6n@e2+@d!vSvzNJ%Ww?ZcBp>GT~VH&m*;$mKCnO4pPKs2`>*B_`9=_Hly^1h z+$ou2vY=7RHcUQ2uh6IeUT5u~2JLm-mC9tz$l5KVyK#QI8s)KU6}h&p zT)uiWgx|5m#;3(G`izD8A#U+4gS1S>bg0zI*P)nWkffMLwpdJomlenWgPZV;csn79 z`fsGif%joV$$`B}{9#mQv?S3f#~UEX$as&U8=J0Kdtc_TEjMsP?q#SvCLQfJ)co zi;5+?Mss#;d#?9vH&!^IEK-ev<#x522=Twi0E^$W zbYM?Mx=$Oz8pQ*#Y-Se6Kc?cAJ)!g#Zsri5jsEt4FeVaMTVt2~F(XcNde@7OZ*pc* zb|=E*opl)h6d=_tb5E7fNn9(}PZ6#K<0BrI{tXC29$DYHzo6Kq0n@3w_H z`*N$7G=Fm8Mrx0(h1$(qEgOgiww+<90owVo1uU_@kVh>}7%rL?LKoMSwExe4f!K+w zh3Z~9`}Q#hR$alAF~5QbsE*VMZ;a^t7l2Rdvg4FO^O;ZTYMNM`Wx)?9@@#9bt|K-> z{j^G}o7-gF`I&ytGy%$2)N=wC7vM^~{+Mq{&0z1$NO z8CTV@^D}X03(QH+Efyau!SKqA^-++tHX1*MLn^3a(};_V)4a&@gzq%41QeBKsEj4R zU7i~igjL1hlE={LlyJ?@9@;U}G@`v$Md=ioO~_7`-rDOat*yqt-Q2f%YqC!!78jl> zyVk9$RTri;^N}d4j8QhEpKK|bo*R@-MpW7x52O?EJDZGXZUc*?fFylT%ELLig__?s z(xFzi+_^yjRd+)fQSp?~-To)#jODeB%@7QgvLPnHVQx85#ALgCsq4BuUx>QAyCHSc zi>iibRj3QYVI#t-@@G||U{T`g`+{p>@kO0dlr}8#jM(m>o~0>FT_su=F#G$PPzbG1 z%=weiPBALlc!P?hpW^VV+P`ZhdN6}YwA$5et5TY6C{49>8bc~bRg7PBEvhKNHPV4e zZ8*6YBPAB<4lT-TWoP4FqywE>i%!Mu%rI27tDam}?sJ7D*oLIcE5YVI;`gWt*jHQ4*{Z0;hMAqJ-{eIj8(F+sJduM0i;DF518GBoNcT>v<5D z{LsV&21y@9)Rq^=LpV{x@c<>q3GM|>43n^H{wWI80&+>!KYCkBam1Ar$?V2&tg!;@ zN<@7lZaX+hkkp54!wyU!Gq|TIi@_m@)itug1jO4;*s?9xGZGqQ>K*!>e$r~1Ih3YZ_}7K9Bi*?s6btSi7bM{m<7DBCW|An z`#d$qvcO#B#vm=7cPDP}6Gbz9nrFbEecp%YDe%EwRz<>+|Io-@^491rAL10ja`%9p z+P_g34Ob1sl>WD2MHMLh`|sYxfw!uw?Zons4x;MfY26`E7?9$Qke~e#l7IupKSdSRj5wg!JWhRsnJN)$r9sF&+NA>%w&$T`slFKhTj3&$XA@Ka}wPuWPN4d@b2&3WS`>TxT8>4cU zC4wDDNf7-J2sef9IaI7=><-0Gqkl#d30+28O+b2?#id0gg%z<&t=T`9HNA3@Uo+Zn zw5=zG`5B1I8gA2oQHq1A=flsYOUk2x?0Z6R?8sY?c;c8TRxZgrAT?dhKt;wchv>Tk#6gw;;Raodq})PGX( z$yFU@H4mW+4f8FJgJUS#W${e5%GU@Ag8?%Hp+mxh0`I7iM#<$4Ylp}cTVD^tFI;zLWR(G! zqPjzdbDbh^8_+TI;P6uhR=VcxI17~7nhnxDoQi`T!@Q$^7+%3tj?+IrY~NWX_RO=O z|3>VLR{K$!eJW+&9CQME7a$U@ghOlE(^yH7G=g&|Mo_8VOk_^$+5e(+)FjAXA{^^P zb2wF$6Ete(I5_5A8#SS%6j}iH7xczGI7H02Oa5UU${{!ZhXyW_cM}DQGdkI2v_&n_ zXUx52%0kv2pYG)Qq>oACv<-!|%@em5N8bJbav$m)B zySubVpm__f9Fr^DPsk&z)2oM)8_F1f88-oEe}E!sT~X@IN0pX9oWKgw(^??-46<*b zJ%Gq_qvFo(eWGaB@gX%ryjY z^Q!MJ=sST^-`hfVBZ19%7}zni{3y#TrU#*jJSw(b-U)(5*sfj?mdajOlajo0(fxh5 zJ;#uiYUDS5=;`aOo_Lp(q;$B-A+60t(A`h<*AP8mGsi12dFsn6mix>hkrdsDZmhy_f*N~ZHD}*o zPwQRs6!j9t^9CT1C~;>cu$w67LkozMrNl3Ob`KR`;*tRnzy8P;))(c~xfWz=beqf3`AcT2BIzGCg}iXE5R;FadVVqkcELqI<7@6q-+CeSeFh>H*~pei%Z-_ zE8>)w72yQ-OZvMCv$z)?F9jZ#(ABvx2V7f|yP%AX(^{)531{4LL{#)F5@Ps}#=;rD z$W<^uL#mm;F(`z&oL(IP0c0`WsxREd<4oYXBD|Zf0a&ANTaxVH;jar9B9+H$?38Dk z7Sk%&`#o#z!`8ZR2R7mdP~d580y$~XberYJ@-TVJPn;WvD+R$tK)_XEgbPbXP=<+~ zr)C0pBPBCKy*85}+#8_nQ`KtfxT`B-b}2I1ko$1@I`G%Vsn--{v7%l%o_0H6%bW*~ zVOEu^j2eUMc-&)mP)X^&2}gCia=S78%EF0ThJ4I)!h&VoOz6TEUe?il`O-GttGUzm z&9X+_(#=z}f=}PxOZtK}8+lEWLexw8^sam8pn#z%;cT0v@EM9DF8V!& zW7Ka-#~;+OKbVa+LF5tZ5rez=I#;WgT*h3XJh5J4=aQTuAAHjVmlJ=BoMng5T;!CQ zUKLGdquYDAwW%j>O0HV2_)#m;4t8dMUMGv1CU$oB-;TfP4bw}-#s;zmF4A<1I(W_N zS>~S2qOsm`$z`hHTqJ`gb~$h!b*-*~kQ#ROxEuyX>H*v39&g>>`go6p5Oh|-f=hvO z{e1Y{m)5nS@#Zm5`=|ooCpPrpb9(MLq9w8<{AWofu@!h#d6#pd29y(49H<7VUM+A z;qJ;$jnZ)5(`ciE1J`WE_YJ34gjAB?)UZM7WDe6J=>GXR;k9DxJcqzbiq+u`=Q76m z5s~4%26Qj6nWe#wV0uL2KKIE=uk%hUpN|kG;t*WN^P`hd*!xZ!4KiA(@b+vpcRWCgG%7+8D2(s4alkK;G?$KC|{1f9NDhbW2kZO&aEl7gbJ#^|%ujmcw_* z6%dw-2p5i!X16G;1I>3Bb82g5_L#ZDW^=YfiwP`=i5s}8yCnAh2_eX8HzRIL%*rs^ z(Z6sBKU-jcHSUm*I@$3fZQqC>rSy1j*oc>Q=p(8v(P3hJy!Re!m+fSqr}8k3Gtm{p zRa^%D(9)$<-3`}U1IMS2;vxee5Olr`)cGyeIR)kf&D|If4bA9vHf}?r@+Uu#5<@k= zv^>VUL{SVFBa7Z+YR8LIY_`^hsVEbT&;;XXDlG8_c{2QxCm1FN>?{fpIvnKwqm>#( zz%p`kCA{+*P9KSKDrR)#;hbO(P0K+odxUO`ja~f*S-1?~V&<6r7z$}vxF&X<4(2{|kA;KX&p z!3B$I=7L8-eM%fp+R7Q2uN-M&=AElH+4AHH^ECLI$m#_lA5QY8qsJX2{Ae^@&SjKv zWFVgR;V!4;AgxKKq?-hqQbt6jEstms}K(l7EQii;~Pkscg(tD z$0}uVQ+?rRWMwgtcfgY7t=hYo;dlH_)E1ub*bY;M%Aa~UNEUngP)v$A<=gW#8|)QG z3;77gqO80&D`1dVqmRWUR;2RxPR^01H15!MZ!+yO9 ziKv2etA?dbjBn+pwnzz=+_|(WFJPx%N6P$Nh;L3N-Kn0P)ARYSs8%v*mhzrCmSS4( zxfnCLzWs@y?M;3ee`@0<&qBqe8wpj_=7V6N;;Inzm3>MgutBd7Q#r04RF+(GR^9^? zyKY)F_MK;@zR}t=8&{m=>l|O;>(tezSrU{J*0miwr0eAP!aFO;y6V90QQMx-S)8uZ+>`f zQtPC%<=2&-7KOg`)kA%E4a;sUp})jD{n~+XPKa1|f_3|o=ngs8-{npfc1sO&^MPF+ zxRy=yE!m2YHf9xy^`I71GF>Un=+V~p3z@pb)eK!$Zrj};KOddvPuJ!;E8jWXSIsoA zuH9GY6)%_3x+7mAQ zG6dRb#sI`=SxoqzROv|M8J@ElNt>5?zg1}Lw*iwhZ?1&Us2fcw z`L2b`i6&gBoi3UYDd64y!;_L2t;jTIlh*{PfB)<%K;$krCekW3^w$b8dgPhOgy50a5lRr#4`($3c05;T`EM&67jS8>Ko#ijA zBy*eO6DtOuw?1>5%u^fiR{jHPronL&C7x>kQg^;Z`wql*47 zvq>LkI=K-~Ee>+i-xBC8YPRB~YbUAOx}`bP4P2d{>sX3w;*!(uC8-Vp5GF8%gL~{Y z#w*zoCjPn&9-2i!0@W1umikl~MpKgAgzgR`nvwZ2m=aFQl`SepP4C8<6*U#47RxL! zdJq8HwwAhz%-F@=-*JqnC?12}syNv8aPbqRr}$`?r%Q4u^j!<4;EgBgBa-G|`cVn@ zYnGGio{Lu5N~beSqw+rhZ3SQ?m@}r%0Qte;+W_~jWIe=bwj>*F?<}@K6|zRZWzYH2 z6-SYt&FkSYSBPjTN(Sx#l@Nh)8HY+9)`7V$<*ID}YVvW>XoJgtsKT$j6YBJ}>G^1P zRo`iB69bCH^@3Pv{T%ddJ!IKZp?tUaj@6th1<*E9GR zfq=5HRw)Lra^F9yRkWQ}2m<`mt&_Z4y_Mz+En`pal~0-#eAW2+DGLmU)?2k}*Vcr; zk#?A!HftpjC6L)OPNJ;lyX)r<6GwtxU=2F_*E$P=l3Y~Pv!c{scx7SoFig9IcfpfS zDgv7ui9N>XmbPjV>R6_ARrlyBy?1tOR8YjtQ~N?98ZWKz8AER?S)8q&*)-_-%0TiR zcx`jF=5>7*Y2>t`92XedxE2I>;51^(PwWjC3~$4b4E;UB_9Eo`j-lV&8n=zBQ^`oghh;QOaw}`h%EKNxVC59)6s4frtgUy zj6lh3URbAA+4SoR6!Q462z5mzs8gyiG}fF@1+wl9r5Q(I&_pV-9&nI8ChRukb1hrx zw^+dAYhO`)gF=#g>I>w@+mg8~T`oF~kG5-7rBPK}fXAx#HQgs3zKlFrdpquA4#|4A zPWb-;Q$Vc0#Ycje@buk@A{+ebcw)(O8qlY*xPJmkzsoCF<(#Ox>*~%L)ae-A<=>4Q z{KazlN^X_bY=}F-tMd990~%~wbT>7{dtgW^km=Yg?7gt%cz?VHF`TTjW~Z)8Rc|Kz zbo}b>s+-T_^p&sg-z-fs3HeZ2>FHT3)gnTrw&LN-(G$zqgDQLrcF z`(-rD@o()h&p8%tKa;c*r?Wg>opjh>^pLALk+(MMDeaL#fmw{Z+os7GmsP7X_)T6O zesfeZ`c_*$c|=RsjRHE{nD`%58K%s z67F{=CA2WZU0rbaEu{BCPH`-5A0lc&!8ekw9dKN?IW_lY_O)3{^79t+Wy5s!Ne@X> zi}aRI<}mvwW``RCi@}oum_cAaCQ4lh+{LUfasP_*a1b*?l4@Rx}9v*rCIDm!-BHBhazaZMe zt1+^tz#u=k{ob9e!_j9A#VJ+hX~%~Cy8U3)eo$$@_velSE6C0z1Up$}aqet@rrRPv3W5;zwiD4Jq)m>7;*~CG}7LShYVrqt^bk_jJWX(~+3|Jhw7hKyTW< z=j~^Q5Y2t1b06KUR{K~Oi5VMi)tdjwO^(5}<(UdfhUY!l*XK<5d#rIWN$aHqL$;F7 z+Twltn8(ISo1i(jc9CdT*DJ+Hk`7-%2Bf-%;{ zAiF^I9vqdLCiE7P8@c-5%0+68(BY%~)?EKXIO=~8+YE)FBe_ahFCOd!(lHiwH)Pop zzwHr1yn{RrzQtxx6O)lge<%%E8cX7L538zE746PVCSHkC8 zYww?)QygSEl8o1Fx`q_%8e8iv{A@Tv&?sHMVQEA?y;N$QoDe#RGY(QL@8cqZy2|%< zBY{@sd%2pRuJ1T^6l~OheCdKerE6nEj41;-1k`aNW?AS zTuantuAcd{htW38kczi@f7)C{H~%_F^{qk-SL@Vqeu|Av4MChW$0hRL6 zqdyqv=HluZj0{tuF9V1R$fGKN4o&hANZDp8MCuW`Iv&9_TH>038YsIp};(Pc0W3GZ$JfHNuFU0i#eeYtfyz^d0p_EYW@-u@2E!~J)PLzTaer1fVVR&XE)G*a}j6jd;wB?PQLx9>?z*P`Mi9aXSiw* z+0-=9x|Mlg%!grtY{Z)CGC^MYfRB(~!q}X}k^%NR-gHynOWP)g>eo%{*4xHnuVs!H zx>MZ^yd}+1jp1$hPRMrrDC+uoP=|-zW4N*Njpp>7hSj>T>-qpej!vh69@;bf^hsyi zLfn?nP49In)spmGPSDU6ZQ~8m>vGEgebVVz9TEdGPa3^xlsi$KXg=24K4STx*t-?5 zdfR$u-(%TBc>CdW?UGj9j49Lg1p+z6n>KpMY<#?#&ijxV3#p@klU+r|Wxbp60aC@M z_04(|Vs^&CPbrDcAlt^OQQaS4top~`v(^~&%*12Hpf+6h(_cm^ESBg?$@?NxOpmZ* z$|&T7a9|U;^n^~;?AO1m1KKcy@3LMi7C7RVv;F$t8l&5pyqZ?)AC@)#6c%hf)P%BJ z%SyJF-S1sU0eS=zTwXGbZ}Q!Rdk33+>M0AqL6RO_m}YZ2&p zS53P1+ge+@l%CK@&4HB1aO>c-4Y1!CR^1nSj( z{<^Wf3IntfdoR?=cwzkd?7JtnDF{v*6m)B>TAO<^QD9qosza^mS(^Ko^5TL$u~aGN z^SiZ(Lk%!Qs4@FFxXVxc_L(-agEYYtp#+8=RRNi-nDv)Hl62$nwCl z?J&z?Cr!d43xhC?Q^#`R&`(k?bgd$D+$?Zh*S1{81%2y+)^*~-dYC5dxqI`tdes}M zSGz46qh$|w; z+4-glWhE#@vj+OYHusO_4egpLB~KWm{|0xpf?LkAR*L$7$s&K#dZ)We^m!bW>k`1% zKh>4;wDsAgB5T+VHL0k&%$K-=)kq=&De(wR>nkfS4DDk0>BRUPWAbq5r}a(a)_5$% zGR-r*S4Fh2)V6UO6~xAEz5)%fegt3Z%AgOH3FEi|X1QH1_}Uy%79X>-%>Rdas`rli zqBn$H59+F$x0DDKP5x6{_R~6Vk4Z(JH09v6_<}ann;QNX)>Ew^KIzT4YgQGGAv~c_ zBq|ZUUyw!-aKdZoA-z&FXRAdI2|?H=E~EM-`lF5ILySaU+H@6DVt2 z2Q_Luq>Gk0EY4z2uQLbh&&oP5Ng?q>H;>PCs&)p5nMhdTD-SKOzbAHFh4-AFD_YAh)pBrBZ z>mN?Xd3|$KuaDD2&-gXay&hF%M4V$eD_mMY)$A74QnXu!ykF^TnQ}(?6K&9G8)h=h z@rN13V+_Uya%~%pj(M*sb-kyFyXBynyhpU!8!9a`Pa7ybYRfF!wL1m>^wXf|bzLlk zM#v2_27cP_jLV*`wkjjP&VKed=>uasSa;(>EBF1(j#9HIGTRQ^ERP%~3(efJGCvF> zt8ic)=M-iTCb{eRW^5;J@_l<+fg0|)u^#%iX*&Zit%udCsB?IX$1 z6M%2nh6%sTS3U23{CRuSiEg+F8Hmro8;avKUSQd==D^#uFARljZiTM!pOZ6l&s!MV z&O71kkaeS!Ze7c5Bf8*@om7|66nb_G_pMvT9obd43eWbyx)J1ZpR2VBiX{#QsGM~X z90^!Of0p5IDis>I!ZS26S{Kt-7`F%)hUJPU)my-AIXnrRH2&Tg=3(GdLC7Ka|6|gM`gtj2tE%&f(@B`bwOFuO4AAE4Hq(R|P zeWBXsj=tV{i`&Ec%FNvA?PGl|QMYw1tExl@(-C319#o#Wd#COIdlS={mWt0E@)cmT ztpGT|zsL`1%b_wLtU>;dpW(h(GD8IA5iKZSAU5-GT7+^OvG>K!(>bj}Nt}7ZrT- z^4TL@V8w~OEa%}!_*|TnkvgN?nF4*4&+t0E$$a_GayE-6%hmNozBvE>#YMJEtBb$p z$;IPuuP#6dyvXBKDrVvzr>zImpXS0En|mK_%@5P;J+s&s;{MFq zQdjZloUHOwnz&fgD>UAF86{vNSTRqw%*=n#s{=dc=KU%CMC^^wacfjB^&00)_zL1c zJXy|fK`CV)Ryg-jOvi0^cu;A*o|#*LLBmw=fKJiEQ*IAP)>(-d0r&v#y%)*{^tI5& z#$yaPu+saAUnz-h^Z8KQrmHt{g_ost(4gQ2E6`ks5=2x3z~+om;3eNaV0?iy{Fy}R zI9;zB*RRqVyAlP|)h79MxzMj+sYfc=ak5huJ^B{512SD>eDJI?9f{=uNoUI{pBO*X zKQ@w&_D)NtwZwdQ(I~F*c*$4So87G#>nhssCei3S+x8_9awJ+Vi?R)H=>`hg^{O|! zMBnA?*i?kd4yDj7fh*=CaRID4YmP}P7LU5#Sxy(WmUH%4#I_MoOYZI^pWZIt;0hkz z%Bd5Ep>aE}NZ8OPvJsmJ|60Fw=5J!0UB_gAgI=zl$SS_yeHCsRW8ao zZ(|9364*{H#N63@s2 zLP!x;$tQYj4|!Ym=~<6^);6UzFgWfXVmQQ=f!i&RyGik|=(yaLuGMdNXxx42+19H6 zuKT8d4qjtGjhc`cj7kF=DDBf4B5dydA*8nZ=fROq_I`Uj_2n?g-PZY2Z(a~a7vEk@bGRwb&b-Je3e%5m$8(AxEMm)zve>Z-JB=f^FrCcGiz14WEO)Ia z2#VM)@+kD;$UdN(VdtReaXk$?C%fA9qqE^wPs66m;FINi4lGwH&q3Na*H*=6&7+%) z5jo!Aul(pdUm!Til&2u`wy34g&(PES4C|W3xl8FbxXaOJAy-XCTDwb^wVkpnU@VzW z#d~(L&N@CzB0ug#w_l+-L1yp1T`%RkQT|G75n5wV(}F#!m8F$CW(Xeww1=p!;$Ejr z2db>LlDsBH*wJ^Q^bP{#y5Cm*x?J8>pR;H-j%s~AL~ZMbKI9Rdcus>Sn{3dIbYsOm z!2Hm*#5COYVGTUoJkW0D&gQlEdScL$Xw7AlUc=V1&7Rjh<2uN$bf_-sXT|D{#!6oI z>0e!)w2Z@|l-*cLuC;;{DHb=IX;o3xXJU7#T4 z1~)fU1o1ix`TaOA!C<(+Y-Uou+6?a@o+CIl86apD6^T;ieibH9N8q2AO#fxUOqjQJCWwC$(+g z^@_-hqcp{6o4M!3rst)uX9oa_a(Iv>R*_n9Vp-+`VGvDS7b1A*MLWLgdqYFJn=$?b z#)d-}R|8IAbPgN??KEaaav2 z*40lRr+hlEt?Q>%T;wkWD0vR@G1Y9ja(e}}2`N`GBwMC|CF+p;mTQqpv+9{J1Qnx&b!*IHO zvyjE&Fn3BQGs=JURPH)6H}F|;*^-qWeqLncx%y=T0g0&dyED^T@^QTir{AMl$bG#j#KE1n z&UYI%hTIA5(HT`sY1BoQ)mEkPIY!0Zp*bo7XLXSeQ6eYR=>zo0=Z!$#8yM@ypS5p0 z6iSj>QILl3L!l(t_V=w;D&sNUud#~nX}uqpG`u+=C}4W#ATJ45I;? zQ!j+?1QpzExOm%FGi#{_){f2JQ1x+D+5_2df8Exs_%I4iJ4J{T-H~F$hS@%fZ}Vy7 z#0i|jDzY?40zkoj9C)S$Q+||0xf6%6X{VMOn5JtNnGbk53n77N#-W*Hxw$2P-Z*?5 z*w#hsri=H0j{PP&-q464*tiC`>vGN01(YIWZKcqw1hyhAPCZu*!(zO+ug?>UyK5F4 z!9>P()NyCU1(DhkRiYE)x@~FfqH3*=Taff$Z}J5OcBDW}BHKG-O5M83rlNmnx6l*` z`H+=W-H+F0ta6{XVe`AX%H-adN~xN1r>6Mtw0%L4nqd1TiL13f&(RF?LXMf7U9gSh zhPTp!%c)Li))G8|0z<;)TxF%`n0?)bF^7Cuc= zom#gkE^EVP$8461@h=oFAj8k%wG{0d9jz&FtI#h%8M;tRG+>KXQFgf19fhr}t#3F( zE4|St2|r$a_3by`y?p%jOYPv#C43t4U*dT$R5Y{=P~q`JR;KZy=1&kMdHs~GTLhog z0Esew!znzmj%`||nIXD?oU_x+QX)3dr%<}f;EiMAjdiK4($vF(+i zR;xDsG&p;d6#Vz{P8@_>e28-)E?pK)a)E5zu9j}o1kDOK+9JZIp!~`I4NhKkIv-NIx71L z!zZnf6+j)WHCd!P1pi~Pte}b)Am6;%nk{plcA-0XbQ0#u^lnA-J((BFwVX85a+TiA zU#p23n~&Y#V3ev0b%kji!Ee*BbY{+)#@+3KvJv{V>A2d62Lsxl4?yJWnulZ8zNFoODzOb&_i#y@tH9+KHlvNpcbMl>W&0IA65WN1*)1pqCFFM!mHmY##J!% zlRZ;~$EM^diD!{%wcOZsyN>x(9D_6AtO6)^x$5=MmB(B2^0u0ghje~7r=zXUuD*SN zkI$_zbbo|j`1fad>_}Liu(otrY3zr`K%ingK)t-BVLy|{yYBHMG>M=Z&g*4;e}wIr zCKWg<=cQI68u2S;{+e26vMk6shpAIUfR+mvWNn}&z<7;*D)Yqn6=_ZJDBnSrIkchT zNtNo3n>wvaE#w=(K=;*Tk*_Z@Pzu*MI&LJh<@JSaTG53WT>uN-o|A*pxdbxRxopGv zV)^Fc$1n4Eh0d|7{O8_vfz+9gKog`fo**aEEoVIom9q=1*~3Qn-gzhSr=0CAuOfZi2Bv!W<8(%8M=H9+0IkEV7fZznW#D^oy1d5b$$za zA2igDThbUJjYj2;4pbbWRG{?G)z(3BNx(9yDMwuq%FuP99KJqtA~#q*yA-+k4hexh z@wS2Lt|-bBE0Q)?=8#uw);a6JpJrcFNBjc1RsNF_YPNOZg zJRwztIlHcgB9hWpyj%h{%HOIBzvW}Kh?>ECT3fKsFVZ{Amb(J8`5n zxl71_>h6}8)4lbb5IR`p*LSmcwSgX0uU%Pp3|Pf-UPezJSc*>2te)aQZ)lcS0OfCS zzcbI|eAe8e_=u=7Kx%PORjn`X7A1%n%rocLvn4R=`RjO9BG0hg{)NC4#&Ng=bu!@~ z3x9^M93BN#BIc#%_(Lt*ew^0nr@cCHcXUfNO!6dV-`WP!NhGDxvnc`zDDtA3%8;6WgFEm!=_M+ii1t6`L+UHe13Da(2#gM&egMr^X2M z3tWM~to`fTRbHHnQqT2RCqOS`TCJH$j%lib8RFT?FO;7HE@9VrS{~kuW=#4@1C80$%TlvU1w`m=@q^f{ z9?6}G;;gytd^9E!C}5lJAPvek=fkTJ)vgxXiQc!_PbC)$rmm0m{O?V{)MS6SrrGF+ zaBvm01L^khOdrtYRX$Lm15{gZx6y5GAy1ZLq{Wek+B%Hkf0{~ftw z0~~r;&NTB0FGgM@y?D)bB)IUt;qy^dr?Mc1<?QHxa;2R^6&pGkhNwBE?TWaf)yCaIi|{~gLTAE4?($)C zc5lS?oxBUTvEY_r7{-V?Z){>vZT$9R)1fm9-xy1+>0S$qFYBhrO`6L~!|bNT5AFlu zUJ)6NwLLJo|4M_@WD^yZO>lWeesPtN&u`cF8>&E7dQ$=uys57RezgGhBu*`P=({_4 z+DF1{ZJUlq>a?YAC95x%wU$m7mO+7ushWm4W5f|w0lwQ5UhfDGnxrK3K zaxOju_0kpM<{rgBAs#A*TcKN940YjqPa;MkNFORA(26E zB8cdh%jGLtfi_tJIg8Es$X0i^NSa#^w0xlpX}{L_tWW9C4tZ`s>1AH6IdJ(>R?(eT zN*UikbO@ai(N}Vw%-Xu<0*d~3r~KB0sf~A_~&LvGUBx?Kldp z#4SQEM{i=+GGi}KGRMz7H;UafjU2}{v-BXIcBshnx9h`u+JPo=Czf=r)2bQg6HHrm ztOe2Of?eTJ2;&6rEuraA9Qsy{6EuZEZ5WOdzbXxmh@hBH&N z4AFrTnAeJUWw6gxe0vKlrh)_V2^~Ciikp1ABPfRIWy5h<`oA>dZ_*qv&oew`a%Kpx z$8*|yRD8)r;>6XxB}#CS631F21I1rZ^G`P25v^t%fiZj6mGwCGApS;ePhog>*Tpjg z!UbNsY^YM7z_zN4+|C^*$o(wKqrC7FKQwbQaGWr8BPUPt*h;)2Go!?HT-&uQJM_am zN>eK^{UnWpgQ$!bG`qcT=UlDUAsR$KaeDzOak`{?RMy5XFaG9&kBz55BddWRM*|ZbX1b@vq{|)JY5^*&Ie9)eIWzlk3Wzc}lme-bf zBC7k?u-XfaCL~MliXshR};>+BTqq zpEopRouKP(|3VY0I6rUq0zadBf}gFu!OxtWAHx%R|*TXG6v_HB$3 zCMfo)VH$rSEp(3m7<^R|{&!ZlL{pJ4Jqvk*PtSDuAkA}=zm4~x*BANQ<0~LRO}#e3 z(^3=RQOsHu?OInJiBJp|3%rm;D3E@ZNBb;LJ>96IRRK+PyK278_jC9|LHZ;!1yjhA- zsA#E3w^ncIFTHPe!su9ylFcTw&WQ)n>G~Wv%T;`Oiu~1noHW(-X8VM1`&k$#PF7@b zW)^YgJ7#KIcAQzRpLvlRIPlmFlOV8y&`o_S4pJ*ia2--O4~>J!uph6pUmans(KJug zwG3HXG?xQtES5`bj0t_agmJ6R==+M#K+v@reBfALC2*~3Br7@rLQetO&u^R45ftjX z#xF8xb`P^E{<_ZB>du+EG{INYtc|?I)%1%LW}FOaK-Jp-M1%1)-w7iwZiODL<@*gz z?5%2X_fO{7)&$f%>rIspuBz`?jjE!ozF#ye8ARfZ;@hcyXZ~;tp)w(inIoN z%jTxt4cK*NYhwfWlBGdIURL5(?t?X_rm!gBgAY1Q{Pc1_8--|pUWem5h;ZxW4I25w zi?`l{-$1}ORzJA1K_Why(1SUAxR4*O4THseKobT^)+RycShK^V{BW%qCFk8HZbnd1 z5LvNrN1ho6QRw8R9s7afJ5dTyDYP;xciqsBtk5)F&rj_%catazEYFFo#BvXUptMNj z_ZQEeJbm%_@MvnQ<+i^8Lx5H@Y@%iX-e{YBHk;v17b#vy`8qeAme(bQUwt9tuN#kN z*UJ?wbmqnhHRZHp$K}#q(#DVEI(3DVyalr988GK9Kz0cr3yBO}a5jsqyb}F{bf&X9?lHzgIXSn~^VCb)x^i1EIzgoabv&<9;w!Qn3 z4?=HA@nYM{A8=>+DK7g`Vg$Ur7H&wlty97~s10b+4; z_@0wD&k1@?@#Wg5HPy5OM@BpJ%HQ#@F}84yx`&NSrEnvfR^sk@gRfdD#kCQ5uUlQ> zO*|_Mie#rQYci&mFqlN}(n?69w^+F@~~x$z4gQ~E{jHm}I>h&3O+uNAP2*ix6( zpf9(8j%nwQ`Yvo;#l>197BNI!mY_YRj8{pyCfzDVH)r}I(FNbI6To8%873WMU|PJ> zFQKI&z$3OuZ#?c_lK(Duij_UgHPJl|x=#B9dsign?OHpQ=GvsMBP> zu9wf&H^K(b1>%iP?=ZAN+3TnIbeZ1Gl|`7sgD4SXj|P09vDG=70p$tYH+kaxz3MwP zZ%v$uOYhI~_073(KoG~}v63JE3hyR=uYTTGI2A{+9;npU-bH*{UU01Ji$7C0SLgUs z^z}zh`*Tk}M?1o;SNB4#u~p2mY1~?F$BI}RLAGF^vxbuFab!~$z|`KLzSm=L7HwI5 zvf)M5e!<(quiKAdl2hu2;w^{(`D*m*%WG_?ftZnvgB34_nxcymPV;0)3G|x6=^&#u7?O3_gsX2`~ z?DZLjW3T$A-G0cTxaqp7r&~@)j^Y5!o4CALEh8A1M{nuI$G66F zi9MbPeQ5l5j?Do$e~Z4`N@q%Sc@2Q$F2Uv1Jtd@c7xeGsHY;G3%<`gKNDqgxG6z69|^E*o;a#zeMl zhQ_aUa0dA2-Ng7xi`vI^YY2p+V+#L%wufRYN3n9nh)PT$Z7?_%*21XH8F%SeO@nBY zMxD(DTouOs@@^#^)Kztr1~BVJo(V7hN>*9PI`3|AOo)IO32&C(&0=+fx=7rtnHq1t zeZKwk?DNNupFMr@%zymc4Ii7%=bt}+YJ1PZCr?escP-a~g?44}2+Yb`AUn|!Kqr7O zI|KqWYkiG(*8{g!fY{o7r&u{P0kpB)h;BgXeiB_tdNkoE6P1|fOVAda}^4nB1K>p{8Z@xbN?%OAZhz%T9>YhfN;jPHpv>5qSa@!Uz z>0ezom}dJqSjX-F56D+CPb-&DvF?O669Y8U=XgXetv4Vs(z(X;ak6}^&pCn>Y8Szd zbGUE<|LLt2Z5a1Q_?%&Z946DFSqcRBf4Qk)bQs4^hZ}7kYq=w@jt5l2ynTua z>A_6!5_mT=p3*_erfR9nm}bj)TrOU)7RSp^P}9fck$jh~zo<3PHdd+28^tr54HJQ7 z*E~c0z;29S9w^{p%%du8=%5z0wE0Sr>xe8xe@u&+r_&Uz3Bw$eJvYx?+f9lzbkf{+ z5<8BpFo|L-FA~p;%-AdvKg^QM%5o>M%p~>wAPD?0^s>x7jDvF1yXERz9Jt@ozecrS ztb>i_8??#0W+3Ck4+H-GO!1I0`q(0iSG*cT(JT3UGRYTyM^i6JIy1oCN}7+UX0HC_ z4F=EWD81UvXmT+O6(X?CyZUSBq!$-9l^-*RTI6`DjCdF%bZZpK-OYb{6s2 z)fr@UV}dG-nxGn2uB&`jOz_b9dYLX~kT_?bp=Ji`^10|qsm2V_|4 zbU9DT1@~l$H^C^u6KGe7%d|5)`?LlZrghX1U*##j}y#x>gYg@(ox_{6+i6|@!E zOesKYX`7c?oFJOe>9)8~g{$HH6L^xVsFAU@gTkjT*+c|W4J`d<_bjsdxEkpVR#8%M z?K?y$Wca6_oqe zE^BA_*>e*YPFhAiX>rw!?R*SRFpsNOXmPr}E3^DUi1|5*GBD_+KIB?q>gHy06%21bUK-I!iDqf31uq9cy8D-I| z1HLS->#b8ct4sH}y1liWnDfaO znDOeV%pq5Q*x zqNk5WCH0qK)=IW#ocpm?q{RVVZ)~vCQvQj;w#j*B$L8k-}2ZaSFGxE3M z65!SH?i#TJMtXcS!~0PlJ-WLEltmW>G-LQxlNglWkMyvvQ|TklmiJuxk=FPAw9W$} zt=dNdMX&pJ4SC=FYb0^^$RCz=+OPpNv;83G+07~I?9GfA2Jw0$pOy|k?d_ld>56-n`l|BU1jpFTH$RCDJ3F4Gtv}eB4ok$X%Y3)2~w&k?10@SHSZONs8*Nt>a*P+c&R5EHo z-mA%khlvu$8i!B`opopzHFkpLY+qlZ;kwaDv|l%f@WBVo;m{MvA=_x?-ZdQ(wYK_Z z^$%-J{<8)@p0ycom#bDy$=-Ul2<2JNI~2N2?}QNIYw@;rzaKDATMPjjldA^k)txm5 z@T|$z1MNuv!G|aoDzxQZ^C1czYvdnU2F0TEXTC?bu2b6@sKtd0OJYtc?l4vu6Cjh2 zR4!&%j9@C?JYx}*XG>M%=*cy8g{@MZjgZF5N$mHKqnN08Vm!yagtsw5`@T7TI-N>O zLH$q}k9Y|N;?-JTo%D`+T>yTXmy~}6kiL!$y_6Gyu$PEC$j_Q30HtOxmuH)b<@pK| zJ&~noH?C`J1iw0aXl(nC+dSOSUJolG(H4Ezrp#9R+LoYU8^nv-*|zTWY1xK7ZIC%F za>Fc4?92)aC$wA(ulY?q+m5mzFtf-r^8}t?h{D3fD1^C_rb!YNz~5fz`iHssw_(i6 z&?E8uw>PS_+cCtnCY(l4>Oqj7ler_VIHZPcpPS*iWeLM{frbNA2I}P0MoIejMgrk|kE;cv)m-mLI067pA7~xvp>F4fgg! zucc?|0f(=axJ*Hz!297X-#h#OHe)z!s&mL-H3)sBwRe*x^s3i>^sC7Fjzt`=HPvsueYxf>kERh4mxQRPR(NIWuj2OC>Pl8hGXX_u;ff_{1GPsp z9k8Nmpt4ZN`-eqocXEnc;(%q!rMTbW=H0Y4K^%h1sHU}Q<^!e4Si@+NF+P& zGQ$>lex&hg&RKl}CR*DVtU;4hW|>joWw~jYSqO8F1yfR%dU+T}agYav8~IignxU6k zp5?n?VVh|ZTfUz-wig~nz3KYmz3Dft(jf}2rM;B!3&kZBkJzdq^Dp}a$}I@aJpfZf zIcP;{m~fT06gC$Og*U@UN%G!mXhvn;RAexVj~oGEsC{b+%0%&sjPxQZ85*s1xv~%8pfV#f-s$sNYgsIf0ugL zIQ;o$`R2SP=Q&XPyp;Txk*%*{cGC8xL3z#8ZNMVR@(o=QfVQ(T;}BP3JAUKBMQIoc zl~32yp-Pmn?Vr zx~tikmlf?#iZ!U(U!BE^>pNV5DnXMTrq~80V;tRJdB+Ys`egES`37VbI{R{o7mgbX zy!wUa)CDcz^@D`p-|8uQ68xWhwbWAl6Mp_wPd>Zl9eOsyi!UnP?R>K|I4a0CW}e4y zRUAU?uEfo8-b9MtIW@+JDaK#m?;|4_WFOJnUXjn~sK%FzLpJ`?2Q)qgTU~wtQWxeUiR$u8ShAos}3vQn=kKzYSFi-&c7tW#Q&cO`>x} zmr}3;cwHn^x{{Kdf%I;nI=1_1`TCGlH_i-=C z5>tdGU{({D6-rj6YB8oa4$oq_M%Vf$()AxGJ6kSSCvV~9J(L2vd^txS4s`A1@SAt! zJ&>nFab)Tho;3k%Ay`{>1U+jci2&YcB~gQ0Jo1e^MhWvabRH-9@A7%N#E4`FQH(nZ z{SOn0A?CCCD9PK!`MG@#oHI$6^9$R$n8V_ZWg~qfoiwBSwYlDOtd1G1VwAxaVMJ3?@p*;%Pd9loVPN4zr zW*C$l_zU<7t6!M%0d znvnVn-4S46L^QakKT*+pY@^Y+X#Eg%Gj!-I*_6$DhYv-s>uO`?<>|KSnKAVZD zCfocit|6gXU?jrxr3gl_Qc8iQ>4sL?B$p~rdsw$h33@^aZ7%uly2?+9ZH7uc_xX&+6U`li24mx^ft| zc-XL#s0&xn@KtAKoE1_*TDg#*OfnC#!E)8ghjR2LzOV2`YpctGjZ^b!g}2$lxMu|89rS$ImXl1-*dANxc|!VT8*1xJFL~;}68wRnHma+sv|}t|mO# zQk&v4tVi(K_8Ok!DNdqPJwtQ+4xW`SxGp+vh^gQOj);I7B@PjcKAss`Vs_?hbnMTTcj^{RMLgoR61QMLK+vtc1BXQaKf)Uz&bu_k zm!Aj^T*(ta&+stCSZ&;n;qS0-H^_*|cRBsQYM8gB$ddXw{( z0&8IqHo0I^@`iaOBgtA@6Kl6(GKkQgD28V>?y3g638<^lo`xz_tDy67!FT&puCsiuE!%IllPLP<25 zypd7U_DCEOmcl2Ib1z@r*G1=4%%#xV^{95z(c*%W>o0rU+;-VbdMqY=29q<;ml)+j zY6s9eFj_#G+7LxoEtXsFBN=OZIIAtzvYuV$h?X6qVWTiEWed8vStlc1_$n*LFsygTik_PuvN2iqpAf862D(Q3IA!OH}SmoX9q&@bin#E{QVUVUtxZp=*yF6>rbd`kJm8;TC;4KjxCTu1F~cYms7eu_(Zjbfh>9swF2W{`0V={WS>&Q=_o2q^D*KM zpl{H`;iNTCy6_NYsX)SJdNeDg5}EMv3KSmT~7Cp*)#JP>IKVLl9!YR-`l$4NUcg;mrP-PnprakF&`fD(y5l3zXr zD*pv^)gzd-M-jP3LPSc?bGTAX@L(ZcO|L;b2GUP8eHETE5kc^^5#|>1 zlSY-KdA;=}%wf2+0ZKNHMtuz{vM;ERUc`wXnd%agwFe77a-@0_yxUfxw4yfB@q3wfN^3$sOpekM#YWaieKB%Ubg@%KwKA^&vMGhP51L}QQ zHh)Z^Vz^lxw`*|Y6VDTn}x)|J;QgfyhRfiMv)mvMc!4`LU|911x0T(r6 zRPmwKG-I^zp_Vjb6!4)|G-Gt{)&LpW zaSwQW=tW%QPvUC*TO1+M>ptbO>O<`qKks(6O!Mq+Mb>W_NnQkUtPJUDtpc z+cqYi*tRFOZQHh;$;8%7Y}>Xvb|$uQdfw+d=loh-yVky!y87y_uD!MwykAlRezYFSWl#rHIuBjlLcXuFE?JsaG)k43tQK<I6_dC)6ZU5AM z%lS5gQ0Ld;CYwYO?R(MbvQKS*w zS0sYTiw|?`A#s=yT>!!W!W`2w^_!N@f)V`xuUZGN`Rc+Q=A%4ee**71auTZXa-6k^ z2kSceCqTQ7KxS=-5biTaAi9qH^H=zgPS}x=yr-1%R|tTD87M%!r$mGFU8nf*284Fs zm=H{Pp#}^!kSCZF_h7<>tr1LdzHKOm|9)%AFsdzqHcr2e%*Te?jxp*l3e-P84Z@`) z0QXM969r08?=ycpqx5UV{1v!(81I7XE*wfOxRar3qI9ER=6vkm%&A7fsQE3Izz|`P zAie3o{txy3f2d*N|4_rk|DkZcfT-Jqf2a?fBkFwY4sXkF+kURyFdZ%-36Mz!i#g_mH_L$`5{!}LojXQuqn(0YC~r$UOi^c?43rh)KfP{4m1nkdVBqfK|W)3SbrRK)kC$g7ojw^H(;Ifz<*Qu1~mz8}2@H04SjDGr@s{ zrJltnM7@*n5#BnXj^xCH^n`xy7c;rGXT!OaAe*&s#6Opa=x^UeEwFFJo<~doa~(kC z@<>#M9qHY0WEw}54BT+!97aTjbQ&Q0w&BPah))E$9Uc+hvWw%2j|A1S3uB9a8Q#2G zkZ9*9W{7_tW&{3)@xiF#AngPr}55N!T|YUrNm zH$)s_wywm$aTg^BHul;PR2e``a7Kta;_b7mc}2~&j2~tKeUhR?wb9XHYqy8)01^M- zzP~y>w&C}3kWMxK$eZY%eP;2-Qe&E>w4(E$2tx{=h-$K}2l)Ue6*XgD$z?**{!88BZ~ay(BjG7q^QD^D>WK+cTg zw&2)FU+a_4AVeL$3^PsuGnO=573O1s>PM2OB?CFPf9HYg7AR=FvO%y^R~khTy^oK? zHW9+U(RF?6BTG4uYu2hp7)81ddG$7FbAukwNbi7#19-D|7N1{K%+D|&HUzku{xXHB zsDk?>p;gSJ2|c-FY6~X)v5@vk}6Ig~1nDH_RByy`qF;Gx@_4#iS3$tFa)=v!F^~3C>-WG z8BNB-Z~AcI;fMw`_cf-o&!}VFW=rmXzHt4Y>gs>0Kf8dcYWM%I>My`QRd(|#{>Zw@ zpc7q1TP71X^^s>UCX)yHi6=9MM z<{5uXZpFIMUE3o;T$1ySe$ph^t#u=h4Tr`zNB7WtbaKgDf^#`JH0!ECfx|;m4;lNSHsEwT%_e9 z@YGU;xz(xwIy^dAi#ih%mZga$VNB)zeIce3pX6mpJ-CkZ_ee>j1Cw7cqjJo ze`z^(tS(|&79Kd(RpO0cP2&aY^f2DsIqr*H!Zx!o71(f z-$lh}+6%7*MPF!ekfwNr!+_TO;gFyw%_<8;?@|O2(h`s@R6mIdaS@pnUIs|p1PPKn zf|38Tc5kWRe;Xe<(q-i7>$_TXi;Vhk65S7rcu3{IMRY}gIy58tGR8|lB)B}b5CpC8 z#N*+eZBiB?;Ks8z`!|xcOp@E#yBED|gvXKRy7RC8h+KjT;C?njPBNRF&}s3Wno17Y zbM{{ISQeUyb@MFsuM<*6JhurCgkT((G0$G;UnQh;qFdj;N!QP_3ngzmH)J{Vgh3+_ zCuPi3G7?9Atkl!7|#RPVF^;J4lJQvY^mDlh#<`(==J}n*N`1DH_ZbQsbX9JMQ;WSV@KJNe*j9g6fv}Y-o>4=DtNB*} zUg`!>^*KN+Z1ht%&WUAUuB&6pIF&n)c6X4EU7lmve_YwEBf9386CSGHBm&U&ReMWaN}N)4 z7mr>dr+>|iD!1v(c(FY0$PLt*7Tru?TNVEFJj*&JCdDRG^!e4@WF+AP1ob4unkEL% zuh*0o%@I;#L!b4QA)g2#v}1+W_k0XzIr}w0u+tnLwTli<;M?lEaTdXPLoQfJ{5V9s zRxx{LHK1>~*I#^9gbO_9GpIiDXh;Wza;Mf}Fi6sV{U&d4NSi*J7YuCwS9z0>rlI5hZ8JgibGuM@x&0kkUdJ zX|VVonnGP!of24MZhg}c3+ZkPNg^BA ze#p)svoN|UZ*$~)bF1X4Q(lL)<8%W)6z5DeF&{DsvE=O*(UZ$?1%k*YD*PO9<&5)t zUjeq8gTmGZY8tT%J%pAr+*v*(QiLTVa!q{lY!T6Oi#Lpq<9i@H_a5=iqI1rSmJLkq z@b3enHgd*j7W#s+2A`dgQz%1WsGWUvQ*Iin7l_qAU&As0v)g$XfAA*6-U z>mXmL0*+GouB^2&r-&y^Z)k9CK&8h^B z(5Iw(Psa#jt+qj#`-_|QkCi!sZ3)TJ{oR|JKKG+a@vf_}uPB?yS{1n(jMlehebY*v zGT7scXmxP-;X+eY#&o;3bkfg*=%`A!taQ2JAhhZz<+j zpGy{NH@K0Uz0w`;^eBfng+%=OW}p2E%aFSq-beupNGQY8?qHN70Pt3bjMYM6-&~PC)vGgp$V% z2_Vg5|=Ri9-ay0C^|oA4TFtTn^ah2m7R+t}rM?irJU??aM;eT+P&8Yb=Q`N#jh` zgLIYsDY=X-5E_%9%4p}XG!h&i)gU2ORlV$ei*M+RVt7_;vm;^DRGa_`16wlXD|ie${gA7AnLU)Y61F9%4=vnF<#$Fz1oD!5quX zZ3L4$MSl_$Ulh+V)7avE@}$t8tulMRCaBzES{2Jo^ILi7@*UPC{SM#=Es<7e!>w4R z5bbUsPe8OmuicR9zk&%+{b6TYSO7vBTQ%XjdvB((!MKvx&1 z|D+s#nWoQA`wrKm#q$27UOHnplGa9(Hdd&jH9-f~?zVS`gOeMj6?5W4)`DWFKBuI0 za(O^eaa>XT&#hYtGeZ5hE3ik+@28Un0slI<)RUEXRA4exo|&=X<{Az`@h{r)&x`z#+Fv2Nxbn?2SN=YsefYyFg+ByNZFXP za`sEPkaXElOuW%Fg{fk1&=aEebCpxc37@dvhQM@^&xO*7XD7>nl2n5k#H`%>A>Sw0 z#!5%Z)1R+Yq@Uv}lqEGwm@}EL{9BXg3$>=2OEASi%hEdetKVtz&WYFyUn$lOudOL- z7DEcH{7%1MyLG14he?C0FE0DSQyXA{k#gv~+;Lo1w_o-lWpq{@h3~DTWa^*xl7tSZ zJA8FNNdIj`>3=C!Z3U%8km-eTlxv1XRLpYG%RSKP7-8~tz`^4k0O5~X~g!T|4AIp>)vZO?tq6q;XR5rF@_Nu*YA{9rQ}fY zOVeDlf#-HBR8OT$C{(r%7&O{Qv<497gneqH&dG)X1FlBMROrDYydB;}VklMC#&4mN z5dvRue>Dz7Z1iT_YYAt)CqvjmJ&-#4Hjql8j&{)s;!q!xw*a#Xqr;!ZUYc;F2l@a? zh?$RtWo+h@5{V0dF30p*cZz|W=_^}?9@pT8|L;PoXr26*( zZG9rAqIW?6kutyWbU981+41A3-DW&bi z+QB`0kurL01<~=w(fLfMNLPZ|==y4mP9Rq`c2dFG5KIZZ_)d=CAQiwUcJwTD9(+#F zm2gy+e8nB40#=0}V%V`yF&V^v$dZ$X2Luh*N>@K?OkSls6!_v4v;%)z@i#h7*2>=S zp#oA%7NA~S>6W(om)JRNx=I^`iG80FMnKI8`1vgn=Am;F$y3>-vc6pjF)$muM|ugt z_p_eIQJKz)$UBEZNG1+Dxo{#R_lj&e!>x11WKZ9dm8L6oJ;I@rTIp-NE--Dwhzc5!{895jH zhw5?}r)57hP+k5m3Y`B|IauXoe+upg)o&7Nh;{-u64EY79KL~@Eeu4UyL5{0Jm;0R z78j1rhEbT}+AY%}8gWW2eP3kMR?sUB$+=k|D4vRD`IYyIB}gw+lV7@9R^S`Ghb-Es zV4@_F1h(DU?U`wgn7gnZd6m>cqXCzUdnn(lFd)R&G(g@2&oGg2sDj)|I@$(YVxDWB zFML7%_-sYgcoy~}XVNL%*xbm4;Q_#2ZW!jsUD1?d#W1SO2}Scd zVN8KgIBO7|9$G9quid|c-TJ*8ifT{SKXIKKEj`zJ&nl72%Fql+@aI0ZsXmc5cgryR z(84V3IZh+1U|fuQ7l%+Xfmh};r8M_1=*5Hq^8GRrqp31YELUMZx6MK+vLk%X$iszi zF02V}@P?9n4+V_!qaRN2bHt4GCh00-+f|k(_&5CbkuIQshJA8W1#~5>S`}@f&386T zXOKdjR#YZB{;44q?D6P)PkY38g9d$+IJya8lW&+Hf=>UUTg%u%VZF^yp;1GHP$W5Ne!5&$bxI)&g-oE|c0+x1l3rK3rl`x1#{#~6YpBpLKsPq#do zzb7YS%!;G_Y~;o6{A&jD)A2qNq=dsJIBFA=rc$OtrcfQlx$Y8FH zdOkAs?#?MFh4@i%s6dXmCyP&SKpLdGV?VeU3DvHu(FiG4IsPCboyFCXbpcn2Xc7`L z#9*hASS9gU&KaOcF29FSdkfw+Bf=R*T5DuIHV;-x%M1E4o!uy9Yq-qj5z+`^cL-ow z^9BLi{|3>tSV?tJU~uAWHaG+7WsYwhQsB>D%+S@D={#t09NY+UL~WpZ9pDwUV|mig+Viu1`gJ zBVUp8@9B1GC|;URI#bHK7cG*lQTU9i;FJ6On8eaeD$!>RNO*7fyk>i;Y5P8r#WU%` zxqM~yfUO*GAWYlSL(`MeVupwnnRNh!4#%jb`k*C?-AvD5E|(Yu!<`+TE{EeDehQ}Epw{)!UrT+txMG{?i`qu9 zdL0jZdyI$ex^qjN)cmi_PqRZK){^b2ykiorUq&^B|>oo8y$wIGps zkY$(V9Bg?karLweryZ(RtU$^(Enq`17!c+2x~7&fgP`prM(G9+EWPNXxv{ynQn1}+RaV)xg^;>=q+^fr zTV54*fnYb%Pn1$!96fhXdzOKeht;3|=tO}#Q!Hl^vrWFx%MzTehWks<*h&gW^dXE> z-?fhSM2STD8rX(?fVMM|5@bX$>2-kpK&Gj%EnL)CNxe(b7LK}7OgYcl=<0QCT}Mq` znkD^|7{q|xJjgJTSPp<^7vnEgA`s8aW~Z2TS|tKWVgE77#M^;s?f#f=XCVpCqdot@ z7KwL7_l&GQrwM;sR55<%WU9><=p1wL!|N-eJfn~T^Lbtb9G#Dy(Aq2Zefl?R!g;X& zHxC|5F<3H|y-+r<-t1$E!UJZLc|ug3RD2!z2HknFx|uY*X6pe5=)aS^s=X1pF%P?+ z3U(n_ZM6tGYsEUvZuN*A$*f^Rnd{&s$!_HCb39;IPKYo~Z@PF&;_r+sB@X}#+oe8L zBpqhsW@W^EB$a)nK#WoJYP-E@ct@ddtli6#{no+XwqvDwrH`!o@cEco#o6xpo~6wD zvob96?pT)P5N=`9Pd{dc!iMT)=4qKgr5R5>ee)v9VTWGjI}36Y*}#&!wpo zS`;E>PCg+n;$k-dZRf!*Yhk%DT->lByBNR?TqnA*FDx^zD@ZEASil3vRrkTDheyK7 zptlJiB3@T_q%fI3D;{g45;%q{^b3A;(WsZBI=T4vfd+NeMHo# z46vh2iHVWX#hVW@-4B&9Y|Ri3<8RsZ;Uvc6DNt)VY?5*M&zM zxAvupAO_;Hjoz}e^ERIMWkKVMwf}(|-zg_6qRT6Mv3L&pA6%`hr+J)b?B7%)A`9gQ zj6zb;$A3nP-83OU%6SFdXlTo=nKg_mO3Xq`zfT#H+6lw2j5Zegkkv~rwiymhww-g} z1-IZfg5JSaU_U0k3Ee3S)7BUzTbuDxU_Qm6zaq9bXgHJ2rr)nsitBBh6*s@dpJc49 z5gt6X@~KuZpX=mss+Knu3EtR=aFbCjA9c{B-9ytgZ{CI^2a>RuqGx(uhZ?+CIK_KGY)P;aJLbA-c*n36$K|-4ZuQFRQccB1NDW)pr?JM9 z)w&Zk)V4}B{SEnL22vczmw`FZFbe(wr+^Os(c-=bcCJA1!*@xG*UFOCRaoC>NJ?3w zSf^xK^?_+i9*36K8`g`b8)A=^4pak$QfDhXPSk{dkrzqm7-6_SO!{}x+|;r~g|7V| z?#ZDDUoP(uM^l}u6RK96e-&=0h*NN~4xq(+2UpG}rcM#L=# zu{cfRG;kuv4261GXQ6~V)j$@J3rAZaTrU)G#v=}yK%2AogxsG37r(^t%y2pRHo7B| z|MD7Law`#)7Srpcxvsq>(kbVc8EgLXGA5WsBjUlcpI!aD=?)?ipxYiZsAp$JEk{1soKu>r^!lGjV5iYhgxFR$L5SdREu?S4g)-&~H? zg%QIzNlh72lddx++WN%qNUy@ie_aq_q%{TJ*1^X*yH3 z>q{~&OLL9cVW5~(1-o3lnO>Ekp%mz4XRx+-+f4?feehFY-`@*UtcVA!q#XonHd0`F zz-A^-kOj>!O9p!*hkZa4m2d+_I&wxwN3-cKl~~xnQz7#M_s{m6p!|NBlc&Xtx+o zC8y~fJqf6-^eC*OsieCzF@fk_Q5)|pLK`V}1s%l4Q-vhw+CgIWi1if`v^~lc0`ZdC z(!=E?%Y_P5dRPd1u0OVrF-LocR;a8gPr zFYb_hr$$$c2-r88jZ+BeE$4H#619oBf=t1DjHh2Ah;_ezSU)RwVt0HezAu+gvrrzA zgZXJq9?$61@*w=N9Mnr4SG$ERZe&jtwO=ZI>QxXc#<0IJlg)%+H_{6*W4>J10W*bWD{`dm>)mPtd6jtz8L1(A& zBCqoOpJvf>aEfYKjq?`=tctD@9EXhG7-c)KCFX$5R+?0AWH01Yh>#=@-aHX^q>-J# z8Nh4ore%Y&y8EVDw;iy;8YK#8O1ePby^y{@qAf&V?ZVLj@b7SA0q$2~us!G$GGw$_ z*h69UZu79i?@Fji#9=7t+&ok+E_xLdjQEFop)(c$E+l7o&J`yVm(?NfrX84QHc+;a zpD@CCh6uI-SN(NhBk=O7`HwKSwvZzTv66!x6gsDU8hFpcS+j2=W$XHp zzYx~XO!%pLo2YA34RzEOLzYPM_K0e8Eu+Ar{^GtPku={}4vE46A~wYN1?bgo*dUuizq93T(e|s>nu&i7PVc+GY-I&=jL3D8xFtvK z?W){DMe=o9ZS5TJq^x*>Ycn>4vsf(b70AKg_{4G`KG0k`H;U$6dw%u><{n83+o&Z( z{GH3C4$k0NYYD>ju+j8Bd|bsJ`5cX(6`;)77bK$05r3yleC1d7{Nz#IRsus?=j*$G z{{z^^{AB|{CzCwN#D(SG{ad=DXLx}(-Hf)3Rn@1xr|cV_-y>HgTPOTX=Vd-wb36#oxHI6A zyNYJWzA$fix`HEqjMq^WjVKK!X^5~ZK^Tmc1CgkZZK7}OmJLsl!8_R>phG6qffg*| zOuar(bEt3|%#cRC7&|zWkgXM$u5h8A1dux~dZ?$Zz4;(_)CL-PSRQ1EkAwvLjOY)? zW~!!?tyr6R8Kj?vYWuDXp?x>m=q|mpl0*ljQyb-Qi#3@Ky1mM|q0%uV3uDf`B)rXV zyv569<)y&e56KG&>rO|8VpmsZWB^>bZA z-07b=YHp>w(g11?LG7JBqMilg_Az_0-=~>UK!oqXkek3g=-uCkyJDZQp}Fu?*-Pj^ zErhG~m`0{#`-5B~?`gytj`zy_>dL-{rw@JC4%Dae(p{#V)e-o91__gK^kTGJ;eNZ5 zsT4UgT#!tD3rSM7N)yoUR{8G zMfSZ^!mO9Nx_VHtxH=#&f4lRl7i+CA$U}+ec~7Oh;;6agqhAo97vvRH?*y;=!b8A`jX|_ z2rWWcx$+WlZ0y^OY8syLOD<}W1_+&CzD*b5JpMkZqVxLB^CiNU*hMb;L3=?RKQGTS zbp7rCQB5)&JBk|Y;UNY)aM+dG$|H=5X^M-kY;XE6 z`&}~zqae8wH?cnCF3zzkGO-A^4~@Z#qB?u`D%-m$mT5%Iaq`2MAId!I^p~9S89Kv# zlz)=C@lhk7N%D9brIf~|6{)nMt$*m_v(Y>xZRvs!Uncpi7V)xa)~)H>6SxTprX+ud zZIM#Uj+dZHLrEu}-#1gWxm`l2cx|s;f~*nZ>Sj1XLI9nCwy_gcT(76VES8mNn?=j`mOI>BF}D0W5KCT*WuK<8a3q#x^M=VolN+S&L&t&!>L%^)3!G-r7Ne{UK=$E%H zDYWIKR3RdoafyK(IwaLJ^!w!vb6T6hY*xpT z05sj9u>q}^@CGcTj~-?l(nB(phHx%O$-UCKmw?W_m;99Kc=Ptwu@NoxE!xb)-C4mC zWQu-}Z+wZno&Xz~ZE;8BHWUPQeEf}gHk~nZ9GQVDq&>!~^fJPnuMye|hm)LAViPuG zGPQvSf(G&3@~e${dN_FQe)9ShRy!r~b7q939IKdb3b96>^MM8QNoiryI6<7LkmFdh z2D^X6PV%Xu`<46)ObC7&P=DYYW3!cFLlXWf^0W;o8a#ZSi|tkI5)n7dePyS`o~!*r z*B>Jk_+X`&*!)tc>je%#>y0^T2t_d4xW}#;maUmrdPSR$7*B4mVuqU|n;J=!)ou2{ zgkQ<^I<9Ty8DnF)@x>3{!drWwSXG>(`%Q@R*ehtCa}k~yWQSp}x-|roxgg%z*5FS# z`Qu^t4Q5kyrq!|?%ev(Ua7RBa+~#{FM&3N9G;Q(8iMlnF^_G6oQ4CEFqrQkp&z>++B7-mZyQzx(1?sKv0uA&eAXxQeIp3qMaq>V z0M#KiO!2-4xUG-ngbbAk^Ga+n<|WQ~y51kSYO89P-{N8JV1OHTPlJIIPdiInW4kZz zO$SpS5}kJn;H>G1lkIa$!tP!^y%XkJG#`AoOr6`X0Ng2>jVwJt_^aSTb7|5dZFr!+;A0{(Tj@H$RnL$cLRfqd4#>J7G(ur*~@jeP9R zRjXsp5R!gmT;S8pYNg?{!Z8pT3&y^$1G7|huiVK13YWXdudad*=l znlb7yxOMdYq*m{57teqEOQ4MaVEx{XX}Cu-lVYW!c92g`XRRKD#Kcoc_)5qZ05ZeA zO96c?7O$nnZ`22i1e!P%bvB)Jbgzsb)r~P#O!TVEIbEt((l9ARJBcmm@7q6aPR?Gg<|Gii^ubf(6Il4%&fB%ax zqLtM`ycv61GqsMp(B$<7=YDLW5ipaY%`0iGqn)5&T9z6Q?z z#nFd10dh*e*Tmsa2JBX2-lw0{;-N(7;G~DwI{oanx;Y&3 zu6_P7BY^XNxc_GWNQGr-;czhcA6VhDqZaZW(D^~W{(#{|JHS)*KV!$%mw-;aG2n?! z%XOeZpz@43@K+qrmBYW8z}bvI7}R2umk+Yp{|tF#1G$p;MwMO9aTu-ac zz&vfs$QIY5q`Mfqs;SPcXZqa#oU?yQZD;{zX@M`k$gvLS>CN+=69zC*9p7jFKkp~W zfj}N8pmo}r4C17O?xjIMXHGd2GtMP~W>yP63h*=xr%@{~#vpZ|ZxLxe%RF)}4*zor zILjdR0jO^`{+~slf`ZljWGgVl2pq;KAPSfy0n3A~|HY>;`SSnTH3&|?9sb`zHT|+s z$2+i&|1OGk;1JAzY{53KH$Q!|8GUVoYbxDDH@zjf08oamwaq5v8H3)Y?R)l$9=U{r zdN~dq-;1@U61B}S9xF~YEB;?AoGZ(}3aiH-&){h*9@jhHMQuvZy00#q>wmWWyee5z zSNEZ<3b>$nmpUx%tRqMA`KTm5uK0ZA4S4Y`ar|tgaUsBq^eU~nF!j+n6cy3`xPS8K z>Gpg2g&gql_W}RgXnue3E;daSqr;c-=0tnt=@rzK--XgVOz(u&eB)QS_KR;1jSkbM z#xrh?K&XEJ?kh5KkF9;UXnDXwggQs{Y~C@lZ2m9FuNpa@H+@PuwRlBK03PM}JF`z< z8PdC7##i>@Sarr=;O_tgBEt6u)XYpg^a=-d1s72TGP*DN27W2CfB&Nd4>GroC2^zy`XzIYdmfc+=I?t0UxFSUe? z*HudP>pw4+6mB_ux^v*fS1A|z@zrKy?paiJg^W7V84EeO99ms%qAS;VOwkXzNydKN zo2D(xrFI9+LcZ6#3M>=J3PLO2{W<(?hQ}SS=IcKtomh}PRt+wAc{DC7Xh{S`=?uy z>21lwZr;pnSL&M{+$kjEMv+aEb?uL=Ogjo2{UDC`%VexlG=z*$TJ40dm-B&d%LJwb z7E@1JP`64;JOd=UGK#JQc<9N_5;K_JVsf81dNum8a}xqCD!hAmgNmQ(H&@Jx&?tSS zome;3*QhEs&rKI7J343&I21c<9KT7Z+|IwQo&&E;?sId6-H&_+I+~=zhike4zL%H4%O0r zgWB&7C5I7*6@>w@$d?S7DebHg_}w}pR&ZA!B#ij#tMKPT8tmApl@l*+`869Po(uK| z6>lm}HYviUolvBpG^-(?_5(MueXRgN0j=4AJo-&CvohhCO*7vwg9>F*PVRf`ioW5} z-zF<&VZ@5lX0HlFa_G)2rJWND@UM=Lr?QB(ZDBUrFAn9%{m{sCr_;m6x!GvSbc-z`~$-TFlb zAih}Nk@mgsn1|qT3PH8_$wX8fWE-$-DNY7$l%F6I??KkqwT$}wzCdJdDj-!p-GVx3JF$B1(YR3LhCiIc8lqM^yq3n#!kSb|C5RH=a zcI2P{&;m7g`pQ~lXltCvcA;Y$?P$Ex!(wlFmoWPGYKr&^v|Eby%uU74AQL+`UQHZS1mwx~&bpz>lF8@V_RUf9-Ad5W_eprcW%Lxcp6|_SbiN&sEu6(F zy3Wwn0lt^pLhSl1a(~(I=%oPy>T?5TF}6hK=>&zmQMN05C9WS7!4-mP?4O);Lfne+ zfOkg4sH@|-+jbZKRnk{h;FWlvEnM&Mvazqom`Hwg-sZt?z=udI!Tg1reQm*2a3Yw* zHu5mI5a~vnvWa^D!Fo_0d*JH4QIiNgZLL{xElfp-qJ_QJ)pq-laWRFGY3@@N@eZ?UK@r&2=_C+@|NX1 znKIAGT$w$p+hM!Y>tQ*FQHEzw^t>Boq*ZQRL)#m^CBnn59GN6JKcFN}r)vsEPv0XZ zwx^Ow!gi)>s1Usc#AwviR>L8G1Rvsh@eAGHJ6$GjSWU+nKYPU|R?4SLGR1!r;QUOw zz7+}io&MPlDARcQ#(cy7ey zcjsCv^b^$pcspxG&0LOvtRmEO=hwrjDsVIJdD;ozTy3gnVyY*@K?fOz>N*3aj%lzq z86v0Nkk64Ts7BEy#7^-hz1oEYm37>nTbwY=Rq{h=3k(^%9>a@^U@bi~z`YiehWZeGB$tf7;e@i=4&nc$-FxKkcicQZ5%divAb1}l=&gj7@?*-H7 z({X#{Gitd#p1Iz_6wi*@!9S^0AU*l3ru|2kO6%ZDZ_{&Fj1Av;y|#{&^{Y^^r)N|j zb}Q?GawQQ6JtxTU>&FdFz&~GJw-sf;AuvEdKwv;3{aDmhnFgusL_k1P9zj9Sfulyw z##XM*Zg!074z6a-4Aw3V_UC>!F8G{jCr?#?ui2X_KoVv2f>6)CwEb8O?#eW|3hvcp zmsyAE2^8RnUEEswM|1K+K+o~c9HMJcmRwYF$zUv5vgOXsPA9Vd`@{AZJq!`kw1#n) z|FzyV$-7hxl~ZmVbyOZ2S`xV|9Nw_P*|XR1-Tp{u9n++^mH?Ns-2`rZGj zP{YvLi}|L2Q|>7qew}vh%ftk05I;V7e6}{c`}e%uY~9Fd;I52DZ`TWRxja=`O3b)O^tMmBzY+%)HrC(6ZD9HDS@Xhzu>pmHL`%E~%If$7K6j)lLz9T2H3jk$t& z)Ws(IJ?1lX0sw1hz(|muG#~im@ua4EWZ`o-={EO5KRRwlG9=`T^;YMpFtp~(-(a}O z2>NM!MHx9U&BFJc@o8kZ+juG3cbmuqioIi~)Wqn-d=d-I3GkH<~yiK*PMBLD$_`&$oU@grBljL+v%?DZDQ--*d34!74cx zIcg77KV=BUCJys}orWlkvdM~U{CKa2Lh@yGePrqlLK``&H5{NMIIR4zwGBiS4Z3hI z^{mI1w`x|uT7z@XD+`FW@C=u-r{sw}q`cm~v;1VyDJjGVGL!Rf8Rg-3eV@$pbK<;1Ze?X!h zbP#+zDvavNt4S-%s5_xkaH&L}#SGhv9lb~rJ-fhz`#nmtua%>uSA2n4Yx@yX$ zH$U@O=;*qeY;A~?J6t(tq08e9CKj>x8c9SeGk#E~`!hkc175MVk+2oN(Oq(V__#N^ zEw#hawyl%(j#btm7jSk|MLX<&ax0EhO#z)7mdH!{|8Vt<(Va9;xUrqx*tU(0ZCe}L zwr$(~#kOtRb~biy{_p*C@0U5%-7{6y)qUp7bay=u6ua3eRszR+Cq&j7Ztt@wTtg^c z&jdIqBCb*ILkGz)E=KA=5Ixtci#xDTJ^RfU9#q{yYc)5Y59v&o@%+B>au1q0JdJo8 zJ2PAEr$g@DTxMKT3PF$Ih&SZ$(yf6vPp*zDw)C1F(P}`E)j!YD54;q?Zuu|Cr01LP z55e!Mhn)lAulF@CAKMfk8@sC&p!9~vl8)pz7!>!wwCynMHwr>DTlO2DXQR`QTs6W0 zc+CZD!huEmt@W&p{-3i~o4}rWQ%kxn0olNScm4$I#h{d56R-D27KjF0@I;=WOD^p^ zcv~)^TCFiY@313*Gb4WVs8H?0bc;Kc_&|zbo_pA~w0#<5_bbn2Lu-Pm6&;TPf4Z@Z z`4w|y))nn*C>C>1QfF$U3;1HIu{ROSdD5&?u-U$Ukg{)8qORfFL$Dd!@ien??N3kL zd~ye$Q(V$1=Xt(6_qmfA!6(m%O+6oOvmOt0`JRqPd3Bz#=8^@Y2cA9HDiM<3 z??K!vXFlmU>8-RnpFcmG!hV*{e;fI#9kZl@Y_%fyvx8svnGB&>lI4B{SM3;F-5O@h z2Hmqr7Isz}_L--Lvq&fkFys9;AgQO29w>l8eVLrkQ0dGIf~BAg3nLEh4@@o_ytD#k zU=8k5>PsDZ^{Te_lK+{f6*D9ig(J}JUo4(@bC;OzszWo1_LBt%40Ph!%CVG{t4bCj zp{eVjcT30WsIMJcz8ZbF->{v55WPtEm$X{nE1J5J_kIZs(L(D_fAqR__;TpspY~E$ zZr+wgML6|TZ?t42%b+f}_B8q}J#BpEY8--|v@%gvlv5uad&s(@7`bq-W2l-=E- zH?K}kE12JM(a@-py#Z@=H368SqJ!ivvSx!q%>M-iiQMsokKG?c6q7_RRM5nTq?j0R zhuj`89vQ15Wh9bohmDZBKV6z9AJIfacJ8uzYu|HFkDIEZz8y+nmK?rNQYOZsDDuuk za774f2H6W95K;f_H=_lR#a5Cl{4NRLDSptv!B=xnVI$ml{ z-NC`VXne97&D6&rfx3SxJlE&AUk2u6SU8vG!{`%scMEUK(&Hbjjvb;aQQ$3Qu; z8vIE@WtIOO%|*vT(?_oo$zHtzfQ&} z_su?SNHw}+E)A!5TMG*mZTLnQ;!uK~x=Oa5fc@o^mWnG`VE3kN<>j&Wj}g*cNxNb* znZOQgjTXDf;>u3_%cpQIzD%~eY(F2m2wlj=bugB2wKuz?E9MLKD&X@KVw>Eu^Zirv z!X4<_Xa#3QRUQKlN{ah zEg`eGPW}MdVC1Ql$hwRz0AO=$rJ-E%sdZ;Ru=CFy?ZwQvm^M6^m9G{AcO*VIM;W)g zS}EAOZ0i(t%`p=bG8+_eMP+2Mt0vq_qufmUw=p7bV&oomEZ;ecyiJc>#pa|Lyb(6N z)8vT1P6Rfny&ZaPW$RDC3$M*_nTcCC-!`sq(7--KyBvFFj;{%rq%+(46v-mhl^in@91P!cyLfN#RBne(n|tv6s1uKbp0-IX9TGon26ARj;I z5bPc9e0@V#b$++|f^HF#+R&+Ys8rV9YpW}jw*gthSh`#vXTUiyCZi{9xwFusJ0Sw@ zogIHtb#!v|u3a@5dovqtejjDG+2pTpJ30SQ0EaOyG^~aLR6-qn6C2N?oxE#8+Y+a% zZFkrAx~3MOGX=8)3(TU z9?VcnfXKtcB6L+}1{c`_uN^+kor}W7#b+>iNe6d5vv;#YLicEHmd(S87Z<;vaR-8-g7;*C+hl@k@)O$tuO>*GSaw`|6)8iQk{j~30= zGDeS3R8uwPGT4;|JB z)pzTXMKAl{eAtx*uI@=PtG|eKsW5y)Be%LN@T-tPtWmyravoqWr?@3yU-t***UaonY)PAdhpIY zpV%9n1G3+@qgo0Tf>S_SwtAyil^u)T)v8G3Z1Dp9bk44z-56_s)KrbT6l8r^L_zi=;ZnKqV+|R^*uKKENUj$RV42=IQU@F40768;AIIQ zIAQ|&Ql{2mfcZG}bi()mfhHgXZXO>>)IPj|uxG`hmvAb+80xW_g|G*)n!0JO?5AkJf3z#lMZuq;Kaj8S!y8~cx`B`;NZzl;& z2UM^_lAzr2t`=AfYVBf$|ERF`s2sV=QYY|SHqFf(e!I*_7$_XZJ6kxm_OHZoX|uQ)clqXIdb?G? z$9EoHi;b!2{$s^c?r&sOQ^K?6Q501m+Y}o$X$gJaYfk6Sxtbrpy}o+k6|DH$MDkK$IHIa%X?q;vDv8c_zlmg~avRqN<9T7zc`UygTgiTm0rdl2nBFANq z*3D25C?9i-3*uByVdz@x^p_22Q>D@aWt=(ab0+^{Bn+vGEdm(y;7 zH|f{AS2GHvs*u^)>{N(EHl$Efm?;T73P$q>#UCD_)M7xo#;hY_V7{eV3le@(D5xgC z+sfNOFLNBIJO0kVvcJ#9;C5&q{szZK=<>gACa6wMkgyv3&X2R7*NL0M$4YK4F5hPl z`S-`!Q9~&?{rBBIKKabo*Fs{CezXuhCSWe3EhTS@%j_3~;F^+s1WJi3vt~s8;6-ip zpclXb9KyXglS2{|q>O?a)Fdc&_e!p$A=JVWF6jrKSIU+%X&49R^sUCk7H2irYus+% zgyavGI;>^Y5yScXApAz?1`DQq2gEU&Q9Eoht)j<}BV<;)Mg+BX%XNhq zF(WTxI%A9(HX#=`w-#{ri(F;yY`OXYr$vWj$esckhJ@G(PL({dS>DurbfvYh{|b#Ide1;Am95s+@$D|0NZn(zSXWzi(lnR_^>p|$4yzyKAuE_%KjP`a2*Y~GFUJ1E0-)nEf70!+E4sK~Z1;j0!~rQHbl~t4h5i^*3L*CaG!Eu@7xg{N zwivADa*MM()Q;n-tD;?}70gx-4r%LK@RV);sSMb7hoG(ADZvo)0Z(LF%TnJm6A5s^ zKw+IhgyZK{P8Gs#WFb}^egF|Q9C@cxIN2TB3-sHd{{Fq~C zg1{L_^KA!7m3IAf0_)NmJ4R}a%st1??ZLUOf5cr)z2N(JY+f{XHYR5;3L2os*14Sh zYP@42LR34mM)zGAPO@NQwv)CoJ$(@@%`ffOEf=-@$SKSx6SOEZw;aRAKK9)xjGM{I zn6>I%@s8DX1!PB$sRf22`6;M8>6*gW%V*@m^!dToxaKUo~9lsbu&KG>f99JS$FL!Dq4@7Ekw#4~gu zl=?6MFh@~)-j^6?87%5FZucM1P_gA6^mpy(G|FLz?#(njWtzA*(1;Dth6b|r<&{Q4 z)Hj5Wr5CLvXFGCB&8F!WsW?T;13H08L)KX?GW50Hx%U$O;2fevicRZN)1$# zKhEapURfTTA_1hl5pZlx$95&HrtQl&m2W3<53b{S+n)qp7g%7IW&q6blN;#{sfSc@b@rlVTdB6E*1`6;D>W*T$ys1^V@VxF? z4+fG>#L~P&Yn=AgD^CuD0+X(FWTO`rg&NfIf2H7Q=42F=zqV>M2#qo3ZB^iw zZLRYIaXNn``=fu1_=3rf8S2q23S>(X8(LQ|)Kmwa&2BS+>1l)zyr|HL($n`6VNb;w z5Nm0V6C8=tnSw1TNX(>P1K7&z>i3V#$@4|l5{!{D&3}ydmn(Oms8%m zd%H*Zev0MpD<0n0^*&nn@}-W9-4=T(ihBSUGg;{+HvtWYN1f0aS*)6Omhd?9E(+me zu4UA4Wd^#Jf8!4K*BE4Xa>3bgxqc#`reDdAnlWYzEkV>K+%%sn;-;)gaS0S#i^8O_v3N660oma^AKi<-t>OyeO{l0w zP;oCPAO6~pM<>#~V?{=>3_)6-FRhPKTt;w#ICpI}58{H#wIx0_Yq?AF;OF?H$|iwA z2eDQ2a1`9XvW|@bcIBPy1a>NJrI*S$tmB$BeFxmHuL<40*5447MwM%BPCC=&EN{Jn zFo+(FXDM)4Tw#*<#XLpas8-H-WSp5-Bdy89i&(2?W=EA5_YDoNN0AcIPSsl+kzzRl zPdC~etJ86btd&DjAHRn*0rC~bR!55KMX8yt%-T&%4=L~N&QfhcS~>tI(8gVM<_c<_ zCtx=1CWJ2xB!RnKEl)HF!K9(6@1FZd2;bjGuK6_t8(;@`xA(toI+BD>&B7sWbWoD4 z;!&;Z6KG9bo`^)I*J4c;_!W!;%9?=He8Gj*UVvp^Os7;5X}LMu1-5r(V-$jp@)d&p zd0HwSF`;&|FYNy%)Bc*C)#on2k}KD1?QA4&AGv?+1H$D#fR4o>&FSsH?JwE8UFQy8 zN{ohRcSWh}AlsM1v8rcnC!?K^wwZAtzv-ARt~y)7X<{>3qcn1Qp9&S)uqwf(sHC{} zu7lp5PAz6k&X;_p{_H3(+dH>VMb9b~OK!nzjR24dR86ZBvulw+${|W@NN4HxjKFi3^uNGtR1!mV&;+lG2MsY87{b)tOPM8HmR5El zAY`6h-IRr=Vq3EMqpjP!m{QKYz)ni|ut|$*dim@38Xhuo=$3@jQSA_It4~j8%ydY* zbu@ZcN@dfTO%Hckc2C?V9NNgb(WsrXMDg9?|A;SMdTo!U^DuMH)vux-AY$2CR^_*} z+1`ZcOf{~GeiEL>jc}WTxiG#jBg(izRGRP%LsWJRq+Fq@=`xw`a)I6@DiU@CCt2i7 zNFQ+&fn`=8)h;hqi_3QotqaNWv^mO!g_p?^lP-5c3%0uk?C4?ylg$>|H?YDIa0=lxsCrf0ty5I!A(Ii{Jb_qd4?$Q9+C?FhoBYH@QQQ*9u1W&AftyNoQz zQW_mDHh@KBy~q;`E*x&9_3yn~?{o;;`U+pW9~Z>-JUU}_$la~-xaCRICU#_#D=?%+ z)-*?3LgdA|hj+Q$sok@FaE=+;8);P4hd%VLrWBS-xM`IMJ49w? zUTy`v*V9??QhFk**CwImY30K8(_vvfIX>@`5%%^lhgVjNJs+bh8rQ~JDppR@4%@_2 z-YR%zF5(f|aH_aI;y(w_hEE{pNzpt0>W%7|N|;?CBCl{yTh=o>`XPhcE)}f-!?@f! zhbN>0d7x-i&Tk|~!Won^&?jt5vpoLuy?8wM7(s)Z?5Bm%ylf8sUw~{>gIm6DRQ(z4 z?NtJN{BlMdJUlKz+VYrGj!txyq3wxCfkPGK#_GcM0*#E@j9?X%6Ag;L8TVmxRK*gw ziDh(30)l-FG$lk6N~**57|djfx@Vr0RJWezYzUnm0=m?7N8LeR!3YN{tQZ*Ur0j4u z!K2%YMW*yzBO_SlzKfQZR@&Q5&U_TL*d9-=E{3Og!m(4=WkIg(m5^dwSfxiVox6pM z8WQ4D&=Q3_h0gs8Wh5fFss^~n#tLXOR4BRvdKwB#BARtfk&#UF4yvI=M8-7DX|7-#;{PZ{JT-~(?E5R2h|LAglNPAx8%Sy*%c7vE z1?l`S8)@7oVf7_6L^M!RS;8Y3BiLPiwX+vdgmZ@-GVbx2Dsgi|h6`_b1F#I&!mcEh z8yeCva-3}SQ=ZN%o01d+{FwA&4-%fStLfz?j=Wki+dGG}1`c%ZO&py%2Fx?h-J$n5 z2B&!*o5G1(2naG{5VH?jFPPU3Vp@MP-Ek?fB(4Brc8j-*oI9yH;S48kTXuQ8TNh6E zqyEK;Vr(~kSRBEZLSD+o_W>y+Q^Lu!9FzxT6>d7koTd4r)S?uKiEx`1>8e5eq|+CT zfClN?TB-u70z)e5gSU%v0N9+`n)hp_%lI&h?Q(;QYk;c7S^V$tH~>iF!pm7r5q+GR zeGmc=H7lOQ>JKNn9RuVz+VZ z*lc|kA-7J#_=ECkZ#=Fl42?oEulj|qnaj)7v*kl^inl^7lh~r6)?4~^rLsgcv7+X@ zLhz?_d5YXe&zie3q$Fy_6!w!9kUxQ@elh6 zk}?SIssQvsGtEQZ*veLi_cLWMbD&c1lxdu4q4u+YxM?$5C2Sq3i*o37UQXY*7rTQO z(F{!|ix}G1_%dF8;C0dkxS+*Z77hnOMifANfC1QXR8m16MZ|uLfHjiPT3^?a?FZS1IefFTHBvu}o#%l?5O9YwIc=zwY5_8Ao*P`VHO zLg=&%bdu$imInSv(LXO~__Gv>-g?Ov*p4QOOeg{EA(GH2>7H)#J942jWH$APhzvZa zhi7_%s^&Z>o+aOyP!ca#L&9CS`82~(;3w;>+Mk3~E>U0$@cY9%ypahjoc;x2n25r3 zvMpNxz2;V}2O2DYQu7c>*{>k?Mh@trCqsxjuyT<2Q%O|eh4t!`6%7qJ! z*aP6tW7k#)%PrKO-I-Z+g!$`tBTc0MLBzCBqGD_O;UH+;T>WPs`jw3OXVaIzziZzZ z&~vG#%4)j6XEun;!ylO0ny>EG?Qut)uk4Sc=F;(2USfr` zw&^(r77*v{5Ud)xkw9v_cHl2nKm*MXHOr?TY+wkz|7+Dcgg(gA&yNpeH#T%ts3oJ}K!}Y9&Ff0>CHP$uiAhE5Ei&^ zP=&8>3D5w7xAp)!iUY84k8nQzE^arP+twm!@B0uWxZa(gUrVf9cKx+$6;O=ZDi1b` zKhH#D+K_QSWu->Ku|aZxePrvXo63A+1&3GJ0RMh6g-LHC)oLj1b;@)8CM*k-{ z8y=3gXJ6QW<7X;7FLZrXNkPE@mZ*WC5(DvhB#;x5h04+ZnG3;Os1dB#uc5e+JU1u;2CIKs5<0lqzyBe6SMXNDe^hg7_6G$j6L6 zrYO{Y!MvjBelhAvMfn6plhDfpckTV&7?e-QA%5<%LW=y{SZMNvKw+Gnp$g&-38m1p zi6mDqcT{6U)uI^Cj}p;Fk@5mG<_3Qf0k_fU3`88= zFe8!<5xL-AA+CO?l3}aN`$<5t9aj?hn!rhLqEIj)a&^@-(Y4Ac3N%7kamrsRM<@+~ z1SSdfIyOkqoXa?lFR{d+n~Q1vJS@KPf$k7#3NmUaA}-uIWDYWq?V=bWNoHI_Ag{@w z?%5}cJaR!vf!B_Ib4qV{uJ|Ce1t3s*xrXIvkL%epM%acapmm}mX-esaQ6z;xMfk|R zRqtwgdm@uP%M88;VBY*ls^5>+V|zhjw6&`dT_ zDP;+nr>XkES@=u1ubzAi0fK6;KCo+K9$z-kB^l8Q#$#+wd1=qNI(mXU$I-t!9%ov? z!niu7UjfC#&oZpvX|1;!7!| zk!1ZnznWAJpr{v&Wh#fL>pOv7K~Y=;VxLy7EMi+F+3gb|`UPM(@3$zDX_jP3W>O6n z(V)&DO{bg6uOzB*MrILdZl43;ny~7YH#N zkde7`I|tjU_!#Sa%JJ_}tMXxNH7r%lLwg81z2s$HO50)TTyhV%T{O;Cw_t%Rb4ti% z(L5%=5(bS7QP{z};B%a%22f?v$M4D%IDc>$m9aZ|CKL_t%)a8>nq58Rkg7tt zJBt4UsdK)SfU@}{F%k?+eYs@tFi(JRM!llB8jc0!NMBr%IZk;9b|_LcP_eSPva3Cu zQp^O71%C7o(g zAT)7Om~`G(2($bjy{1#+#V$HkpA%TzU$8tcbWua9X_{J^>tP`b_;S@ca!tj#(nub^YP zDgq7WCL-~B>8k!>brh8xg?UZ0^nwK^ZAlm-GG2EW{{12}&=K`QGme(tAn$q+@Rf0XR*4>YC*&#yPr!PSnM3etDYq ztnoKK^aQ7A!x!w!$h_ke<(IAdJX7w}&qQgyStX%V>P?#1!P#AQw z#4ftsGsOOr5IDR=O5RieEKqt%pkFl-0!O4tH3j3=3YAPI-tPILbY! z!B#y%Cr5K-mn?%hr*A7Znm zhZcbBert>rlmvKAZRC*wuv=^*$Xz|l@W~6}j-z-vQCTuc+~N?&QX$1AzpSBL(zFb; z5ocVc-w`S8_aU6s0$wdh&I$6gvffVngK-^{77k1}=bvI+N_&%f|7OgM10J?s>Y!r+ zQZ5@P*yBm?3AsgjQpRNFso4@D&QXYHC$I{0?RYMLJzrKKF}s}F0{wilWV`I_AJIbO zD?LR(S0hpiG-uiXxkQm4pj? zMTh>{IqEg7fTSlavq5N2#g9}Mc+Vt{iCuS-*iwc{R1(6g6P8MD`r15U12yCMkbchy zF%MyCSn!za{THju2t#=$^I`In$*^ewp{%ZvrD&*?ta|w>$s}5nQ%Wp81rzPNSP7mg z?X59O(rBY-l31E|J&Sj}n2qloG0eRB9=*ek#p03`7Uiyz{0-`6_+mr>-LW-W4L&J5 zgig~9jclro80R~|w`M4}IOXOk#HNr`V|VYV$O4MNF=Y!Tmvq!!j$&gElShrG0P3=-9;e(&IuqL ziGfX9wK|nKiiC3E7Y3#$COGxdzUXqMR_sW@iFHWvw%Jk6m=Xh-@tRv}+MxUNoO@#VKaCeS!WVTNtBE^^aG zezebe+qAkSlW`l2bt1=lV?mR|N{b+dfCOCcd;SO*V~BPm;P5MQ7{WTd)-tZ#d%ix# zGBpK*Hobcugout(>Q2k#j`m?|n0z126%dU&u1KU)vA|eiI4L4j+(6L8AIl_zs!eTi zWJT{(nsKd=$gOaoGmDz0yTM}`Kwc)oxesmeU?=1?UrVfq7B8bVsJ{7IkzXO7If=d{%uE7%m!WlB|T8zhpoLk0F@}qG0Nm92JcKfkS;BEX7DBZAMg!mx~E4 zS5q#}YDslbY` zmF&{n_~9l^u2f%5QzmZ5Ik2gRMq`Vys0j{UUC>Xs*h0_Icq*zjStE3j>S(wmneP9h z;SQJDR-c{WnaJ7C^7R0}nz&ASB6aHdCxh~QfDHwTYYX*{+az<)iABaMQZJ6TEGQ3Um( z{7Sp(DZM*j7V(V%D1K?f`cH??jiZVb(0v5Dz@BQ%SXFt|s`^sA)G(R^93?uehR8J) z87EQx+%l0=5Cwk=6I20yFI^Fd6s9Z%3Lu?eG~(k@{pxD4+MPdqr_al~?li0;Ass5e zb)?v`s~vg(uPM93x_LTDLzuIfp$Ci1K7u*-3GE4?>r$h(WkQO+6fxkr6)LE7pF?uh@)m*uySC>W$)C|1tCAh?CcDC2j5nfNP4KE83<0NoxZx2v#;C`tC4ePNv2XJCWSnI+B;dYs0_I+2mS5g zX|EXRZTQm(0(Fb;7PUpBu>Q}YiBEI3xriuUm)kzy$@>847bg8Uqa2>OadhL)RGfwa z>%d^|^Bnqzx=Pb*yg1H1_r0^d^w}DX{m++lR0$TWN?7rOBM*EXgcgBfwq<)@4@sUV znR!}+e!1g}HsXDUo0)`EA;oy&qKJNzz_R9#__Q6zedgYXI>q1%+d{#Tc~7@acL1*B z<6PPq!!fij)?8@S0pPd9xWh$IRfhS$>aG)A3pk|G7l@0+MZvD@CnfV#ZJ4bG74pWI zq)ixY^!fFDcTk52n|16UQ4^G-CYP2BVsw_QXfy#;uw-3t_I{8 zpO0D3OWsEd_vv0GjN0kLT1(Z0lai&FXB^Bh?C@vt(EDE8t_$1Wbut{ysfD^yI1R2k zeDd$phiQ%yaxA9ZYxrpTE>JZh=QBZ=hBXEeie;J(N}NHmDt)5=52MloOHrB%Elfgydm70236Na zf!N(58=k>hrkV^Iv`@RvmVQoRP;fIv7^l!_xeLBZ$h7o9_w7+IW=C(4eL(I&i&ebBQYIEEAw1qa$448x}+ zm5IK0Z?7^ymF!ctOq-(_A~uESBq$*mCye$(eb92mYB=gkSm+gD6(`O+px9L9UV5H0 znbV-bk`g6YS)ZVUMw(@!@&r9fZpR=Zh3lAlFQbr{D@27we=R|2U!sGNF^Kg6_2lh?E|j_x79}erkUPpM-4*e`An>k-Sl{(-j7jy{e5eu* zYWqV`n9SJJmsN&G7BUl?R=#7_SPdry5T#RGmfUNwg+O%y*9pAJ#(hfy%;5Sc1ju59 zpwg@5?e)=h08og;Vd1VK?eiMo@J7RpL=`bj=jI(h)`4)!01sw!F1k_Qk(rBQq{bMt zfsl9e++FCC@EZ(Em>1xK3X`zslH~h5lL2#f&J`3CohYmkyZ|<>aB-#qe0NSq`mL-x z$;2pq^K8U>Uygu`)_%UKW%B8A^$4AQA9CjjmIgs)x%+kf+ngHOe;+E~mFTxw>1P}k z^-Hkw6C&UD2->sXzH|>h!LaZMp{#VLwV}lZfu)$P$+rybQwQUeFT<1>JmY8ul?t9` zN>||OD-WFw@cK@(VzXp7npyVuDwbn<$lXelpve_Y+6>zV68w2AKdZiY)8Z4vdqq&}H1l?@{h-`lqQZW=d?x*iriNUg)YN>dL0sV^i84Ek!%OrB=7 z{zK4J$Z*++VQUxM@fxH%DWISX(5HY1uylyKwv5MDWDsVia8=|7GQF%j-_(zldpb9^ z?vC-bSbDpV1T3?qwsT@BDzPMKHQ;F${+c-Ol3E7jYBoG9lUYJkm=0x_JJ0p>C35es zoM{xm-gk`s4aQJ;i@6EKtuJY}_EjptIiw!)q6h2-L2{$A4*A6&e1zvck#hEo3Mf?p zWrDiQ2v>Avny|Oi=7m6Xel_($V0OB;5#Vs^$E49V#{D3Jpjy$?V(vFV zDll9}%FQyp3`^L)vZO(xVgT31{*?#o9)~{=v(AKH{uIK~b8%Jg8giyw<9-#mbMo_u zqW<0e9JNv0u?sy#(WyMPnk^Hv1vG9w_a{P|$_UKhVdJ;9jFTkd0$CAh;i`6OZu8dl z%`Z`8uo_DON}-I&E61S~ekx|aD9MzcOE3u>Ryjz#?CJ0N%OcTNgNn?{S%$wSrHyBxA{6{XGr?f1S{B51BixakDhS zqJC!-fTGe`T&Bu4fb)5oB$_Ah&@}s5{>_i6bu5Jb1G&z<&dB+~EU^;p-Qt7-d;v6R zKYvU-f04!|;NedF2uNP)>;bLFeDEkuDL}ALjo~PE;b+g@Kbe~n9*}92??U>9y=R`l zDQRXmgq9JER^g9&p*2JPK%3*WuRt)hRWeEnun}&MqFx`^)RuASw$!26ppn9i@tQ|e zKej3gn&ZnkhA)16ZR=zmsib&OPPGgeNvxtf>4&XiFy}aH6He}R3G+KLYQ&xs74@Yv zqp;F*K8E|%NNJ~}u%WH~9h}R=2OB)xZ$^zaF3IB*^l|1$6L_f@NNbA8G#{l2Bh(?f z(`)Y8kA2DAYFNgC`r(Lf%C(DKi1BRaA&N@eMQfpbexWHQBf;!l7u~>IhM6;sko)%* zTZbc%?IGH-#2aNO&0XrA!WP#O8FV*@YYMSSZIe$UzD``4<(fzo(x)f{Je??_`d}uk!a3S+@)1dP& zc$0{XmLMYoj^l2@9hq?22-CWBHL(aKzRF**f{)d zdx{dVogIKcmVPntiWoSla-!KN@56WVz2tKpoc8Z`tY^9%$zAfpoF+E<>q6zn;jKp( z?d!`3wdlOGNMe&nQByr9eyz`7?Cf3s7h6rPUR-^*CsAf33zjSd~E zTUATz0p*xQQvIkB@-5-t{ndeoZ!5%uwoB&Rg8n%i=18Ozget5F{u?ZoI4CTrUYp$1 z+HGbI-wds00!U#_#4b9C0Yf>J0WGRXL|Q4^Wml9J9(nUS=0$92Vuqu4O}V>@s=J)Q zBZIuI*5*~n&cFGHv-lN)ZN0|c>$y1EGw!~3A?lOJQc8R&3cIOh`fA z#v8UZWZi=?9}oK+97HE}_`gVj@!ToP-zYu%V<@Ap3q?6|n8eLe?4cFFXlbJ{X%DbO(WR;9VA*`xD zzC`NOhMi<7v*Y$S>Y)!&SHuS>+Eeo~)6#P7FIwa?+dD_2Lxs4YMttav4Hfm{@(0Hl z3o}{&IZhpjJDiTrL7{ri z|J7?D63~o!AM;Ik(T;gfo0(ZD!EC7t)EGpw*i_Mtc}qIvR{H*25;n;{vtmFN`+u}) zFYEkg2Nl2QKi33xeiTQLQjB@8t~5?-dCw$lo-__x76>^1+!u8N?xmUVu032z+J-o; z@Kdu{Z6M{4`&g&_Ba)8O{m8|0KaOiF1pYX(ygoyAML*_kk|3Y(4%hjk^T+sX{g3&- zaS5BD^5PQLflbjqViMPmGQ2+;KeJLa65atCQ3;!3DTjZwn%sU`;8TAdvgFkJ&r20` zLyiB!CFeZ#VIpyjI&1o0IKXIi|7+J89$(66CV4Ku;|%(7eEi_kxXY!p=f^Txdo9Ux z{?|_wj3lm^`x1V-j!IHW^2`}p|D)gWs|TS0?q?LVn@v6!Gk!*({l94Z5UBom`|NWv z^J7(E`=@({IyKdt)MMTyU()l=KcNClCv5(x`5Dye(rS|DKE{=wL95J?`TU88B173s@$jeuxZHB7zt_MTekt4W7=vnjv(@AcM*@6~sGWnkjIXw?n3`U9i7 zQ>x{(nfH%x?9wvG!$jy<^!4rShY>f8#f#6!K@Z~0*BRo-z!&%1lh51mcC$}xtnW7O zGJ-9xLDTX%PiaTZsg$I>AnRqRUFBcXm0_y^}}veP}rND z=rB9%HurOZ{Cl?R>+1Gy_UZ{c%)pgcbSFIRWT0W|d)GDB$7h=#l22#^HjE&TyWRp^S}aMTqpeESdC=%u4_Te!$aVfuT`$gRmruIUMjycIml;C3rblJ zmH$*%n$|~7>3ZRRE@LW7*<~9-`EDE5`BylyZK&4I0Ye=Js#5B? z1N2gcwZZna!2nN#iLHO3xvn!lJ=`{z&9oFI#P)Bx-?Rw3RE1awKbGT+C9jVPgr90p4!9k9_M%>WPiZCOoBO{*|&sxy08T?>n9jRH) zo*nO28=on_gLHxMtn2-$xqp!#xJ3NsK~ecWI--1T9}yA85d$7uTe9`YsJi}iz24rn zJ<5HbGkQKUD%y`svA3BA( zjj4#Ep@XgK{{^Y&dUwTUpC@>G&uRD;iha(C&N`jD3FV!x{yTx0JyT;jG3K>0o&4_K z+?FryO=2vT`1tKp3B%9sC(53QawImK6)xfe8Z4M!A+JIKFh+I3Bm2M0Rs`nXX1lI&Yi$))@DqnDJUm7NT%mXu1bAv`^RpYFogISTdkal`!w6MYFFc$1&@q~XZIUZMIJ7Fgq{ zl+*zMiEic?UHpVAmreuL1n!gi39>Q|ie^|M^w5Qx6mu#zW80QLqANocx|1__c9W~r2zsWaOZ(yuB^ za}X?;jLO7^UT!uVdbQ7}c~f$)EV;?vqZ-Fya{il9-m4fj$WadyUPCE*ob36U*~(fu zak}ajQSnW;kL?;(GbQ7yI)S?Pxzxb5$$rrD^Qm!Q@H$si=^y_qERcYy;1eO=j)5**}4#V^qjPKt7RfcD^)2#-@Ki_!pUVP5+ zuwk`WJ=2$nt|G3(12}%%EadyQ5!cl!FW-Gm?${1dwn&UKuvV6KihKdMepbd@qcJyJ zr5YHCg2zvv*5Ag#*|=YuD~R1KHC$kbaD2047~pXAW;nhLMpI&w zer-M&+Y-su_$Eh=|KaN2ivw)rKs|RlyErSfsNKIOG0JzW{QZ0mIN3?@WtoxN@)e|b!~oerLEFF3nVv!qL^i$zYo9o_s8M=Tgn`BXQ? zw$BmQ!u1PK1%D}a7~T9DA8wO%ws9eMj4D}`EqqKU**$Ia_bew+Km&@83f*ExaV3fgnv$cP?nM;sOLSvBXHu~?onu*NnRiqTB4ZS63M2c9mT>OB38 z3D%FrR>lDJ;&nqWgSLw~FVf3?3ua4v3es^c@_fO=zEu(A!+(0J(d#NaaD%M+C6C3x zCh8lslzKBb#t~G)Ib(~rpVc0+;6#6~#fi(+VlsQ%L%JTii8@~}AKqYiyCFR;_%eK%Qx3x8)hb``Y+FttkuRr^_v6`u-K?s!_wTfpflY zOkO@ezTQB5{rdUaZj|fvYl|ngDI@Xkc0$y4`n8>ty0l^Vc2=7xvC*XcEn2+ENH&c3 zmBnpukhvug+Wx`UNWbkTmY*Bz*Or80e1qdg{@d#K_%_!}kl$9vH)5J?EB`Ig^mI~f z$1Uv&+3D%(nxW(y)D1Vn3l_4xXNx6Pz7`$6F2`_euWoR38|u$j*WEGkRY#5A_b+jc z?f+jjR=90_Jj{if_Wna5rn#$}NmvLsI2pn; zHebG6(j{iM0yj{sE(pM ztm?=Qih$K>E6$**82K3u&_nhTbSRMyHPE5XTRP-jI&25S7T#|vjVTF}hDaklFrQ>B zjcv9qN)mMICw^md@%R(6`RC)xtpmI=n|B%OCfJ;Rk*Ezb@U8OV>|&a)ChytL16B_j zo^+dUVzevy??TKiRc z6jXKSr&V!3z28nt?jKZA8S56Kld#aHxv)hYaOcQmYg zvEoU{eV~4W$A%k1C0aj3uL;)r68NKB%@+cZ=5lCw&o2q?^qTGvhF^36^jOp>rDd1` zSAr`u)~^Rzc!ZXbJ2oIUC5hHeS()pu7p5zWzf!`=9SGw>goV~lCci1BiEqVf#{ zpPsbMS>EGlun}x@u^))jy>9^gYQ7G*Mrm32KIK(cpN-TbNzuz~RyjUju=f){`6qrG zS)V*#r->Q+um-x7+;r~ZXQMd^*Q6S&JT@c98r^vv&~(n;IKUgJdo;xGFt>4_dvRu9 z=s3SnAoXZjF6JNhAMi8Wc?q5A`Qh#>`9^Cs9p9#X2$myxk&xI5`)!6G$|X-Zx+cl3 z(3gXdH4@m6xFQ8M5U{~|&0lkVqYxI53Y!4){Yj$BY# zgY(nJhsR$LzK;+8c`E39^kNLQR!$h=gKJ_t8i&(Olt^9xT9cXC;Y~f1EXjseZqsO9~u0uAxIr$r0958y{Gf3J}!e`aC zYw;e>@pO*zMvQI+!*4>~7>>aa@9ivMt!@pS7#=_yI~fmR*$2YP3v{{g7sC+!3yN0c zM+xpm)BOzz?@imXgR_T0y5`#4Pde&XqJV+)rt@FIh+79h+W(p8$-Q~N9dDvx|?2hC5>&yMtjIc7r&VV z+nQe1n&My94-G$AVrXP!iJKajjeW?rk92X`m|lJf40w%xYB!XP?eFLH3a+nX#8qHp zy1OxHKUIgvcT~A^YfO(fZtaWev39c1nC?z2(=VRQrMEU2oP2FCTGwkN5Nn@T%f4QZ zhfz#_|HQ**w>sD7TaN;>F28yVNjB0J=KVG%S8Z*U9Z!R=h?G`Hv|ePusq$5>0}-XZ z_|aJBL)uBuacp`rU2R+QI@kMr0aRGKGgiaCC*k!o;Ek6Bj79rImi@da({Wv6asH(# z{Hc(>`s}S;FJt07cIMSvnrty{spI-pt>*9xRSZ6&Qv4nki{=eGqhsE)GN$vNE`X!s zO820QLGaVMsTz_ii#i#t1%~8*t4QMf{v~2L8iy+ci-$~|X8mlPHnZHoF@}y`g1Wep zsn_lN%jd^qdi*&>@atQcw~x*E{R!G-17CHg$7R>+mn(cN9scSaKYa{7m&dm8P&S3k zdjP%`#@Psm@x#3-&Ax@;)ZTpZ5ZskSc6^8MIQT1a1RnQ3hATGa!fR4dL%TV_Y(1Wz z)_BNH7SF*XuOlj=s`TfNA+Lc|THuaB4 zj!Etl+>iwH#OR>&flc1NTR9ag^UI|(oy=Ii0IJSG3p$wZweLIv=YqaEWj>qDS5Cp4 zv-yHKDWIz=MpL}Z|_q}zfUlW;|`4`Jvd`9lGRcSE01^Y2+7

(G3C;7%?gbWQYsjrn&Tmn6)+ixtS=Px9c zRL0roK=S2s@)qF$ie?cf2Y$k%Jn`rwC^DJRxb1gIC*n{F-H=cp-hl!Dxc_y*7MBEF z^jH!=J0=tXsX&Qx;(${C{N|UVM^E1fdbU#@foZo-?g&vcL{3B2NEHRxPa4858Q@gW zuun-dU~{}TI}1={6_BBV-eLh%CTt0u#n|thon$U9(t#4)uvjGzLNjs2T|_3nyE-R) zD!kEc)|tLij&B>$ExD&`ryqZ1*CGHyJ(jD@@s|!7M)<^lOB?M>eX9LUcg0>k`PU*$ z@_fXlXohAe;{OFA@uorX4RYwNw%@CVvsCbhv&;Dmrd2%P3Y6UPEMKe~Id|R02}V+l z24*=wV_2Ty$y-iwvEt$@<{|b6XsZgPX0mYP8G@jQD-A~O6bpPdV;>y!NV=k_swH9# zd5DE|RDr_y2SI(eba>>A21427w9`+4pJ6)dpTdCDv$s=5dVd(vR)3<3)l^6>mWQFh zev2Dzh8SSJW^YB8^`N$3he95;i9i=z@e1VJre>>z<(wmU33~WOH1noK%-pkJ5U-a4 zT+g*c=tt@o97b7ELtx`Z4WVR2wk#tfSrl zrO8xc#M_W98yW14uIQgy$%>Toq%dh{szhr?GH_$-(D=%U)-nS&sS+lKy~}}OV7of= z85jZY@@XvxiyJFk7~2`NQyE?@B^xXy&nwx)V_E7YFySyO9bq_-Tf+iH(ioJnOs$Ii z!T}AS+AFdbYIhZuUZVq$4q$k|h=Vt=P>o=LjF~WF4*7tlmerOmVwg;b$niG#)PUMq z(G)r8Ww5cYY*Pz++HOpfosFgGV^yFlG-t_Z?$~*VZew3t3}TB--eVP7N)A}>^f^`l zn$zB{0}7)A7Y|4?pK?qQ;rjA+;pif5X@CcYbGOng0&s zyYu=raHav<$_(5zxQ*p+-?m9HUxg6Nr;)J3x6)>!IRTWFD$FJui%Cqb6>Q4D676qn z{EdxAu`$m$(F~(NOJuxivgF?zE0G(Xz;cVq0UE6?9ZqLCT_X((W4b`TTfp?`1j*rXdgpxp z0q2L+fG1=t4m?inys=?-GC-%p3PYDm$zm|pzU#bEs=sN+k|g?Yk-r5d!OMAoU1SV? zG_DfA5p%C?*4^?<`IStPpW9lpFSw5JE@??uIzW{2;3#K2UeWFD`bz47jD)dVKpNou zr?crL@Z@qifoV(XZj#V<`O=|dwU~6iXwB)Dd@-RZj>7^`0j+p?{N&{5`NPBeN2jC& z%?XkUDI&zfEBrC96mTaIlKzEr87&|>SVhz(0XmsOYgp*M2yP7_#syRH14wVjEZ9mhu;_Kwba6LN+rRaA{loii}H~{0&>pg)8b?` z;e}%8ciDF#GuxV2g7z}bXKcfo+5NfOAEdar3n}eJ2b~-Pl z!-Zm|P74}{rDlCLD;5gGL$K2cCJd2WoTwxVwQvY)mcx7`0?@mLt=d^=Q`)#Mdg>UL z_KjIrQ^1J(e!z$zH&?9GiMY6GBcYE>GaQeoYN6jZorXs&l8r^8@zB?_-m{jaHKVOo zkx*%U)EARXKU)mta+ZbNbz?Wu|@ZaOUsllWK{t1q0}4Ih%Ows!=19Y2{bG%R&QY^2sY0}NwSSGm zB(Oa54JX-|0!OStI`w2WS-xY!aNuWH^s|JjHOXk^6vBmGB*p=EYH}Jee3*myG_bXE zBl_DQN2Xm09MHwWG#C@r(%^$sewZ(QUs5~?1(+)rn2y*IMVQ2Ub}4xv=X^?8P0}pr z4-TmMzl{S}oqAlRcBpR{hru?^^X1CYgz4drY(qdA?~5CwfDuc;6vzc-&oNsCT`96} zXCkMHLKDIZF7tErpK#O`6l6t2cs|X7mf{_!3EWnE%lXJQEgJ#8;I+Q7idBzWsX&+aZaF-dYta$H)KlubXJ{5q&d#R{?}Oo17LksT z`M0DHobO6_f)_A;EY=(FJ@{=%Ow!pj**JNdgolT7k)1uGe(wTn@fMJZGTR7mQ(m?C zNc9B@C$_Nj0g5up+{2N<(t?cuhuaihK{sGM8vwyMkb2gpKl+4xk8*#5lBR!xT8yv{xfdQ8K0x<8YC=gd~+TdGE zHl3j@a&WN%ckFs#k zeiad&N8~h!Tdy^wC$z=Q;eOLy>yH1f2W#!$*si*{~mnr{MzsVIA6e$V9)cS!kt*6sR_2eQyi2W4;=P$ z!A`prd&FNVc;|capqs}SC7f2sXmvh8b}aIW;2mKElL2FhlSp`RGD7!TSihoT`oMU? z>YSF2=9rJV$j|3w#DD+&_lGM-?rT{(-ygITS9Rf`YSE$rdX_JKN3~_dvW_beM9D>B zeR~MFHjJ%6YGcVqLRK*cCaLn%gy0vrbIHFB)`jCchFM5CtKn!AmdfPC;n<8Euy6bE@vsiIC*B#ZF2T}Dvf zqBQotl=27#nx++U;760dSMG27V5LBDn*R5>;c<7U_-fgd)+Sn|jzxN2S-AZ-q`=~W z-CbYR|?yf7}mi2qe$|9$< zNT32e!Ik44EhXI;fWO+RuUm(QOnzR_g%FX=OD9^ zya^LoC{;9z^pG5J!e%pT(Ak`~X^$UqqK&UwU5`9P6)ZEtscNTvv^On7Z*B8pcDhdc z%B0iII0h02Qr1T#!YVcRoGjNWoD(W+&4M-hN;PCkZUaE+Cmw_$mdlsUj$nZ^b_TPY zUAUX9uU8V=LgSaNgt!pR_{if z%b--I&&{9E(4{P={-LOc1RXe@!Jx6!6zv2;&=l^_>C9QjLSzdQz2dOG5nB?wb1Fzf z?Vf3@m)gy+2>_o`>pG3%J$&};`O{wxAAL5R+fC@+MAtS6Z>>>0a)l=?Gv2|*LLmc`Q_}CL14CXhFnOJYct<&kv_>I%+*EtlRPY;|} zCw)PirL~@Hpi_15Bmsk%eP<#FyxM?O(_Sx?d8E`r;vJI{r9Qv?s)1@H_zfx^`Uvgw z=;_bL_is++e6sVql!oaueiPc0E1%@m)8^WpVxzXQ4#1Y3zs~7iU72b~DyQYun4`VM zXgKc8u8cFj3}F;6S{alj#e!7FbXA3|v7||#+#51hIl5!VN)u@A^71w`C)bQ?jvp)w z{B|Iq4c#yi;7JF|@|d8rRNm8~4`=n`B78_KFTTfN18mrGI8eor*f&=!LOq$)h% ziN$KCrPbehg}EcGij*og$S9c+ooylPsvU0oYBgw_ljny|UOYT{?mT??su28Y-uxjTb?Ur2yA^I71oxif73B^r>bHmOMmG3q9^jDERaoWOIag9sb z4`+mVBHOX885mtbS@pwD=} zN-+4y!#&J)RNt^Y>q8hQTC-%aPp9(_6mo1CzMZV+xFZXYJ(Y&epm)`G8pu$cHAjvN zH`nhdb`*fN3(O+CgvhS##cJM3HMFgJwX8{`5^s9uJ!#kHt5sgUBS%D^!CdEm{!iy` zn7N}Y*zpxXUI)kBSpHk*-!yKLjpt34??C3pg*59n7()e)VKH!;cg0LJ`J9~rjxxA0 zYTVVf7F7KN3)7&lX$?dTt=B!7K&*ml05!+_?zDTZ3GVG(M|rZE-|lY+Y;zM;;2i>g zGRM08Ri!`2Q?cdY3Un}Eqknc#?jKI^!~u*n0I65}I0$u_w5cb8wVKh=m%0TAJeulUuz|ePXe({jSZuw2Hu1&fM(bwQUKO3I4ApXY@JV z@_C&md_??)PwxCeCA4!e?Wd8_PP2AFMe1p0mCY*w^GT+DH~xq?kYNL-@!)_*|M)>h zP;xq9wEPD6<0kASNZ&5_&Xe+81IFcB`Q=_hXiNv#WRU}!ySSQK@)H;l9{f(o8A(QTZ;t zORV{$<9<_|-xTM+q2g4F)3INN*FAUnQz>Ni1(CQ(NL7+@txJ+uFsYQ<80b}1G}N)j zbXy*8d?(OMtI4c6COB_+S14j!mEpU<q6Jqi!N0S^$wlnon9{4DUqfECFYuY1SQAwvn=0Z-X( z(1B$qRv|whjb|T$T`>=PM`Ia0ObQ&>fj;8<{VAKh1!=(W$y(gMlZZEi4z9lATBx#}6FadEch`>^YEJ1GITq+P3#hh4_i{o@krflfy^OWB7LP z)63^iZh9z3r$2U2faQ<|k{`A7#oj!0em3phb-1<3pvH-(IvRS)WYgq|NBt-WOXsWF z+H)-D#2ai#Z|&#LTi0W;z~))MHUi0{yjKe3!8Aw=f9BHM$!CIW%9)e>E7po_B|9hN zb0O5VwJLCF3^c-4~%-g8a z)uu3BRiDJPh2ssUFuvH?oy3eqP|Hll9nFy{7e`)O8eKEL(bA~1*Q%IK9ZtJ@Llc)V zL!!fHw0KVkXLa{46#Z*nK%f`4Pr=v~%OvdH?QN>lC8Oj(mrcMuP9{+j51ba5$~>Y` z$QxwE50}oHrX7tDc2U86n^aW5sz%Smu&Jm|bsWlfih51j%9RX1;!9`GZu%*Eb74j__sUs^XCSjk3u;Oz ze5I{TW58kLWSY$vN@AM`8ma>-r%Wm>)ZNp1M7wbu_^F$rchRDl6U$VmqP3MH?t|xTi?%S`v12 zN-SU}_Mr3AKY0O5Tl@$^MU?1eBl^uDHNPGm{Rf^*<9uN3_vPK;!s0kuC?7iCJ3$=5 zziAx0&7{RUVW~M;TeYvrmyb@4pFKK0dQMnU9=g)2o91)L=ri$HLp3k>nUD86!aaD_O;?WF;;%T!-}d=& zy%rT|A^wIpE?kYya+#v~!|7f+*d33-y9AAq8Mtwx!A+WL(EjG}<3WleNIVU246#RF z>e5f+=F0jpG$Wue-I^3Luc2Ab!@aaI4`;$Nkk*hwzZ6Uy)4WIXkmZK3ep2u-@9(td zX5V=-=Tn)&zhHB_-TL!sCC`?6#@U%+M zc^;X8^B*;^$txcai8uThpt{gemBKIlU>a~f2AY;n@KPWbJ)eRr|`Xd z26_6EV>JEIVr=7(HF+-@B)z*jdY$eP@Bw)-_(xNmWLWY^>mGlz^CvR#9mn0}SkSi> zJTUka4=4Qnj<)yZqsF?V9=ZOs%AD4;VdQXQ@~+Vd`MrtaDl?aej&gwe`dtvfsbJr% zCi(PKX>_vWSC-b4vAYsCDu|W4_C|K~LI@q^4#h+Mn4Cc|Jj@;e;bjcss@2;hLCc)4 zubt_2K~3;m9WatpPu^beOGs7@o}kYD$V+rbD9$*cL(aG*Dw6B^2Gi0>l`5UtjkossBP2KvVPVVmT>cDpt&+>Z-O`IRMr-A~ex_ujTZKuIKqrpDrfIb}8 zRMu(6IiG^#Rw@1+X{U*}b3-utJy(bF)5VI01Z?E_?{sAcjM(q9`3D*c&K48QJOTzU zbJ`T71NeE)@17xFADODgHCMso#2hV`;jKbiU{>O;fHWygW4Jnmn=&rbbi58|Y$3$$=l2`0G#Rb1mRNnI=3l<9__$NO| znjh|234k9yEjyJW06o(K0_s>7{c{2z63YqgX2CTxLW`L`9RU1Ma{zu+$wJ#?Pg9e2 z3kC7tGxclNEHS`ySU_)qb{{cKjQ&29dwL)?eV}E*d9A0Q3AJZ5Z6q>~;{6zl6{>F` z1bfc^xmbz>@}+4k$xo-D4G`_lcra3HMujd5SYM1^LC~E)=*1608J|ja5gcME4tg1t zcdP7e?FyqnO{7sjQsVA)WT<~cI$i18lB<3Sm=u1$f?Qf{mEM`Q0ct!Ou+XH_sR!Kg z1Dy8+CLj$1oZxU~0d)&*%4F)S?#<|$J*D0_S5==kF)PQICmVl4I2pkD@QyJ$L1&7& z!eXZF!p7NDoh@-PCAZe)5OSi!jWvf{&Cc<2Za{{(2#N)D9ov0r2z_Sncf`-NS1B zVP-M}K=>8vT@-wW33^3sNSqtXrmNJ2Ag?z^UrnhEWH7x-%ZROuw)C1#iZ6>|^><9v zB0u;?or~!*O70kxY)W>O1)u`$2QARjr%tc#-zrV*X>kp57LK`=$Z6M>xND4Gi`QJ| zIzkiTN4Ic{kr;HXEzyxN!J*N?fFDQGO7Y+=v;ruC=kX{%uo&`YS1E8k2~`hVoi+xC zi%``-*ul<`IK$mRR%?BtRpTdtqHYPkMw5vt39zfCJicsEDEQ$kPt7u~Gqm~yHiu`Z z7y{8>;hqB8Bm*CczI&6pCD)q}!%Jc9Qnri*s`dNQjKm^^xW11R75SJ1SDyH6UkcDy zCeRss2jj<=7c8auPS8Uh)&$KbB)41gVn%i!tsp!B5vMOaEIk)5ohGqzNgH=vl%b26 zm}a^lIqS-VN9Wn1XC=hEc2WVMUTVm*k@3sCHu}-7Z^#Nj!chwx{Kb3g&5H_2)-H7D zeN~J1-O(tD^el*28QZI9!rpeW;hDZPIIGtI+CX(cCUf_^8lwr&!=K)T3)G5>f*8lpNCx5j{qL-)Xi>Gj8fcZq2gcOxX^p zdS~F~Q)%yxiY9%xQF^!e;t6|y2Z#b7py54Q#HSLrs``ZUBd)T2_r#dafY=waO5a9r z0Hz3;aP{Q*-2fU;x=k!S5t%L1@_mKfj6z`%O8;%sV?|tF2T~S>PA|=`bXL1!m~EEmyRxW4qh{iX65(ulsCLvPKvo zw4>Uaf{`^umD@p9bK7pWt`0SARWz^6`Sk~*ncHI3NG=*7M?aD(08A;95VWqfb-_@P z?%`{GE)xxuhnaJ?>K`%5Ru>k&HOTNrBEbCgnT8-Im`d}&a^Ln_(8}^ z$Lwx2q1dve7vXywPdmHp#*3xukaYBxE~)pQA03_?oj!Vc|37p|Zmon3M6_?tS#RcOnn1JP6!{-q05pl$uq`ePZ6O3)v#_{=e2~~Qgy%#ZBHDZ@tpWmZpU2HDwEr;NA8L; zHRYrEb&NXM_|>PbFUY1FKY#R@b;nO|x_BX`i^IoHUp_fm$GAt0_n`9L`aFI^ae!Ab z>nIN~({m=}(0iFtnG@|CIZAhbUe1(NKer{fh9wcKYQfy9BDLoO1u-ZO_yaL-^fH-U_` zqyp}w`I9vpg9IQ61^JLf+U=I1aCXzokH`X?JgN*@!^4fpb&1po6Ay)LHNI5>wFaJO z3F`aM2sPRp-sj^{;8jYrRX#+ETZ-R`A+_q5Ywqz}v&r-4!@p8Z9fBN2cwq&pd&f2=_M)@+DNv zmpo@%=A+8dWr>>s794%*05QF`oxorAN%ls#s=;Sv~^j$UdB(y05NCbJxL z)e`0(+-nCy1SaJfoq*BE7b3v(lDpd*g{8$`|3v>%Msg!&N-3D$#2Wnrp3aLW=3LIn zvcn}ce5KZs2R^mw@HV7g8#Bu(HqH^^t%)f{=-rnHI4?pUp4cz9TqLZLa`9<%86@8x0qs5Jj9=02h0{ zi8Xi8OwEwpt!Qx-VgA57`Ge!3iRhaEux%r&0c!t72@!w4Cx*t3kf17-@1WJ6PAN!E zIPP`RLCvf-`CaK|Np3Zk>z&$$?qPH3u)<4#m(u$s72>>Ul*1d&k#u@00yBlnbuO4qXvP=g7<#owXfVOx;wwn#&$*=;tf7q9{Szbk$-Vv1@t&DA>KD{$u%j z0?i{bdeos+b_Usx9u|EWbE4BT%44+cW*Xi+%{n`b@N<=Pc_bGmL(>l<7uqIZH-u!q6Rlcp z(7iRN0jxFp>9MdQG{K&02mIw?qn7iI?|XT})$owMdJKlnW2Pvp!^2N9$JeRX*j`G`|s~U}X+k#rXw%_Jv$Ar~CejOC8*Tfxp1e z$Gl{!gCc!mPNBaW+<*7A<`i7lkQt|p|9vc*;R)f3GIW%m+5~qoZgK+@&FHpnPCNJX z9QzdpDNeres_{UCWZX^0e#LRldNpyw+=2MZGF8y4tLx%hVPuTGpya zHLU*bY@kbLK*vE8tV*?sF_1F-+dTyssR!%yNvQ7_`h*w%UWP0PLaTA*Uep~OzE;`9 zO`C@8(%nH{V~Hyu-=nu1^lkINdgPVw2YiE0#nVIc$qcu3)^of->>WI>@vP4U?Z*^B zK5D|EOhgDdUvUELHi*JFSGuRe+ugn*;YBdE%fIcQRzBbxKvA&(2^T9FB*oN=5fbWslX!~;M2mOO->%Y8&WC8mtN(Net2fYpGQ_|U3zN0S zD@>ZB6;^h^;kb8pQxBNgn;e;7`V?1*{U}Ezv{KvG&wKa!Iy%bd+2E{&H3t9~rq<}7 z)S7^lB|@tiQoWHVn^mMt-&fc>piTZKrjEUi*`pTkj}j~GZyG1=RWkz=!ahn(B2J`T zN2oOh%NjK^d4?3$y#=y)@S%MPBQtfVpA?J3VMERlnUc@1|hQn6&K zU*O%MJrW*^E_ybx$drY4JsEWnuc3|@Jwc03ROc@M-iF`^@<54dZvlz*7+D=@%QU!BT6DpUiJ&1kux; zbRZKPzgh+?`BNn`S1Yh4gNZIhxKd5LX;l$({5+cXXDDGnjeiq8ygRa@=cu_&UC)q` zK@d94*Ap!X$qp(eMAIzrLfrHM*{K&FSVeIeJplshaE~HbRQF zhWF-CWuA`HxzEDP;uC2%0DzLaB=&mxp0W}2GfZv|4xiq9K22*Jq4RZg{A@4reA;;b zE?>TDQeWf-#P60)H9yOn`_}1>&%l@STXWw0gQt%VkDn0f{&D!?A28_ph1AdxwDW*K z?JQRdG=^sR8KaA+p%9)QGr@qCoDbi#1y6vN*BRe7(*Q^JMO;Wh(=OfY&X2S!F14Pn z>)_F&qn{5?j-L*6@_2E*yuZQ2=*; zZM!OMfZTYK9yW*y2(mwM;>28E{}UW-YE z?hc;d1Y=(1fY6)!;LPkV=hHXMpe@zg-MB~4f>Wexj*H2dg)R}}Y03P^Ys@`sxM07n zPlxXjOD(aSXhoL9@ADa3vT5DckxEptj*Kh$T8w&ps75GMn?zQY`9=2>QF+xswE0I( z4fR4Km@k`3Fj(kr0ajJl#pK<{PCpkBf;H`c08@I?7W6qg0fx zsxA;(+x9j)qw$veHSJ)CDjRtILab+sAi-$plJ!b}?PMeAwZ`Wp8STIN%|W*~f6E$+ z8<8k27`)P&1XKC9eOaSxo)IaHXp1#c*R(3Gc88}w{Lt+Sj}_3K)TYL(ZiGy>%m4mh zq`9nyl5g;1i3bs+A*TQs;aR@q%%I=O+-Q1^eA8lozylTRm&75U%O6e_%N6Gb_39Z@ zwnUp_`KDPrP_ylO@!K&WbOuew`3WxbaFi!!=RoR-xSwDHq+J!uA4eeBA!2tNrxbg) zqzu5ji}Q1OXLeOB`r+MV%5YH_i~h*L*+m5a;wTYBUVKm1+mrP$=LD%$vdMIpPfj>5 z;Q`R~l#b(6p|)r>3Zp#l(-gdI>q1(2uF&<~;OOH=PCW$BgeSu49k7322UQNlAXr;P zIZA@KBl2S8chM1Qd8|5Ft4S32T&E}xP`h;6m-CQ#VbL|*M^KlmtWuItG4?m^IsQ} z6%z#QETc+b9U|a<@q1R(ditT^VktA+A<$QcxaAf-;QWk%c$aum2wEuUE)+u2)V*&pn)zD3Z4 zP>vTgUcoA8{M8si<0ZMEwE)KonrP=$TXS-y7VB^45Sb^3jX^*XK0Em+2+n!KD%_<@qB&D z0>MgRt5z_P9Iq9cngd#)8OC8Dw+XmWwNWZ}M+v^*6HSDA1mFB_v%3a(+6*8m07*c$ zzYyiTuRIzu>jS^fuy;-sr)%g)Y3T)UH}u(vkb{aYs62x{I-nnE&C@7icL20{M$iE7 zb#Hzt(0YCI4m7pP!%5LvRju04Xro~Wnqbf@49sZQpUwD4+$=^VhPgylCo z@|zv`RoRim`oy{vUARxnT=(RYClA}FujrX|G&eUc%@#kSscC4Qu`1?^HAbO7&(Im5 zqp!pjjX>?uzPB+nGBt)w&v6}C-IXOz}#u~gd z6OlrV#n>+H-_@yXU9MNEn#W#=BrE0n-UG^Ykq9DNoZfAE(ZH^^r^+Ti71TncYe;S%|0Fyd-b;_WepW6fA1fd-8YUlmb5*EiFU>sue;p-h-v z9!%tZsO14aXc6rJDEucc1T!DiJO_{AEO+4Dq?)WQ9d|$7_X05;H!vIyqS1?+Zyx3{2)eVV(IjG8-4=0jJg1Q|_4ROGtGdpq#SL-K`QD2i1ByV>Je9nQ zqkxB3?5vyd*=`?$Tm^nW;e6+h<`Pj69A2M{XM(c}5@DIQmY^=W2QCZMji zh5_zZa#DA7)f3Clc5Fi2TZ139v7sg*-&<~aIK5-+^3SeXE$+(I+Je&KJTmw zeSODGaHNx9{-6RI4^VdpoG8k>*$dD!xYq`EeM#J`2()2V1tx>mUx&fO$n3<#FkIVVwneSh|(R)%SE#9Dqig z{fnKSv*~2E*Xr~3+go(2X4vV2i`8Vx^*dYI6+32lK6~)by+_<+-aD?~&7_{N#T^Gt z=hrhR@f4c;e?^my+}O6{hc-AD=T(lIq~3@7(Y|}z*%@dbT|{##`TuY(amCPySkm|W zY=isrvojQ7?fim2$=)WAA9v|j;(PKZ9-la0;Q{b}@<)4YmKRezAYP)qPYv)^P7mMb zlPMMehX?&Q>clC%#BkC?o7vd1nY#3t7vg$!Hd!GV=yu|K)@)~y7tF8dMnmZh?Kib$ z)QTHsW?;`W#FQYN%?xZKc3pE&zEh=ST{pzeH>vgT0R1NZ#ybWwu)LVAu%WiAbEqlH zeYaHh=1|OTUEhh)YX~5&QNkJiT-@L+_S&{DX6%D_Hr(asLWB=?9OP5^c?Ra#`BECIj%cz=1uhXwJ} z)fofJd6_RJ(@V3WWYNlGcjuROuxL#U0TqnRlqz@<)^ddhoSx%JQgkg=ONd<(6$kIy zdi##=Q{+o@{24$l1mva<4c=~7L@ zUi_r;S*i;bG_d?Q3Vpd^1b((f2a9nv5)%xlT?GrilF(f~XqDt#)0rY#*enw$ivw*i zTklA($>Xvl3B%C!vXtSMp!C7siR#SFv$BlbC}&ZWyHQkzkq^dC#^6C!cy;OJh3C2b zp}bLM5KUbN+&rK-AN>6UHc(17P+#M>`N$92K$ElcIfy<6T=(}6;Q!o;f)QEFm*+>HR`cmO4-!|30fj1R=5T!I2&m}<_svVHaofnSd_-wbe4^2@R?r(^`HMRs zNyiFHVj&C`=MDbLR|8jb3rAlo_JthXKI`O*u0x+3&o>UYAeW%1gd<7lp5-%4C_xor z^s}!Mn+Dxvb2rf!G~^~r{(YzI*lj3y&S+&v?Ig}>z&R7(cRZ1F)oa4ZE_n+$s@d?IC+m$zRpi;#!;I4c5Hd`M z4c)Q4-&25`T`Y0Qcd{JnsTxh8u-Tfhj82cie!c()7tJ9dtjmr97?k*p`pjX76YvWz zhO{SGpu4Y?##?8{m(@^iX-d9j!AFozVc|$AbZZAQhR^oT4I1X5$1^{#AfJu zRlhgUB{EM4N0^Jj|Ac==T3lD*+g%JB9()-iL9S{Wi@cTjWfaLiMgzKy=*@zXV=sCIPAWaJ*_=I1y2LsSHi6&$&`;+uTRJb7XyyQ*KTRTjlp=}u#A1lQ^}QwD$Q5ma7w9h1 z$wZtlf$U4Pxtr+~YYDbEpQ8^lfd`i&?u|n(Z!;|~o%a`0n00f0Nb6T2^V^X08<-%k zC0N!Jgl!2G-g~qpmYgh?e8GW_0v_lqv|KqO}^p3=+c;bEKc+~Jy;^QUC7^=xBie_WkM#0n;M3P^(A6gMp=yyWlp zBt#;O(%Gk?#F9pkw9ua`P1BJOb@U$sZ1VnF;kLE0>F_DN&~;8f;O;;OSzkLG9re(< zHa-65xWUol@K7*I{R(6(En|peK9OInYiEw4xp`0u=3r!0l5RoW^K$pyM z7u`mY7mV37dVi1Gb$)Yn^`Jx3yR{4dy@AcpD~iG|L(dK3GLOT;uj4XfSrV|ctn=LS z0#=lvpVw)exPDo=l^-W{=0$nJ(low-z@{`oKS6*q?hSCNNQ?<|w$aMfWHoL4A+Bf^ z0$3Zo6lIb5jW3)!BkbPEjb{vSw)k?lI9YzH4G~II1mH< z73NuT)lf@`Y9H4HL+SW_oUCO(-cRzT_FhLTw@sp*)yke?i0^WMihu|o#3pXX!t~-& zK#{%|a?F-&%1WGCG>cqLv|T3#jXWF@Zl5&EYaBFA#C(EkNh{32#<6NA7$vWhT9o$C z2XO-+xx_1bmvDkGD&?e3!}WK z;v!5E(04@uPI-`2`8L%W_F#tQ@KP$5$842jC%3QRK&OTKo}to)5g4Q0^kp1%0m`;s z(`djw)JIR|v%QBGv$y03pOBor5Qp9F0s|qh!RVd|jGP8pMMdHSDz8~(lk??1Lvdsm zXZ!QT+k>OyXD{&ao^Y1!%1(A!uKgft{d!Mdy+@qO`E<(HtLV_|0l~r7o1~au4GEsg zK4c?qoa;Uck(aXx%u{FZY&pMJAblJ5baq}oKfXO|Cw3iDd@qxe$C!3qya)1(i`38R z+OPe%^ui#DDz7YZ-(_B0v!w8|G6yYDL^Z49IARqG)1q|itc=SfEV65Afpu%0HzN6K z8XY6;`pRo-pR}P~TsU1eLY(7jd@bi9D8g%xkXV583V!^?jTBz(xS2YIdsne?N~t8m z{=svRrDf5Gd6UzEHC7lMC4lML1?*i=vW{Z!v)#e|P5!O!Nv_Wdc+d!*eu~jT zc+SItJ%){H){!Gmwi|9{o>HLU9Sla`Iw5Su%)K&5UHHHJl?FkUdSDVknbga$4T2FOc>LxSX%t5Vw#5I- z;SoUaQxDruIac^L3<9&1mjMNQFNU&73i=n{VaYV`;>^wPsYg$JdLB(K0GC6tD#5LCZdNB{m}I$MvVuV;W0nSS4)sFMXMrEOL78Q)pB0&318Jhr zzcv(?aK$`l=rwr3H3Pc(aphMTE9=;eG9S#%uwr?Yxp5BOGz*~~xYlK!_(`1lKz)`0 zwaPdzy>=us7pV!1l^|83D5*nmvr9LR>ne+jBu|stO9RHzBn)dmtYFwfKLB@}x$vb3 z>L?DdM3q)q9)iV7RQ4rIz&ij=U|x^`nhXckhaNEOpIekQV40*@Qq?dm`d;Y+mz(7bEv1vdnVaN+-efY8(^D8-{*)y-NK3`bx}Y=YDHH-Ot5W_nO^l}@Jk5(z zJWX@NFW^s^EL&7T?q?M}E!40k%v(^#~?SO!Ax3(WJ(Yys>`zsQS%_qVQjt>!7#%Cb^EtyzKF+~{d8 z%Z4lp%RrQ6vR&YgFfVw2b63(l3_UN1M1Q=%#HJZ3f(0Ya$Imar5-Rbh;1=_zpiJ@z z7>u4Kv3Qy$z_AslewKFnn?;}@3c!MRp%4^>DKCKj`1~no8vQB4N=q@mx$l=n7;`$O zm7sneRw-EP9P?CCp#Wz+D8YIsY$O$mG_AtA5>Lal7e{;#E%92QJPOjI)I!SSQ&6^5 z%IOS$#M2y#vO<(CI((G^NwXps62ZhsHczQmAVwWp3Nn`RF-t>Pwk`_zN0f~P#h{C2 z4gVK7MrON>eB%4064ZyMSrVq4pA#lVGGREuxuOri4ZPi`_H$N?G4VU&8+bvazQ(I?!%BX{xqqKr-V%)%SJWKgbA1RBo@37qsf#)2k2>%%co^s z*CFQ+n5jj7Knzkp;G+sNrHOfiBfbX^0&|$hfKvoEuAn{$Lk6-e=;#aTM|D)VW#9|U zJJg5AH4sKIGMDW8^Eoaf?cAzBEF($8Uh_|sBwW(3R}RuLbmxa#n8GbZ#t z5F?2*bK&J&GsThMh0sq!p9zVHW5Eky;Fi9da@xg7XVkqQiNVy(`KV`N%zTiv#0OnK zPo+j|o+2zvf96j?ji#VE_|r;^ug|pywUBDRPQs{+xOR-)j&5sk zq*|e90jEZ{lGsSi<*L-{fshOImSSu_9Z9tyN zIx2a8L#g-SDa(^WwCf4lxK*6{ZXlleNvB=#EXpkB;~TnygWNE|r@X&mDBA`5uwpKU z)#x^u%R#@2`8CX7)TKp3HVZrhy8{08@&G*uC>4NBsayF>*ze?HxM-h}oiA)(v@A0G z#_drp==dI#UqOhUoG++P7( z2yGaptvK|mECUVeWnjkucNF+8a@96CT(tGD-%wh#kP}Vvu%$_vig%#*l=?v}KHT>0 z!x(Ho__r)uc(pHW%Z8p=m!5_PrP0=WJBR_gCh)IYNeqB)g?I-J34R0ODJ6a1()S8Y z!e+#vR1kH0m_=IsF^8`1rAGg%z@w!fLOxD2-hjKk@}bw~)3pJn>Vq zg+YQ{^jMO%>p$5>l34TyxS=|?CuwSFw-}+N_&kv0X{W#7%JkQ7X9bnQ z9GB82pFyb8E@55=V-#80FV3?`9d`TW`2%0P##Iyjq;;w;`unA=9G z)JH0fDqFuRsR_A6r-^IncQn-R&PcePr;amkJ?ru(=DbK<%egD>tkUmL z6-qTTseo14_&3f9y%baUFOw~z_oJ1n3k$5&lX@=m8UE`s3+>!K+NDAYN$Yu>gQO0` zI32IA%+nO91s)5yeoBLOKDJsUFr_wFdx6x>d1GgYQgLRXd68=);}w;zVZqREVKV^{ zeKa{zDRNVmB^KCqWWdTT{Og0GElZI-lNDY5b%9yeP?zi%{N`iqRMHuv>Of@?M^8bn zh_*1lx)hx>I4)Dh-w#D^eXrqOUMhE)r61tt>ZSay{&8KlRwoEsiG^SnfT~W48Z5>t zidYCN9VQ<5cR>aoe3g~h>AXsctP0Bryp$NcJ3oRE%&Xdv%RKJtZ@@WdN|9DT=c?&{ z(qq$L6kNq0U|TI3v@tucV&5vRI6p?RhGh()JGe@nR zdvTqrGvfliT(qEzRQS^vgO4z>U6!F0erUi?bognQQOrFrNm?u{2He7?fQqyDAm_EH4b2(SbrtU?7VT$cc= zLGP>j%kwz&qUO-yKOEyS1dLTk^sM6Eb{I7BTY{4WSS#hsey3yl-C~4mhM*l48qn&L zN9!zLK4dQOM+yFZ0#5=-349-kRTx?`OJvV-jQDu6WFcp9G+&Tf3ho4>kks|5kCC7^ zz7^j@FKsrihz6C+Q=>uDj?E?(E5GWq%onSt+=rtzzh;!Z@zyqRMCF^&&ThHxT5n7g zuEN0RgNw6T+rBx5T`bawR_P+Ht#MQVLWD816xWdaEEGDLYGbdx5baUUrMw3z`qIb) z1^uczIE4ZyB?5z5q@AJHQ9R8MOPXJB!sC}2=?j8oDv9P^m84N53f zgLwzXoYwUiu9#^(2d}Z^szECxip01JJH&TGVFjYE+2{~#C8$Eb^;T$ovt37(qhA{u z*6(5)i)c-Z8YGBh8-z3BB4#pIlPQddpaz8hfqM-z3U6DZSuAIAghH~$vc#Z_nOWhB zm2)VYGvGbwp$`U)Y_rHYu0@Wx#iycWR}hu56N?ji|Mnk0a0H z0Q8Hpid`0YA}ZnH3Nw}xdNx&JhE3eHGVpVCX+%yYz3F2ejI*JHMSj|Pkz}dJQ9$0| z86%-D=9)UGhOi`SB$Samq_Ho4CAjLJ#vtQy8Q0(*fE)l1WbhyJlLYJ{T)IfW2~N=5 zf^qe*cMYt#>A%q9p7c;sj;BwUlZ1;IoBR~cn`y#(=1J>|=#XJ;Odvf8!Yo{C^w*KKE*jT6i_~32k>*M9z3Lj7tN$+|vFigoTbSAWAR(RixKLHwdj4 z9~^#3OB#(P`bIPhIoE?E1r&`&Yy#Bxu3uwbjf?BoNx||Y0?RM-%Blv5&w?P#fz=E6 zHvoonSrwPiVCZLYoRnprh2-OTWUIKGhoC|oF+b1anAKGhmL*I5!Uv4NuksRxl8D(y zWyWHla}?wZ7y)_0^P{vZ{W>ZsUj*q8>iow0COwdj=dNjwoLi5*`Df!S92jKZ(7IB; ztetNMEgT$YkXCMcw(B*fU2z?o66Y*#PqxyXk%a-08R85^-0Qn?J(Y6g_#4Eo@`>Z% zZ#%c~+@?l1y0l(KGaQy=U}2;waAQ%**p62R7zIEGRcm`9<}S4@_?(eXB`to>DyWwq@NWX+wl4vsq>xN@n&Pwo8>cz(11SUEA>QSF>!EEcEt$r)^+b#D#THvECi&P2GgVecElN@j%+vnKJRI#M-X^629@=3j*Ci@uw zsy3&j2)qd~Vt{Z1Kag>iFN;#7L9y>bU*bF^BM1S_RACIJAhp?Oxn}m|R*}y&2Dg=Y z_A>W>K2cAE?TA(YZYRSmRO}T=QA8OVKA*oMN=V_~uxFJoEfGEkbDc}&eEAK_u~;uh ztw!=~jW%Ddyv1j=sDYWB{23?>`OI%)O$F(3pgcZ7-jeun>|=^Rh|$89ati~jHR;IMoVXTkzdd+n0{)UB1F{<6;shSnPw;q;<9k-p=gP7T(?H<6ODNA>!m zo3=dVM7)bvuNmFjgVuUZIm~`NC%OM)HPx$C}cd(=)uIVKOx8LD!OV@z6BQ9&u z6O!hL?^~c;Ca+x?NmgM1vM_(tNyNPzusuynUF4NkKaUj`!6!EvA7mUQDBg$ZDn@J&CP5g_1Y?9y1Fgqi z+5ujfk6E#4SVBpa4-jvfqcXM$9hr)G6vs8;!C-n)ag;ss5%(bU-6W&F_z7x-3d4o2 zyAJc3>oMAg6w?~kXniL9d+^z7jEkh98XZslprD=?S=sbFaPu@OD%12~1>cCd=XuTw;(gu3bj5Y1l5>dne+K^F1dh0_SAODSMlz8rGzzBj^ zvy5G7Q;TdE8X;&g7|%_CugL+-3ouZ?B7q0SrJIDv=P|>C15i6YK8ZoC1Gm-4U26G= zV&jsV5>z&R5f(+@7pUOFB1VS;egS(HNs!}nkZ})XJZ|twJF#>r=WC=Pv9rts3RI>rG*8oHG`)Z55yqs&t8 z4)_ija5a2~#@;s8b5tp9;zXWT;;NY2$OZRuIQQ|$TP*YU{MO>eU(wa-G^+%>ca}Ah zNUSt;GU;h<_Ibp+wM%(?l-lZKrM7lyxl|cFeB zJkMF^76nV=D$U)jW*}Kv;+Jh)BaCAaodAvDBB!KUJRLNe(0e>`%txo>ln=?OLHiDB z06$+ln+m0qQ>&xDbBq3pZzCx9JLkXAhoo2%3Xbs?hiATg{R%uwO3U&FsomcV*0Ye3ylr=+j;s1x&Pn?5aA!IUtWwXQDfukUfR_ z>wunZ^(ojbF^US>GgJ!W@(H)cKvQIc`qkPqRcor*7@o}G!M@YJe8rEa z2vL;M{xFYK8_c(UenXVWTFUU*nPw@s7^DbjF&W*hgU>L&Vhok>1-+eu8mZ7T2|IpD z<`0f9^a3DxX`!t<@c*^nl-YGCHz^iUr_a6EMv;!E6wO>MrFh80Cl3Ru<~O4iB`Mex z+=gJ7bI@82Zu1$i*4=H#b7H=eqf3FH!X;lX%rNfd!E9he#jquc7K1MGq>h0ZA?DI) zT5vMD=Tb&M7IK|VRMT`M^jyv0h=5$uJwEvO}<{jBMJ0``{sds)?=x>PMgg<#IMIVPwx zLFLjKJYo~JK7QQ0TI+lD==?QMaUudRdbPH*f*z}DmW`fK^mn1p+))??Jm=Q;@stCx zV&OGw*kY|y*IV7FqwmM&`b=Lxx2}INp6+AjerJ6M|8=!UobT7g26NIUi=>0Y%r?+j z{gHH6Y4{f>xmelH>GLgD%@foKK~%{0LZ4>> z0ZV#;NhM9jUCh@(8AmOd2AOA$7L>p&Xw-};&xWol%#O>!!eoA#W-#ofUw}B*Wsm@y z=UL;tC$`B8q@Y5Q6sj#ZSr7i+iYuV6N`_WuGARfy2jEA#em#4(}WG*J3#+Yr+ z=eZa-C&gH2>hk%I)@dTj)bTUyTLk78&j3O(YxB=B1_N{~dH%Ua+4K0jl=rh8X#nRY0@FB6S{)PKQQN=QT_n`Zea!ZXsEs65F+6qI6IYq8rOH-5G;ltfqvQIcTRfw}^pMv4Uyr80ja zO7a#WjxA}(xQjiW!y>Sc`>vv($M%GepC&op~Up@Iu>MY;17>>>Z@(F{++iCKE=&T9lxzFQZ+(YF!ik^BzO`;EQ znaFVR6IXZ*GA{;$D3+|5NWO*f*E4QBbmoC061QT&T1Aj2FzeHt+-A}ELQ>ilO_4=| z<-}?zmh#X)kJWWgc-G|KwCkQ&4{O)8%;fOX4E=5>A7st?YM^9Zc)S+%osU`)R;VvB z9(zuB){!xr`rX+SIf!Ex7irA1JA|Ypilih-u1iV^#uUcz@Et}kF}pp+$-Qpn2(?|r zeWV0qgP42u|F`$8J#r&Qg5MX||4`7E)d1reGLw&_fjdB+k#_}nJch0H-NCz%l4Mfq zo9-@MS4lIy3;*|vM?T496|2=Pdx6#1&2B#O5$}kMjO12Ct7Z76_TR9VWVu*b`o}$# z0@vtyX1%Mq*)lb-6cn)>5e$*hdTulV6;TiUWql^jDnq@4+5KXPc^>biG2WO^ib85; z{Cdhz#Vo%HrDfxws7jw7@2s!JjtrlQk$9nt@Z8d>xFl(zP?pq%<=EDJ)w$ics7Ft8 zYlm@9r7fgpzL<>=x;rAyw^fuE;bkH3W~%+@%ZOKN!V=bFEu$!+#hs8$m9!RE;%*A? z@>u3~xRR%omy{}^KGnPYI!j+pij#bzHwH(a5j8mqL`ouRg7-!cWrt`23!b2Lem z)Og99Qf60}h~8>PZ_cV;&}S!H{Gsx1)@Lx-5C)xYxEzCZ27~UN$DqXsp0tb>NFQ`K zk9#Cb8R^O5ry~iV0^HEA`-l-1pjlU-<8>ChS?(HzzcqO03QGc!R9iSk33@OMoih3Oe2G(5nnMN++qsgqVK z4ShX1FWJSN_;-9J$o@nQ2Ix?I9Lr%8p#cA>V_6pNA(!&H>X~*II}nA|HEB4wHa;hj z?Fr%Z_jwAZ_!07pwY+Ra0XqiX<0Y0fZz+8yw`Otkx!-_sq-A`tuTJLAg=mCZ6$=q^ z%3B$5#eibt9c8N+TwlQKoVKM%xs96BwQP&Fp!Eg}+*Rwbi6*w)+6A3>xH@m2))u$BSPEgUrHhGKYq`o>%ft_Ug*mpA zc}HQB$^0jMG>~tC+|_8(!XaLTPa8S2=t_$(c-D%XMVDA-BC7)jzyF)GpVN3eBB}xq z;R)Z@HBwDPSu-ke>y|#Q)kHWcPVFLBs8AY`8F6N3g_0EG2~_(WE0veBGD-{6j9qI0 zHyZc)fq7yy5KKL`W7#$1Si>}c?ka=j@(O8`k<$PM8Tot~xWVr3qFs#=tDHJ&N-`wH zSWc=*GbF_*X8Q;5o^<$`c?ycE!HTg;_V-~llJDzcn>?bw(p;crW}wfpYiXqp^I2)N z4j@8#f*ro!x*f$)E>MG|X8l_A>0BThwK<(PD8}iM9nW7XZx9?eOYNwAO);=_@2uXA z?P0F94$sSxcZTBR@Qu{Vet0asE3!Ljphxr-F=nXne1HZGAQxNC>`)|XBB?^-3UnKG z&tRLF1305rV4zKY?IcH%m%v-6{90V2v3NI_`GuYt$rm$>5!}xEwQ(%KjDG(@CKhB& zKa+>SGce@+t$MgPTGA?0F;e7&=h@JT9e0cK(GRSzIhFDmwjPw*C}$!3nTI2wP~2q1Z6st{K*Z zQ``(YVU>r!`+bpUdMBGS^EXXg!K5Vddm+<1ORte#)+!d7?$eUtvv{%3aaxMDEhxjhDL;q~cue!acK; zyAlJuOSzkHbdbA_My>p9NrKVNe=kLawT)q@w<05z$8`23Zpp?9P9dwy2$a3JnW7KA^uAXLT)qqQEMupXYxc*Bft;j`b^?#7*^k5M^?_tUsBA*GWw zU$_ioWwYrBA4#PgDY4?iwv4(hm2v<|et){Flw%=B*I;dh+$>ejVOKWoG)-9fUQdI> z{UA->v?KI6mTfndR}2EDhKIfixw zkFPC!eIA66+rRh-wQ?x4LN`jMT*~};Nv)jOe{%^H#lP~k_!MPFb9MoaX%dWwNd!D3 zEp9kVfT*Sx?hLDyFV|uh9HV}e*ni^=p3mv(0UcTX zm=>OCsh+jeX072_g;8vwpf=ks3-4^JVSEH-``zQz9|+z(wydy*NGVO1uf5Q2ne%0p zpinA?st2<5=W$hW)dShk`Y&CB-_&tbLa@}2s~#vmtq$6w^R8?@xXo;+ZTl7;UBN!R z<5P_6!FPRPuQ*G(VF^#ax1bl8yFjwK^ABbaQ|t8R`7_|Fi?NrjljQg)%c&>0;-b31 zmhM}7&R^QngDUHKx(8L0h0~e3!bJD&*gg^6tAgyORl0As%=u(hUFoXoHie7uVf+rA zEsEo*%GGzVy3<-{bgG%v=jXE`+r~$#XM7dTUrYH4EJxxi#d_OEPYPF;McCQ7c!8=T zUTW)F@l26M1@T{PIY?mwZia)DiFS%Fc^pzS>ztlX}6^@(BsFNJ$ zcr50@6I}N|o5X4)JfgMb>nZKM;H4EEo|`#->sClqVIxF}e^Zo+XH%qn{;|#_F37Z>HI;uZj?QRjk&eX*LOa36t_%fNBn>| z*VcmWagFx@_CR0CtTfYFdV8Q3?OA)^BI)#5_CR^k9+>YS-NG|{-*2#}FXNeh%C8ll zsl!D))8mfqC*hd^>!+XKnc`xuX_#wx-?cpptVh3xC3JucPJUfU%# zb~Ar<$WmkFaY3h*oVRIcj3b`Um>c8Z*6-jQ(NT=;(PY4bER>Lyk>e{oCW=;W@fuko z@VDZx7W-ZBSy#{ZxI|e&X)krjdy|Ss$_f&k6-4|Xy7lUPXQCA~^7J^d-&n>`iYBr= zi*atxv2IZ|-$>eu0<*rWO_W!sQh?UyYg}{Yo`Y6JdzY#VW#-9t*p~j>iGz4o3728R z^o?AA)*p=^?VsMXJDO{Z-r+kPMb&w1S?HhDDYSbdsm>ThsSVfRJqOoCMMg>f6SCw9 zUEpLs`(43$a5|u_%8H{(R6Cfe#SURrcyZcFT*XJ(I>1G8=5SNk++nPkA$b*FPBPhl ztdNm-hbYcrD*PHNT2NlnO=$J9mxO!9e7+A!89DJ93cb%25vVp*ZM7N6;XvbMZR>jA zm$+_CV{D3W#TKpHDkr?pJILJ{wAG>s7Yav%1<%^6k{K{;Q&C80HoRw1!+^P8W{7X6)K$ zC9iW(buP;Iqk1j;f5KNu=Mk^bc5Ys}o{vYH1Sixd(}tukdP5o&DU$kRs^U?2*vkq~ z+xD&HJK_)IUZf>kaRKk~$XsO@B?9fziheuI{vp4hq=SdFORp+9{}Zn`Cc94*TNE=& zShi)eY^qXdZbRtM2F^O>C1;7I_{E>NLWzeqT8NgFnL)I~{HX|{vvyRK-Zv5yv=qCkRmu zwC8#plJlFaOtPzaL@TZ5KdO*`5{*}&`9Iw8(_ys)qMRjE`R7o8_1Oj3PQwhgpawAi z-@~uA)Y=mKDhtilNfWno2jv>U&&o1f4oqZO-6_zeEsxXXlVFP|2R*+_fA-aBt`~KR zA1OJX&ce)M8uK?Mhy7?y3qD`rWuf{xbh>K6%XmVc@Yu@qa$1U4qMy^Z7}^sOLq^o< zpk2(`SdkWGR$3IXk0x!b0OM2M&!{A=NYE9>XJ|fTgNaC^to16+_FC|MY3!k5`2$z# zuV*fHmVQwsT6d*Knd@=o-69JU^5Hm33}bn0ZL}p-H^L)bMqN@(qk$_b`0TMJm1!(l z34#=RrfYy;jrncsx>XJd{VB@nah8(P7u*k6VNUv@!`|{W>8Xr+DroOWgBeH^f5L10 zHolR}glt5(fu{pf#uE(&`>QC5NY|u45yJtW({3ZW2F${Hm3uG1T=+T~E{EIiA}O1y zseC2N_++Ol%7iuoXVp<2cfgKps3KQM^qc3} z&FZu|qtj|Jlb@Kq&GmW^9L-z7l1ATTt_PG;h(!S?CSYET0O-ibFf%!z%hH6}on(ZIBh8~xrrB-U(CQB3sG9Pts zDO@YV$gK=x(hBCF(XMEWOYs+!`RRMN{9niX5AW9Y-7#W!G2E)DS$^QsSu|Fx6toGGh&d6jx!7JXVj|OK;m~l}qGbtnOB7=4TjUZbbU){nRpcz0kf)+ttqHrT7?xUeveiQGX z0l;=~b-zfvfYQR&VE!tvTP6c`Vg*_WJk(YK^9n4lC8~NHt5JidGku4Jl_xW{V^_+d z>IaZ@&0vsw4T!*DtPJkR?^`j9Lp|!g9H`F;#w;sIq%{Jv<>$s5pMCw0|FGLV8_kF7 z{k<7~bAL3$el*X1y?a*t(iAQM5UeyZZ_rwZMLii1sJROY*;{pkP680e0AI_t#GRtW zfRtNc02&Xik^^{%Q{PQ=x0Lp-X#p(N$nRn;7P<>BiPnsY@8aRj$z5DX)%{@aD%wQG zN9Ahc-t9-JMK{vj9*@bSyF)S5z{PwQ!y9yWtaJ+is(WAB2v zsGE_Y->JoXyLtq|txBea-a=G^z=Qb+zKe+)$z5zq4Hmyzhyl!PhO-(i^znejx*mDt z%0U6lb1jF$@Ms(qdZor{8tvUmt&S0&qh_M7IuHOr3p`(?jJweaItqaylQ&; zZoi-_1t9HuZ8^eNO!~X@m9$ugo@8ef<4jfV-Kp>4hkduP5Q8ZW6a3GPaeioX;7@$s zju!fG7mRAf^xPVY$<_>}H-()89%4xS)|1d?vN#b7{DR)Xnwu@n3{5)vss?jIgT`RF zpe^j+K1j>b@ZENt-KEh;_ihbBPPNSIZDVPnnd(X@m;l{vwYxijda0N~+Rol>fen<9 zjMa81<|FrG#OKXqp%2#80F+`!Q&{K&GvL-)3rAt0Ur(T<1}W^w7tn{>69C3aM`Oq3 z?^3^NaCe8U(c0eaZ4aP31Qw>^yMv|78i=_X`M5FAXA64vIHBj#ViH)U=}XO$si`e3 zR9L^oSdO6+2I#H?pSa+#MA5VhtYaK&lA~sw6R)wXYqH6Ij&$p^vzs)p`rr@@`Yy({m^402Buz2d$nY8TU zVO>A`S!#((RuwvTqDqa|P&^pF^ow^Cpl8S0rI2yr1%Hh}?al_|*(@zeci$gWEqM$$ zZ`wLj#@|Ls4>(U=z$@{1BiD*s4nx}p|0<%smd6_4Gb+^Q``~stiBV2n=X%ft6I}(E z49Y(1-GQ^b!Ni%ow5;8%jTp^)+$Is)o5Epo4xSs5`eWG6pPn26xUKlJ7~Kc}ZoPdr z44RDaB7Red%-nrh4#F6`CF|vkN>3MIZf-^v_V8t`>1Q3rTwbc%V@mDbiVVDl-aGMQ=UEkrpW?MiKg~9DJcg{EZCp%F>zt z!t@JRW1`dy!?>e(j^PrM5aSu+>ew8+b86y5jSH6R(cR?41KU@Fi(Tk&$25D6Q+RyM za(plghK`?W(^g9ufs)gwWeH*I2;u0 zXqIB_^Ld3*6q#|kt)p>Ys%$f}>&`+4wfQE>;$AA9!_<&sO4Va--maXwL}WSTOWM+s3wtKAOW628@fYYcp+6^{g$OpmvM%%9T$mJ@xWix-gk} zfSa4XC6@9hDz$P-Vxp~NKJ!Sc8DHvVDZgRN(!WJg0i7#9|8~WuStMKPyhVdHCNCm7 z>RtFZjxu!L<{(;k=^TbYKX}Xl^IaSF4x_SLj%gefr&VEsHH~8dXKZ!K*xymwq33H~ z8iBZYHiN#*!B+~elT7>hTi<8aPhX2%pS4>uP4ITvW*L|AT43=E@~2(Wb5yb-ZU0=l zCLK&w^m-s}rRAarrE5|vlmv*^MXKh*#yPFM1#n!;k}cW-i!HF2EwI2siaM80J33coWoGS&j$V~nwDH&&*lPEU z4UX&F`ZIB}hz}48M+rRwF3HfQg)YV71(WU!O_102&oocXX3VpO|(}Syy zaS<243)PWjJUAU3#<0FU3QG>ri5U({*m#FSNZmy%x9lp;Q8Rw`_>y>&?gAmSAyyHc zuMFWM39I2z`BX9qPMYDdv8Cc&TP$<{H5GYVj5+q^ff&Sra(9UR*E7FgQ;3IX^#c-P67~jO03wq&HU5Y|W zjkL1ZS?pQ`K5^)%y6>Td8@6A^Fv=J`J1}tOxL2UH?~N(0I_!&?uGNyMwEq`FHR1`g zTH++UGs7V9zk%I+{5Gp|!uqIg9O zZweD~=VX_;HsyIcv1ED{livz*t3Q25RCadCYvJ_^-=pFkd@Z zbpsBnQ2*3y@L_Nk5apX(Xux2ZmtzQ1Sh`VVcyyJvi_ArWCDLB_e(sVO(1p}7)QC#BGVcD zVWb4rS6TF#f)evf7~!Z7A_+V#1nyzPfs^=jUU+;up_op3tqovApUg4CgS`wWtIqbz zgnEjv(L}W>WfeWkKw-ZrIxo<7wO$K{rPI)aVwa}Gh+Q5Gz8z}4Q5y?tGe56f2^DdQ z>Jm*Y9GuBZkY=?il;~^vi!7^GqLGe9nnMZ&mYHnuW#N|e5YL?ya&Dq#e4&j-v7%kK z5$(vNIYpiMv$P@iWnov~C&7cgdJnA?$Vj^-0m|}B^~fDaVfmEq0Af}RA94zYf;Ro_ z2^M=`BJ-~VpWX`zZs3)L<#tbPmk^2!jM{JCkH~{H~&!5k<;43 zANZBb=yykvw<3vs*@pnNHAh2#LXitXKA!Xo;R zgm=lX;-mD5Bz2+UIQ35J`d_Ka5Dk+}kQHGcgdT9Jo` z6@QP6q#|kwM?lxBVN7!2bK=d_q~DV`x(Ow5&lY=D-facD`>EFf9xg?pZK04(C{$Nc zy5L59Qp0;trSXpGLDFcenJCUaGOhO1s2F5(<+DLY{f-K{i!_l)^^Vfe+$;7t=@?=L zt{zb22JmR2#bm-gh-^(3R+K_nkLo*XZQTqy! zVt7-luOO~tNwIDDKb|(4`#T`%bGvmFE;Z*BVgyDUmUSlOih}9fe&)ctz>GH8lvo=I z;?mCKAPdXQN}OCzC4J|mrC}<^=Qijg5v;2kAQHP~i`=G3|n>+m|+; zC)m>~!ngLoicw^&F*Njp#l#aDq4~E5G!QtsV6RVmYnxk(_wZG62=jE0{?_(Sh3%s| zvFh4`%4;?7AG!d1$OvRio6c*_)XSFsT76KfFwRy1KX-q7%otS!Psq)&FUlwRz@&G*8d;xh0 zG(QXkN|aN)(#J{1N@ms5N)O%hQss_v(-3Tw7ek5qnM(_6reS$x1Xd}0>%{nS)mnyP z3@UReo7reQ==J})*00Z|{@d&&jqD&l250HhTipU_Kz;=%v z%CQV-O(j(nJy||wRfkWbkKkVHP4Gx23*aXoF1v~$&HS8zhQZT2yK?yx5mumvWE{h2 z$|xUm*v*OF&+9h-)qLSs=jMueq6Nf(Qha&TTB&;gVVqWNx}@HBzcUL_BE@(uIOT*_hnM3Bh(f< zFbq!h1Q_-E>qTV^fEht9*`@krCk_vf62|oJaTqHiFaNOIEF(({K!aXyu8fL?lyo0B zH_<4{Q9{%H;hgxci;-Ns?|?oCK~^@_YYWU8??oA~ndzdbRb!*IqYC{Ik+p@-9Toel zclc4m*cHH*91&LRDBvDhrKw$WB^U2v6rg*sOR>-jQLaBiSg2i4edwi<$MT5~ZS1^` zn-A!~Jo}NT{NNXcNsOc7TjVwAaBYdXTN`S|B#}W$@PMdGM*s<|L$Ig)(RqbxY2c{I z^$l%WFuZ`RlXHZ!a=#?5oon~e*Q`jF`D^};KObx=;lJ2aNrFJn4>pyc6CxM(5e!$B zfgeMif?|F0LPzP=E^Ap?LvA|DL6z^XIuxIYvW7798#3*>8#}VtP0!MnlhW99dn!m} z_G&7O0-e4_i;R*rbrJkP)BO`hi)#;u$FNHW-<0RDTcQ^=(ik?P!Z+}Yn*rjZE&4Qg z!v#0e4zc2^02PFD)rNqjR3__O^actZ_rl=D%=_vA5aNxeZ(_7da<{NL_tfmB}0PTq;3pyUKD~rQPI|+XnKi1MY)N6(Ug?a%cY=zEGj3t=0Ke$&b-D zcjriN12zgXxyqj_Qa(0RW76u`uQpqb;rs8Pw>3XeaTbRKuk? zb9nNU>*wtwy8C{VY<)Z7RWB-`RDecG>3QMcsg7Ldby6RJ-7t*?BzLQ zLD9y(r)F<^y!FZt!GegAUZ9>!rGIRCUa_4umwySMG-ud>vavR&kLUwyG%|Y(Ft<_V zAqtJyBT1qj3J_wd6(3u?T|y`NF5CW7QYF%@w(YgVrXnh53BpkihQ=7bpXx$$ZHilk z*1MOWWQ>N`T3mo-Y}x=HgY(JQ>IUj$b8bzL*AmAQHKNlt4>xV#u*~JA@ONbAj)6vr zmeCOApUj^;BtgY<_`G-r_+zawst7+}x?(!5tI0yXEJT`FN<&6PxOVxT@8A#NVQz{< zBul1MZYnVdEugK2NE04fe9NL-xau4-wBWs=db zNP|fl6a0z#5><1B{I3LRvt>bboQa|)VU6>YMFDwrmoKK_MKiNxco}DrB4jHTKUjXX zsH}yWHXv*U?8Yxk)@r8XHEGH7yS>a{I$OVPkLu-9i$V$-)@R~I@CnZedaGrH)Q$cG z={j|(>Sqpd9z`Nfgi;6-F*AB`8x`v(>IBZz+Wu55n2d5>P%#hZJ3AHCXrOZ{x1{R*@KH`D$ z5N_6|~lcO8#^PZ0f~L*E`& zIU|2-A5+Z!L&F__|rNHa;ek+KVF=@V)!<8EpYK?JH1dD1+eie$=z-^*-=@ z!@M`s$kSc`wX}alGm3Rf?&ks(|EkdBenHKZruE$Awc%PTUvgv3n)@FVNml*QMnfEI z>WGI>Fd}D-L-SO37qN_bb+f~h5!Vsg^Zu?~M!6-D^Pl_wBX?;ZyvN1LLxy-2wf6{g zjV5zR@(0txbvYE=388&RlG_Jy2V>}Cf8m8$x2JxTxCWft0 zuz^9&QDxhL^`ie*#3dShs1r|(M6(*!RVrMaTdyDd{RE#9)wH%w6Gbl+#q~9S^AQuS z)9{FwC_5XftKEAgWbU`?k$aS{Jc0udgvkDjd;?UC&Fcg5FwQoy|KKfY)x7!<_wD*GIvcu5Q&j=|;#Cv%I&Une}Uj8bE;|n17&{-5? zMlqTw?yt~zYF0+w&Sz@~)65YNkL)_5;EDW;x#U2KZ<9l9WE784h~2gTux2{Hg}ClF z<$|`c9ICY#tO+s$tSdo{?V-<5kQ9L-FkC${+4!%o3%B8XQ)YLZi#HSttw~pmGZqV# z8^1%^;y$`yyhcM)@<%sFI0f~Yl5Q>zu(%3&7qsw=jq_z0EY3*a@7K+kYXuioU5`?~ zPH=|iX=X!7PCPXn&$jR}ncH&!e}>O~%xU#T~7~EOc-A^j5(6I>m;kWAA#S-}`c^afM-0v5DWO7CC0u|KWrG$hj zDyeStT_iO9f(utYCf)tJ!qMFa!yi3eMX4W~b4ot$GCw?3pKWVW|6E6^;hGL|WJljj z&KFX%oHtO*2HX<47h{FkjG#qxzPdiB7%td08E&vy0yA&BE2PzQ(kI!W%rt>EHdujf zUzvIx-`GJ#hzAru1F!{Dz!=xx2~l-9L^L#3dGSBR=TllsTPIZLli1FO4-$_E3Q~VE zw`(vnjTDA5iIYe9eZ1HFcrp5D>RVs@_DQ>|J;Ig)XQ;*^hm9CnuHrqfy z`Tu9i5*p#68sh(V&Jq-l8#*INYQc+DyHWbO?6M=HZ2j;9RXMCe3zb{Ou+~%CrJahO zV)~d?vq_?zioTCCr88&m9dR86z8(2iJyl1zgqPAtv^oAU^K)< zy_BHiR(E?=7>32K>We%GA5r}Y5DN{n-=e@7XZcd^zF|Bjwnl>)shy}fUq)Gc!?;&g zBmGtGy2)c8#ZF6~D=>cXygL+84f$={?h~jx_M1`Bx)~F0}0IR3sE0<$RyF);H?G z?0XExp{dBN%Z9+JNq=O!XH3EzWke(8Ly@C+$rN6?k_5(QAZ>#u@Ive;XSzV9rBJlk5~({pEE^f7d-wDz(F zui3S@vq{DXXL}iG=Iaty%9**!=tF7H=8RX3wll1l!=th-yWG>CAbQ${644isDKFFK zPY+jU>^sZ9ph*n;yya_rGl;@{k_2AB8?+b0w(e4gT#~!O~|!5Dod>u znqdeBK~u}QY?-B+o|t8v6@el}scN2HJXEz-9{FyAD%&p&@m1Y+q@D8RO`bRTHjZim z85v=i#T+{Yjg{z=Xl9DY@AHZNXk=T)Y+@~@CA0V+|9&%H7lc2?x+}@(l%U*7PS|U0 zH@AdyjMzpF=@W4EI3m@Hmx~;eR?uzV#@}gQ%!DFNPT+MpQjwNcqYw{tQI7W4SA53$ z1Fhbj0h=sKl-p&?s#BppKH|$N>Mf-XXkZE zUb7Jc=MHp#OCyFultnvIHT09baY4$$%qm2O>EsForg+h0E%a#IUAG7H5k}_GvzNcH zC-&rxf>*_Z6h7@v3W2jFFYF|OD(@@gBpRl@bf0G5bLE+uF832Rbq<7~&nVUJL|K>7 zWjH1dys`+Hf`wiix!0mO^>M8PQA*w=V- zAcNQ6Cee(5TL}CEUjJqaY4(0oxIV3EaD%vcL{a+NU`*h>Tqb87SKM)sLc*#U5yak1 z`<+4JDl7V%>>)V$^)d)?fz z0K!PwgI(;%n?YcBKc|o_qQdr~>a^cgthGQ{QU~c8k34FZahxZXDmj^^;iS(VKj;feYPceuznH=z}lYC(N*yWBItD&r<@m?_XL= zXXU87C}y7$!^KesqX{_^ImO)tmWge<1h$#T?=pT9J`ZV9b;kgUGH-RzrTgfc=(Cys zz}dHcWKA|$h053_E~8J(rlu5f4wKBSq_DFi4xua-baCAnxuTQYIcY8_~{!ySH6~;(#T_$ z%fOFi&)lWlWVzm2nlvMY1OaJT=mle_2uITx!?9>g^>%C zRDFc-uYm!c{c>lABWK8fC6k;U&(fRIo7AC+MwIjA%28{lJNE6`Ifz$Faecp2{kEL% zBDIlhgFT%5zs$3_7k8u6Hw}$qwI)c^&A8v?0wLo~+rcN^w`G-1UR~RMcMm;t`Gxett4%Rta8v5cMfwNVza+R=)kq zYkKFvRAw|5L#{IPnf}6HXgx*UOztmFCNqOiSXozIBHzq}{VLgb1h0v3rG#*dDpYJ6 z7ya%f4Uj%^xi`yubKBR{-GqIgZl&TL)r_J7VW=fXBMqtPV~rVDP z`K&3|V-m$&B4sclftIy+@@sNY1GwM^=x*Ru*~H4B=!bi2h@BL5^?uN#Tcw{ByW$e4ZP9 zdBYm3QqPa)$}J2{cWWI4(eKrWo=w$|bq|&D&vXOMme_P%OanV(j%UgRw>s$w-7$PS z7aR?a6m+QPxtm;z*2+cm*cr-UDKGt}R+WqX7rz=BqQ1}<$dNU75Nj=HzGGMUI)N8< z+ZxLX#iP$sz8N3YS*P%9;~dsO)J|rw#ocj(dahC{Eal}p;K#{pSrm8O<}Ba4nQxl$ zXd2{qS=4grqaTaiCAZbFMXZgm;*{y3Bb<8;UNjIgKSY8o{DxS4^=&w*cY{K9Ss zy_-%i5VztL;@N#CCat7|WkPMR5_F5H*%uyWmm-dBhKXGdZwk4*^Kgu@0hj>fqSV72 ze+k6>VN3XV{wmGo9Rbi7R`x8s@+lsp5$amSb)5mb8kK5FVk@WdOR|ctD~;Uzu4)7h zQ^pY|bvai`4St(Eq7tu9xdoK}ngt&uqJfc(sMltw9^SFs{T`pE485_MIB^9^G|hhz zmWph7xt?#&c`s#~b9f0hL7=U{I>Ni%c?YAxb%&;|sb@1 zG7`jlw~6qa21I%pe_?1}YyyQpKd-*IZF;-sA&J`GpH+8pZyasAJlw@SLTNvIw|Z-f za?X-!yadaVQt^15FTU@BliuTexPEhSd_LdPYhHbSnJ9WzlkM8{Zs$Jj^u9D`Y|7eR z%U%rBD}J`fB!o!j^O#dv zgodOHA3ybCQ2}ibI_F{Eyy`i7I$GS|1DxJR*3KeTSohP`L3e$!Hz(FpO-;|cm8@-P zuNlkuV4ZDEyzLL0RXVR1S7+z04Q;_uNIIUooXR%m<9)V8Jv zd?!RmTNCT3rDf~)>x!0Vx1kP3Se;ks`j&Uy^BWXvP|+V;H{P=&^OX)y`?YsNYn=$7 ztL0F}hUX057+20g*Zbw|m`>mG#T3u`Sk;5+ID5l5(_@#RQQUU~zXr{NMs_76lM>`p8e=`8-5C z9+k1nfs63qfM0+1aO%Goz1H(?=CID%#65K48LCndy9Tl^?s^UOS{FuriksFBZJj zcQ?1cZa!hRe-2MZ2+dB)i$l%mZ0^|H^xM<_S$Mp@EwYL4{G00m4!v0re!5rB+u*{} z-jiMj^b{p(J$>wY4L|&fB0M;cAA^DohGRWob*SYXd~ZE5*%k#I&8tDGM7kKl!%u6S zO~LnByE@66W9rv$-Mb9-&T6=wN7t=a#wD~9C&;byyY&X5J@+F#|8oKEBp8EpDV;v} z14xE(DCx$&!1CN+FtB7jG}EasMM|)jfE~(>8WGLkH8vGc+(*=KlDB}?CMQVXdh8_}bPfxuJ0cO;B*Hrh&CDge`-pDWqt<2;SJO3JibC_w24oH?ebZF^&YMvHW0W zBF#KZd26I+`gA*8jL$UnasoGcHmm3RJKW2i4TkHZ9&ft|^t4Qh5C_81_!cabZcJ9v zc#ZJ654u0A{*GDPX2n5D(f-&?gjOTrE3W*e;En$R~3z15Ulgh0_AQ_TiD?0A*VDvWP? zJN~;~0}7+I-ZaB`oKl;d;p0usf^{p$YXH1~vqGd#y<9-d%g1Wt^q}|uTyYMv zW|F$|`A8>LfE_m*Sf^prvq|O7ejuzfd7AANg|e>XOfVUmdIS=w#temFWzB3ScB8SsUA&EYq`r3Wc=VfAD87b9y6zzQY zi@=`0c8RSIw1b#QhWPk|ShAr0xzXKxz2oNA+HXYH1BK!hb?djFm072-lP(%wNcg2c zQ64vm`fnV^;3z_#Q&42EN|UHP>roGv2?3|C-Fqpk5fsCit(z~6530`(ZzYynmY_Df ziq5A@4s3kE2WS&x0fdX)8xp%A;JFT%op;OELD@GpSKC+appyx@7CzXH%PMaVM_=rt z>iI?Q7U>L7}^>44T6` zF7BEj7^_G7U@~TIFpenn%kka%dEc9fVyrlxb(`%w$0FJV-RJFe!7Qn(TPVm5EL+O` zEf<(yN@#6Oa*RNTqZm?m+oDad1f=IQBtFpV{O$bZ+w#Hq`C2$jGG`G&hA4~7TiDXK zwB}=wBD?~1=z{zvKojiY9=L&rgcOmY8PUaMkJv=il>$LVKKR0BTV4>y^B}y#h|G6w z-ag9<+}b1rR)Kt@5QC}cInpb?Vc%*KI_)PRsW_7feX=yEEHeovfvM&_X`^CL+tJSS zB?VO6?$3jCx?XmHIv)2|pUv`_pM$j{Nk0YaJUYn)RyRB?R|w*gtG{pWonUTuxxDWD zXnpJ{DU)&r`aEx7y@ZcvChUX4`J=X+nm0S1i$Q~$k}A6=9gGKvC(^F~d6+%&1I8&1 z+GT<3gqsFhulk(ou~hQQreA4V_;u@R$GCMHf_Pf`*0^_zi^g9e;CLq*#e4T}2}A<2 zJWK>nHOPA8X|4>RF?WPVCSqnjYjxsyLxUgXcy25eO;M#NLn>I`+2n!? zJuR>58uzQQJ7U^$>{FGiLuyQJQk_~iy&-jWI&!AKZX#Nbk6~ydKxCXj&uL!XuY6y2 zqU!A7?Ys)MLFHt4u}VJkh19Gu1)c!m-SFVwHnu0lA__~iXjv(=8OO<>J>RdK>E0g)PE>f`-X>1ouY;4`uXbeLuRJRK z0bwfsI`B~U7b;eiPD9T~P-v6xSr+<>ny{4dD?Sz>@ss>G(@^4eQ?GABgxc*-FJR5I zJ{yDF`__9;aH)?%tRKX40?h~K#pjIy{-3eb32u$sf;&Mpi#3A0blsSRnLe~@vA2h& zT=k-iOgNSZZA97%>K&Y6E?q65UXVhU-~k1ZWDIBxDpV8YtUV(c$` zzUk@fhMjJBLBHV@(sbUEI$wnP=Q5%NhqJjw!Ga}E?l65`&Aiuj_F`yycRoCm9?g9ms}Hbu1>|gcvkc8uNGU(7U>wY5 zHdYRkXUJ!6?j^ z3eTEc>na$UJ&zyte3<0GH|DyRsJOk_AFWF|Wy-cGDE9&i zM_1f22R3%K`5Rx_yPl8uVt{CZ)NK6gX%KM4U*wzaBX^jt;f&M|Dq26=_KKMVvFWnd z1jFiZ`awYX*Bl^qZHDC#`1`fpsZcG0IFC7UUmNA6SLVA1D1YmZ?NatH=n6n00WB2338 zhrZ7AUie;FR>)v^2aA^xqz-Ns?)K8U&|(E4iO*)>DW4`oA81W2kITh2gsUJy1e>Z} zW5_e39xFTI`}Ryv`+i69Q7rhEq_fk`L%eHe-Ys3a51W2TJ3=P$^Zd;(mbkCVb!F@3hb z;GXEONnSEFM`;>M1T-7=9!!)>rc}qva&M1K9NJB^kB;87aeBVLcOu z($yn%wZY?=XHNs{FFB9@u;Kwkv*VA!kc%@#wspo~EE3lOMOdYZ-C|*m??r8Zl*?^JUnq1C1AxsxV zub0HzB(ycnw06gBr5Lgd1FT*@Zev}w^$oR-r5%*6nMPUEK`n-r2Q($j{_>&O2E82U z-?1n={8}JsW%CSXmFgw=>^Jr$xJ}0?m$_E&%!++fDCtu6Tp3Rk(|x=jomU|}GYc64 zU94Nb8(0Uw!kihHs5B8)+L{PEiJV_Q5LMZ|vAseG{+d(;&=I|#`Z{e}=6CR@Mwd6m zhFf3HSqdoo8JoY*>HU27a@$eNjegGv@)2Bj@pgC0l)scSAXdz6QEP2etrFPlY1SuUS=4#(Hkyq|Z1GSOd$2Yt`BXHkaSc$sU0naUG-E0t>gwe;RWY z*uDSk{*`{g^OA88gqcq0bdNo&QODVPYFsvpl&(HVp*kME`AFPK443Rx7(1ErD=bBL z<{X~#aWWFdo5;qp_Jt6!Jb2ub)08)igf?&v^G^sBuF|Ujqy0L!jrGgp-LjS1=LZ4C zNjYzh%3$!l7g9PXRTkD0APfb;qzO0$X73V0@?^uu@snQ6T9ZZ%udE-SWs17l4Z~v| zG%ORcB0j;_t5|5TQ5-tdbFPnuvePz+R)iti_M=ZIM>j}O zM3$I*?us6_Do;cL2PMS{TouU$XtB3PWGNvxha(3X+(#Z!NIho*~k2>^hMX25@%{C^wQul4UR zX4VcycK;S(`RZoE&jkRe{|^2S`vxxm4dJJrnce@*F48$6N_>O>z}YiT$Jiz{SHq(b{eQ8=AA8ouR#unZ3h@-yA=j z_HUQC*vTrH$N>O^Z-f2ANS%p)M*}+kpGNvu4F6}q{KxRG$o}gR`J)F-{|&(&XlWpB zZR6-*PxsIG;|+cyXruxI&}c&e*#86Pe>XiG>XDcN9zDzt!R?IxpYtL$K^a{v$a5CeJ|f4|zj7pp}u7nZBLg z|FGfWu-I08GCwx%Jj6dX?jiF(utb3$@nro!1c4%bKe?3v0HAOO20;C9I%UuO9S8V- z#=yTGL~e5XS}!#K087n372&~z{F_mL4rbOS!uAGsK Date: Wed, 18 Jan 2023 16:35:02 +1100 Subject: [PATCH 14/43] Fix URL for verify contracts --- hardhat.config.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index 3e9269da..8858281b 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -43,7 +43,7 @@ const config: HardhatUserConfig = { saveDeployments: true, verify: { etherscan: { - apiUrl: 'https://api.arbiscan.io/api/', + apiUrl: 'https://api.arbiscan.io', apiKey: process.env.ARB_SCAN_API_KEY! } } @@ -55,10 +55,8 @@ const config: HardhatUserConfig = { saveDeployments: true, verify: { etherscan: { - apiUrl: 'https://api-goerli.arbiscan.io/', - apiKey: { - arbitrumOne: 'Dyp61CtoHxyYVSrAY7oD6IzSVzOgkJuf' - } + apiUrl: 'https://api-goerli.arbiscan.io', + apiKey: 'Dyp61CtoHxyYVSrAY7oD6IzSVzOgkJuf' } } } @@ -107,7 +105,7 @@ const config: HardhatUserConfig = { // ftmTestnet: process.env.FTM_SCAN_API_KEY!, // optimisticEthereum: process.env.OP_SCAN_API_KEY!, - // arbitrum: process.env.ARB_SCAN_API_KEY!, + arbitrum: process.env.ARB_SCAN_API_KEY!, arbitrumGoerli: process.env.ARB_SCAN_API_KEY! } } From 4696882a5bce2594fdb205aae83ab4b7d6316f78 Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Tue, 24 Jan 2023 02:11:32 +1100 Subject: [PATCH 15/43] update names --- contracts/{Velo.sol => Flow.sol} | 4 +- contracts/Minter.sol | 4 +- contracts/VotingEscrow.sol | 2 +- contracts/interfaces/{IVelo.sol => IFlow.sol} | 0 contracts/redeem/MerkleClaim.sol | 12 +- contracts/redeem/RedemptionReceiver.sol | 36 +- contracts/redeem/RedemptionSender.sol | 2 +- package.json | 5 +- yarn.lock | 8584 ----------------- 9 files changed, 33 insertions(+), 8616 deletions(-) rename contracts/{Velo.sol => Flow.sol} (97%) rename contracts/interfaces/{IVelo.sol => IFlow.sol} (100%) delete mode 100644 yarn.lock diff --git a/contracts/Velo.sol b/contracts/Flow.sol similarity index 97% rename from contracts/Velo.sol rename to contracts/Flow.sol index 47cd3382..aae971a5 100644 --- a/contracts/Velo.sol +++ b/contracts/Flow.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.13; -import "contracts/interfaces/IVelo.sol"; +import "contracts/interfaces/IFlow.sol"; contract Velo is IVelo { string public constant name = "Velodrome"; - string public constant symbol = "VELO"; + string public constant symbol = "FLOW"; uint8 public constant decimals = 18; uint public totalSupply = 0; diff --git a/contracts/Minter.sol b/contracts/Minter.sol index 712a3255..72d0be09 100644 --- a/contracts/Minter.sol +++ b/contracts/Minter.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.13; import "contracts/libraries/Math.sol"; import "contracts/interfaces/IMinter.sol"; import "contracts/interfaces/IRewardsDistributor.sol"; -import "contracts/interfaces/IVelo.sol"; +import "contracts/interfaces/IFlow.sol"; import "contracts/interfaces/IVoter.sol"; import "contracts/interfaces/IVotingEscrow.sol"; @@ -19,7 +19,7 @@ contract Minter is IMinter { IVoter public immutable _voter; IVotingEscrow public immutable _ve; IRewardsDistributor public immutable _rewards_distributor; - uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals) + uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M FLOW (FLOW has 18 decimals) uint256 public active_period; uint256 internal constant LOCK = 86400 * 7 * 52 * 4; diff --git a/contracts/VotingEscrow.sol b/contracts/VotingEscrow.sol index 66eff883..ead6fa57 100644 --- a/contracts/VotingEscrow.sol +++ b/contracts/VotingEscrow.sol @@ -87,7 +87,7 @@ contract VotingEscrow is IERC721, IERC721Metadata, IVotes { uint internal tokenId; /// @notice Contract constructor - /// @param token_addr `VELO` token address + /// @param token_addr `FLOW` token address constructor(address token_addr, address art_proxy) { token = token_addr; voter = msg.sender; diff --git a/contracts/interfaces/IVelo.sol b/contracts/interfaces/IFlow.sol similarity index 100% rename from contracts/interfaces/IVelo.sol rename to contracts/interfaces/IFlow.sol diff --git a/contracts/redeem/MerkleClaim.sol b/contracts/redeem/MerkleClaim.sol index 6883ce58..190119e2 100644 --- a/contracts/redeem/MerkleClaim.sol +++ b/contracts/redeem/MerkleClaim.sol @@ -3,17 +3,17 @@ pragma solidity 0.8.13; /// ============ Imports ============ -import {IVelo} from "contracts/interfaces/IVelo.sol"; +import {IVelo} from "contracts/interfaces/IFlow.sol"; import {MerkleProof} from "openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol"; // OZ: MerkleProof /// @title MerkleClaim -/// @notice Claims VELO for members of a merkle tree +/// @notice Claims FLOW for members of a merkle tree /// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol) contract MerkleClaim { /// ============ Immutable storage ============ - /// @notice VELO token to claim - IVelo public immutable VELO; + /// @notice FLOW token to claim + IVelo public immutable FLOW; /// @notice ERC20-claimee inclusion root bytes32 public immutable merkleRoot; @@ -28,7 +28,7 @@ contract MerkleClaim { /// @param _velo address /// @param _merkleRoot of claimees constructor(address _velo, bytes32 _merkleRoot) { - VELO = IVelo(_velo); + FLOW = IVelo(_velo); merkleRoot = _merkleRoot; } @@ -62,7 +62,7 @@ contract MerkleClaim { hasClaimed[to] = true; // Claim tokens for address - require(VELO.claim(to, amount), "CLAIM_FAILED"); + require(FLOW.claim(to, amount), "CLAIM_FAILED"); // Emit claim event emit Claim(to, amount); diff --git a/contracts/redeem/RedemptionReceiver.sol b/contracts/redeem/RedemptionReceiver.sol index eaaa87a9..deb0ed22 100644 --- a/contracts/redeem/RedemptionReceiver.sol +++ b/contracts/redeem/RedemptionReceiver.sol @@ -4,13 +4,13 @@ pragma solidity 0.8.13; import "LayerZero/interfaces/ILayerZeroEndpoint.sol"; import "LayerZero/interfaces/ILayerZeroReceiver.sol"; import "contracts/interfaces/IERC20.sol"; -import "contracts/interfaces/IVelo.sol"; +import "contracts/interfaces/IFlow.sol"; -/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process -/// This contract is responsible for receiving the LZ message and distributing USDC + VELO +/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process +/// This contract is responsible for receiving the LZ message and distributing USDC + FLOW contract RedemptionReceiver is ILayerZeroReceiver { IERC20 public immutable USDC; - IVelo public immutable VELO; + IVelo public immutable FLOW; uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet address public immutable endpoint; @@ -22,8 +22,8 @@ contract RedemptionReceiver is ILayerZeroReceiver { uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18; uint256 public redeemedWEVE; uint256 public redeemableUSDC; - uint256 public redeemableVELO; - uint256 public leftoverVELO; + uint256 public redeemableFLOW; + uint256 public leftoverFLOW; constructor( address _usdc, @@ -34,7 +34,7 @@ contract RedemptionReceiver is ILayerZeroReceiver { require(_fantomChainId == 12 || _fantomChainId == 10012, "CHAIN_ID_NOT_FTM"); USDC = IERC20(_usdc); - VELO = IVelo(_velo); + FLOW = IVelo(_velo); fantomChainId = _fantomChainId; endpoint = _endpoint; @@ -48,12 +48,12 @@ contract RedemptionReceiver is ILayerZeroReceiver { _; } - event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO); + event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableFLOW); function initializeReceiverWith( address _fantomSender, uint256 _redeemableUSDC, - uint256 _redeemableVELO + uint256 _redeemableFLOW ) external onlyTeam { require(fantomSender == address(0), "ALREADY_INITIALIZED"); require( @@ -63,10 +63,10 @@ contract RedemptionReceiver is ILayerZeroReceiver { fantomSender = _fantomSender; redeemableUSDC = _redeemableUSDC; - redeemableVELO = _redeemableVELO; - leftoverVELO = _redeemableVELO; + redeemableFLOW = _redeemableFLOW; + leftoverFLOW = _redeemableFLOW; - emit Initialized(fantomSender, redeemableUSDC, redeemableVELO); + emit Initialized(fantomSender, redeemableUSDC, redeemableFLOW); } function setTeam(address _team) external onlyTeam { @@ -76,12 +76,12 @@ contract RedemptionReceiver is ILayerZeroReceiver { function previewRedeem(uint256 amountWEVE) public view - returns (uint256 shareOfUSDC, uint256 shareOfVELO) + returns (uint256 shareOfUSDC, uint256 shareOfFLOW) { // pro rata USDC shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE; - // pro rata VELO - shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE; + // pro rata FLOW + shareOfFLOW = (amountWEVE * redeemableFLOW) / ELIGIBLE_WEVE; } function lzReceive( @@ -107,16 +107,16 @@ contract RedemptionReceiver is ILayerZeroReceiver { (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE, "cannot redeem more than eligible" ); - (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE); + (uint256 shareOfUSDC, uint256 shareOfFLOW) = previewRedeem(amountWEVE); require( USDC.transfer(redemptionAddress, shareOfUSDC), "USDC_TRANSFER_FAILED" ); - leftoverVELO -= shareOfVELO; // this will revert if underflows + leftoverFLOW -= shareOfFLOW; // this will revert if underflows require( - VELO.claim(redemptionAddress, shareOfVELO), + FLOW.claim(redemptionAddress, shareOfFLOW), "CLAIM_FAILED" ); } diff --git a/contracts/redeem/RedemptionSender.sol b/contracts/redeem/RedemptionSender.sol index 0c1cc1b7..db4ac72b 100644 --- a/contracts/redeem/RedemptionSender.sol +++ b/contracts/redeem/RedemptionSender.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.13; import "LayerZero/interfaces/ILayerZeroEndpoint.sol"; import "contracts/interfaces/IERC20.sol"; -/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process +/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process /// This contract is responsible for burning WeVE and sending the LZ message contract RedemptionSender { address public immutable weve; diff --git a/package.json b/package.json index f8b4de84..6377e94f 100644 --- a/package.json +++ b/package.json @@ -37,5 +37,6 @@ }, "dependencies": { "zod": "^3.20.2" - } -} \ No newline at end of file + }, + "packageManager": "yarn@3.3.1" +} diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index 1aaf132c..00000000 --- a/yarn.lock +++ /dev/null @@ -1,8584 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@cspotcode/source-map-support@^0.8.0": - version "0.8.1" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" - integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== - dependencies: - "@jridgewell/trace-mapping" "0.3.9" - -"@ensdomains/ens@^0.4.4": - version "0.4.5" - resolved "https://registry.yarnpkg.com/@ensdomains/ens/-/ens-0.4.5.tgz#e0aebc005afdc066447c6e22feb4eda89a5edbfc" - integrity sha512-JSvpj1iNMFjK6K+uVl4unqMoa9rf5jopb8cya5UGBWz23Nw8hSNT7efgUx4BTlAPAgpNlEioUfeTyQ6J9ZvTVw== - dependencies: - bluebird "^3.5.2" - eth-ens-namehash "^2.0.8" - solc "^0.4.20" - testrpc "0.0.1" - web3-utils "^1.0.0-beta.31" - -"@ensdomains/resolver@^0.2.4": - version "0.2.4" - resolved "https://registry.yarnpkg.com/@ensdomains/resolver/-/resolver-0.2.4.tgz#c10fe28bf5efbf49bff4666d909aed0265efbc89" - integrity sha512-bvaTH34PMCbv6anRa9I/0zjLJgY4EuznbEMgbV77JBCQ9KNC46rzi0avuxpOfu+xDjPEtSFGqVEOr5GlUSGudA== - -"@ethereum-waffle/chai@^3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@ethereum-waffle/chai/-/chai-3.4.4.tgz#16c4cc877df31b035d6d92486dfdf983df9138ff" - integrity sha512-/K8czydBtXXkcM9X6q29EqEkc5dN3oYenyH2a9hF7rGAApAJUpH8QBtojxOY/xQ2up5W332jqgxwp0yPiYug1g== - dependencies: - "@ethereum-waffle/provider" "^3.4.4" - ethers "^5.5.2" - -"@ethereum-waffle/compiler@^3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@ethereum-waffle/compiler/-/compiler-3.4.4.tgz#d568ee0f6029e68b5c645506079fbf67d0dfcf19" - integrity sha512-RUK3axJ8IkD5xpWjWoJgyHclOeEzDLQFga6gKpeGxiS/zBu+HB0W2FvsrrLalTFIaPw/CGYACRBSIxqiCqwqTQ== - dependencies: - "@resolver-engine/imports" "^0.3.3" - "@resolver-engine/imports-fs" "^0.3.3" - "@typechain/ethers-v5" "^2.0.0" - "@types/mkdirp" "^0.5.2" - "@types/node-fetch" "^2.5.5" - ethers "^5.0.1" - mkdirp "^0.5.1" - node-fetch "^2.6.1" - solc "^0.6.3" - ts-generator "^0.1.1" - typechain "^3.0.0" - -"@ethereum-waffle/ens@^3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@ethereum-waffle/ens/-/ens-3.4.4.tgz#db97ea2c9decbb70b9205d53de2ccbd6f3182ba1" - integrity sha512-0m4NdwWxliy3heBYva1Wr4WbJKLnwXizmy5FfSSr5PMbjI7SIGCdCB59U7/ZzY773/hY3bLnzLwvG5mggVjJWg== - dependencies: - "@ensdomains/ens" "^0.4.4" - "@ensdomains/resolver" "^0.2.4" - ethers "^5.5.2" - -"@ethereum-waffle/mock-contract@^3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@ethereum-waffle/mock-contract/-/mock-contract-3.4.4.tgz#fc6ffa18813546f4950a69f5892d4dd54b2c685a" - integrity sha512-Mp0iB2YNWYGUV+VMl5tjPsaXKbKo8MDH9wSJ702l9EBjdxFf/vBvnMBAC1Fub1lLtmD0JHtp1pq+mWzg/xlLnA== - dependencies: - "@ethersproject/abi" "^5.5.0" - ethers "^5.5.2" - -"@ethereum-waffle/provider@^3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@ethereum-waffle/provider/-/provider-3.4.4.tgz#398fc1f7eb91cc2df7d011272eacba8af0c7fffb" - integrity sha512-GK8oKJAM8+PKy2nK08yDgl4A80mFuI8zBkE0C9GqTRYQqvuxIyXoLmJ5NZU9lIwyWVv5/KsoA11BgAv2jXE82g== - dependencies: - "@ethereum-waffle/ens" "^3.4.4" - ethers "^5.5.2" - ganache-core "^2.13.2" - patch-package "^6.2.2" - postinstall-postinstall "^2.1.0" - -"@ethersproject/abi@5.0.0-beta.153": - version "5.0.0-beta.153" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.0-beta.153.tgz#43a37172b33794e4562999f6e2d555b7599a8eee" - integrity sha512-aXweZ1Z7vMNzJdLpR1CZUAIgnwjrZeUSvN9syCwlBaEBUFJmFY+HHnfuTI5vIhVs/mRkfJVrbEyl51JZQqyjAg== - dependencies: - "@ethersproject/address" ">=5.0.0-beta.128" - "@ethersproject/bignumber" ">=5.0.0-beta.130" - "@ethersproject/bytes" ">=5.0.0-beta.129" - "@ethersproject/constants" ">=5.0.0-beta.128" - "@ethersproject/hash" ">=5.0.0-beta.128" - "@ethersproject/keccak256" ">=5.0.0-beta.127" - "@ethersproject/logger" ">=5.0.0-beta.129" - "@ethersproject/properties" ">=5.0.0-beta.131" - "@ethersproject/strings" ">=5.0.0-beta.130" - -"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.5.0", "@ethersproject/abi@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" - integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== - dependencies: - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" - integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/networks" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/web" "^5.7.0" - -"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" - integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - -"@ethersproject/address@5.7.0", "@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" - integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - -"@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" - integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== - dependencies: - "@ethersproject/bytes" "^5.7.0" - -"@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" - integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - -"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" - integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - bn.js "^5.2.1" - -"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" - integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/constants@5.7.0", "@ethersproject/constants@>=5.0.0-beta.128", "@ethersproject/constants@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" - integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - -"@ethersproject/contracts@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" - integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== - dependencies: - "@ethersproject/abi" "^5.7.0" - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - -"@ethersproject/hash@5.7.0", "@ethersproject/hash@>=5.0.0-beta.128", "@ethersproject/hash@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" - integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/base64" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" - integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/basex" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/pbkdf2" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/wordlists" "^5.7.0" - -"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" - integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hdnode" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/pbkdf2" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - aes-js "3.0.0" - scrypt-js "3.0.1" - -"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@>=5.0.0-beta.127", "@ethersproject/keccak256@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" - integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== - dependencies: - "@ethersproject/bytes" "^5.7.0" - js-sha3 "0.8.0" - -"@ethersproject/logger@5.7.0", "@ethersproject/logger@>=5.0.0-beta.129", "@ethersproject/logger@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" - integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== - -"@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.7.0": - version "5.7.1" - resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" - integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" - integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - -"@ethersproject/properties@5.7.0", "@ethersproject/properties@>=5.0.0-beta.131", "@ethersproject/properties@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" - integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/providers@5.7.2": - version "5.7.2" - resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" - integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/base64" "^5.7.0" - "@ethersproject/basex" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/networks" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/web" "^5.7.0" - bech32 "1.1.4" - ws "7.4.6" - -"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" - integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" - integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" - integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - hash.js "1.1.7" - -"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" - integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - bn.js "^5.2.1" - elliptic "6.5.4" - hash.js "1.1.7" - -"@ethersproject/solidity@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" - integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/strings@5.7.0", "@ethersproject/strings@>=5.0.0-beta.130", "@ethersproject/strings@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" - integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.0.0-beta.135", "@ethersproject/transactions@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" - integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== - dependencies: - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - -"@ethersproject/units@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" - integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/wallet@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" - integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/hdnode" "^5.7.0" - "@ethersproject/json-wallets" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/wordlists" "^5.7.0" - -"@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0": - version "5.7.1" - resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" - integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== - dependencies: - "@ethersproject/base64" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" - integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@jridgewell/resolve-uri@^3.0.3": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" - integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== - -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.14" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" - integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== - -"@jridgewell/trace-mapping@0.3.9": - version "0.3.9" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" - integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@metamask/eth-sig-util@^4.0.0": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz#3ad61f6ea9ad73ba5b19db780d40d9aae5157088" - integrity sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ== - dependencies: - ethereumjs-abi "^0.6.8" - ethereumjs-util "^6.2.1" - ethjs-util "^0.1.6" - tweetnacl "^1.0.3" - tweetnacl-util "^0.15.1" - -"@noble/hashes@1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.2.tgz#e9e035b9b166ca0af657a7848eb2718f0f22f183" - integrity sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA== - -"@noble/hashes@~1.1.1": - version "1.1.5" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.5.tgz#1a0377f3b9020efe2fae03290bd2a12140c95c11" - integrity sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ== - -"@noble/secp256k1@1.6.3", "@noble/secp256k1@~1.6.0": - version "1.6.3" - resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.6.3.tgz#7eed12d9f4404b416999d0c87686836c4c5c9b94" - integrity sha512-T04e4iTurVy7I8Sw4+c5OSN9/RkPlo1uKxAomtxQNLq8j1uPAqnsqG1bqvY3Jv7c13gyr6dui0zmh/I3+f/JaQ== - -"@nomicfoundation/ethereumjs-block@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-4.0.0.tgz#fdd5c045e7baa5169abeed0e1202bf94e4481c49" - integrity sha512-bk8uP8VuexLgyIZAHExH1QEovqx0Lzhc9Ntm63nCRKLHXIZkobaFaeCVwTESV7YkPKUk7NiK11s8ryed4CS9yA== - dependencies: - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-trie" "^5.0.0" - "@nomicfoundation/ethereumjs-tx" "^4.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - ethereum-cryptography "0.1.3" - -"@nomicfoundation/ethereumjs-blockchain@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-6.0.0.tgz#1a8c243a46d4d3691631f139bfb3a4a157187b0c" - integrity sha512-pLFEoea6MWd81QQYSReLlLfH7N9v7lH66JC/NMPN848ySPPQA5renWnE7wPByfQFzNrPBuDDRFFULMDmj1C0xw== - dependencies: - "@nomicfoundation/ethereumjs-block" "^4.0.0" - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-ethash" "^2.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-trie" "^5.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - abstract-level "^1.0.3" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - level "^8.0.0" - lru-cache "^5.1.1" - memory-level "^1.0.0" - -"@nomicfoundation/ethereumjs-common@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-3.0.0.tgz#f6bcc7753994555e49ab3aa517fc8bcf89c280b9" - integrity sha512-WS7qSshQfxoZOpHG/XqlHEGRG1zmyjYrvmATvc4c62+gZXgre1ymYP8ZNgx/3FyZY0TWe9OjFlKOfLqmgOeYwA== - dependencies: - "@nomicfoundation/ethereumjs-util" "^8.0.0" - crc-32 "^1.2.0" - -"@nomicfoundation/ethereumjs-ethash@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-2.0.0.tgz#11539c32fe0990e1122ff987d1b84cfa34774e81" - integrity sha512-WpDvnRncfDUuXdsAXlI4lXbqUDOA+adYRQaEezIkxqDkc+LDyYDbd/xairmY98GnQzo1zIqsIL6GB5MoMSJDew== - dependencies: - "@nomicfoundation/ethereumjs-block" "^4.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - abstract-level "^1.0.3" - bigint-crypto-utils "^3.0.23" - ethereum-cryptography "0.1.3" - -"@nomicfoundation/ethereumjs-evm@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-1.0.0.tgz#99cd173c03b59107c156a69c5e215409098a370b" - integrity sha512-hVS6qRo3V1PLKCO210UfcEQHvlG7GqR8iFzp0yyjTg2TmJQizcChKgWo8KFsdMw6AyoLgLhHGHw4HdlP8a4i+Q== - dependencies: - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - "@types/async-eventemitter" "^0.2.1" - async-eventemitter "^0.2.4" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - mcl-wasm "^0.7.1" - rustbn.js "~0.2.0" - -"@nomicfoundation/ethereumjs-rlp@^4.0.0", "@nomicfoundation/ethereumjs-rlp@^4.0.0-beta.2": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-4.0.0.tgz#d9a9c5f0f10310c8849b6525101de455a53e771d" - integrity sha512-GaSOGk5QbUk4eBP5qFbpXoZoZUj/NrW7MRa0tKY4Ew4c2HAS0GXArEMAamtFrkazp0BO4K5p2ZCG3b2FmbShmw== - -"@nomicfoundation/ethereumjs-statemanager@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-1.0.0.tgz#14a9d4e1c828230368f7ab520c144c34d8721e4b" - integrity sha512-jCtqFjcd2QejtuAMjQzbil/4NHf5aAWxUc+CvS0JclQpl+7M0bxMofR2AJdtz+P3u0ke2euhYREDiE7iSO31vQ== - dependencies: - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-trie" "^5.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - functional-red-black-tree "^1.0.1" - -"@nomicfoundation/ethereumjs-trie@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-5.0.0.tgz#dcfbe3be53a94bc061c9767a396c16702bc2f5b7" - integrity sha512-LIj5XdE+s+t6WSuq/ttegJzZ1vliwg6wlb+Y9f4RlBpuK35B9K02bO7xU+E6Rgg9RGptkWd6TVLdedTI4eNc2A== - dependencies: - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - ethereum-cryptography "0.1.3" - readable-stream "^3.6.0" - -"@nomicfoundation/ethereumjs-tx@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-4.0.0.tgz#59dc7452b0862b30342966f7052ab9a1f7802f52" - integrity sha512-Gg3Lir2lNUck43Kp/3x6TfBNwcWC9Z1wYue9Nz3v4xjdcv6oDW9QSMJxqsKw9QEGoBBZ+gqwpW7+F05/rs/g1w== - dependencies: - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - ethereum-cryptography "0.1.3" - -"@nomicfoundation/ethereumjs-util@^8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-8.0.0.tgz#deb2b15d2c308a731e82977aefc4e61ca0ece6c5" - integrity sha512-2emi0NJ/HmTG+CGY58fa+DQuAoroFeSH9gKu9O6JnwTtlzJtgfTixuoOqLEgyyzZVvwfIpRueuePb8TonL1y+A== - dependencies: - "@nomicfoundation/ethereumjs-rlp" "^4.0.0-beta.2" - ethereum-cryptography "0.1.3" - -"@nomicfoundation/ethereumjs-vm@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-6.0.0.tgz#2bb50d332bf41790b01a3767ffec3987585d1de6" - integrity sha512-JMPxvPQ3fzD063Sg3Tp+UdwUkVxMoo1uML6KSzFhMH3hoQi/LMuXBoEHAoW83/vyNS9BxEe6jm6LmT5xdeEJ6w== - dependencies: - "@nomicfoundation/ethereumjs-block" "^4.0.0" - "@nomicfoundation/ethereumjs-blockchain" "^6.0.0" - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-evm" "^1.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-statemanager" "^1.0.0" - "@nomicfoundation/ethereumjs-trie" "^5.0.0" - "@nomicfoundation/ethereumjs-tx" "^4.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - "@types/async-eventemitter" "^0.2.1" - async-eventemitter "^0.2.4" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - functional-red-black-tree "^1.0.1" - mcl-wasm "^0.7.1" - rustbn.js "~0.2.0" - -"@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.0.tgz#83a7367342bd053a76d04bbcf4f373fef07cf760" - integrity sha512-vEF3yKuuzfMHsZecHQcnkUrqm8mnTWfJeEVFHpg+cO+le96xQA4lAJYdUan8pXZohQxv1fSReQsn4QGNuBNuCw== - -"@nomicfoundation/solidity-analyzer-darwin-x64@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.0.tgz#1225f7da647ae1ad25a87125664704ecc0af6ccc" - integrity sha512-dlHeIg0pTL4dB1l9JDwbi/JG6dHQaU1xpDK+ugYO8eJ1kxx9Dh2isEUtA4d02cQAl22cjOHTvifAk96A+ItEHA== - -"@nomicfoundation/solidity-analyzer-freebsd-x64@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-freebsd-x64/-/solidity-analyzer-freebsd-x64-0.1.0.tgz#dbc052dcdfd50ae50fd5ae1788b69b4e0fa40040" - integrity sha512-WFCZYMv86WowDA4GiJKnebMQRt3kCcFqHeIomW6NMyqiKqhK1kIZCxSLDYsxqlx396kKLPN1713Q1S8tu68GKg== - -"@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.0.tgz#e6b2eea633995b557e74e881d2a43eab4760903d" - integrity sha512-DTw6MNQWWlCgc71Pq7CEhEqkb7fZnS7oly13pujs4cMH1sR0JzNk90Mp1zpSCsCs4oKan2ClhMlLKtNat/XRKQ== - -"@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.0.tgz#af81107f5afa794f19988a368647727806e18dc4" - integrity sha512-wUpUnR/3GV5Da88MhrxXh/lhb9kxh9V3Jya2NpBEhKDIRCDmtXMSqPMXHZmOR9DfCwCvG6vLFPr/+YrPCnUN0w== - -"@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.0.tgz#6877e1da1a06a9f08446070ab6e0a5347109f868" - integrity sha512-lR0AxK1x/MeKQ/3Pt923kPvwigmGX3OxeU5qNtQ9pj9iucgk4PzhbS3ruUeSpYhUxG50jN4RkIGwUMoev5lguw== - -"@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.0.tgz#bb6cd83a0c259eccef4183796b6329a66cf7ebd9" - integrity sha512-A1he/8gy/JeBD3FKvmI6WUJrGrI5uWJNr5Xb9WdV+DK0F8msuOqpEByLlnTdLkXMwW7nSl3awvLezOs9xBHJEg== - -"@nomicfoundation/solidity-analyzer-win32-arm64-msvc@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-arm64-msvc/-/solidity-analyzer-win32-arm64-msvc-0.1.0.tgz#9d4bca1cc9a1333fde985675083b0b7d165f6076" - integrity sha512-7x5SXZ9R9H4SluJZZP8XPN+ju7Mx+XeUMWZw7ZAqkdhP5mK19I4vz3x0zIWygmfE8RT7uQ5xMap0/9NPsO+ykw== - -"@nomicfoundation/solidity-analyzer-win32-ia32-msvc@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-ia32-msvc/-/solidity-analyzer-win32-ia32-msvc-0.1.0.tgz#0db5bfc6aa952bea4098d8d2c8947b4e5c4337ee" - integrity sha512-m7w3xf+hnE774YRXu+2mGV7RiF3QJtUoiYU61FascCkQhX3QMQavh7saH/vzb2jN5D24nT/jwvaHYX/MAM9zUw== - -"@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.0.tgz#2e0f39a2924dcd77db6b419828595e984fabcb33" - integrity sha512-xCuybjY0sLJQnJhupiFAXaek2EqF0AP0eBjgzaalPXSNvCEN6ZYHvUzdA50ENDVeSYFXcUsYf3+FsD3XKaeptA== - -"@nomicfoundation/solidity-analyzer@^0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.0.tgz#e5ddc43ad5c0aab96e5054520d8e16212e125f50" - integrity sha512-xGWAiVCGOycvGiP/qrlf9f9eOn7fpNbyJygcB0P21a1MDuVPlKt0Srp7rvtBEutYQ48ouYnRXm33zlRnlTOPHg== - optionalDependencies: - "@nomicfoundation/solidity-analyzer-darwin-arm64" "0.1.0" - "@nomicfoundation/solidity-analyzer-darwin-x64" "0.1.0" - "@nomicfoundation/solidity-analyzer-freebsd-x64" "0.1.0" - "@nomicfoundation/solidity-analyzer-linux-arm64-gnu" "0.1.0" - "@nomicfoundation/solidity-analyzer-linux-arm64-musl" "0.1.0" - "@nomicfoundation/solidity-analyzer-linux-x64-gnu" "0.1.0" - "@nomicfoundation/solidity-analyzer-linux-x64-musl" "0.1.0" - "@nomicfoundation/solidity-analyzer-win32-arm64-msvc" "0.1.0" - "@nomicfoundation/solidity-analyzer-win32-ia32-msvc" "0.1.0" - "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.0" - -"@nomiclabs/hardhat-ethers@yarn:hardhat-deploy-ethers": - version "0.3.0-beta.13" - resolved "https://registry.yarnpkg.com/hardhat-deploy-ethers/-/hardhat-deploy-ethers-0.3.0-beta.13.tgz#b96086ff768ddf69928984d5eb0a8d78cfca9366" - integrity sha512-PdWVcKB9coqWV1L7JTpfXRCI91Cgwsm7KLmBcwZ8f0COSm1xtABHZTyz3fvF6p42cTnz1VM0QnfDvMFlIRkSNw== - -"@nomiclabs/hardhat-etherscan@^3.1.4": - version "3.1.4" - resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.1.4.tgz#970e57fabc6060489c93b3f646ca790db36ffee0" - integrity sha512-fw8JCfukf6MdIGoySRmSftlM2wBgoaSbWQZgiYfD/KTeaSFEWCdMpuPZcLSBXtwtnQyyWDs07Lo7fL8HSqtD2Q== - dependencies: - "@ethersproject/abi" "^5.1.2" - "@ethersproject/address" "^5.0.2" - cbor "^8.1.0" - chalk "^2.4.2" - debug "^4.1.1" - fs-extra "^7.0.1" - lodash "^4.17.11" - semver "^6.3.0" - table "^6.8.0" - undici "^5.4.0" - -"@nomiclabs/hardhat-waffle@^2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.3.tgz#9c538a09c5ed89f68f5fd2dc3f78f16ed1d6e0b1" - integrity sha512-049PHSnI1CZq6+XTbrMbMv5NaL7cednTfPenx02k3cEh8wBMLa6ys++dBETJa6JjfwgA9nBhhHQ173LJv6k2Pg== - dependencies: - "@types/sinon-chai" "^3.2.3" - "@types/web3" "1.0.19" - -"@resolver-engine/core@^0.3.3": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@resolver-engine/core/-/core-0.3.3.tgz#590f77d85d45bc7ecc4e06c654f41345db6ca967" - integrity sha512-eB8nEbKDJJBi5p5SrvrvILn4a0h42bKtbCTri3ZxCGt6UvoQyp7HnGOfki944bUjBSHKK3RvgfViHn+kqdXtnQ== - dependencies: - debug "^3.1.0" - is-url "^1.2.4" - request "^2.85.0" - -"@resolver-engine/fs@^0.3.3": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@resolver-engine/fs/-/fs-0.3.3.tgz#fbf83fa0c4f60154a82c817d2fe3f3b0c049a973" - integrity sha512-wQ9RhPUcny02Wm0IuJwYMyAG8fXVeKdmhm8xizNByD4ryZlx6PP6kRen+t/haF43cMfmaV7T3Cx6ChOdHEhFUQ== - dependencies: - "@resolver-engine/core" "^0.3.3" - debug "^3.1.0" - -"@resolver-engine/imports-fs@^0.3.3": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@resolver-engine/imports-fs/-/imports-fs-0.3.3.tgz#4085db4b8d3c03feb7a425fbfcf5325c0d1e6c1b" - integrity sha512-7Pjg/ZAZtxpeyCFlZR5zqYkz+Wdo84ugB5LApwriT8XFeQoLwGUj4tZFFvvCuxaNCcqZzCYbonJgmGObYBzyCA== - dependencies: - "@resolver-engine/fs" "^0.3.3" - "@resolver-engine/imports" "^0.3.3" - debug "^3.1.0" - -"@resolver-engine/imports@^0.3.3": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@resolver-engine/imports/-/imports-0.3.3.tgz#badfb513bb3ff3c1ee9fd56073e3144245588bcc" - integrity sha512-anHpS4wN4sRMwsAbMXhMfOD/y4a4Oo0Cw/5+rue7hSwGWsDOQaAU1ClK1OxjUC35/peazxEl8JaSRRS+Xb8t3Q== - dependencies: - "@resolver-engine/core" "^0.3.3" - debug "^3.1.0" - hosted-git-info "^2.6.0" - path-browserify "^1.0.0" - url "^0.11.0" - -"@scure/base@~1.1.0": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" - integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA== - -"@scure/bip32@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.0.tgz#dea45875e7fbc720c2b4560325f1cf5d2246d95b" - integrity sha512-ftTW3kKX54YXLCxH6BB7oEEoJfoE2pIgw7MINKAs5PsS6nqKPuKk1haTF/EuHmYqG330t5GSrdmtRuHaY1a62Q== - dependencies: - "@noble/hashes" "~1.1.1" - "@noble/secp256k1" "~1.6.0" - "@scure/base" "~1.1.0" - -"@scure/bip39@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.0.tgz#92f11d095bae025f166bef3defcc5bf4945d419a" - integrity sha512-pwrPOS16VeTKg98dYXQyIjJEcWfz7/1YJIwxUEPFfQPtc86Ym/1sVgQ2RLoD43AazMk2l/unK4ITySSpW2+82w== - dependencies: - "@noble/hashes" "~1.1.1" - "@scure/base" "~1.1.0" - -"@sentry/core@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" - integrity sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg== - dependencies: - "@sentry/hub" "5.30.0" - "@sentry/minimal" "5.30.0" - "@sentry/types" "5.30.0" - "@sentry/utils" "5.30.0" - tslib "^1.9.3" - -"@sentry/hub@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.30.0.tgz#2453be9b9cb903404366e198bd30c7ca74cdc100" - integrity sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ== - dependencies: - "@sentry/types" "5.30.0" - "@sentry/utils" "5.30.0" - tslib "^1.9.3" - -"@sentry/minimal@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.30.0.tgz#ce3d3a6a273428e0084adcb800bc12e72d34637b" - integrity sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw== - dependencies: - "@sentry/hub" "5.30.0" - "@sentry/types" "5.30.0" - tslib "^1.9.3" - -"@sentry/node@^5.18.1": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.30.0.tgz#4ca479e799b1021285d7fe12ac0858951c11cd48" - integrity sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg== - dependencies: - "@sentry/core" "5.30.0" - "@sentry/hub" "5.30.0" - "@sentry/tracing" "5.30.0" - "@sentry/types" "5.30.0" - "@sentry/utils" "5.30.0" - cookie "^0.4.1" - https-proxy-agent "^5.0.0" - lru_map "^0.3.3" - tslib "^1.9.3" - -"@sentry/tracing@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-5.30.0.tgz#501d21f00c3f3be7f7635d8710da70d9419d4e1f" - integrity sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw== - dependencies: - "@sentry/hub" "5.30.0" - "@sentry/minimal" "5.30.0" - "@sentry/types" "5.30.0" - "@sentry/utils" "5.30.0" - tslib "^1.9.3" - -"@sentry/types@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.30.0.tgz#19709bbe12a1a0115bc790b8942917da5636f402" - integrity sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw== - -"@sentry/utils@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.30.0.tgz#9a5bd7ccff85ccfe7856d493bffa64cabc41e980" - integrity sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww== - dependencies: - "@sentry/types" "5.30.0" - tslib "^1.9.3" - -"@sindresorhus/is@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" - integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== - -"@sindresorhus/is@^4.0.0": - version "4.6.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" - integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== - -"@solidity-parser/parser@^0.14.5": - version "0.14.5" - resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.14.5.tgz#87bc3cc7b068e08195c219c91cd8ddff5ef1a804" - integrity sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg== - dependencies: - antlr4ts "^0.5.0-alpha.4" - -"@szmarczak/http-timer@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" - integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== - dependencies: - defer-to-connect "^1.0.1" - -"@szmarczak/http-timer@^4.0.5": - version "4.0.6" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807" - integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w== - dependencies: - defer-to-connect "^2.0.0" - -"@tsconfig/node10@^1.0.7": - version "1.0.9" - resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" - integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== - -"@tsconfig/node12@^1.0.7": - version "1.0.11" - resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" - integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== - -"@tsconfig/node14@^1.0.0": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" - integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== - -"@tsconfig/node16@^1.0.2": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" - integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== - -"@typechain/ethers-v5@^10.0.0": - version "10.2.0" - resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-10.2.0.tgz#68f5963efb5214cb2d881477228e4b5b315473e1" - integrity sha512-ikaq0N/w9fABM+G01OFmU3U3dNnyRwEahkdvi9mqy1a3XwKiPZaF/lu54OcNaEWnpvEYyhhS0N7buCtLQqC92w== - dependencies: - lodash "^4.17.15" - ts-essentials "^7.0.1" - -"@typechain/ethers-v5@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-2.0.0.tgz#cd3ca1590240d587ca301f4c029b67bfccd08810" - integrity sha512-0xdCkyGOzdqh4h5JSf+zoWx85IusEjDcPIwNEHP8mrWSnCae4rvrqB+/gtpdNfX7zjlFlZiMeePn2r63EI3Lrw== - dependencies: - ethers "^5.0.2" - -"@typechain/hardhat@^6.0.0": - version "6.1.5" - resolved "https://registry.yarnpkg.com/@typechain/hardhat/-/hardhat-6.1.5.tgz#caad58a1d3e9cd88061a584eb4f4fa763d5dcad1" - integrity sha512-lg7LW4qDZpxFMknp3Xool61Fg6Lays8F8TXdFGBG+MxyYcYU5795P1U2XdStuzGq9S2Dzdgh+1jGww9wvZ6r4Q== - dependencies: - fs-extra "^9.1.0" - -"@types/async-eventemitter@^0.2.1": - version "0.2.1" - resolved "https://registry.yarnpkg.com/@types/async-eventemitter/-/async-eventemitter-0.2.1.tgz#f8e6280e87e8c60b2b938624b0a3530fb3e24712" - integrity sha512-M2P4Ng26QbAeITiH7w1d7OxtldgfAe0wobpyJzVK/XOb0cUGKU2R4pfAhqcJBXAe2ife5ZOhSv4wk7p+ffURtg== - -"@types/bn.js@*", "@types/bn.js@^5.1.0": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" - integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== - dependencies: - "@types/node" "*" - -"@types/bn.js@^4.11.3", "@types/bn.js@^4.11.5": - version "4.11.6" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" - integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== - dependencies: - "@types/node" "*" - -"@types/cacheable-request@^6.0.1": - version "6.0.3" - resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183" - integrity sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw== - dependencies: - "@types/http-cache-semantics" "*" - "@types/keyv" "^3.1.4" - "@types/node" "*" - "@types/responselike" "^1.0.0" - -"@types/chai@*", "@types/chai@^4.3.0": - version "4.3.4" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.4.tgz#e913e8175db8307d78b4e8fa690408ba6b65dee4" - integrity sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw== - -"@types/http-cache-semantics@*": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812" - integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ== - -"@types/keyv@^3.1.4": - version "3.1.4" - resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6" - integrity sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg== - dependencies: - "@types/node" "*" - -"@types/lru-cache@^5.1.0": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" - integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw== - -"@types/mkdirp@^0.5.2": - version "0.5.2" - resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-0.5.2.tgz#503aacfe5cc2703d5484326b1b27efa67a339c1f" - integrity sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg== - dependencies: - "@types/node" "*" - -"@types/mocha@^9.1.0": - version "9.1.1" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4" - integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== - -"@types/node-fetch@^2.5.5": - version "2.6.2" - resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.2.tgz#d1a9c5fd049d9415dce61571557104dec3ec81da" - integrity sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A== - dependencies: - "@types/node" "*" - form-data "^3.0.0" - -"@types/node@*": - version "18.11.18" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.18.tgz#8dfb97f0da23c2293e554c5a50d61ef134d7697f" - integrity sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA== - -"@types/node@^12.12.6": - version "12.20.55" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" - integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== - -"@types/node@^17.0.35": - version "17.0.45" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190" - integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw== - -"@types/pbkdf2@^3.0.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.0.tgz#039a0e9b67da0cdc4ee5dab865caa6b267bb66b1" - integrity sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ== - dependencies: - "@types/node" "*" - -"@types/prettier@^2.1.1": - version "2.7.2" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.2.tgz#6c2324641cc4ba050a8c710b2b251b377581fbf0" - integrity sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg== - -"@types/qs@^6.9.7": - version "6.9.7" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" - integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== - -"@types/resolve@^0.0.8": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194" - integrity sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ== - dependencies: - "@types/node" "*" - -"@types/responselike@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" - integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA== - dependencies: - "@types/node" "*" - -"@types/secp256k1@^4.0.1": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.3.tgz#1b8e55d8e00f08ee7220b4d59a6abe89c37a901c" - integrity sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w== - dependencies: - "@types/node" "*" - -"@types/sinon-chai@^3.2.3": - version "3.2.9" - resolved "https://registry.yarnpkg.com/@types/sinon-chai/-/sinon-chai-3.2.9.tgz#71feb938574bbadcb176c68e5ff1a6014c5e69d4" - integrity sha512-/19t63pFYU0ikrdbXKBWj9PCdnKyTd0Qkz0X91Ta081cYsq90OxYdcWwK/dwEoDa6dtXgj2HJfmzgq+QZTHdmQ== - dependencies: - "@types/chai" "*" - "@types/sinon" "*" - -"@types/sinon@*": - version "10.0.13" - resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.13.tgz#60a7a87a70d9372d0b7b38cc03e825f46981fb83" - integrity sha512-UVjDqJblVNQYvVNUsj0PuYYw0ELRmgt1Nt5Vk0pT5f16ROGfcKJY8o1HVuMOJOpD727RrGB9EGvoaTQE5tgxZQ== - dependencies: - "@types/sinonjs__fake-timers" "*" - -"@types/sinonjs__fake-timers@*": - version "8.1.2" - resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz#bf2e02a3dbd4aecaf95942ecd99b7402e03fad5e" - integrity sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA== - -"@types/underscore@*": - version "1.11.4" - resolved "https://registry.yarnpkg.com/@types/underscore/-/underscore-1.11.4.tgz#62e393f8bc4bd8a06154d110c7d042a93751def3" - integrity sha512-uO4CD2ELOjw8tasUrAhvnn2W4A0ZECOvMjCivJr4gA9pGgjv+qxKWY9GLTMVEK8ej85BxQOocUyE7hImmSQYcg== - -"@types/web3@1.0.19": - version "1.0.19" - resolved "https://registry.yarnpkg.com/@types/web3/-/web3-1.0.19.tgz#46b85d91d398ded9ab7c85a5dd57cb33ac558924" - integrity sha512-fhZ9DyvDYDwHZUp5/STa9XW2re0E8GxoioYJ4pEUZ13YHpApSagixj7IAdoYH5uAK+UalGq6Ml8LYzmgRA/q+A== - dependencies: - "@types/bn.js" "*" - "@types/underscore" "*" - -"@yarnpkg/lockfile@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" - integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== - -abort-controller@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" - integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== - dependencies: - event-target-shim "^5.0.0" - -abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/abstract-level/-/abstract-level-1.0.3.tgz#78a67d3d84da55ee15201486ab44c09560070741" - integrity sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA== - dependencies: - buffer "^6.0.3" - catering "^2.1.0" - is-buffer "^2.0.5" - level-supports "^4.0.0" - level-transcoder "^1.0.1" - module-error "^1.0.1" - queue-microtask "^1.2.3" - -abstract-leveldown@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-3.0.0.tgz#5cb89f958a44f526779d740d1440e743e0c30a57" - integrity sha512-KUWx9UWGQD12zsmLNj64/pndaz4iJh/Pj7nopgkfDG6RlCcbMZvT6+9l7dchK4idog2Is8VdC/PvNbFuFmalIQ== - dependencies: - xtend "~4.0.0" - -abstract-leveldown@^2.4.1, abstract-leveldown@~2.7.1: - version "2.7.2" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz#87a44d7ebebc341d59665204834c8b7e0932cc93" - integrity sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w== - dependencies: - xtend "~4.0.0" - -abstract-leveldown@^5.0.0, abstract-leveldown@~5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz#f7128e1f86ccabf7d2893077ce5d06d798e386c6" - integrity sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A== - dependencies: - xtend "~4.0.0" - -abstract-leveldown@~2.6.0: - version "2.6.3" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz#1c5e8c6a5ef965ae8c35dfb3a8770c476b82c4b8" - integrity sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA== - dependencies: - xtend "~4.0.0" - -accepts@~1.3.8: - version "1.3.8" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" - integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== - dependencies: - mime-types "~2.1.34" - negotiator "0.6.3" - -acorn-walk@^8.1.1: - version "8.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" - integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== - -acorn@^8.4.1: - version "8.8.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.1.tgz#0a3f9cbecc4ec3bea6f0a80b66ae8dd2da250b73" - integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA== - -adm-zip@^0.4.16: - version "0.4.16" - resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365" - integrity sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg== - -aes-js@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" - integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== - -aes-js@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" - integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== - -agent-base@6: - version "6.0.2" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" - integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== - dependencies: - debug "4" - -aggregate-error@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" - integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== - dependencies: - clean-stack "^2.0.0" - indent-string "^4.0.0" - -ajv@^6.12.3: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ajv@^8.0.1: - version "8.12.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" - integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== - dependencies: - fast-deep-equal "^3.1.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - uri-js "^4.2.2" - -ansi-colors@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" - integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== - -ansi-colors@^4.1.0, ansi-colors@^4.1.1: - version "4.1.3" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" - integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== - -ansi-escapes@^4.3.0: - version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" - integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== - dependencies: - type-fest "^0.21.3" - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA== - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -antlr4ts@^0.5.0-alpha.4: - version "0.5.0-alpha.4" - resolved "https://registry.yarnpkg.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz#71702865a87478ed0b40c0709f422cf14d51652a" - integrity sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ== - -anymatch@~3.1.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" - integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -arg@^4.1.0: - version "4.1.3" - resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" - integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA== - -arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q== - -array-back@^1.0.3, array-back@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-1.0.4.tgz#644ba7f095f7ffcf7c43b5f0dc39d3c1f03c063b" - integrity sha512-1WxbZvrmyhkNoeYcizokbmh5oiOCIfyvGtcqbK3Ls1v1fKcquzxnQSceOx6tzq7jmai2kFLWIpGND2cLhH6TPw== - dependencies: - typical "^2.6.0" - -array-back@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-2.0.0.tgz#6877471d51ecc9c9bfa6136fb6c7d5fe69748022" - integrity sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw== - dependencies: - typical "^2.6.1" - -array-back@^3.0.1, array-back@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" - integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== - -array-back@^4.0.1, array-back@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e" - integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg== - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== - -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ== - -array.prototype.reduce@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz#6b20b0daa9d9734dd6bc7ea66b5bbce395471eac" - integrity sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - es-array-method-boxes-properly "^1.0.0" - is-string "^1.0.7" - -asn1.js@^5.2.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" - integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - safer-buffer "^2.1.0" - -asn1@~0.2.3: - version "0.2.6" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" - integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== - dependencies: - safer-buffer "~2.1.0" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== - -assertion-error@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" - integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== - -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw== - -astral-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" - integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== - -async-eventemitter@^0.2.2, async-eventemitter@^0.2.4: - version "0.2.4" - resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" - integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw== - dependencies: - async "^2.4.0" - -async-limiter@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" - integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== - -async@2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381" - integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg== - dependencies: - lodash "^4.17.11" - -async@^1.4.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - integrity sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w== - -async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.5.0, async@^2.6.1: - version "2.6.4" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" - integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== - dependencies: - lodash "^4.17.14" - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== - -at-least-node@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" - integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== - -atob@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== - -available-typed-arrays@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" - integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== - -aws4@^1.8.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" - integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== - -axios@^0.21.1: - version "0.21.4" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" - integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== - dependencies: - follow-redirects "^1.14.0" - -babel-code-frame@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - integrity sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g== - dependencies: - chalk "^1.1.3" - esutils "^2.0.2" - js-tokens "^3.0.2" - -babel-core@^6.0.14, babel-core@^6.26.0: - version "6.26.3" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" - integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== - dependencies: - babel-code-frame "^6.26.0" - babel-generator "^6.26.0" - babel-helpers "^6.24.1" - babel-messages "^6.23.0" - babel-register "^6.26.0" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - convert-source-map "^1.5.1" - debug "^2.6.9" - json5 "^0.5.1" - lodash "^4.17.4" - minimatch "^3.0.4" - path-is-absolute "^1.0.1" - private "^0.1.8" - slash "^1.0.0" - source-map "^0.5.7" - -babel-generator@^6.26.0: - version "6.26.1" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" - integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== - dependencies: - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - detect-indent "^4.0.0" - jsesc "^1.3.0" - lodash "^4.17.4" - source-map "^0.5.7" - trim-right "^1.0.1" - -babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" - integrity sha512-gCtfYORSG1fUMX4kKraymq607FWgMWg+j42IFPc18kFQEsmtaibP4UrqsXt8FlEJle25HUd4tsoDR7H2wDhe9Q== - dependencies: - babel-helper-explode-assignable-expression "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-call-delegate@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" - integrity sha512-RL8n2NiEj+kKztlrVJM9JT1cXzzAdvWFh76xh/H1I4nKwunzE4INBXn8ieCZ+wh4zWszZk7NBS1s/8HR5jDkzQ== - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-define-map@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" - integrity sha512-bHkmjcC9lM1kmZcVpA5t2om2nzT/xiZpo6TJq7UlZ3wqKfzia4veeXbIhKvJXAMzhhEBd3cR1IElL5AenWEUpA== - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-helper-explode-assignable-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" - integrity sha512-qe5csbhbvq6ccry9G7tkXbzNtcDiH4r51rrPUbwwoTzZ18AqxWYRZT6AOmxrpxKnQBW0pYlBI/8vh73Z//78nQ== - dependencies: - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-function-name@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" - integrity sha512-Oo6+e2iX+o9eVvJ9Y5eKL5iryeRdsIkwRYheCuhYdVHsdEQysbc2z2QkqCLIYnNxkT5Ss3ggrHdXiDI7Dhrn4Q== - dependencies: - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-get-function-arity@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" - integrity sha512-WfgKFX6swFB1jS2vo+DwivRN4NB8XUdM3ij0Y1gnC21y1tdBoe6xjVnd7NSI6alv+gZXCtJqvrTeMW3fR/c0ng== - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-hoist-variables@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" - integrity sha512-zAYl3tqerLItvG5cKYw7f1SpvIxS9zi7ohyGHaI9cgDUjAT6YcY9jIEH5CstetP5wHIVSceXwNS7Z5BpJg+rOw== - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-optimise-call-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" - integrity sha512-Op9IhEaxhbRT8MDXx2iNuMgciu2V8lDvYCNQbDGjdBNCjaMvyLf4wl4A3b8IgndCyQF8TwfgsQ8T3VD8aX1/pA== - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-regex@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" - integrity sha512-VlPiWmqmGJp0x0oK27Out1D+71nVVCTSdlbhIVoaBAj2lUgrNjBCRR9+llO4lTSb2O4r7PJg+RobRkhBrf6ofg== - dependencies: - babel-runtime "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-helper-remap-async-to-generator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" - integrity sha512-RYqaPD0mQyQIFRu7Ho5wE2yvA/5jxqCIj/Lv4BXNq23mHYu/vxikOy2JueLiBxQknwapwrJeNCesvY0ZcfnlHg== - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-replace-supers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" - integrity sha512-sLI+u7sXJh6+ToqDr57Bv973kCepItDhMou0xCP2YPVmR1jkHSCY+p1no8xErbV1Siz5QE8qKT1WIwybSWlqjw== - dependencies: - babel-helper-optimise-call-expression "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helpers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" - integrity sha512-n7pFrqQm44TCYvrCDb0MqabAF+JUBq+ijBvNMUxpkLjJaAu32faIexewMumrH5KLLJ1HDyT0PTEqRyAe/GwwuQ== - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-messages@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - integrity sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-check-es2015-constants@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" - integrity sha512-B1M5KBP29248dViEo1owyY32lk1ZSH2DaNNrXLGt8lyjjHm7pBqAdQ7VKUPR6EEDO323+OvT3MQXbCin8ooWdA== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-syntax-async-functions@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" - integrity sha512-4Zp4unmHgw30A1eWI5EpACji2qMocisdXhAftfhXoSV9j0Tvj6nRFE3tOmRY912E0FMRm/L5xWE7MGVT2FoLnw== - -babel-plugin-syntax-exponentiation-operator@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" - integrity sha512-Z/flU+T9ta0aIEKl1tGEmN/pZiI1uXmCiGFRegKacQfEJzp7iNsKloZmyJlQr+75FCJtiFfGIK03SiCvCt9cPQ== - -babel-plugin-syntax-trailing-function-commas@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" - integrity sha512-Gx9CH3Q/3GKbhs07Bszw5fPTlU+ygrOGfAhEt7W2JICwufpC4SuO0mG0+4NykPBSYPMJhqvVlDBU17qB1D+hMQ== - -babel-plugin-transform-async-to-generator@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" - integrity sha512-7BgYJujNCg0Ti3x0c/DL3tStvnKS6ktIYOmo9wginv/dfZOrbSZ+qG4IRRHMBOzZ5Awb1skTiAsQXg/+IWkZYw== - dependencies: - babel-helper-remap-async-to-generator "^6.24.1" - babel-plugin-syntax-async-functions "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-arrow-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" - integrity sha512-PCqwwzODXW7JMrzu+yZIaYbPQSKjDTAsNNlK2l5Gg9g4rz2VzLnZsStvp/3c46GfXpwkyufb3NCyG9+50FF1Vg== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" - integrity sha512-2+ujAT2UMBzYFm7tidUsYh+ZoIutxJ3pN9IYrF1/H6dCKtECfhmB8UkHVpyxDwkj0CYbQG35ykoz925TUnBc3A== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoping@^6.23.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" - integrity sha512-YiN6sFAQ5lML8JjCmr7uerS5Yc/EMbgg9G8ZNmk2E3nYX4ckHR01wrkeeMijEf5WHNK5TW0Sl0Uu3pv3EdOJWw== - dependencies: - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-plugin-transform-es2015-classes@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" - integrity sha512-5Dy7ZbRinGrNtmWpquZKZ3EGY8sDgIVB4CU8Om8q8tnMLrD/m94cKglVcHps0BCTdZ0TJeeAWOq2TK9MIY6cag== - dependencies: - babel-helper-define-map "^6.24.1" - babel-helper-function-name "^6.24.1" - babel-helper-optimise-call-expression "^6.24.1" - babel-helper-replace-supers "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-computed-properties@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" - integrity sha512-C/uAv4ktFP/Hmh01gMTvYvICrKze0XVX9f2PdIXuriCSvUmV9j+u+BB9f5fJK3+878yMK6dkdcq+Ymr9mrcLzw== - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-destructuring@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" - integrity sha512-aNv/GDAW0j/f4Uy1OEPZn1mqD+Nfy9viFGBfQ5bZyT35YqOiqx7/tXdyfZkJ1sC21NyEsBdfDY6PYmLHF4r5iA== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-duplicate-keys@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" - integrity sha512-ossocTuPOssfxO2h+Z3/Ea1Vo1wWx31Uqy9vIiJusOP4TbF7tPs9U0sJ9pX9OJPf4lXRGj5+6Gkl/HHKiAP5ug== - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-for-of@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" - integrity sha512-DLuRwoygCoXx+YfxHLkVx5/NpeSbVwfoTeBykpJK7JhYWlL/O8hgAK/reforUnZDlxasOrVPPJVI/guE3dCwkw== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-function-name@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" - integrity sha512-iFp5KIcorf11iBqu/y/a7DK3MN5di3pNCzto61FqCNnUX4qeBwcV1SLqe10oXNnCaxBUImX3SckX2/o1nsrTcg== - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" - integrity sha512-tjFl0cwMPpDYyoqYA9li1/7mGFit39XiNX5DKC/uCNjBctMxyL1/PT/l4rSlbvBG1pOKI88STRdUsWXB3/Q9hQ== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" - integrity sha512-LnIIdGWIKdw7zwckqx+eGjcS8/cl8D74A3BpJbGjKTFFNJSMrjN4bIh22HY1AlkUbeLG6X6OZj56BDvWD+OeFA== - dependencies: - babel-plugin-transform-es2015-modules-commonjs "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: - version "6.26.2" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" - integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== - dependencies: - babel-plugin-transform-strict-mode "^6.24.1" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-types "^6.26.0" - -babel-plugin-transform-es2015-modules-systemjs@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" - integrity sha512-ONFIPsq8y4bls5PPsAWYXH/21Hqv64TBxdje0FvU3MhIV6QM2j5YS7KvAzg/nTIVLot2D2fmFQrFWCbgHlFEjg== - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-umd@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" - integrity sha512-LpVbiT9CLsuAIp3IG0tfbVo81QIhn6pE8xBJ7XSeCtFlMltuar5VuBV6y6Q45tpui9QWcy5i0vLQfCfrnF7Kiw== - dependencies: - babel-plugin-transform-es2015-modules-amd "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-object-super@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" - integrity sha512-8G5hpZMecb53vpD3mjs64NhI1au24TAmokQ4B+TBFBjN9cVoGoOvotdrMMRmHvVZUEvqGUPWL514woru1ChZMA== - dependencies: - babel-helper-replace-supers "^6.24.1" - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-parameters@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" - integrity sha512-8HxlW+BB5HqniD+nLkQ4xSAVq3bR/pcYW9IigY+2y0dI+Y7INFeTbfAQr+63T3E4UDsZGjyb+l9txUnABWxlOQ== - dependencies: - babel-helper-call-delegate "^6.24.1" - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-shorthand-properties@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" - integrity sha512-mDdocSfUVm1/7Jw/FIRNw9vPrBQNePy6wZJlR8HAUBLybNp1w/6lr6zZ2pjMShee65t/ybR5pT8ulkLzD1xwiw== - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-spread@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" - integrity sha512-3Ghhi26r4l3d0Js933E5+IhHwk0A1yiutj9gwvzmFbVV0sPMYk2lekhOufHBswX7NCoSeF4Xrl3sCIuSIa+zOg== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-sticky-regex@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" - integrity sha512-CYP359ADryTo3pCsH0oxRo/0yn6UsEZLqYohHmvLQdfS9xkf+MbCzE3/Kolw9OYIY4ZMilH25z/5CbQbwDD+lQ== - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-template-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" - integrity sha512-x8b9W0ngnKzDMHimVtTfn5ryimars1ByTqsfBDwAqLibmuuQY6pgBQi5z1ErIsUOWBdw1bW9FSz5RZUojM4apg== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-typeof-symbol@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" - integrity sha512-fz6J2Sf4gYN6gWgRZaoFXmq93X+Li/8vf+fb0sGDVtdeWvxC9y5/bTD7bvfWMEq6zetGEHpWjtzRGSugt5kNqw== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-unicode-regex@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" - integrity sha512-v61Dbbihf5XxnYjtBN04B/JBvsScY37R1cZT5r9permN1cp+b70DY3Ib3fIkgn1DI9U3tGgBJZVD8p/mE/4JbQ== - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - regexpu-core "^2.0.0" - -babel-plugin-transform-exponentiation-operator@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" - integrity sha512-LzXDmbMkklvNhprr20//RStKVcT8Cu+SQtX18eMHLhjHf2yFzwtQ0S2f0jQ+89rokoNdmwoSqYzAhq86FxlLSQ== - dependencies: - babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" - babel-plugin-syntax-exponentiation-operator "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-regenerator@^6.22.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" - integrity sha512-LS+dBkUGlNR15/5WHKe/8Neawx663qttS6AGqoOUhICc9d1KciBvtrQSuc0PI+CxQ2Q/S1aKuJ+u64GtLdcEZg== - dependencies: - regenerator-transform "^0.10.0" - -babel-plugin-transform-strict-mode@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" - integrity sha512-j3KtSpjyLSJxNoCDrhwiJad8kw0gJ9REGj8/CqL0HeRyLnvUNYV9zcqluL6QJSXh3nfsLEmSLvwRfGzrgR96Pw== - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-preset-env@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" - integrity sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg== - dependencies: - babel-plugin-check-es2015-constants "^6.22.0" - babel-plugin-syntax-trailing-function-commas "^6.22.0" - babel-plugin-transform-async-to-generator "^6.22.0" - babel-plugin-transform-es2015-arrow-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoping "^6.23.0" - babel-plugin-transform-es2015-classes "^6.23.0" - babel-plugin-transform-es2015-computed-properties "^6.22.0" - babel-plugin-transform-es2015-destructuring "^6.23.0" - babel-plugin-transform-es2015-duplicate-keys "^6.22.0" - babel-plugin-transform-es2015-for-of "^6.23.0" - babel-plugin-transform-es2015-function-name "^6.22.0" - babel-plugin-transform-es2015-literals "^6.22.0" - babel-plugin-transform-es2015-modules-amd "^6.22.0" - babel-plugin-transform-es2015-modules-commonjs "^6.23.0" - babel-plugin-transform-es2015-modules-systemjs "^6.23.0" - babel-plugin-transform-es2015-modules-umd "^6.23.0" - babel-plugin-transform-es2015-object-super "^6.22.0" - babel-plugin-transform-es2015-parameters "^6.23.0" - babel-plugin-transform-es2015-shorthand-properties "^6.22.0" - babel-plugin-transform-es2015-spread "^6.22.0" - babel-plugin-transform-es2015-sticky-regex "^6.22.0" - babel-plugin-transform-es2015-template-literals "^6.22.0" - babel-plugin-transform-es2015-typeof-symbol "^6.23.0" - babel-plugin-transform-es2015-unicode-regex "^6.22.0" - babel-plugin-transform-exponentiation-operator "^6.22.0" - babel-plugin-transform-regenerator "^6.22.0" - browserslist "^3.2.6" - invariant "^2.2.2" - semver "^5.3.0" - -babel-register@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" - integrity sha512-veliHlHX06wjaeY8xNITbveXSiI+ASFnOqvne/LaIJIqOWi2Ogmj91KOugEz/hoh/fwMhXNBJPCv8Xaz5CyM4A== - dependencies: - babel-core "^6.26.0" - babel-runtime "^6.26.0" - core-js "^2.5.0" - home-or-tmp "^2.0.0" - lodash "^4.17.4" - mkdirp "^0.5.1" - source-map-support "^0.4.15" - -babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g== - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - -babel-template@^6.24.1, babel-template@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" - integrity sha512-PCOcLFW7/eazGUKIoqH97sO9A2UYMahsn/yRQ7uOk37iutwjq7ODtcTNF+iFDSHNfkctqsLRjLP7URnOx0T1fg== - dependencies: - babel-runtime "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - lodash "^4.17.4" - -babel-traverse@^6.24.1, babel-traverse@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - integrity sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA== - dependencies: - babel-code-frame "^6.26.0" - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - debug "^2.6.8" - globals "^9.18.0" - invariant "^2.2.2" - lodash "^4.17.4" - -babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - integrity sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g== - dependencies: - babel-runtime "^6.26.0" - esutils "^2.0.2" - lodash "^4.17.4" - to-fast-properties "^1.0.3" - -babelify@^7.3.0: - version "7.3.0" - resolved "https://registry.yarnpkg.com/babelify/-/babelify-7.3.0.tgz#aa56aede7067fd7bd549666ee16dc285087e88e5" - integrity sha512-vID8Fz6pPN5pJMdlUnNFSfrlcx5MUule4k9aKs/zbZPyXxMTcRrB0M4Tarw22L8afr8eYSWxDPYCob3TdrqtlA== - dependencies: - babel-core "^6.0.14" - object-assign "^4.0.0" - -babylon@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== - -backoff@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f" - integrity sha512-wC5ihrnUXmR2douXmXLCe5O3zg3GKIyvRi/hi58a/XyRxVI+3/yM0PYueQOZXPXQ9pxBislYkw+sF9b7C/RuMA== - dependencies: - precond "0.2" - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -base-x@^3.0.2, base-x@^3.0.8: - version "3.0.9" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" - integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== - dependencies: - safe-buffer "^5.0.1" - -base64-js@^1.3.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - -base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - -bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== - dependencies: - tweetnacl "^0.14.3" - -bech32@1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" - integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== - -bigint-crypto-utils@^3.0.23: - version "3.1.8" - resolved "https://registry.yarnpkg.com/bigint-crypto-utils/-/bigint-crypto-utils-3.1.8.tgz#e2e0f40cf45488f9d7f0e32ff84152aa73819d5d" - integrity sha512-+VMV9Laq8pXLBKKKK49nOoq9bfR3j7NNQAtbA617a4nw9bVLo8rsqkKMBgM2AJWlNX9fEIyYaYX+d0laqYV4tw== - dependencies: - bigint-mod-arith "^3.1.0" - -bigint-mod-arith@^3.1.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bigint-mod-arith/-/bigint-mod-arith-3.1.2.tgz#658e416bc593a463d97b59766226d0a3021a76b1" - integrity sha512-nx8J8bBeiRR+NlsROFH9jHswW5HO8mgfOSqW0AmjicMMvaONDa8AO+5ViKDUUNytBPWiwfvZP4/Bj4Y3lUfvgQ== - -bignumber.js@^9.0.0: - version "9.1.1" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.1.tgz#c4df7dc496bd849d4c9464344c1aa74228b4dac6" - integrity sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig== - -binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== - -bip39@2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.5.0.tgz#51cbd5179460504a63ea3c000db3f787ca051235" - integrity sha512-xwIx/8JKoT2+IPJpFEfXoWdYwP7UVAoUxxLNfGCfVowaJE7yg1Y5B1BVPqlUNsBq5/nGwmFkwRJ8xDW4sX8OdA== - dependencies: - create-hash "^1.1.0" - pbkdf2 "^3.0.9" - randombytes "^2.0.1" - safe-buffer "^5.0.1" - unorm "^1.3.3" - -blakejs@^1.1.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" - integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== - -bluebird@^3.5.0, bluebird@^3.5.2: - version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - -bn.js@4.11.6: - version "4.11.6" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" - integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA== - -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.11.9, bn.js@^4.8.0: - version "4.12.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" - integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== - -bn.js@^5.0.0, bn.js@^5.1.1, bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" - integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== - -body-parser@1.20.1, body-parser@^1.16.0: - version "1.20.1" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" - integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== - dependencies: - bytes "3.1.2" - content-type "~1.0.4" - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - http-errors "2.0.0" - iconv-lite "0.4.24" - on-finished "2.4.1" - qs "6.11.0" - raw-body "2.5.1" - type-is "~1.6.18" - unpipe "1.0.0" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== - dependencies: - balanced-match "^1.0.0" - -braces@^2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - -braces@^3.0.2, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -brorand@^1.0.1, brorand@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== - -browser-level@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browser-level/-/browser-level-1.0.1.tgz#36e8c3183d0fe1c405239792faaab5f315871011" - integrity sha512-XECYKJ+Dbzw0lbydyQuJzwNXtOpbMSq737qxJN11sIRTErOMShvDpbzTlgju7orJKvx4epULolZAuJGLzCmWRQ== - dependencies: - abstract-level "^1.0.2" - catering "^2.1.1" - module-error "^1.0.2" - run-parallel-limit "^1.1.0" - -browser-stdout@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== - -browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== - dependencies: - buffer-xor "^1.0.3" - cipher-base "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.3" - inherits "^2.0.1" - safe-buffer "^5.0.1" - -browserify-cipher@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== - dependencies: - browserify-aes "^1.0.4" - browserify-des "^1.0.0" - evp_bytestokey "^1.0.0" - -browserify-des@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== - dependencies: - cipher-base "^1.0.1" - des.js "^1.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" - integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== - dependencies: - bn.js "^5.0.0" - randombytes "^2.0.1" - -browserify-sign@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" - integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== - dependencies: - bn.js "^5.1.1" - browserify-rsa "^4.0.1" - create-hash "^1.2.0" - create-hmac "^1.1.7" - elliptic "^6.5.3" - inherits "^2.0.4" - parse-asn1 "^5.1.5" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" - -browserslist@^3.2.6: - version "3.2.8" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" - integrity sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ== - dependencies: - caniuse-lite "^1.0.30000844" - electron-to-chromium "^1.3.47" - -bs58@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" - integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== - dependencies: - base-x "^3.0.2" - -bs58check@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" - integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== - dependencies: - bs58 "^4.0.0" - create-hash "^1.1.0" - safe-buffer "^5.1.2" - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -buffer-to-arraybuffer@^0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz#6064a40fa76eb43c723aba9ef8f6e1216d10511a" - integrity sha512-3dthu5CYiVB1DEJp61FtApNnNndTckcqe4pFcLdvHtrpG+kcyekCJKg4MRiDcFW7A6AODnXB9U4dwQiCW5kzJQ== - -buffer-xor@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== - -buffer-xor@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-2.0.2.tgz#34f7c64f04c777a1f8aac5e661273bb9dd320289" - integrity sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ== - dependencies: - safe-buffer "^5.1.1" - -buffer@^5.0.5, buffer@^5.2.1, buffer@^5.5.0, buffer@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" - integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.1.13" - -buffer@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" - integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.2.1" - -bufferutil@^4.0.1: - version "4.0.7" - resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.7.tgz#60c0d19ba2c992dd8273d3f73772ffc894c153ad" - integrity sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw== - dependencies: - node-gyp-build "^4.3.0" - -busboy@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" - integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== - dependencies: - streamsearch "^1.1.0" - -bytes@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" - integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== - -bytewise-core@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/bytewise-core/-/bytewise-core-1.2.3.tgz#3fb410c7e91558eb1ab22a82834577aa6bd61d42" - integrity sha512-nZD//kc78OOxeYtRlVk8/zXqTB4gf/nlguL1ggWA8FuchMyOxcyHR4QPQZMUmA7czC+YnaBrPUCubqAWe50DaA== - dependencies: - typewise-core "^1.2" - -bytewise@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/bytewise/-/bytewise-1.1.0.tgz#1d13cbff717ae7158094aa881b35d081b387253e" - integrity sha512-rHuuseJ9iQ0na6UDhnrRVDh8YnWVlU6xM3VH6q/+yHDeUH2zIhUzP+2/h3LIrhLDBtTqzWpE3p3tP/boefskKQ== - dependencies: - bytewise-core "^1.2.2" - typewise "^1.0.3" - -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - -cacheable-lookup@^5.0.3: - version "5.0.4" - resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" - integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA== - -cacheable-request@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" - integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^3.0.0" - lowercase-keys "^2.0.0" - normalize-url "^4.1.0" - responselike "^1.0.2" - -cacheable-request@^7.0.2: - version "7.0.2" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.2.tgz#ea0d0b889364a25854757301ca12b2da77f91d27" - integrity sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^4.0.0" - lowercase-keys "^2.0.0" - normalize-url "^6.0.1" - responselike "^2.0.0" - -cachedown@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/cachedown/-/cachedown-1.0.0.tgz#d43f036e4510696b31246d7db31ebf0f7ac32d15" - integrity sha512-t+yVk82vQWCJF3PsWHMld+jhhjkkWjcAzz8NbFx1iULOXWl8Tm/FdM4smZNVw3MRr0X+lVTx9PKzvEn4Ng19RQ== - dependencies: - abstract-leveldown "^2.4.1" - lru-cache "^3.2.0" - -call-bind@^1.0.0, call-bind@^1.0.2, call-bind@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== - dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" - -camelcase@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" - integrity sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg== - -camelcase@^6.0.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== - -caniuse-lite@^1.0.30000844: - version "1.0.30001442" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001442.tgz#40337f1cf3be7c637b061e2f78582dc1daec0614" - integrity sha512-239m03Pqy0hwxYPYR5JwOIxRJfLTWtle9FV8zosfV5pHg+/51uD4nxcUlM8+mWWGfwKtt8lJNHnD3cWw9VZ6ow== - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== - -catering@^2.1.0, catering@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/catering/-/catering-2.1.1.tgz#66acba06ed5ee28d5286133982a927de9a04b510" - integrity sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w== - -cbor@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/cbor/-/cbor-8.1.0.tgz#cfc56437e770b73417a2ecbfc9caf6b771af60d5" - integrity sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg== - dependencies: - nofilter "^3.1.0" - -chai@^4.3.6: - version "4.3.7" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" - integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A== - dependencies: - assertion-error "^1.1.0" - check-error "^1.0.2" - deep-eql "^4.1.2" - get-func-name "^2.0.0" - loupe "^2.3.1" - pathval "^1.1.1" - type-detect "^4.0.5" - -chalk@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -chalk@^2.4.1, chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^4.1.0, chalk@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -check-error@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" - integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== - -checkpoint-store@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06" - integrity sha512-J/NdY2WvIx654cc6LWSq/IYFFCUf75fFTgwzFnmbqyORH4MwgiQCgswLLKBGzmsyTI5V7i5bp/So6sMbDWhedg== - dependencies: - functional-red-black-tree "^1.0.1" - -chokidar@3.5.3, chokidar@^3.4.0, chokidar@^3.5.2: - version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - -chownr@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" - integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== - -ci-info@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" - integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== - -cids@^0.7.1: - version "0.7.5" - resolved "https://registry.yarnpkg.com/cids/-/cids-0.7.5.tgz#60a08138a99bfb69b6be4ceb63bfef7a396b28b2" - integrity sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA== - dependencies: - buffer "^5.5.0" - class-is "^1.1.0" - multibase "~0.6.0" - multicodec "^1.0.0" - multihashes "~0.4.15" - -cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -class-is@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/class-is/-/class-is-1.1.0.tgz#9d3c0fba0440d211d843cec3dedfa48055005825" - integrity sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw== - -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - -classic-level@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/classic-level/-/classic-level-1.2.0.tgz#2d52bdec8e7a27f534e67fdeb890abef3e643c27" - integrity sha512-qw5B31ANxSluWz9xBzklRWTUAJ1SXIdaVKTVS7HcTGKOAmExx65Wo5BUICW+YGORe2FOUaDghoI9ZDxj82QcFg== - dependencies: - abstract-level "^1.0.2" - catering "^2.1.0" - module-error "^1.0.1" - napi-macros "~2.0.0" - node-gyp-build "^4.3.0" - -clean-stack@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" - integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== - -cliui@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" - integrity sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w== - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - wrap-ansi "^2.0.0" - -cliui@^7.0.2: - version "7.0.4" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" - integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.0" - wrap-ansi "^7.0.0" - -clone-response@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3" - integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA== - dependencies: - mimic-response "^1.0.0" - -clone@2.1.2, clone@^2.0.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" - integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w== - -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA== - -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw== - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -command-exists@^1.2.8: - version "1.2.9" - resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" - integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== - -command-line-args@^4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-4.0.7.tgz#f8d1916ecb90e9e121eda6428e41300bfb64cc46" - integrity sha512-aUdPvQRAyBvQd2n7jXcsMDz68ckBJELXNzBybCHOibUWEg0mWTnaYCSRU8h9R+aNRSvDihJtssSRCiDRpLaezA== - dependencies: - array-back "^2.0.0" - find-replace "^1.0.3" - typical "^2.6.1" - -command-line-args@^5.1.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.1.tgz#c44c32e437a57d7c51157696893c5909e9cec42e" - integrity sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg== - dependencies: - array-back "^3.1.0" - find-replace "^3.0.0" - lodash.camelcase "^4.3.0" - typical "^4.0.0" - -command-line-usage@^6.1.0: - version "6.1.3" - resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-6.1.3.tgz#428fa5acde6a838779dfa30e44686f4b6761d957" - integrity sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw== - dependencies: - array-back "^4.0.2" - chalk "^2.4.2" - table-layout "^1.0.2" - typical "^5.2.0" - -commander@3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" - integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== - -component-emitter@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" - integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -concat-stream@^1.5.1: - version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - -content-disposition@0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" - integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== - dependencies: - safe-buffer "5.2.1" - -content-hash@^2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/content-hash/-/content-hash-2.5.2.tgz#bbc2655e7c21f14fd3bfc7b7d4bfe6e454c9e211" - integrity sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw== - dependencies: - cids "^0.7.1" - multicodec "^0.5.5" - multihashes "^0.4.15" - -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - -convert-source-map@^1.5.1: - version "1.9.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" - integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== - -cookie@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" - integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== - -cookie@^0.4.1: - version "0.4.2" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" - integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== - -cookiejar@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.3.tgz#fc7a6216e408e74414b90230050842dacda75acc" - integrity sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ== - -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== - -core-js-pure@^3.0.1: - version "3.27.1" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.27.1.tgz#ede4a6b8440585c7190062757069c01d37a19dca" - integrity sha512-BS2NHgwwUppfeoqOXqi08mUqS5FiZpuRuJJpKsaME7kJz0xxuk0xkhDdfMIlP/zLa80krBqss1LtD7f889heAw== - -core-js@^2.4.0, core-js@^2.5.0: - version "2.6.12" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" - integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== - -core-util-is@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== - -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - -cors@^2.8.1: - version "2.8.5" - resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" - integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== - dependencies: - object-assign "^4" - vary "^1" - -crc-32@^1.2.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" - integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== - -create-ecdh@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" - integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== - dependencies: - bn.js "^4.1.0" - elliptic "^6.5.3" - -create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== - dependencies: - cipher-base "^1.0.1" - inherits "^2.0.1" - md5.js "^1.3.4" - ripemd160 "^2.0.1" - sha.js "^2.4.0" - -create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== - dependencies: - cipher-base "^1.0.3" - create-hash "^1.1.0" - inherits "^2.0.1" - ripemd160 "^2.0.0" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -create-require@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" - integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== - -cross-fetch@^2.1.0, cross-fetch@^2.1.1: - version "2.2.6" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-2.2.6.tgz#2ef0bb39a24ac034787965c457368a28730e220a" - integrity sha512-9JZz+vXCmfKUZ68zAptS7k4Nu8e2qcibe7WVZYps7sAgk5R8GYTc+T1WR0v1rlP9HxgARmOX1UTIJZFytajpNA== - dependencies: - node-fetch "^2.6.7" - whatwg-fetch "^2.0.4" - -cross-spawn@^6.0.5: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - -crypto-browserify@3.12.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== - dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.0" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "^3.0.3" - public-encrypt "^4.0.0" - randombytes "^2.0.0" - randomfill "^1.0.3" - -d@1, d@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" - integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== - dependencies: - es5-ext "^0.10.50" - type "^1.0.1" - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== - dependencies: - assert-plus "^1.0.0" - -debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@3.2.6: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - -debug@4, debug@4.3.4, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -debug@^3.1.0: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - -decamelize@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== - -decamelize@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" - integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== - -decode-uri-component@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" - integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== - -decompress-response@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA== - dependencies: - mimic-response "^1.0.0" - -decompress-response@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" - integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== - dependencies: - mimic-response "^3.1.0" - -deep-eql@^4.1.2: - version "4.1.3" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" - integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== - dependencies: - type-detect "^4.0.0" - -deep-equal@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" - integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== - dependencies: - is-arguments "^1.0.4" - is-date-object "^1.0.1" - is-regex "^1.0.4" - object-is "^1.0.1" - object-keys "^1.1.1" - regexp.prototype.flags "^1.2.0" - -deep-extend@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -defer-to-connect@^1.0.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" - integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== - -defer-to-connect@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" - integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== - -deferred-leveldown@~1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz#3acd2e0b75d1669924bc0a4b642851131173e1eb" - integrity sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA== - dependencies: - abstract-leveldown "~2.6.0" - -deferred-leveldown@~4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz#0b0570087827bf480a23494b398f04c128c19a20" - integrity sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww== - dependencies: - abstract-leveldown "~5.0.0" - inherits "^2.0.3" - -define-properties@^1.1.3, define-properties@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" - integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== - dependencies: - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA== - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA== - dependencies: - is-descriptor "^1.0.0" - -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - -defined@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.1.tgz#c0b9db27bfaffd95d6f61399419b893df0f91ebf" - integrity sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q== - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== - -delete-empty@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/delete-empty/-/delete-empty-3.0.0.tgz#f8040f2669f26fa7060bc2304e9859c593b685e8" - integrity sha512-ZUyiwo76W+DYnKsL3Kim6M/UOavPdBJgDYWOmuQhYaZvJH0AXAHbUNyEDtRbBra8wqqr686+63/0azfEk1ebUQ== - dependencies: - ansi-colors "^4.1.0" - minimist "^1.2.0" - path-starts-with "^2.0.0" - rimraf "^2.6.2" - -depd@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - -des.js@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" - integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== - dependencies: - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -destroy@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" - integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== - -detect-indent@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" - integrity sha512-BDKtmHlOzwI7iRuEkhzsnPoi5ypEhWAJB5RvHWe1kMr06js3uK5B3734i3ui5Yd+wOJV1cpE4JnivPD283GU/A== - dependencies: - repeating "^2.0.0" - -diff@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" - integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== - -diff@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" - integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== - -diffie-hellman@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== - dependencies: - bn.js "^4.1.0" - miller-rabin "^4.0.0" - randombytes "^2.0.0" - -dom-walk@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" - integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w== - -dotenv@^16.0.0: - version "16.0.3" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" - integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== - -dotignore@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/dotignore/-/dotignore-0.1.2.tgz#f942f2200d28c3a76fbdd6f0ee9f3257c8a2e905" - integrity sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw== - dependencies: - minimatch "^3.0.4" - -duplexer3@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e" - integrity sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA== - -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== - -electron-to-chromium@^1.3.47: - version "1.4.284" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" - integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== - -elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5.4: - version "6.5.4" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" - integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== - dependencies: - bn.js "^4.11.9" - brorand "^1.1.0" - hash.js "^1.0.0" - hmac-drbg "^1.0.1" - inherits "^2.0.4" - minimalistic-assert "^1.0.1" - minimalistic-crypto-utils "^1.0.1" - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -encode-utf8@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda" - integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw== - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== - -encoding-down@5.0.4, encoding-down@~5.0.0: - version "5.0.4" - resolved "https://registry.yarnpkg.com/encoding-down/-/encoding-down-5.0.4.tgz#1e477da8e9e9d0f7c8293d320044f8b2cd8e9614" - integrity sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw== - dependencies: - abstract-leveldown "^5.0.0" - inherits "^2.0.3" - level-codec "^9.0.0" - level-errors "^2.0.0" - xtend "^4.0.1" - -encoding@^0.1.11: - version "0.1.13" - resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" - integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== - dependencies: - iconv-lite "^0.6.2" - -end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -enquirer@^2.3.0, enquirer@^2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" - integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== - dependencies: - ansi-colors "^4.1.1" - -env-paths@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" - integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== - -errno@~0.1.1: - version "0.1.8" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" - integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== - dependencies: - prr "~1.0.1" - -error-ex@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -es-abstract@^1.19.0, es-abstract@^1.20.4: - version "1.21.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.0.tgz#dd1b69ea5bfc3c27199c9753efd4de015102c252" - integrity sha512-GUGtW7eXQay0c+PRq0sGIKSdaBorfVqsCMhGHo4elP7YVqZu9nCZS4UkK4gv71gOWNMra/PaSKD3ao1oWExO0g== - dependencies: - call-bind "^1.0.2" - es-set-tostringtag "^2.0.0" - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - function.prototype.name "^1.1.5" - get-intrinsic "^1.1.3" - get-symbol-description "^1.0.0" - globalthis "^1.0.3" - gopd "^1.0.1" - has "^1.0.3" - has-property-descriptors "^1.0.0" - has-proto "^1.0.1" - has-symbols "^1.0.3" - internal-slot "^1.0.4" - is-array-buffer "^3.0.0" - is-callable "^1.2.7" - is-negative-zero "^2.0.2" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" - is-string "^1.0.7" - is-typed-array "^1.1.10" - is-weakref "^1.0.2" - object-inspect "^1.12.2" - object-keys "^1.1.1" - object.assign "^4.1.4" - regexp.prototype.flags "^1.4.3" - safe-regex-test "^1.0.0" - string.prototype.trimend "^1.0.6" - string.prototype.trimstart "^1.0.6" - typed-array-length "^1.0.4" - unbox-primitive "^1.0.2" - which-typed-array "^1.1.9" - -es-array-method-boxes-properly@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" - integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== - -es-set-tostringtag@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" - integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== - dependencies: - get-intrinsic "^1.1.3" - has "^1.0.3" - has-tostringtag "^1.0.0" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -es5-ext@^0.10.35, es5-ext@^0.10.50: - version "0.10.62" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.62.tgz#5e6adc19a6da524bf3d1e02bbc8960e5eb49a9a5" - integrity sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA== - dependencies: - es6-iterator "^2.0.3" - es6-symbol "^3.1.3" - next-tick "^1.1.0" - -es6-iterator@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== - dependencies: - d "1" - es5-ext "^0.10.35" - es6-symbol "^3.1.1" - -es6-symbol@^3.1.1, es6-symbol@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" - integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== - dependencies: - d "^1.0.1" - ext "^1.1.2" - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== - -escape-string-regexp@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== - -eth-block-tracker@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-3.0.1.tgz#95cd5e763c7293e0b1b2790a2a39ac2ac188a5e1" - integrity sha512-WUVxWLuhMmsfenfZvFO5sbl1qFY2IqUlw/FPVmjjdElpqLsZtSG+wPe9Dz7W/sB6e80HgFKknOmKk2eNlznHug== - dependencies: - eth-query "^2.1.0" - ethereumjs-tx "^1.3.3" - ethereumjs-util "^5.1.3" - ethjs-util "^0.1.3" - json-rpc-engine "^3.6.0" - pify "^2.3.0" - tape "^4.6.3" - -eth-ens-namehash@2.0.8, eth-ens-namehash@^2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz#229ac46eca86d52e0c991e7cb2aef83ff0f68bcf" - integrity sha512-VWEI1+KJfz4Km//dadyvBBoBeSQ0MHTXPvr8UIXiLW6IanxvAV+DmlZAijZwAyggqGUfwQBeHf7tc9wzc1piSw== - dependencies: - idna-uts46-hx "^2.3.1" - js-sha3 "^0.5.7" - -eth-json-rpc-infura@^3.1.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/eth-json-rpc-infura/-/eth-json-rpc-infura-3.2.1.tgz#26702a821067862b72d979c016fd611502c6057f" - integrity sha512-W7zR4DZvyTn23Bxc0EWsq4XGDdD63+XPUCEhV2zQvQGavDVC4ZpFDK4k99qN7bd7/fjj37+rxmuBOBeIqCA5Mw== - dependencies: - cross-fetch "^2.1.1" - eth-json-rpc-middleware "^1.5.0" - json-rpc-engine "^3.4.0" - json-rpc-error "^2.0.0" - -eth-json-rpc-middleware@^1.5.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz#5c9d4c28f745ccb01630f0300ba945f4bef9593f" - integrity sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q== - dependencies: - async "^2.5.0" - eth-query "^2.1.2" - eth-tx-summary "^3.1.2" - ethereumjs-block "^1.6.0" - ethereumjs-tx "^1.3.3" - ethereumjs-util "^5.1.2" - ethereumjs-vm "^2.1.0" - fetch-ponyfill "^4.0.0" - json-rpc-engine "^3.6.0" - json-rpc-error "^2.0.0" - json-stable-stringify "^1.0.1" - promise-to-callback "^1.0.0" - tape "^4.6.3" - -eth-lib@0.2.8: - version "0.2.8" - resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.8.tgz#b194058bef4b220ad12ea497431d6cb6aa0623c8" - integrity sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw== - dependencies: - bn.js "^4.11.6" - elliptic "^6.4.0" - xhr-request-promise "^0.1.2" - -eth-lib@^0.1.26: - version "0.1.29" - resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.29.tgz#0c11f5060d42da9f931eab6199084734f4dbd1d9" - integrity sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ== - dependencies: - bn.js "^4.11.6" - elliptic "^6.4.0" - nano-json-stream-parser "^0.1.2" - servify "^0.1.12" - ws "^3.0.0" - xhr-request-promise "^0.1.2" - -eth-query@^2.0.2, eth-query@^2.1.0, eth-query@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/eth-query/-/eth-query-2.1.2.tgz#d6741d9000106b51510c72db92d6365456a6da5e" - integrity sha512-srES0ZcvwkR/wd5OQBRA1bIJMww1skfGS0s8wlwK3/oNP4+wnds60krvu5R1QbpRQjMmpG5OMIWro5s7gvDPsA== - dependencies: - json-rpc-random-id "^1.0.0" - xtend "^4.0.1" - -eth-sig-util@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-3.0.0.tgz#75133b3d7c20a5731af0690c385e184ab942b97e" - integrity sha512-4eFkMOhpGbTxBQ3AMzVf0haUX2uTur7DpWiHzWyTURa28BVJJtOkcb9Ok5TV0YvEPG61DODPW7ZUATbJTslioQ== - dependencies: - buffer "^5.2.1" - elliptic "^6.4.0" - ethereumjs-abi "0.6.5" - ethereumjs-util "^5.1.1" - tweetnacl "^1.0.0" - tweetnacl-util "^0.15.0" - -eth-sig-util@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.2.tgz#8d958202c7edbaae839707fba6f09ff327606210" - integrity sha512-iNZ576iTOGcfllftB73cPB5AN+XUQAT/T8xzsILsghXC1o8gJUqe3RHlcDqagu+biFpYQ61KQrZZJza8eRSYqw== - dependencies: - ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" - ethereumjs-util "^5.1.1" - -eth-tx-summary@^3.1.2: - version "3.2.4" - resolved "https://registry.yarnpkg.com/eth-tx-summary/-/eth-tx-summary-3.2.4.tgz#e10eb95eb57cdfe549bf29f97f1e4f1db679035c" - integrity sha512-NtlDnaVZah146Rm8HMRUNMgIwG/ED4jiqk0TME9zFheMl1jOp6jL1m0NKGjJwehXQ6ZKCPr16MTr+qspKpEXNg== - dependencies: - async "^2.1.2" - clone "^2.0.0" - concat-stream "^1.5.1" - end-of-stream "^1.1.0" - eth-query "^2.0.2" - ethereumjs-block "^1.4.1" - ethereumjs-tx "^1.1.1" - ethereumjs-util "^5.0.1" - ethereumjs-vm "^2.6.0" - through2 "^2.0.3" - -ethashjs@~0.0.7: - version "0.0.8" - resolved "https://registry.yarnpkg.com/ethashjs/-/ethashjs-0.0.8.tgz#227442f1bdee409a548fb04136e24c874f3aa6f9" - integrity sha512-/MSbf/r2/Ld8o0l15AymjOTlPqpN8Cr4ByUEA9GtR4x0yAh3TdtDzEg29zMjXCNPI7u6E5fOQdj/Cf9Tc7oVNw== - dependencies: - async "^2.1.2" - buffer-xor "^2.0.1" - ethereumjs-util "^7.0.2" - miller-rabin "^4.0.0" - -ethereum-bloom-filters@^1.0.6: - version "1.0.10" - resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz#3ca07f4aed698e75bd134584850260246a5fed8a" - integrity sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA== - dependencies: - js-sha3 "^0.8.0" - -ethereum-common@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.2.0.tgz#13bf966131cce1eeade62a1b434249bb4cb120ca" - integrity sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA== - -ethereum-common@^0.0.18: - version "0.0.18" - resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" - integrity sha512-EoltVQTRNg2Uy4o84qpa2aXymXDJhxm7eos/ACOg0DG4baAbMjhbdAEsx9GeE8sC3XCxnYvrrzZDH8D8MtA2iQ== - -ethereum-cryptography@0.1.3, ethereum-cryptography@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" - integrity sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ== - dependencies: - "@types/pbkdf2" "^3.0.0" - "@types/secp256k1" "^4.0.1" - blakejs "^1.1.0" - browserify-aes "^1.2.0" - bs58check "^2.1.2" - create-hash "^1.2.0" - create-hmac "^1.1.7" - hash.js "^1.1.7" - keccak "^3.0.0" - pbkdf2 "^3.0.17" - randombytes "^2.1.0" - safe-buffer "^5.1.2" - scrypt-js "^3.0.0" - secp256k1 "^4.0.1" - setimmediate "^1.0.5" - -ethereum-cryptography@^1.0.3: - version "1.1.2" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-1.1.2.tgz#74f2ac0f0f5fe79f012c889b3b8446a9a6264e6d" - integrity sha512-XDSJlg4BD+hq9N2FjvotwUET9Tfxpxc3kWGE2AqUG5vcbeunnbImVk3cj6e/xT3phdW21mE8R5IugU4fspQDcQ== - dependencies: - "@noble/hashes" "1.1.2" - "@noble/secp256k1" "1.6.3" - "@scure/bip32" "1.1.0" - "@scure/bip39" "1.1.0" - -ethereum-waffle@^3.4.0: - version "3.4.4" - resolved "https://registry.yarnpkg.com/ethereum-waffle/-/ethereum-waffle-3.4.4.tgz#1378b72040697857b7f5e8f473ca8f97a37b5840" - integrity sha512-PA9+jCjw4WC3Oc5ocSMBj5sXvueWQeAbvCA+hUlb6oFgwwKyq5ka3bWQ7QZcjzIX+TdFkxP4IbFmoY2D8Dkj9Q== - dependencies: - "@ethereum-waffle/chai" "^3.4.4" - "@ethereum-waffle/compiler" "^3.4.4" - "@ethereum-waffle/mock-contract" "^3.4.4" - "@ethereum-waffle/provider" "^3.4.4" - ethers "^5.0.1" - -ethereumjs-abi@0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz#5a637ef16ab43473fa72a29ad90871405b3f5241" - integrity sha512-rCjJZ/AE96c/AAZc6O3kaog4FhOsAViaysBxqJNy2+LHP0ttH0zkZ7nXdVHOAyt6lFwLO0nlCwWszysG/ao1+g== - dependencies: - bn.js "^4.10.0" - ethereumjs-util "^4.3.0" - -ethereumjs-abi@0.6.8, ethereumjs-abi@^0.6.8: - version "0.6.8" - resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae" - integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== - dependencies: - bn.js "^4.11.8" - ethereumjs-util "^6.0.0" - -"ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git": - version "0.6.8" - resolved "git+https://github.com/ethereumjs/ethereumjs-abi.git#ee3994657fa7a427238e6ba92a84d0b529bbcde0" - dependencies: - bn.js "^4.11.8" - ethereumjs-util "^6.0.0" - -ethereumjs-account@3.0.0, ethereumjs-account@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-3.0.0.tgz#728f060c8e0c6e87f1e987f751d3da25422570a9" - integrity sha512-WP6BdscjiiPkQfF9PVfMcwx/rDvfZTjFKY0Uwc09zSQr9JfIVH87dYIJu0gNhBhpmovV4yq295fdllS925fnBA== - dependencies: - ethereumjs-util "^6.0.0" - rlp "^2.2.1" - safe-buffer "^5.1.1" - -ethereumjs-account@^2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz#eeafc62de544cb07b0ee44b10f572c9c49e00a84" - integrity sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA== - dependencies: - ethereumjs-util "^5.0.0" - rlp "^2.0.0" - safe-buffer "^5.1.1" - -ethereumjs-block@2.2.2, ethereumjs-block@^2.2.2, ethereumjs-block@~2.2.0, ethereumjs-block@~2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz#c7654be7e22df489fda206139ecd63e2e9c04965" - integrity sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg== - dependencies: - async "^2.0.1" - ethereumjs-common "^1.5.0" - ethereumjs-tx "^2.1.1" - ethereumjs-util "^5.0.0" - merkle-patricia-tree "^2.1.2" - -ethereumjs-block@^1.2.2, ethereumjs-block@^1.4.1, ethereumjs-block@^1.6.0: - version "1.7.1" - resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz#78b88e6cc56de29a6b4884ee75379b6860333c3f" - integrity sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg== - dependencies: - async "^2.0.1" - ethereum-common "0.2.0" - ethereumjs-tx "^1.2.2" - ethereumjs-util "^5.0.0" - merkle-patricia-tree "^2.1.2" - -ethereumjs-blockchain@^4.0.3: - version "4.0.4" - resolved "https://registry.yarnpkg.com/ethereumjs-blockchain/-/ethereumjs-blockchain-4.0.4.tgz#30f2228dc35f6dcf94423692a6902604ae34960f" - integrity sha512-zCxaRMUOzzjvX78DTGiKjA+4h2/sF0OYL1QuPux0DHpyq8XiNoF5GYHtb++GUxVlMsMfZV7AVyzbtgcRdIcEPQ== - dependencies: - async "^2.6.1" - ethashjs "~0.0.7" - ethereumjs-block "~2.2.2" - ethereumjs-common "^1.5.0" - ethereumjs-util "^6.1.0" - flow-stoplight "^1.0.0" - level-mem "^3.0.1" - lru-cache "^5.1.1" - rlp "^2.2.2" - semaphore "^1.1.0" - -ethereumjs-common@1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.0.tgz#d3e82fc7c47c0cef95047f431a99485abc9bb1cd" - integrity sha512-SZOjgK1356hIY7MRj3/ma5qtfr/4B5BL+G4rP/XSMYr2z1H5el4RX5GReYCKmQmYI/nSBmRnwrZ17IfHuG0viQ== - -ethereumjs-common@^1.1.0, ethereumjs-common@^1.3.2, ethereumjs-common@^1.5.0: - version "1.5.2" - resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz#2065dbe9214e850f2e955a80e650cb6999066979" - integrity sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA== - -ethereumjs-tx@2.1.2, ethereumjs-tx@^2.1.1, ethereumjs-tx@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz#5dfe7688bf177b45c9a23f86cf9104d47ea35fed" - integrity sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw== - dependencies: - ethereumjs-common "^1.5.0" - ethereumjs-util "^6.0.0" - -ethereumjs-tx@^1.1.1, ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.3: - version "1.3.7" - resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a" - integrity sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA== - dependencies: - ethereum-common "^0.0.18" - ethereumjs-util "^5.0.0" - -ethereumjs-util@6.2.1, ethereumjs-util@^6.0.0, ethereumjs-util@^6.1.0, ethereumjs-util@^6.2.0, ethereumjs-util@^6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" - integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== - dependencies: - "@types/bn.js" "^4.11.3" - bn.js "^4.11.0" - create-hash "^1.1.2" - elliptic "^6.5.2" - ethereum-cryptography "^0.1.3" - ethjs-util "0.1.6" - rlp "^2.2.3" - -ethereumjs-util@^4.3.0: - version "4.5.1" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.1.tgz#f4bf9b3b515a484e3cc8781d61d9d980f7c83bd0" - integrity sha512-WrckOZ7uBnei4+AKimpuF1B3Fv25OmoRgmYCpGsP7u8PFxXAmAgiJSYT2kRWnt6fVIlKaQlZvuwXp7PIrmn3/w== - dependencies: - bn.js "^4.8.0" - create-hash "^1.1.2" - elliptic "^6.5.2" - ethereum-cryptography "^0.1.3" - rlp "^2.0.0" - -ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.2, ethereumjs-util@^5.1.3, ethereumjs-util@^5.1.5, ethereumjs-util@^5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz#a833f0e5fca7e5b361384dc76301a721f537bf65" - integrity sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ== - dependencies: - bn.js "^4.11.0" - create-hash "^1.1.2" - elliptic "^6.5.2" - ethereum-cryptography "^0.1.3" - ethjs-util "^0.1.3" - rlp "^2.0.0" - safe-buffer "^5.1.1" - -ethereumjs-util@^7.0.2, ethereumjs-util@^7.1.0: - version "7.1.5" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" - integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== - dependencies: - "@types/bn.js" "^5.1.0" - bn.js "^5.1.2" - create-hash "^1.1.2" - ethereum-cryptography "^0.1.3" - rlp "^2.2.4" - -ethereumjs-vm@4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-4.2.0.tgz#e885e861424e373dbc556278f7259ff3fca5edab" - integrity sha512-X6qqZbsY33p5FTuZqCnQ4+lo957iUJMM6Mpa6bL4UW0dxM6WmDSHuI4j/zOp1E2TDKImBGCJA9QPfc08PaNubA== - dependencies: - async "^2.1.2" - async-eventemitter "^0.2.2" - core-js-pure "^3.0.1" - ethereumjs-account "^3.0.0" - ethereumjs-block "^2.2.2" - ethereumjs-blockchain "^4.0.3" - ethereumjs-common "^1.5.0" - ethereumjs-tx "^2.1.2" - ethereumjs-util "^6.2.0" - fake-merkle-patricia-tree "^1.0.1" - functional-red-black-tree "^1.0.1" - merkle-patricia-tree "^2.3.2" - rustbn.js "~0.2.0" - safe-buffer "^5.1.1" - util.promisify "^1.0.0" - -ethereumjs-vm@^2.1.0, ethereumjs-vm@^2.3.4, ethereumjs-vm@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz#76243ed8de031b408793ac33907fb3407fe400c6" - integrity sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw== - dependencies: - async "^2.1.2" - async-eventemitter "^0.2.2" - ethereumjs-account "^2.0.3" - ethereumjs-block "~2.2.0" - ethereumjs-common "^1.1.0" - ethereumjs-util "^6.0.0" - fake-merkle-patricia-tree "^1.0.1" - functional-red-black-tree "^1.0.1" - merkle-patricia-tree "^2.3.2" - rustbn.js "~0.2.0" - safe-buffer "^5.1.1" - -ethereumjs-wallet@0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.5.tgz#685e9091645cee230ad125c007658833991ed474" - integrity sha512-MDwjwB9VQVnpp/Dc1XzA6J1a3wgHQ4hSvA1uWNatdpOrtCbPVuQSKSyRnjLvS0a+KKMw2pvQ9Ybqpb3+eW8oNA== - dependencies: - aes-js "^3.1.1" - bs58check "^2.1.2" - ethereum-cryptography "^0.1.3" - ethereumjs-util "^6.0.0" - randombytes "^2.0.6" - safe-buffer "^5.1.2" - scryptsy "^1.2.1" - utf8 "^3.0.0" - uuid "^3.3.2" - -ethers@^5.0.0, ethers@^5.0.1, ethers@^5.0.2, ethers@^5.5.2, ethers@^5.5.3: - version "5.7.2" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" - integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== - dependencies: - "@ethersproject/abi" "5.7.0" - "@ethersproject/abstract-provider" "5.7.0" - "@ethersproject/abstract-signer" "5.7.0" - "@ethersproject/address" "5.7.0" - "@ethersproject/base64" "5.7.0" - "@ethersproject/basex" "5.7.0" - "@ethersproject/bignumber" "5.7.0" - "@ethersproject/bytes" "5.7.0" - "@ethersproject/constants" "5.7.0" - "@ethersproject/contracts" "5.7.0" - "@ethersproject/hash" "5.7.0" - "@ethersproject/hdnode" "5.7.0" - "@ethersproject/json-wallets" "5.7.0" - "@ethersproject/keccak256" "5.7.0" - "@ethersproject/logger" "5.7.0" - "@ethersproject/networks" "5.7.1" - "@ethersproject/pbkdf2" "5.7.0" - "@ethersproject/properties" "5.7.0" - "@ethersproject/providers" "5.7.2" - "@ethersproject/random" "5.7.0" - "@ethersproject/rlp" "5.7.0" - "@ethersproject/sha2" "5.7.0" - "@ethersproject/signing-key" "5.7.0" - "@ethersproject/solidity" "5.7.0" - "@ethersproject/strings" "5.7.0" - "@ethersproject/transactions" "5.7.0" - "@ethersproject/units" "5.7.0" - "@ethersproject/wallet" "5.7.0" - "@ethersproject/web" "5.7.1" - "@ethersproject/wordlists" "5.7.0" - -ethjs-unit@0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" - integrity sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw== - dependencies: - bn.js "4.11.6" - number-to-bn "1.7.0" - -ethjs-util@0.1.6, ethjs-util@^0.1.3, ethjs-util@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" - integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== - dependencies: - is-hex-prefixed "1.0.0" - strip-hex-prefix "1.0.0" - -event-target-shim@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" - integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== - -eventemitter3@4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" - integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== - -events@^3.0.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - -evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== - dependencies: - md5.js "^1.3.4" - safe-buffer "^5.1.1" - -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA== - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -express@^4.14.0: - version "4.18.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" - integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== - dependencies: - accepts "~1.3.8" - array-flatten "1.1.1" - body-parser "1.20.1" - content-disposition "0.5.4" - content-type "~1.0.4" - cookie "0.5.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "2.0.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "1.2.0" - fresh "0.5.2" - http-errors "2.0.0" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "2.4.1" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.7" - qs "6.11.0" - range-parser "~1.2.1" - safe-buffer "5.2.1" - send "0.18.0" - serve-static "1.15.0" - setprototypeof "1.2.0" - statuses "2.0.1" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -ext@^1.1.2: - version "1.7.0" - resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" - integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== - dependencies: - type "^2.7.2" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q== - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - -extend@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== - -extsprintf@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" - integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== - -fake-merkle-patricia-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz#4b8c3acfb520afadf9860b1f14cd8ce3402cddd3" - integrity sha512-Tgq37lkc9pUIgIKw5uitNUKcgcYL3R6JvXtKQbOf/ZSavXbidsksgp/pAY6p//uhw0I4yoMsvTSovvVIsk/qxA== - dependencies: - checkpoint-store "^1.1.0" - -fast-deep-equal@^3.1.1: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fetch-ponyfill@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz#ae3ce5f732c645eab87e4ae8793414709b239893" - integrity sha512-knK9sGskIg2T7OnYLdZ2hZXn0CtDrAIBxYQLpmEf0BqfdWnwmM1weccUl5+4EdA44tzNSFAuxITPbXtPehUB3g== - dependencies: - node-fetch "~1.7.1" - -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ== - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -finalhandler@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" - integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "2.4.1" - parseurl "~1.3.3" - statuses "2.0.1" - unpipe "~1.0.0" - -find-replace@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-1.0.3.tgz#b88e7364d2d9c959559f388c66670d6130441fa0" - integrity sha512-KrUnjzDCD9426YnCP56zGYy/eieTnhtK6Vn++j+JJzmlsWWwEkDnsyVF575spT6HJ6Ow9tlbT3TQTDsa+O4UWA== - dependencies: - array-back "^1.0.4" - test-value "^2.1.0" - -find-replace@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" - integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ== - dependencies: - array-back "^3.0.1" - -find-up@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - integrity sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA== - dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" - -find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== - dependencies: - locate-path "^2.0.0" - -find-yarn-workspace-root@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz#40eb8e6e7c2502ddfaa2577c176f221422f860db" - integrity sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q== - dependencies: - fs-extra "^4.0.3" - micromatch "^3.1.4" - -find-yarn-workspace-root@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" - integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ== - dependencies: - micromatch "^4.0.2" - -flat@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" - integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== - -flow-stoplight@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/flow-stoplight/-/flow-stoplight-1.0.0.tgz#4a292c5bcff8b39fa6cc0cb1a853d86f27eeff7b" - integrity sha512-rDjbZUKpN8OYhB0IE/vY/I8UWO/602IIJEU/76Tv4LvYnwHCk0BCsvz4eRr9n+FQcri7L5cyaXOo0+/Kh4HisA== - -fmix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/fmix/-/fmix-0.1.0.tgz#c7bbf124dec42c9d191cfb947d0a9778dd986c0c" - integrity sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w== - dependencies: - imul "^1.0.0" - -follow-redirects@^1.12.1, follow-redirects@^1.14.0: - version "1.15.2" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" - integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== - -for-each@^0.3.3, for-each@~0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== - dependencies: - is-callable "^1.1.3" - -for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ== - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== - -form-data@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" - integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - -form-data@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" - integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - -form-data@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" - integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - -forwarded@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" - integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== - -fp-ts@1.19.3: - version "1.19.3" - resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.3.tgz#261a60d1088fbff01f91256f91d21d0caaaaa96f" - integrity sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg== - -fp-ts@^1.0.0: - version "1.19.5" - resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a" - integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A== - -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA== - dependencies: - map-cache "^0.2.2" - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== - -fs-extra@^0.30.0: - version "0.30.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" - integrity sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^2.1.0" - klaw "^1.0.0" - path-is-absolute "^1.0.0" - rimraf "^2.2.8" - -fs-extra@^10.0.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" - integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fs-extra@^4.0.2, fs-extra@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" - integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs-extra@^7.0.0, fs-extra@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" - integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs-extra@^9.0.0, fs-extra@^9.1.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" - integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== - dependencies: - at-least-node "^1.0.0" - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fs-minipass@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" - integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== - dependencies: - minipass "^2.6.0" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -function.prototype.name@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" - integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.0" - functions-have-names "^1.2.2" - -functional-red-black-tree@^1.0.1, functional-red-black-tree@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== - -functions-have-names@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" - integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== - -ganache-core@^2.13.2: - version "2.13.2" - resolved "https://registry.yarnpkg.com/ganache-core/-/ganache-core-2.13.2.tgz#27e6fc5417c10e6e76e2e646671869d7665814a3" - integrity sha512-tIF5cR+ANQz0+3pHWxHjIwHqFXcVo0Mb+kcsNhglNFALcYo49aQpnS9dqHartqPfMFjiHh/qFoD3mYK0d/qGgw== - dependencies: - abstract-leveldown "3.0.0" - async "2.6.2" - bip39 "2.5.0" - cachedown "1.0.0" - clone "2.1.2" - debug "3.2.6" - encoding-down "5.0.4" - eth-sig-util "3.0.0" - ethereumjs-abi "0.6.8" - ethereumjs-account "3.0.0" - ethereumjs-block "2.2.2" - ethereumjs-common "1.5.0" - ethereumjs-tx "2.1.2" - ethereumjs-util "6.2.1" - ethereumjs-vm "4.2.0" - heap "0.2.6" - keccak "3.0.1" - level-sublevel "6.6.4" - levelup "3.1.1" - lodash "4.17.20" - lru-cache "5.1.1" - merkle-patricia-tree "3.0.0" - patch-package "6.2.2" - seedrandom "3.0.1" - source-map-support "0.5.12" - tmp "0.1.0" - web3-provider-engine "14.2.1" - websocket "1.0.32" - optionalDependencies: - ethereumjs-wallet "0.6.5" - web3 "1.2.11" - -get-caller-file@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" - integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== - -get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-func-name@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" - integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig== - -get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" - integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.3" - -get-stream@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - -get-stream@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" - integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== - dependencies: - pump "^3.0.0" - -get-symbol-description@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" - integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" - -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== - dependencies: - assert-plus "^1.0.0" - -glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob@7.1.7: - version "7.1.7" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" - integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.1.2, glob@^7.1.3, glob@~7.2.3: - version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - -global@~4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" - integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w== - dependencies: - min-document "^2.19.0" - process "^0.11.10" - -globals@^9.18.0: - version "9.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== - -globalthis@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" - integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== - dependencies: - define-properties "^1.1.3" - -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" - -got@9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" - integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== - dependencies: - "@sindresorhus/is" "^0.14.0" - "@szmarczak/http-timer" "^1.1.2" - cacheable-request "^6.0.0" - decompress-response "^3.3.0" - duplexer3 "^0.1.4" - get-stream "^4.1.0" - lowercase-keys "^1.0.1" - mimic-response "^1.0.1" - p-cancelable "^1.0.0" - to-readable-stream "^1.0.0" - url-parse-lax "^3.0.0" - -got@^11.8.5: - version "11.8.6" - resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a" - integrity sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g== - dependencies: - "@sindresorhus/is" "^4.0.0" - "@szmarczak/http-timer" "^4.0.5" - "@types/cacheable-request" "^6.0.1" - "@types/responselike" "^1.0.0" - cacheable-lookup "^5.0.3" - cacheable-request "^7.0.2" - decompress-response "^6.0.0" - http2-wrapper "^1.0.0-beta.5.2" - lowercase-keys "^2.0.0" - p-cancelable "^2.0.0" - responselike "^2.0.0" - -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0: - version "4.2.10" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" - integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== - -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== - -har-validator@~5.1.3: - version "5.1.5" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" - integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== - dependencies: - ajv "^6.12.3" - har-schema "^2.0.0" - -hardhat-abi-exporter@^2.9.0: - version "2.10.1" - resolved "https://registry.yarnpkg.com/hardhat-abi-exporter/-/hardhat-abi-exporter-2.10.1.tgz#b14884e233c73fe3f43360f014ad7fd6df4b6d25" - integrity sha512-X8GRxUTtebMAd2k4fcPyVnCdPa6dYK4lBsrwzKP5yiSq4i+WadWPIumaLfce53TUf/o2TnLpLOduyO1ylE2NHQ== - dependencies: - "@ethersproject/abi" "^5.5.0" - delete-empty "^3.0.0" - -hardhat-deploy@^0.11.22: - version "0.11.22" - resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.11.22.tgz#9799c0266a0fc40c84690de54760f1b4dae5e487" - integrity sha512-ZhHVNB7Jo2l8Is+KIAk9F8Q3d7pptyiX+nsNbIFXztCz81kaP+6kxNODRBqRCy7SOD3It4+iKCL6tWsPAA/jVQ== - dependencies: - "@types/qs" "^6.9.7" - axios "^0.21.1" - chalk "^4.1.2" - chokidar "^3.5.2" - debug "^4.3.2" - enquirer "^2.3.6" - ethers "^5.5.3" - form-data "^4.0.0" - fs-extra "^10.0.0" - match-all "^1.2.6" - murmur-128 "^0.2.1" - qs "^6.9.4" - zksync-web3 "^0.8.1" - -hardhat-preprocessor@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/hardhat-preprocessor/-/hardhat-preprocessor-0.1.5.tgz#75b22641fd6a680739c995d03bd5f7868eb72144" - integrity sha512-j8m44mmPxpxAAd0G8fPHRHOas/INZdzptSur0TNJvMEGcFdLDhbHHxBcqZVQ/bmiW42q4gC60AP4CXn9EF018g== - dependencies: - murmur-128 "^0.2.1" - -hardhat@^2.9.5: - version "2.12.5" - resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.12.5.tgz#e3cd4d6dae35cb9505055967bd7e15e6adf3aa03" - integrity sha512-f/t7+hLlhsnQZ6LDXyV+8rHGRZFZY1sgFvgrwr9fBjMdGp1Bu6hHq1KXS4/VFZfZcVdL1DAWWEkryinZhqce+A== - dependencies: - "@ethersproject/abi" "^5.1.2" - "@metamask/eth-sig-util" "^4.0.0" - "@nomicfoundation/ethereumjs-block" "^4.0.0" - "@nomicfoundation/ethereumjs-blockchain" "^6.0.0" - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-evm" "^1.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-statemanager" "^1.0.0" - "@nomicfoundation/ethereumjs-trie" "^5.0.0" - "@nomicfoundation/ethereumjs-tx" "^4.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - "@nomicfoundation/ethereumjs-vm" "^6.0.0" - "@nomicfoundation/solidity-analyzer" "^0.1.0" - "@sentry/node" "^5.18.1" - "@types/bn.js" "^5.1.0" - "@types/lru-cache" "^5.1.0" - abort-controller "^3.0.0" - adm-zip "^0.4.16" - aggregate-error "^3.0.0" - ansi-escapes "^4.3.0" - chalk "^2.4.2" - chokidar "^3.4.0" - ci-info "^2.0.0" - debug "^4.1.1" - enquirer "^2.3.0" - env-paths "^2.2.0" - ethereum-cryptography "^1.0.3" - ethereumjs-abi "^0.6.8" - find-up "^2.1.0" - fp-ts "1.19.3" - fs-extra "^7.0.1" - glob "7.2.0" - immutable "^4.0.0-rc.12" - io-ts "1.10.4" - keccak "^3.0.2" - lodash "^4.17.11" - mnemonist "^0.38.0" - mocha "^10.0.0" - p-map "^4.0.0" - qs "^6.7.0" - raw-body "^2.4.1" - resolve "1.17.0" - semver "^6.3.0" - solc "0.7.3" - source-map-support "^0.5.13" - stacktrace-parser "^0.1.10" - tsort "0.0.1" - undici "^5.4.0" - uuid "^8.3.2" - ws "^7.4.6" - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg== - dependencies: - ansi-regex "^2.0.0" - -has-bigints@^1.0.1, has-bigints@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" - integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-property-descriptors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" - integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== - dependencies: - get-intrinsic "^1.1.1" - -has-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" - integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== - -has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== - dependencies: - has-symbols "^1.0.2" - -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q== - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw== - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ== - -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ== - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -has@^1.0.3, has@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -hash-base@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" - integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== - dependencies: - inherits "^2.0.4" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" - -hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" - integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.1" - -he@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== - -heap@0.2.6: - version "0.2.6" - resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.6.tgz#087e1f10b046932fc8594dd9e6d378afc9d1e5ac" - integrity sha512-MzzWcnfB1e4EG2vHi3dXHoBupmuXNZzx6pY6HldVS55JKKBoq3xOyzfSaZRkJp37HIhEYC78knabHff3zc4dQQ== - -hmac-drbg@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== - dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" - -home-or-tmp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" - integrity sha512-ycURW7oUxE2sNiPVw1HVEFsW+ecOpJ5zaj7eC0RlwhibhRBod20muUN8qu/gzx956YrLolVvs1MTXwKgC2rVEg== - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.1" - -hosted-git-info@^2.1.4, hosted-git-info@^2.6.0: - version "2.8.9" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" - integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== - -http-cache-semantics@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== - -http-errors@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" - integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== - dependencies: - depd "2.0.0" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses "2.0.1" - toidentifier "1.0.1" - -http-https@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" - integrity sha512-o0PWwVCSp3O0wS6FvNr6xfBCHgt0m1tvPLFOCc2iFDKTRAXhB7m8klDf7ErowFH8POa6dVdGatKU5I1YYwzUyg== - -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -http2-wrapper@^1.0.0-beta.5.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d" - integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg== - dependencies: - quick-lru "^5.1.1" - resolve-alpn "^1.0.0" - -https-proxy-agent@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" - integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== - dependencies: - agent-base "6" - debug "4" - -iconv-lite@0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -iconv-lite@^0.6.2: - version "0.6.3" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" - integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== - dependencies: - safer-buffer ">= 2.1.2 < 3.0.0" - -idna-uts46-hx@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz#a1dc5c4df37eee522bf66d969cc980e00e8711f9" - integrity sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA== - dependencies: - punycode "2.1.0" - -ieee754@^1.1.13, ieee754@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -immediate@^3.2.3: - version "3.3.0" - resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" - integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q== - -immediate@~3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" - integrity sha512-RrGCXRm/fRVqMIhqXrGEX9rRADavPiDFSoMb/k64i9XMk8uH4r/Omi5Ctierj6XzNecwDbO4WuFbDD1zmpl3Tg== - -immutable@^4.0.0-rc.12: - version "4.2.1" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.2.1.tgz#8a4025691018c560a40c67e43d698f816edc44d4" - integrity sha512-7WYV7Q5BTs0nlQm7tl92rDYYoyELLKHoDMBKhrxEoiV4mrfVdRz8hzPiYOzH7yWjzoVEamxRuAqhxL2PLRwZYQ== - -imul@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/imul/-/imul-1.0.1.tgz#9d5867161e8b3de96c2c38d5dc7cb102f35e2ac9" - integrity sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA== - -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -internal-slot@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.4.tgz#8551e7baf74a7a6ba5f749cfb16aa60722f0d6f3" - integrity sha512-tA8URYccNzMo94s5MQZgH8NB/XTa6HsOo0MLfXTKKEnHVVdegzaQoFZ7Jp44bdvLvY2waT5dc+j5ICEswhi7UQ== - dependencies: - get-intrinsic "^1.1.3" - has "^1.0.3" - side-channel "^1.0.4" - -invariant@^2.2.2: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - -invert-kv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - integrity sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ== - -io-ts@1.10.4: - version "1.10.4" - resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-1.10.4.tgz#cd5401b138de88e4f920adbcb7026e2d1967e6e2" - integrity sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g== - dependencies: - fp-ts "^1.0.0" - -ipaddr.js@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== - -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A== - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== - dependencies: - kind-of "^6.0.0" - -is-arguments@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-array-buffer@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.1.tgz#deb1db4fcae48308d54ef2442706c0393997052a" - integrity sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.3" - is-typed-array "^1.1.10" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== - -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== - dependencies: - has-bigints "^1.0.1" - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - -is-buffer@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" - integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== - -is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" - integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== - -is-ci@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" - integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== - dependencies: - ci-info "^2.0.0" - -is-core-module@^2.9.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" - integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== - dependencies: - has "^1.0.3" - -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg== - dependencies: - kind-of "^3.0.2" - -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== - dependencies: - kind-of "^6.0.0" - -is-date-object@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== - dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - -is-docker@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" - integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== - dependencies: - is-plain-object "^2.0.4" - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-finite@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" - integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== - -is-fn@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fn/-/is-fn-1.0.0.tgz#9543d5de7bcf5b08a22ec8a20bae6e286d510d8c" - integrity sha512-XoFPJQmsAShb3jEQRfzf2rqXavq7fIqF/jOekp308JlThqrODnMpweVSGilKTCXELfLhltGP2AGgbQGVP8F1dg== - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw== - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-function@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.2.tgz#4f097f30abf6efadac9833b17ca5dc03f8144e08" - integrity sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ== - -is-glob@^4.0.1, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-hex-prefixed@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" - integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA== - -is-negative-zero@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" - integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== - -is-number-object@^1.0.4: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" - integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== - dependencies: - has-tostringtag "^1.0.0" - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg== - dependencies: - kind-of "^3.0.2" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-plain-obj@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" - integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== - -is-plain-object@^2.0.3, is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-regex@^1.0.4, is-regex@^1.1.4, is-regex@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-shared-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" - integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== - dependencies: - call-bind "^1.0.2" - -is-stream@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ== - -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== - dependencies: - has-tostringtag "^1.0.0" - -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== - dependencies: - has-symbols "^1.0.2" - -is-typed-array@^1.1.10, is-typed-array@^1.1.9: - version "1.1.10" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" - integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" - -is-typedarray@^1.0.0, is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== - -is-unicode-supported@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" - integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== - -is-url@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" - integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== - -is-utf8@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q== - -is-weakref@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" - integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== - dependencies: - call-bind "^1.0.2" - -is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== - -is-wsl@^2.1.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" - integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== - dependencies: - is-docker "^2.0.0" - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== - -isarray@1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA== - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== - -js-sha3@0.8.0, js-sha3@^0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" - integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== - -js-sha3@^0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" - integrity sha512-GII20kjaPX0zJ8wzkTbNDYMY7msuZcTWk8S5UOh6806Jq/wz1J8/bnr8uGU0DAUmYDjj2Mr4X1cW8v/GLYnR+g== - -"js-tokens@^3.0.0 || ^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-tokens@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - integrity sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg== - -js-yaml@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== - -jsesc@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" - integrity sha512-Mke0DA0QjUWuJlhsE0ZPPhYiJkRap642SmI/4ztCFaUs6V2AiH1sfecc+57NgaryfAA2VR3v6O+CSjC1jZJKOA== - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== - -json-buffer@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" - integrity sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ== - -json-buffer@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" - integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== - -json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz#9d4ff447241792e1d0a232f6ef927302bb0c62a9" - integrity sha512-6QNcvm2gFuuK4TKU1uwfH0Qd/cOSb9c1lls0gbnIhciktIUQJwz6NQNAW4B1KiGPenv7IKu97V222Yo1bNhGuA== - dependencies: - async "^2.0.1" - babel-preset-env "^1.7.0" - babelify "^7.3.0" - json-rpc-error "^2.0.0" - promise-to-callback "^1.0.0" - safe-event-emitter "^1.0.1" - -json-rpc-error@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02" - integrity sha512-EwUeWP+KgAZ/xqFpaP6YDAXMtCJi+o/QQpCQFIYyxr01AdADi2y413eM8hSqJcoQym9WMePAJWoaODEJufC4Ug== - dependencies: - inherits "^2.0.1" - -json-rpc-random-id@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8" - integrity sha512-RJ9YYNCkhVDBuP4zN5BBtYAzEl03yq/jIIsyif0JY9qyJuQQZNeDK7anAPKKlyEtLSj2s8h6hNh2F8zO5q7ScA== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-schema-traverse@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" - integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== - -json-schema@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" - integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== - -json-stable-stringify@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz#e06f23128e0bbe342dc996ed5a19e28b57b580e0" - integrity sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g== - dependencies: - jsonify "^0.0.1" - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== - -json5@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - integrity sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw== - -jsonfile@^2.1.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" - integrity sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw== - optionalDependencies: - graceful-fs "^4.1.6" - -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== - optionalDependencies: - graceful-fs "^4.1.6" - -jsonfile@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" - integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== - dependencies: - universalify "^2.0.0" - optionalDependencies: - graceful-fs "^4.1.6" - -jsonify@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" - integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== - -jsprim@^1.2.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" - integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.4.0" - verror "1.10.0" - -keccak@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.1.tgz#ae30a0e94dbe43414f741375cff6d64c8bea0bff" - integrity sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA== - dependencies: - node-addon-api "^2.0.0" - node-gyp-build "^4.2.0" - -keccak@^3.0.0, keccak@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.3.tgz#4bc35ad917be1ef54ff246f904c2bbbf9ac61276" - integrity sha512-JZrLIAJWuZxKbCilMpNz5Vj7Vtb4scDG3dMXLOsbzBmQGyjwE61BbW7bJkfKKCShXiQZt3T6sBgALRtmd+nZaQ== - dependencies: - node-addon-api "^2.0.0" - node-gyp-build "^4.2.0" - readable-stream "^3.6.0" - -keyv@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" - integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== - dependencies: - json-buffer "3.0.0" - -keyv@^4.0.0: - version "4.5.2" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.2.tgz#0e310ce73bf7851ec702f2eaf46ec4e3805cce56" - integrity sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g== - dependencies: - json-buffer "3.0.1" - -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw== - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== - -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - -klaw-sync@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c" - integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ== - dependencies: - graceful-fs "^4.1.11" - -klaw@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" - integrity sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw== - optionalDependencies: - graceful-fs "^4.1.9" - -lcid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - integrity sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw== - dependencies: - invert-kv "^1.0.0" - -level-codec@^9.0.0: - version "9.0.2" - resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-9.0.2.tgz#fd60df8c64786a80d44e63423096ffead63d8cbc" - integrity sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ== - dependencies: - buffer "^5.6.0" - -level-codec@~7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-7.0.1.tgz#341f22f907ce0f16763f24bddd681e395a0fb8a7" - integrity sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ== - -level-errors@^1.0.3: - version "1.1.2" - resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.1.2.tgz#4399c2f3d3ab87d0625f7e3676e2d807deff404d" - integrity sha512-Sw/IJwWbPKF5Ai4Wz60B52yj0zYeqzObLh8k1Tk88jVmD51cJSKWSYpRyhVIvFzZdvsPqlH5wfhp/yxdsaQH4w== - dependencies: - errno "~0.1.1" - -level-errors@^2.0.0, level-errors@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-2.0.1.tgz#2132a677bf4e679ce029f517c2f17432800c05c8" - integrity sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw== - dependencies: - errno "~0.1.1" - -level-errors@~1.0.3: - version "1.0.5" - resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.0.5.tgz#83dbfb12f0b8a2516bdc9a31c4876038e227b859" - integrity sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig== - dependencies: - errno "~0.1.1" - -level-iterator-stream@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-2.0.3.tgz#ccfff7c046dcf47955ae9a86f46dfa06a31688b4" - integrity sha512-I6Heg70nfF+e5Y3/qfthJFexhRw/Gi3bIymCoXAlijZdAcLaPuWSJs3KXyTYf23ID6g0o2QF62Yh+grOXY3Rig== - dependencies: - inherits "^2.0.1" - readable-stream "^2.0.5" - xtend "^4.0.0" - -level-iterator-stream@~1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz#e43b78b1a8143e6fa97a4f485eb8ea530352f2ed" - integrity sha512-1qua0RHNtr4nrZBgYlpV0qHHeHpcRRWTxEZJ8xsemoHAXNL5tbooh4tPEEqIqsbWCAJBmUmkwYK/sW5OrFjWWw== - dependencies: - inherits "^2.0.1" - level-errors "^1.0.3" - readable-stream "^1.0.33" - xtend "^4.0.0" - -level-iterator-stream@~3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz#2c98a4f8820d87cdacab3132506815419077c730" - integrity sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g== - dependencies: - inherits "^2.0.1" - readable-stream "^2.3.6" - xtend "^4.0.0" - -level-mem@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/level-mem/-/level-mem-3.0.1.tgz#7ce8cf256eac40f716eb6489654726247f5a89e5" - integrity sha512-LbtfK9+3Ug1UmvvhR2DqLqXiPW1OJ5jEh0a3m9ZgAipiwpSxGj/qaVVy54RG5vAQN1nCuXqjvprCuKSCxcJHBg== - dependencies: - level-packager "~4.0.0" - memdown "~3.0.0" - -level-packager@~4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/level-packager/-/level-packager-4.0.1.tgz#7e7d3016af005be0869bc5fa8de93d2a7f56ffe6" - integrity sha512-svCRKfYLn9/4CoFfi+d8krOtrp6RoX8+xm0Na5cgXMqSyRru0AnDYdLl+YI8u1FyS6gGZ94ILLZDE5dh2but3Q== - dependencies: - encoding-down "~5.0.0" - levelup "^3.0.0" - -level-post@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/level-post/-/level-post-1.0.7.tgz#19ccca9441a7cc527879a0635000f06d5e8f27d0" - integrity sha512-PWYqG4Q00asOrLhX7BejSajByB4EmG2GaKHfj3h5UmmZ2duciXLPGYWIjBzLECFWUGOZWlm5B20h/n3Gs3HKew== - dependencies: - ltgt "^2.1.2" - -level-sublevel@6.6.4: - version "6.6.4" - resolved "https://registry.yarnpkg.com/level-sublevel/-/level-sublevel-6.6.4.tgz#f7844ae893919cd9d69ae19d7159499afd5352ba" - integrity sha512-pcCrTUOiO48+Kp6F1+UAzF/OtWqLcQVTVF39HLdZ3RO8XBoXt+XVPKZO1vVr1aUoxHZA9OtD2e1v7G+3S5KFDA== - dependencies: - bytewise "~1.1.0" - level-codec "^9.0.0" - level-errors "^2.0.0" - level-iterator-stream "^2.0.3" - ltgt "~2.1.1" - pull-defer "^0.2.2" - pull-level "^2.0.3" - pull-stream "^3.6.8" - typewiselite "~1.0.0" - xtend "~4.0.0" - -level-supports@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-4.0.1.tgz#431546f9d81f10ff0fea0e74533a0e875c08c66a" - integrity sha512-PbXpve8rKeNcZ9C1mUicC9auIYFyGpkV9/i6g76tLgANwWhtG2v7I4xNBUlkn3lE2/dZF3Pi0ygYGtLc4RXXdA== - -level-transcoder@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/level-transcoder/-/level-transcoder-1.0.1.tgz#f8cef5990c4f1283d4c86d949e73631b0bc8ba9c" - integrity sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w== - dependencies: - buffer "^6.0.3" - module-error "^1.0.1" - -level-ws@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-0.0.0.tgz#372e512177924a00424b0b43aef2bb42496d228b" - integrity sha512-XUTaO/+Db51Uiyp/t7fCMGVFOTdtLS/NIACxE/GHsij15mKzxksZifKVjlXDF41JMUP/oM1Oc4YNGdKnc3dVLw== - dependencies: - readable-stream "~1.0.15" - xtend "~2.1.1" - -level-ws@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-1.0.0.tgz#19a22d2d4ac57b18cc7c6ecc4bd23d899d8f603b" - integrity sha512-RXEfCmkd6WWFlArh3X8ONvQPm8jNpfA0s/36M4QzLqrLEIt1iJE9WBHLZ5vZJK6haMjJPJGJCQWfjMNnRcq/9Q== - dependencies: - inherits "^2.0.3" - readable-stream "^2.2.8" - xtend "^4.0.1" - -level@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/level/-/level-8.0.0.tgz#41b4c515dabe28212a3e881b61c161ffead14394" - integrity sha512-ypf0jjAk2BWI33yzEaaotpq7fkOPALKAgDBxggO6Q9HGX2MRXn0wbP1Jn/tJv1gtL867+YOjOB49WaUF3UoJNQ== - dependencies: - browser-level "^1.0.1" - classic-level "^1.2.0" - -levelup@3.1.1, levelup@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/levelup/-/levelup-3.1.1.tgz#c2c0b3be2b4dc316647c53b42e2f559e232d2189" - integrity sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg== - dependencies: - deferred-leveldown "~4.0.0" - level-errors "~2.0.0" - level-iterator-stream "~3.0.0" - xtend "~4.0.0" - -levelup@^1.2.1: - version "1.3.9" - resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.9.tgz#2dbcae845b2bb2b6bea84df334c475533bbd82ab" - integrity sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ== - dependencies: - deferred-leveldown "~1.2.1" - level-codec "~7.0.0" - level-errors "~1.0.3" - level-iterator-stream "~1.3.0" - prr "~1.0.1" - semver "~5.4.1" - xtend "~4.0.0" - -load-json-file@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - integrity sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A== - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - pinkie-promise "^2.0.0" - strip-bom "^2.0.0" - -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -lodash.assign@^4.0.3, lodash.assign@^4.0.6: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" - integrity sha512-hFuH8TY+Yji7Eja3mGiuAxBqLagejScbG8GbG0j6o9vzn0YL14My+ktnqtZgFTosKymC9/44wP6s7xyuLfnClw== - -lodash.camelcase@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" - integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== - -lodash.truncate@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" - integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== - -lodash@4.17.20: - version "4.17.20" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" - integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== - -lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -log-symbols@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" - integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== - dependencies: - chalk "^4.1.0" - is-unicode-supported "^0.1.0" - -looper@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/looper/-/looper-2.0.0.tgz#66cd0c774af3d4fedac53794f742db56da8f09ec" - integrity sha512-6DzMHJcjbQX/UPHc1rRCBfKlLwDkvuGZ715cIR36wSdYqWXFT35uLXq5P/2orl3tz+t+VOVPxw4yPinQlUDGDQ== - -looper@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/looper/-/looper-3.0.0.tgz#2efa54c3b1cbaba9b94aee2e5914b0be57fbb749" - integrity sha512-LJ9wplN/uSn72oJRsXTx+snxPet5c8XiZmOKCm906NVYu+ag6SB6vUcnJcWxgnl2NfbIyeobAn7Bwv6xRj2XJg== - -loose-envify@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -loupe@^2.3.1: - version "2.3.6" - resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53" - integrity sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA== - dependencies: - get-func-name "^2.0.0" - -lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== - -lowercase-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" - integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== - -lru-cache@5.1.1, lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - -lru-cache@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-3.2.0.tgz#71789b3b7f5399bec8565dda38aa30d2a097efee" - integrity sha512-91gyOKTc2k66UG6kHiH4h3S2eltcPwE1STVfMYC/NG+nZwf8IIuiamfmpGZjpbbxzSyEJaLC0tNSmhjlQUTJow== - dependencies: - pseudomap "^1.0.1" - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -lru_map@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" - integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== - -ltgt@^2.1.2, ltgt@~2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" - integrity sha512-AI2r85+4MquTw9ZYqabu4nMwy9Oftlfa/e/52t9IjtfG+mGBbTNdAoZ3RQKLHR6r0wQnwZnPIEh/Ya6XTWAKNA== - -ltgt@~2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.1.3.tgz#10851a06d9964b971178441c23c9e52698eece34" - integrity sha512-5VjHC5GsENtIi5rbJd+feEpDKhfr7j0odoUR2Uh978g+2p93nd5o34cTjQWohXsPsCZeqoDnIqEf88mPCe0Pfw== - -make-error@^1.1.1: - version "1.3.6" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" - integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== - -map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== - -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w== - dependencies: - object-visit "^1.0.0" - -match-all@^1.2.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/match-all/-/match-all-1.2.6.tgz#66d276ad6b49655551e63d3a6ee53e8be0566f8d" - integrity sha512-0EESkXiTkWzrQQntBu2uzKvLu6vVkUGz40nGPbSZuegcfE5UuSzNjLaIu76zJWuaT/2I3Z/8M06OlUOZLGwLlQ== - -mcl-wasm@^0.7.1: - version "0.7.9" - resolved "https://registry.yarnpkg.com/mcl-wasm/-/mcl-wasm-0.7.9.tgz#c1588ce90042a8700c3b60e40efb339fc07ab87f" - integrity sha512-iJIUcQWA88IJB/5L15GnJVnSQJmf/YaxxV6zRavv83HILHaJQb6y0iFyDMdDO0gN8X37tdxmAOrH/P8B6RB8sQ== - -md5.js@^1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== - -memdown@^1.0.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215" - integrity sha512-iVrGHZB8i4OQfM155xx8akvG9FIj+ht14DX5CQkCTG4EHzZ3d3sgckIf/Lm9ivZalEsFuEVnWv2B2WZvbrro2w== - dependencies: - abstract-leveldown "~2.7.1" - functional-red-black-tree "^1.0.1" - immediate "^3.2.3" - inherits "~2.0.1" - ltgt "~2.2.0" - safe-buffer "~5.1.1" - -memdown@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/memdown/-/memdown-3.0.0.tgz#93aca055d743b20efc37492e9e399784f2958309" - integrity sha512-tbV02LfZMWLcHcq4tw++NuqMO+FZX8tNJEiD2aNRm48ZZusVg5N8NART+dmBkepJVye986oixErf7jfXboMGMA== - dependencies: - abstract-leveldown "~5.0.0" - functional-red-black-tree "~1.0.1" - immediate "~3.2.3" - inherits "~2.0.1" - ltgt "~2.2.0" - safe-buffer "~5.1.1" - -memory-level@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/memory-level/-/memory-level-1.0.0.tgz#7323c3fd368f9af2f71c3cd76ba403a17ac41692" - integrity sha512-UXzwewuWeHBz5krr7EvehKcmLFNoXxGcvuYhC41tRnkrTbJohtS7kVn9akmgirtRygg+f7Yjsfi8Uu5SGSQ4Og== - dependencies: - abstract-level "^1.0.0" - functional-red-black-tree "^1.0.1" - module-error "^1.0.1" - -memorystream@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" - integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== - -merkle-patricia-tree@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-3.0.0.tgz#448d85415565df72febc33ca362b8b614f5a58f8" - integrity sha512-soRaMuNf/ILmw3KWbybaCjhx86EYeBbD8ph0edQCTed0JN/rxDt1EBN52Ajre3VyGo+91f8+/rfPIRQnnGMqmQ== - dependencies: - async "^2.6.1" - ethereumjs-util "^5.2.0" - level-mem "^3.0.1" - level-ws "^1.0.0" - readable-stream "^3.0.6" - rlp "^2.0.0" - semaphore ">=1.0.1" - -merkle-patricia-tree@^2.1.2, merkle-patricia-tree@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz#982ca1b5a0fde00eed2f6aeed1f9152860b8208a" - integrity sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g== - dependencies: - async "^1.4.2" - ethereumjs-util "^5.0.0" - level-ws "0.0.0" - levelup "^1.2.1" - memdown "^1.0.0" - readable-stream "^2.0.0" - rlp "^2.0.0" - semaphore ">=1.0.1" - -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== - -micromatch@^3.1.4: - version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" - -micromatch@^4.0.2: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== - dependencies: - braces "^3.0.2" - picomatch "^2.3.1" - -miller-rabin@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== - dependencies: - bn.js "^4.0.0" - brorand "^1.0.1" - -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - -mime@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -mimic-response@^1.0.0, mimic-response@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== - -mimic-response@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" - integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== - -min-document@^2.19.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" - integrity sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ== - dependencies: - dom-walk "^0.1.0" - -minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== - -minimatch@5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" - integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== - dependencies: - brace-expansion "^2.0.1" - -minimatch@^3.0.4, minimatch@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.2.0, minimist@^1.2.6, minimist@~1.2.6: - version "1.2.7" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" - integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== - -minipass@^2.6.0, minipass@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" - integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - -minizlib@^1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" - integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== - dependencies: - minipass "^2.9.0" - -mixin-deep@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" - integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - -mkdirp-promise@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" - integrity sha512-Hepn5kb1lJPtVW84RFT40YG1OddBNTOVUZR2bzQUHc+Z03en8/3uX0+060JDhcEzyO08HmipsN9DcnFMxhIL9w== - dependencies: - mkdirp "*" - -mkdirp@*, mkdirp@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - -mkdirp@^0.5.1, mkdirp@^0.5.5: - version "0.5.6" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" - integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== - dependencies: - minimist "^1.2.6" - -mnemonist@^0.38.0: - version "0.38.5" - resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.38.5.tgz#4adc7f4200491237fe0fa689ac0b86539685cade" - integrity sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg== - dependencies: - obliterator "^2.0.0" - -mocha@^10.0.0: - version "10.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8" - integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg== - dependencies: - ansi-colors "4.1.1" - browser-stdout "1.3.1" - chokidar "3.5.3" - debug "4.3.4" - diff "5.0.0" - escape-string-regexp "4.0.0" - find-up "5.0.0" - glob "7.2.0" - he "1.2.0" - js-yaml "4.1.0" - log-symbols "4.1.0" - minimatch "5.0.1" - ms "2.1.3" - nanoid "3.3.3" - serialize-javascript "6.0.0" - strip-json-comments "3.1.1" - supports-color "8.1.1" - workerpool "6.2.1" - yargs "16.2.0" - yargs-parser "20.2.4" - yargs-unparser "2.0.0" - -mock-fs@^4.1.0: - version "4.14.0" - resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.14.0.tgz#ce5124d2c601421255985e6e94da80a7357b1b18" - integrity sha512-qYvlv/exQ4+svI3UOvPUpLDF0OMX5euvUH0Ny4N5QyRyhNdgAgUrVH3iUINSzEPLvx0kbo/Bp28GJKIqvE7URw== - -module-error@^1.0.1, module-error@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/module-error/-/module-error-1.0.2.tgz#8d1a48897ca883f47a45816d4fb3e3c6ba404d86" - integrity sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA== - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@2.1.3, ms@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -multibase@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.7.0.tgz#1adfc1c50abe05eefeb5091ac0c2728d6b84581b" - integrity sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg== - dependencies: - base-x "^3.0.8" - buffer "^5.5.0" - -multibase@~0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.6.1.tgz#b76df6298536cc17b9f6a6db53ec88f85f8cc12b" - integrity sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw== - dependencies: - base-x "^3.0.8" - buffer "^5.5.0" - -multicodec@^0.5.5: - version "0.5.7" - resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-0.5.7.tgz#1fb3f9dd866a10a55d226e194abba2dcc1ee9ffd" - integrity sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA== - dependencies: - varint "^5.0.0" - -multicodec@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-1.0.4.tgz#46ac064657c40380c28367c90304d8ed175a714f" - integrity sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg== - dependencies: - buffer "^5.6.0" - varint "^5.0.0" - -multihashes@^0.4.15, multihashes@~0.4.15: - version "0.4.21" - resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-0.4.21.tgz#dc02d525579f334a7909ade8a122dabb58ccfcb5" - integrity sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw== - dependencies: - buffer "^5.5.0" - multibase "^0.7.0" - varint "^5.0.0" - -murmur-128@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/murmur-128/-/murmur-128-0.2.1.tgz#a9f6568781d2350ecb1bf80c14968cadbeaa4b4d" - integrity sha512-WseEgiRkI6aMFBbj8Cg9yBj/y+OdipwVC7zUo3W2W1JAJITwouUOtpqsmGSg67EQmwwSyod7hsVsWY5LsrfQVg== - dependencies: - encode-utf8 "^1.0.2" - fmix "^0.1.0" - imul "^1.0.0" - -nano-json-stream-parser@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" - integrity sha512-9MqxMH/BSJC7dnLsEMPyfN5Dvoo49IsPFYMcHw3Bcfc2kN0lpHRBSzlMSVx4HGyJ7s9B31CyBTVehWJoQ8Ctew== - -nanoid@3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" - integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== - -nanomatch@^1.2.9: - version "1.2.13" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -napi-macros@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.0.0.tgz#2b6bae421e7b96eb687aa6c77a7858640670001b" - integrity sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg== - -negotiator@0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" - integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== - -next-tick@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" - integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== - -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - -node-addon-api@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" - integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== - -node-fetch@^2.6.1, node-fetch@^2.6.7: - version "2.6.7" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== - dependencies: - whatwg-url "^5.0.0" - -node-fetch@~1.7.1: - version "1.7.3" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" - integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== - dependencies: - encoding "^0.1.11" - is-stream "^1.0.1" - -node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" - integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== - -nofilter@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/nofilter/-/nofilter-3.1.0.tgz#c757ba68801d41ff930ba2ec55bab52ca184aa66" - integrity sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g== - -normalize-package-data@^2.3.2: - version "2.5.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== - dependencies: - hosted-git-info "^2.1.4" - resolve "^1.10.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -normalize-url@^4.1.0: - version "4.5.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" - integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== - -normalize-url@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" - integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== - -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ== - -number-to-bn@1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" - integrity sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig== - dependencies: - bn.js "4.11.6" - strip-hex-prefix "1.0.0" - -oauth-sign@~0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== - -object-assign@^4, object-assign@^4.0.0, object-assign@^4.1.0, object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== - -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ== - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - -object-inspect@^1.12.2, object-inspect@^1.9.0, object-inspect@~1.12.2: - version "1.12.2" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" - integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== - -object-is@^1.0.1: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" - integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object-keys@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" - integrity sha512-ncrLw+X55z7bkl5PnUvHwFK9FcGuFYo9gtjws2XtSzL+aZ8tm830P60WJ0dSmFVaSalWieW5MD7kEdnXda9yJw== - -object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA== - dependencies: - isobject "^3.0.0" - -object.assign@^4.1.4: - version "4.1.4" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" - integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - has-symbols "^1.0.3" - object-keys "^1.1.1" - -object.getownpropertydescriptors@^2.1.1: - version "2.1.5" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.5.tgz#db5a9002489b64eef903df81d6623c07e5b4b4d3" - integrity sha512-yDNzckpM6ntyQiGTik1fKV1DcVDRS+w8bvpWNCBanvH5LfRX9O8WTHqQzG4RZwRAM4I0oU7TV11Lj5v0g20ibw== - dependencies: - array.prototype.reduce "^1.0.5" - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - -object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ== - dependencies: - isobject "^3.0.1" - -obliterator@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.4.tgz#fa650e019b2d075d745e44f1effeb13a2adbe816" - integrity sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ== - -oboe@2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.4.tgz#20c88cdb0c15371bb04119257d4fdd34b0aa49f6" - integrity sha512-ymBJ4xSC6GBXLT9Y7lirj+xbqBLa+jADGJldGEYG7u8sZbS9GyG+u1Xk9c5cbriKwSpCg41qUhPjvU5xOpvIyQ== - dependencies: - http-https "^1.0.0" - -on-finished@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" - integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== - dependencies: - ee-first "1.1.1" - -once@^1.3.0, once@^1.3.1, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -open@^7.4.2: - version "7.4.2" - resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" - integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== - dependencies: - is-docker "^2.0.0" - is-wsl "^2.1.1" - -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ== - -os-locale@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" - integrity sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g== - dependencies: - lcid "^1.0.0" - -os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== - -p-cancelable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" - integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== - -p-cancelable@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf" - integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg== - -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== - dependencies: - p-try "^1.0.0" - -p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== - dependencies: - p-limit "^1.1.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -p-map@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" - integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== - dependencies: - aggregate-error "^3.0.0" - -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== - -parse-asn1@^5.0.0, parse-asn1@^5.1.5: - version "5.1.6" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" - integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== - dependencies: - asn1.js "^5.2.0" - browserify-aes "^1.0.0" - evp_bytestokey "^1.0.0" - pbkdf2 "^3.0.3" - safe-buffer "^5.1.1" - -parse-headers@^2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.5.tgz#069793f9356a54008571eb7f9761153e6c770da9" - integrity sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA== - -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ== - dependencies: - error-ex "^1.2.0" - -parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw== - -patch-package@6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.2.2.tgz#71d170d650c65c26556f0d0fbbb48d92b6cc5f39" - integrity sha512-YqScVYkVcClUY0v8fF0kWOjDYopzIM8e3bj/RU1DPeEF14+dCGm6UeOYm4jvCyxqIEQ5/eJzmbWfDWnUleFNMg== - dependencies: - "@yarnpkg/lockfile" "^1.1.0" - chalk "^2.4.2" - cross-spawn "^6.0.5" - find-yarn-workspace-root "^1.2.1" - fs-extra "^7.0.1" - is-ci "^2.0.0" - klaw-sync "^6.0.0" - minimist "^1.2.0" - rimraf "^2.6.3" - semver "^5.6.0" - slash "^2.0.0" - tmp "^0.0.33" - -patch-package@^6.2.2: - version "6.5.1" - resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.5.1.tgz#3e5d00c16997e6160291fee06a521c42ac99b621" - integrity sha512-I/4Zsalfhc6bphmJTlrLoOcAF87jcxko4q0qsv4bGcurbr8IskEOtdnt9iCmsQVGL1B+iUhSQqweyTLJfCF9rA== - dependencies: - "@yarnpkg/lockfile" "^1.1.0" - chalk "^4.1.2" - cross-spawn "^6.0.5" - find-yarn-workspace-root "^2.0.0" - fs-extra "^9.0.0" - is-ci "^2.0.0" - klaw-sync "^6.0.0" - minimist "^1.2.6" - open "^7.4.2" - rimraf "^2.6.3" - semver "^5.6.0" - slash "^2.0.0" - tmp "^0.0.33" - yaml "^1.10.2" - -path-browserify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" - integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== - -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - integrity sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ== - dependencies: - pinkie-promise "^2.0.0" - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== - -path-parse@^1.0.6, path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-starts-with@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/path-starts-with/-/path-starts-with-2.0.0.tgz#ffd6d51926cd497022b44d392196033d5451892f" - integrity sha512-3UHTHbJz5+NLkPafFR+2ycJOjoc4WV2e9qCZCnm71zHiWaFrm1XniLVTkZXvaRgxr1xFh9JsTdicpH2yM03nLA== - -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== - -path-type@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - integrity sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg== - dependencies: - graceful-fs "^4.1.2" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -pathval@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" - integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== - -pbkdf2@^3.0.17, pbkdf2@^3.0.3, pbkdf2@^3.0.9: - version "3.1.2" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" - integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== - dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== - -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -pify@^2.0.0, pify@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw== - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg== - -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg== - -postinstall-postinstall@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz#4f7f77441ef539d1512c40bd04c71b06a4704ca3" - integrity sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ== - -precond@0.2: - version "0.2.3" - resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" - integrity sha512-QCYG84SgGyGzqJ/vlMsxeXd/pgL/I94ixdNFyh1PusWmTCyVfPJjZ1K1jvHtsbfnXQs2TSkEP2fR7QiMZAnKFQ== - -prepend-http@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" - integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA== - -prettier-plugin-solidity@^1.0.0-beta.19: - version "1.1.1" - resolved "https://registry.yarnpkg.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.1.1.tgz#4d3375b85f97812ffcbe48d5a8b3fe914d69c91f" - integrity sha512-uD24KO26tAHF+zMN2nt1OUzfknzza5AgxjogQQrMLZc7j8xiQrDoNWNeOlfFC0YLTwo12CLD10b9niLyP6AqXg== - dependencies: - "@solidity-parser/parser" "^0.14.5" - semver "^7.3.8" - solidity-comments-extractor "^0.0.7" - -prettier@^2.1.2, prettier@^2.3.1, prettier@^2.6.2: - version "2.8.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.1.tgz#4e1fd11c34e2421bc1da9aea9bd8127cd0a35efc" - integrity sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg== - -private@^0.1.6, private@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== - -promise-to-callback@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/promise-to-callback/-/promise-to-callback-1.0.0.tgz#5d2a749010bfb67d963598fcd3960746a68feef7" - integrity sha512-uhMIZmKM5ZteDMfLgJnoSq9GCwsNKrYau73Awf1jIy6/eUcuuZ3P+CD9zUv0kJsIUbU+x6uLNIhXhLHDs1pNPA== - dependencies: - is-fn "^1.0.0" - set-immediate-shim "^1.0.1" - -proxy-addr@~2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" - integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== - dependencies: - forwarded "0.2.0" - ipaddr.js "1.9.1" - -prr@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" - integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw== - -pseudomap@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== - -psl@^1.1.28: - version "1.9.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" - integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== - -public-encrypt@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== - dependencies: - bn.js "^4.1.0" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - parse-asn1 "^5.0.0" - randombytes "^2.0.1" - safe-buffer "^5.1.2" - -pull-cat@^1.1.9: - version "1.1.11" - resolved "https://registry.yarnpkg.com/pull-cat/-/pull-cat-1.1.11.tgz#b642dd1255da376a706b6db4fa962f5fdb74c31b" - integrity sha512-i3w+xZ3DCtTVz8S62hBOuNLRHqVDsHMNZmgrZsjPnsxXUgbWtXEee84lo1XswE7W2a3WHyqsNuDJTjVLAQR8xg== - -pull-defer@^0.2.2: - version "0.2.3" - resolved "https://registry.yarnpkg.com/pull-defer/-/pull-defer-0.2.3.tgz#4ee09c6d9e227bede9938db80391c3dac489d113" - integrity sha512-/An3KE7mVjZCqNhZsr22k1Tx8MACnUnHZZNPSJ0S62td8JtYr/AiRG42Vz7Syu31SoTLUzVIe61jtT/pNdjVYA== - -pull-level@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pull-level/-/pull-level-2.0.4.tgz#4822e61757c10bdcc7cf4a03af04c92734c9afac" - integrity sha512-fW6pljDeUThpq5KXwKbRG3X7Ogk3vc75d5OQU/TvXXui65ykm+Bn+fiktg+MOx2jJ85cd+sheufPL+rw9QSVZg== - dependencies: - level-post "^1.0.7" - pull-cat "^1.1.9" - pull-live "^1.0.1" - pull-pushable "^2.0.0" - pull-stream "^3.4.0" - pull-window "^2.1.4" - stream-to-pull-stream "^1.7.1" - -pull-live@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/pull-live/-/pull-live-1.0.1.tgz#a4ecee01e330155e9124bbbcf4761f21b38f51f5" - integrity sha512-tkNz1QT5gId8aPhV5+dmwoIiA1nmfDOzJDlOOUpU5DNusj6neNd3EePybJ5+sITr2FwyCs/FVpx74YMCfc8YeA== - dependencies: - pull-cat "^1.1.9" - pull-stream "^3.4.0" - -pull-pushable@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/pull-pushable/-/pull-pushable-2.2.0.tgz#5f2f3aed47ad86919f01b12a2e99d6f1bd776581" - integrity sha512-M7dp95enQ2kaHvfCt2+DJfyzgCSpWVR2h2kWYnVsW6ZpxQBx5wOu0QWOvQPVoPnBLUZYitYP2y7HyHkLQNeGXg== - -pull-stream@^3.2.3, pull-stream@^3.4.0, pull-stream@^3.6.8: - version "3.7.0" - resolved "https://registry.yarnpkg.com/pull-stream/-/pull-stream-3.7.0.tgz#85de0e44ff38a4d2ad08cc43fc458e1922f9bf0b" - integrity sha512-Eco+/R004UaCK2qEDE8vGklcTG2OeZSVm1kTUQNrykEjDwcFXDZhygFDsW49DbXyJMEhHeRL3z5cRVqPAhXlIw== - -pull-window@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/pull-window/-/pull-window-2.1.4.tgz#fc3b86feebd1920c7ae297691e23f705f88552f0" - integrity sha512-cbDzN76BMlcGG46OImrgpkMf/VkCnupj8JhsrpBw3aWBM9ye345aYnqitmZCgauBkc0HbbRRn9hCnsa3k2FNUg== - dependencies: - looper "^2.0.0" - -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw== - -punycode@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" - integrity sha512-Yxz2kRwT90aPiWEMHVYnEf4+rhwF1tBmmZ4KepCP+Wkium9JxtWnUm1nqGwpiAHr/tnTSeHqr3wb++jgSkXjhA== - -punycode@^2.1.0, punycode@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -qs@6.11.0, qs@^6.7.0, qs@^6.9.4: - version "6.11.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" - integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== - dependencies: - side-channel "^1.0.4" - -qs@~6.5.2: - version "6.5.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" - integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== - -query-string@^5.0.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" - integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== - dependencies: - decode-uri-component "^0.2.0" - object-assign "^4.1.0" - strict-uri-encode "^1.0.0" - -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g== - -queue-microtask@^1.2.2, queue-microtask@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -quick-lru@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" - integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== - -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.0.6, randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -randomfill@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== - dependencies: - randombytes "^2.0.5" - safe-buffer "^5.1.0" - -range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@2.5.1, raw-body@^2.4.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" - integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== - dependencies: - bytes "3.1.2" - http-errors "2.0.0" - iconv-lite "0.4.24" - unpipe "1.0.0" - -read-pkg-up@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - integrity sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A== - dependencies: - find-up "^1.0.0" - read-pkg "^1.0.0" - -read-pkg@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - integrity sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ== - dependencies: - load-json-file "^1.0.0" - normalize-package-data "^2.3.2" - path-type "^1.0.0" - -readable-stream@^1.0.33: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.2.2, readable-stream@^2.2.8, readable-stream@^2.2.9, readable-stream@^2.3.6, readable-stream@~2.3.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.0.6, readable-stream@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readable-stream@~1.0.15: - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - integrity sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -reduce-flatten@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" - integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w== - -regenerate@^1.2.1: - version "1.4.2" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" - integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== - -regenerator-runtime@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== - -regenerator-transform@^0.10.0: - version "0.10.1" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" - integrity sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q== - dependencies: - babel-runtime "^6.18.0" - babel-types "^6.19.0" - private "^0.1.6" - -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - -regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" - integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - functions-have-names "^1.2.2" - -regexpu-core@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" - integrity sha512-tJ9+S4oKjxY8IZ9jmjnp/mtytu1u3iyIQAfmI51IKWH6bFf7XR1ybtaO6j7INhZKXOTYADk7V5qxaqLkmNxiZQ== - dependencies: - regenerate "^1.2.1" - regjsgen "^0.2.0" - regjsparser "^0.1.4" - -regjsgen@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" - integrity sha512-x+Y3yA24uF68m5GA+tBjbGYo64xXVJpbToBaWCoSNSc1hdk6dfctaRWrNFTVJZIIhL5GxW8zwjoixbnifnK59g== - -regjsparser@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" - integrity sha512-jlQ9gYLfk2p3V5Ag5fYhA7fv7OHzd1KUH0PRP46xc3TgwjwgROIW572AfYg/X9kaNq/LJnu6oJcFRXlIrGoTRw== - dependencies: - jsesc "~0.5.0" - -repeat-element@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" - integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== - -repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== - -repeating@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - integrity sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A== - dependencies: - is-finite "^1.0.0" - -request@^2.79.0, request@^2.85.0: - version "2.88.2" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" - integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.3" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.5.0" - tunnel-agent "^0.6.0" - uuid "^3.3.2" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -require-from-string@^1.1.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" - integrity sha512-H7AkJWMobeskkttHyhTVtS0fxpFLjxhbfMa6Bk3wimP7sdPRGL3EyCg3sAQenFfAe+xQ+oAc85Nmtvq0ROM83Q== - -require-from-string@^2.0.0, require-from-string@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== - -require-main-filename@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - integrity sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug== - -resolve-alpn@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" - integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== - -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== - -resolve@1.17.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" - integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== - dependencies: - path-parse "^1.0.6" - -resolve@^1.10.0, resolve@^1.8.1, resolve@~1.22.1: - version "1.22.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" - integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== - dependencies: - is-core-module "^2.9.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -responselike@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" - integrity sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ== - dependencies: - lowercase-keys "^1.0.0" - -responselike@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.1.tgz#9a0bc8fdc252f3fb1cca68b016591059ba1422bc" - integrity sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw== - dependencies: - lowercase-keys "^2.0.0" - -resumer@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" - integrity sha512-Fn9X8rX8yYF4m81rZCK/5VmrmsSbqS/i3rDLl6ZZHAXgC2nTAx3dhwG8q8odP/RmdLa2YrybDJaAMg+X1ajY3w== - dependencies: - through "~2.3.4" - -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== - -rimraf@^2.2.8, rimraf@^2.6.2, rimraf@^2.6.3: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - -ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - -rlp@^2.0.0, rlp@^2.2.1, rlp@^2.2.2, rlp@^2.2.3, rlp@^2.2.4: - version "2.2.7" - resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" - integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== - dependencies: - bn.js "^5.2.0" - -run-parallel-limit@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz#be80e936f5768623a38a963262d6bef8ff11e7ba" - integrity sha512-jJA7irRNM91jaKc3Hcl1npHsFLOXOoTkPCUL1JEa1R82O2miplXXRaGdjW/KM/98YQWDhJLiSs793CnXfblJUw== - dependencies: - queue-microtask "^1.2.2" - -rustbn.js@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" - integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== - -safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-event-emitter@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz#5b692ef22329ed8f69fdce607e50ca734f6f20af" - integrity sha512-e1wFe99A91XYYxoQbcq2ZJUWurxEyP8vfz7A7vuUe1s95q8r5ebraVaA1BukYJcpM6V16ugWoD9vngi8Ccu5fg== - dependencies: - events "^3.0.0" - -safe-regex-test@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" - integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.3" - is-regex "^1.1.4" - -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg== - dependencies: - ret "~0.1.10" - -"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -scrypt-js@3.0.1, scrypt-js@^3.0.0, scrypt-js@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" - integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== - -scryptsy@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" - integrity sha512-aldIRgMozSJ/Gl6K6qmJZysRP82lz83Wb42vl4PWN8SaLFHIaOzLPc9nUUW2jQN88CuGm5q5HefJ9jZ3nWSmTw== - dependencies: - pbkdf2 "^3.0.3" - -secp256k1@^4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" - integrity sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA== - dependencies: - elliptic "^6.5.4" - node-addon-api "^2.0.0" - node-gyp-build "^4.2.0" - -seedrandom@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.1.tgz#eb3dde015bcf55df05a233514e5df44ef9dce083" - integrity sha512-1/02Y/rUeU1CJBAGLebiC5Lbo5FnB22gQbIFFYTLkwvp1xdABZJH1sn4ZT1MzXmPpzv+Rf/Lu2NcsLJiK4rcDg== - -semaphore@>=1.0.1, semaphore@^1.0.3, semaphore@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" - integrity sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA== - -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -semver@^7.3.8: - version "7.3.8" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" - integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== - dependencies: - lru-cache "^6.0.0" - -semver@~5.4.1: - version "5.4.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" - integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== - -send@0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" - integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== - dependencies: - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "2.0.0" - mime "1.6.0" - ms "2.1.3" - on-finished "2.4.1" - range-parser "~1.2.1" - statuses "2.0.1" - -serialize-javascript@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" - integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== - dependencies: - randombytes "^2.1.0" - -serve-static@1.15.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" - integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.18.0" - -servify@^0.1.12: - version "0.1.12" - resolved "https://registry.yarnpkg.com/servify/-/servify-0.1.12.tgz#142ab7bee1f1d033b66d0707086085b17c06db95" - integrity sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw== - dependencies: - body-parser "^1.16.0" - cors "^2.8.1" - express "^4.14.0" - request "^2.79.0" - xhr "^2.3.3" - -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== - -set-immediate-shim@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" - integrity sha512-Li5AOqrZWCVA2n5kryzEmqai6bKSIvpz5oUJHPVj6+dsbD3X1ixtsY5tEnsaNpH3pFAHmG8eIHUrtEtohrg+UQ== - -set-value@^2.0.0, set-value@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" - integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - -setimmediate@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== - -setprototypeof@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== - -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== - dependencies: - shebang-regex "^1.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== - -side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== - dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" - -simple-concat@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" - integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== - -simple-get@^2.7.0: - version "2.8.2" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.2.tgz#5708fb0919d440657326cd5fe7d2599d07705019" - integrity sha512-Ijd/rV5o+mSBBs4F/x9oDPtTx9Zb6X9brmnXvMW4J7IR15ngi9q5xxqWBKU744jTZiaXtxaPL7uHG6vtN8kUkw== - dependencies: - decompress-response "^3.3.0" - once "^1.3.1" - simple-concat "^1.0.0" - -slash@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - integrity sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg== - -slash@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" - integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== - -slice-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" - integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" - -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - -solc@0.7.3: - version "0.7.3" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a" - integrity sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA== - dependencies: - command-exists "^1.2.8" - commander "3.0.2" - follow-redirects "^1.12.1" - fs-extra "^0.30.0" - js-sha3 "0.8.0" - memorystream "^0.3.1" - require-from-string "^2.0.0" - semver "^5.5.0" - tmp "0.0.33" - -solc@^0.4.20: - version "0.4.26" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.26.tgz#5390a62a99f40806b86258c737c1cf653cc35cb5" - integrity sha512-o+c6FpkiHd+HPjmjEVpQgH7fqZ14tJpXhho+/bQXlXbliLIS/xjXb42Vxh+qQY1WCSTMQ0+a5vR9vi0MfhU6mA== - dependencies: - fs-extra "^0.30.0" - memorystream "^0.3.1" - require-from-string "^1.1.0" - semver "^5.3.0" - yargs "^4.7.1" - -solc@^0.6.3: - version "0.6.12" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.6.12.tgz#48ac854e0c729361b22a7483645077f58cba080e" - integrity sha512-Lm0Ql2G9Qc7yPP2Ba+WNmzw2jwsrd3u4PobHYlSOxaut3TtUbj9+5ZrT6f4DUpNPEoBaFUOEg9Op9C0mk7ge9g== - dependencies: - command-exists "^1.2.8" - commander "3.0.2" - fs-extra "^0.30.0" - js-sha3 "0.8.0" - memorystream "^0.3.1" - require-from-string "^2.0.0" - semver "^5.5.0" - tmp "0.0.33" - -solidity-comments-extractor@^0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz#99d8f1361438f84019795d928b931f4e5c39ca19" - integrity sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw== - -source-map-resolve@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" - integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== - dependencies: - atob "^2.1.2" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - -source-map-support@0.5.12: - version "0.5.12" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" - integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map-support@^0.4.15: - version "0.4.18" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" - integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== - dependencies: - source-map "^0.5.6" - -source-map-support@^0.5.13: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map-url@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" - integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== - -source-map@^0.5.6, source-map@^0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== - -source-map@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -spdx-correct@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" - integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" - integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== - -spdx-expression-parse@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" - integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.12" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz#69077835abe2710b65f03969898b6637b505a779" - integrity sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA== - -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== - dependencies: - extend-shallow "^3.0.0" - -sshpk@^1.7.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" - integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - bcrypt-pbkdf "^1.0.0" - dashdash "^1.12.0" - ecc-jsbn "~0.1.1" - getpass "^0.1.1" - jsbn "~0.1.0" - safer-buffer "^2.0.2" - tweetnacl "~0.14.0" - -stacktrace-parser@^0.1.10: - version "0.1.10" - resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" - integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== - dependencies: - type-fest "^0.7.1" - -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g== - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - -statuses@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" - integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== - -stream-to-pull-stream@^1.7.1: - version "1.7.3" - resolved "https://registry.yarnpkg.com/stream-to-pull-stream/-/stream-to-pull-stream-1.7.3.tgz#4161aa2d2eb9964de60bfa1af7feaf917e874ece" - integrity sha512-6sNyqJpr5dIOQdgNy/xcDWwDuzAsAwVzhzrWlAPAQ7Lkjx/rv0wgvxEyKwTq6FmNd5rjTrELt/CLmaSw7crMGg== - dependencies: - looper "^3.0.0" - pull-stream "^3.2.3" - -streamsearch@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" - integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== - -strict-uri-encode@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" - integrity sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ== - -string-format@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" - integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== - -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw== - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string.prototype.trim@~1.2.6: - version "1.2.7" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" - integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - -string.prototype.trimend@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" - integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - -string.prototype.trimstart@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" - integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g== - dependencies: - is-utf8 "^0.2.0" - -strip-hex-prefix@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" - integrity sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A== - dependencies: - is-hex-prefixed "1.0.0" - -strip-json-comments@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -supports-color@8.1.1: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g== - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -swarm-js@^0.1.40: - version "0.1.42" - resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.42.tgz#497995c62df6696f6e22372f457120e43e727979" - integrity sha512-BV7c/dVlA3R6ya1lMlSSNPLYrntt0LUq4YMgy3iwpCIc6rZnS5W2wUoctarZ5pXlpKtxDDf9hNziEkcfrxdhqQ== - dependencies: - bluebird "^3.5.0" - buffer "^5.0.5" - eth-lib "^0.1.26" - fs-extra "^4.0.2" - got "^11.8.5" - mime-types "^2.1.16" - mkdirp-promise "^5.0.1" - mock-fs "^4.1.0" - setimmediate "^1.0.5" - tar "^4.0.2" - xhr-request "^1.0.1" - -table-layout@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.2.tgz#c4038a1853b0136d63365a734b6931cf4fad4a04" - integrity sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A== - dependencies: - array-back "^4.0.1" - deep-extend "~0.6.0" - typical "^5.2.0" - wordwrapjs "^4.0.0" - -table@^6.8.0: - version "6.8.1" - resolved "https://registry.yarnpkg.com/table/-/table-6.8.1.tgz#ea2b71359fe03b017a5fbc296204471158080bdf" - integrity sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA== - dependencies: - ajv "^8.0.1" - lodash.truncate "^4.4.2" - slice-ansi "^4.0.0" - string-width "^4.2.3" - strip-ansi "^6.0.1" - -tape@^4.6.3: - version "4.16.1" - resolved "https://registry.yarnpkg.com/tape/-/tape-4.16.1.tgz#8d511b3a0be1a30441885972047c1dac822fd9be" - integrity sha512-U4DWOikL5gBYUrlzx+J0oaRedm2vKLFbtA/+BRAXboGWpXO7bMP8ddxlq3Cse2bvXFQ0jZMOj6kk3546mvCdFg== - dependencies: - call-bind "~1.0.2" - deep-equal "~1.1.1" - defined "~1.0.0" - dotignore "~0.1.2" - for-each "~0.3.3" - glob "~7.2.3" - has "~1.0.3" - inherits "~2.0.4" - is-regex "~1.1.4" - minimist "~1.2.6" - object-inspect "~1.12.2" - resolve "~1.22.1" - resumer "~0.0.0" - string.prototype.trim "~1.2.6" - through "~2.3.8" - -tar@^4.0.2: - version "4.4.19" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" - integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA== - dependencies: - chownr "^1.1.4" - fs-minipass "^1.2.7" - minipass "^2.9.0" - minizlib "^1.3.3" - mkdirp "^0.5.5" - safe-buffer "^5.2.1" - yallist "^3.1.1" - -test-value@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/test-value/-/test-value-2.1.0.tgz#11da6ff670f3471a73b625ca4f3fdcf7bb748291" - integrity sha512-+1epbAxtKeXttkGFMTX9H42oqzOTufR1ceCF+GYA5aOmvaPq9wd4PUS8329fn2RRLGNeUkgRLnVpycjx8DsO2w== - dependencies: - array-back "^1.0.3" - typical "^2.6.0" - -testrpc@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/testrpc/-/testrpc-0.0.1.tgz#83e2195b1f5873aec7be1af8cbe6dcf39edb7aed" - integrity sha512-afH1hO+SQ/VPlmaLUFj2636QMeDvPCeQMc/9RBMW0IfjNe9gFD9Ra3ShqYkB7py0do1ZcCna/9acHyzTJ+GcNA== - -through2@^2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" - integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== - dependencies: - readable-stream "~2.3.6" - xtend "~4.0.1" - -through@~2.3.4, through@~2.3.8: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== - -timed-out@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" - integrity sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA== - -tmp@0.0.33, tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - -tmp@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877" - integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw== - dependencies: - rimraf "^2.6.3" - -to-fast-properties@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - integrity sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og== - -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg== - dependencies: - kind-of "^3.0.2" - -to-readable-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" - integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== - -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg== - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - -toidentifier@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" - integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== - -tough-cookie@~2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" - integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== - dependencies: - psl "^1.1.28" - punycode "^2.1.1" - -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== - -trim-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - integrity sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw== - -ts-command-line-args@^2.2.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.3.1.tgz#b6188e42efc6cf7a8898e438a873fbb15505ddd6" - integrity sha512-FR3y7pLl/fuUNSmnPhfLArGqRrpojQgIEEOVzYx9DhTmfIN7C9RWSfpkJEF4J+Gk7aVx5pak8I7vWZsaN4N84g== - dependencies: - chalk "^4.1.0" - command-line-args "^5.1.1" - command-line-usage "^6.1.0" - string-format "^2.0.0" - -ts-essentials@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-1.0.4.tgz#ce3b5dade5f5d97cf69889c11bf7d2da8555b15a" - integrity sha512-q3N1xS4vZpRouhYHDPwO0bDW3EZ6SK9CrrDHxi/D6BPReSjpVgWIOpLS2o0gSBZm+7q/wyKp6RVM1AeeW7uyfQ== - -ts-essentials@^6.0.3: - version "6.0.7" - resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-6.0.7.tgz#5f4880911b7581a873783740ce8b94da163d18a6" - integrity sha512-2E4HIIj4tQJlIHuATRHayv0EfMGK3ris/GRk1E3CFnsZzeNV+hUmelbaTZHLtXaZppM5oLhHRtO04gINC4Jusw== - -ts-essentials@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-7.0.3.tgz#686fd155a02133eedcc5362dc8b5056cde3e5a38" - integrity sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ== - -ts-generator@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ts-generator/-/ts-generator-0.1.1.tgz#af46f2fb88a6db1f9785977e9590e7bcd79220ab" - integrity sha512-N+ahhZxTLYu1HNTQetwWcx3so8hcYbkKBHTr4b4/YgObFTIKkOSSsaa+nal12w8mfrJAyzJfETXawbNjSfP2gQ== - dependencies: - "@types/mkdirp" "^0.5.2" - "@types/prettier" "^2.1.1" - "@types/resolve" "^0.0.8" - chalk "^2.4.1" - glob "^7.1.2" - mkdirp "^0.5.1" - prettier "^2.1.2" - resolve "^1.8.1" - ts-essentials "^1.0.0" - -ts-node@^10.7.0: - version "10.9.1" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" - integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== - dependencies: - "@cspotcode/source-map-support" "^0.8.0" - "@tsconfig/node10" "^1.0.7" - "@tsconfig/node12" "^1.0.7" - "@tsconfig/node14" "^1.0.0" - "@tsconfig/node16" "^1.0.2" - acorn "^8.4.1" - acorn-walk "^8.1.1" - arg "^4.1.0" - create-require "^1.1.0" - diff "^4.0.1" - make-error "^1.1.1" - v8-compile-cache-lib "^3.0.1" - yn "3.1.1" - -tslib@^1.9.3: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tsort@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" - integrity sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw== - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== - dependencies: - safe-buffer "^5.0.1" - -tweetnacl-util@^0.15.0, tweetnacl-util@^0.15.1: - version "0.15.1" - resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" - integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== - -tweetnacl@^1.0.0, tweetnacl@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" - integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== - -type-detect@^4.0.0, type-detect@^4.0.5: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== - -type-fest@^0.21.3: - version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" - integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== - -type-fest@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" - integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== - -type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - -type@^1.0.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" - integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== - -type@^2.7.2: - version "2.7.2" - resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" - integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== - -typechain@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/typechain/-/typechain-3.0.0.tgz#d5a47700831f238e43f7429b987b4bb54849b92e" - integrity sha512-ft4KVmiN3zH4JUFu2WJBrwfHeDf772Tt2d8bssDTo/YcckKW2D+OwFrHXRC6hJvO3mHjFQTihoMV6fJOi0Hngg== - dependencies: - command-line-args "^4.0.7" - debug "^4.1.1" - fs-extra "^7.0.0" - js-sha3 "^0.8.0" - lodash "^4.17.15" - ts-essentials "^6.0.3" - ts-generator "^0.1.1" - -typechain@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/typechain/-/typechain-8.1.1.tgz#9c2e8012c2c4c586536fc18402dcd7034c4ff0bd" - integrity sha512-uF/sUvnXTOVF2FHKhQYnxHk4su4JjZR8vr4mA2mBaRwHTbwh0jIlqARz9XJr1tA0l7afJGvEa1dTSi4zt039LQ== - dependencies: - "@types/prettier" "^2.1.1" - debug "^4.3.1" - fs-extra "^7.0.0" - glob "7.1.7" - js-sha3 "^0.8.0" - lodash "^4.17.15" - mkdirp "^1.0.4" - prettier "^2.3.1" - ts-command-line-args "^2.2.0" - ts-essentials "^7.0.1" - -typed-array-length@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" - integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== - dependencies: - call-bind "^1.0.2" - for-each "^0.3.3" - is-typed-array "^1.1.9" - -typedarray-to-buffer@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== - dependencies: - is-typedarray "^1.0.0" - -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== - -typescript@^4.6.4: - version "4.9.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.4.tgz#a2a3d2756c079abda241d75f149df9d561091e78" - integrity sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg== - -typewise-core@^1.2, typewise-core@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/typewise-core/-/typewise-core-1.2.0.tgz#97eb91805c7f55d2f941748fa50d315d991ef195" - integrity sha512-2SCC/WLzj2SbUwzFOzqMCkz5amXLlxtJqDKTICqg30x+2DZxcfZN2MvQZmGfXWKNWaKK9pBPsvkcwv8bF/gxKg== - -typewise@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/typewise/-/typewise-1.0.3.tgz#1067936540af97937cc5dcf9922486e9fa284651" - integrity sha512-aXofE06xGhaQSPzt8hlTY+/YWQhm9P0jYUp1f2XtmW/3Bk0qzXcyFWAtPoo2uTGQj1ZwbDuSyuxicq+aDo8lCQ== - dependencies: - typewise-core "^1.2.0" - -typewiselite@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/typewiselite/-/typewiselite-1.0.0.tgz#c8882fa1bb1092c06005a97f34ef5c8508e3664e" - integrity sha512-J9alhjVHupW3Wfz6qFRGgQw0N3gr8hOkw6zm7FZ6UR1Cse/oD9/JVok7DNE9TT9IbciDHX2Ex9+ksE6cRmtymw== - -typical@^2.6.0, typical@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/typical/-/typical-2.6.1.tgz#5c080e5d661cbbe38259d2e70a3c7253e873881d" - integrity sha512-ofhi8kjIje6npGozTip9Fr8iecmYfEbS06i0JnIg+rh51KakryWF4+jX8lLKZVhy6N+ID45WYSFCxPOdTWCzNg== - -typical@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" - integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== - -typical@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066" - integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== - -ultron@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" - integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== - -unbox-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" - integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== - dependencies: - call-bind "^1.0.2" - has-bigints "^1.0.2" - has-symbols "^1.0.3" - which-boxed-primitive "^1.0.2" - -underscore@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" - integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== - -undici@^5.4.0: - version "5.14.0" - resolved "https://registry.yarnpkg.com/undici/-/undici-5.14.0.tgz#1169d0cdee06a4ffdd30810f6228d57998884d00" - integrity sha512-yJlHYw6yXPPsuOH0x2Ib1Km61vu4hLiRRQoafs+WUgX1vO64vgnxiCEN9dpIrhZyHFsai3F0AEj4P9zy19enEQ== - dependencies: - busboy "^1.6.0" - -union-value@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" - integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^2.0.1" - -universalify@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== - -universalify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" - integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== - -unorm@^1.3.3: - version "1.6.0" - resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.6.0.tgz#029b289661fba714f1a9af439eb51d9b16c205af" - integrity sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA== - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== - -unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ== - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg== - -url-parse-lax@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" - integrity sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ== - dependencies: - prepend-http "^2.0.0" - -url-set-query@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" - integrity sha512-3AChu4NiXquPfeckE5R5cGdiHCMWJx1dwCWOmWIL4KHAziJNOFIYJlpGFeKDvwLPHovZRCxK3cYlwzqI9Vp+Gg== - -url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ== - dependencies: - punycode "1.3.2" - querystring "0.2.0" - -use@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== - -utf-8-validate@^5.0.2: - version "5.0.10" - resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" - integrity sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ== - dependencies: - node-gyp-build "^4.3.0" - -utf8@3.0.0, utf8@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" - integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== - -util-deprecate@^1.0.1, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== - -util.promisify@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.1.1.tgz#77832f57ced2c9478174149cae9b96e9918cd54b" - integrity sha512-/s3UsZUrIfa6xDhr7zZhnE9SLQ5RIXyYfiVnMMyMDzOc8WhWN4Nbh36H842OyurKbCDAesZOJaVyvmSl6fhGQw== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - for-each "^0.3.3" - has-symbols "^1.0.1" - object.getownpropertydescriptors "^2.1.1" - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== - -uuid@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== - -uuid@^3.3.2: - version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" - integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== - -uuid@^8.3.2: - version "8.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - -v8-compile-cache-lib@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" - integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== - -validate-npm-package-license@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - -varint@^5.0.0: - version "5.0.2" - resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" - integrity sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow== - -vary@^1, vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -web3-bzz@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.11.tgz#41bc19a77444bd5365744596d778b811880f707f" - integrity sha512-XGpWUEElGypBjeFyUhTkiPXFbDVD6Nr/S5jznE3t8cWUA0FxRf1n3n/NuIZeb0H9RkN2Ctd/jNma/k8XGa3YKg== - dependencies: - "@types/node" "^12.12.6" - got "9.6.0" - swarm-js "^0.1.40" - underscore "1.9.1" - -web3-core-helpers@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.2.11.tgz#84c681ed0b942c0203f3b324a245a127e8c67a99" - integrity sha512-PEPoAoZd5ME7UfbnCZBdzIerpe74GEvlwT4AjOmHeCVZoIFk7EqvOZDejJHt+feJA6kMVTdd0xzRNN295UhC1A== - dependencies: - underscore "1.9.1" - web3-eth-iban "1.2.11" - web3-utils "1.2.11" - -web3-core-method@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.11.tgz#f880137d1507a0124912bf052534f168b8d8fbb6" - integrity sha512-ff0q76Cde94HAxLDZ6DbdmKniYCQVtvuaYh+rtOUMB6kssa5FX0q3vPmixi7NPooFnbKmmZCM6NvXg4IreTPIw== - dependencies: - "@ethersproject/transactions" "^5.0.0-beta.135" - underscore "1.9.1" - web3-core-helpers "1.2.11" - web3-core-promievent "1.2.11" - web3-core-subscriptions "1.2.11" - web3-utils "1.2.11" - -web3-core-promievent@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.11.tgz#51fe97ca0ddec2f99bf8c3306a7a8e4b094ea3cf" - integrity sha512-il4McoDa/Ox9Agh4kyfQ8Ak/9ABYpnF8poBLL33R/EnxLsJOGQG2nZhkJa3I067hocrPSjEdlPt/0bHXsln4qA== - dependencies: - eventemitter3 "4.0.4" - -web3-core-requestmanager@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.11.tgz#fe6eb603fbaee18530293a91f8cf26d8ae28c45a" - integrity sha512-oFhBtLfOiIbmfl6T6gYjjj9igOvtyxJ+fjS+byRxiwFJyJ5BQOz4/9/17gWR1Cq74paTlI7vDGxYfuvfE/mKvA== - dependencies: - underscore "1.9.1" - web3-core-helpers "1.2.11" - web3-providers-http "1.2.11" - web3-providers-ipc "1.2.11" - web3-providers-ws "1.2.11" - -web3-core-subscriptions@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.11.tgz#beca908fbfcb050c16f45f3f0f4c205e8505accd" - integrity sha512-qEF/OVqkCvQ7MPs1JylIZCZkin0aKK9lDxpAtQ1F8niEDGFqn7DT8E/vzbIa0GsOjL2fZjDhWJsaW+BSoAW1gg== - dependencies: - eventemitter3 "4.0.4" - underscore "1.9.1" - web3-core-helpers "1.2.11" - -web3-core@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.11.tgz#1043cacc1becb80638453cc5b2a14be9050288a7" - integrity sha512-CN7MEYOY5ryo5iVleIWRE3a3cZqVaLlIbIzDPsvQRUfzYnvzZQRZBm9Mq+ttDi2STOOzc1MKylspz/o3yq/LjQ== - dependencies: - "@types/bn.js" "^4.11.5" - "@types/node" "^12.12.6" - bignumber.js "^9.0.0" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-core-requestmanager "1.2.11" - web3-utils "1.2.11" - -web3-eth-abi@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.11.tgz#a887494e5d447c2926d557a3834edd66e17af9b0" - integrity sha512-PkRYc0+MjuLSgg03QVWqWlQivJqRwKItKtEpRUaxUAeLE7i/uU39gmzm2keHGcQXo3POXAbOnMqkDvOep89Crg== - dependencies: - "@ethersproject/abi" "5.0.0-beta.153" - underscore "1.9.1" - web3-utils "1.2.11" - -web3-eth-accounts@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.11.tgz#a9e3044da442d31903a7ce035a86d8fa33f90520" - integrity sha512-6FwPqEpCfKIh3nSSGeo3uBm2iFSnFJDfwL3oS9pyegRBXNsGRVpgiW63yhNzL0796StsvjHWwQnQHsZNxWAkGw== - dependencies: - crypto-browserify "3.12.0" - eth-lib "0.2.8" - ethereumjs-common "^1.3.2" - ethereumjs-tx "^2.1.1" - scrypt-js "^3.0.1" - underscore "1.9.1" - uuid "3.3.2" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-utils "1.2.11" - -web3-eth-contract@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.2.11.tgz#917065902bc27ce89da9a1da26e62ef663663b90" - integrity sha512-MzYuI/Rq2o6gn7vCGcnQgco63isPNK5lMAan2E51AJLknjSLnOxwNY3gM8BcKoy4Z+v5Dv00a03Xuk78JowFow== - dependencies: - "@types/bn.js" "^4.11.5" - underscore "1.9.1" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-core-promievent "1.2.11" - web3-core-subscriptions "1.2.11" - web3-eth-abi "1.2.11" - web3-utils "1.2.11" - -web3-eth-ens@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.2.11.tgz#26d4d7f16d6cbcfff918e39832b939edc3162532" - integrity sha512-dbW7dXP6HqT1EAPvnniZVnmw6TmQEKF6/1KgAxbo8iBBYrVTMDGFQUUnZ+C4VETGrwwaqtX4L9d/FrQhZ6SUiA== - dependencies: - content-hash "^2.5.2" - eth-ens-namehash "2.0.8" - underscore "1.9.1" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-promievent "1.2.11" - web3-eth-abi "1.2.11" - web3-eth-contract "1.2.11" - web3-utils "1.2.11" - -web3-eth-iban@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.2.11.tgz#f5f73298305bc7392e2f188bf38a7362b42144ef" - integrity sha512-ozuVlZ5jwFC2hJY4+fH9pIcuH1xP0HEFhtWsR69u9uDIANHLPQQtWYmdj7xQ3p2YT4bQLq/axKhZi7EZVetmxQ== - dependencies: - bn.js "^4.11.9" - web3-utils "1.2.11" - -web3-eth-personal@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.11.tgz#a38b3942a1d87a62070ce0622a941553c3d5aa70" - integrity sha512-42IzUtKq9iHZ8K9VN0vAI50iSU9tOA1V7XU2BhF/tb7We2iKBVdkley2fg26TxlOcKNEHm7o6HRtiiFsVK4Ifw== - dependencies: - "@types/node" "^12.12.6" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-net "1.2.11" - web3-utils "1.2.11" - -web3-eth@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.2.11.tgz#4c81fcb6285b8caf544058fba3ae802968fdc793" - integrity sha512-REvxW1wJ58AgHPcXPJOL49d1K/dPmuw4LjPLBPStOVkQjzDTVmJEIsiLwn2YeuNDd4pfakBwT8L3bz1G1/wVsQ== - dependencies: - underscore "1.9.1" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-core-subscriptions "1.2.11" - web3-eth-abi "1.2.11" - web3-eth-accounts "1.2.11" - web3-eth-contract "1.2.11" - web3-eth-ens "1.2.11" - web3-eth-iban "1.2.11" - web3-eth-personal "1.2.11" - web3-net "1.2.11" - web3-utils "1.2.11" - -web3-net@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.2.11.tgz#eda68ef25e5cdb64c96c39085cdb74669aabbe1b" - integrity sha512-sjrSDj0pTfZouR5BSTItCuZ5K/oZPVdVciPQ6981PPPIwJJkCMeVjD7I4zO3qDPCnBjBSbWvVnLdwqUBPtHxyg== - dependencies: - web3-core "1.2.11" - web3-core-method "1.2.11" - web3-utils "1.2.11" - -web3-provider-engine@14.2.1: - version "14.2.1" - resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-14.2.1.tgz#ef351578797bf170e08d529cb5b02f8751329b95" - integrity sha512-iSv31h2qXkr9vrL6UZDm4leZMc32SjWJFGOp/D92JXfcEboCqraZyuExDkpxKw8ziTufXieNM7LSXNHzszYdJw== - dependencies: - async "^2.5.0" - backoff "^2.5.0" - clone "^2.0.0" - cross-fetch "^2.1.0" - eth-block-tracker "^3.0.0" - eth-json-rpc-infura "^3.1.0" - eth-sig-util "^1.4.2" - ethereumjs-block "^1.2.2" - ethereumjs-tx "^1.2.0" - ethereumjs-util "^5.1.5" - ethereumjs-vm "^2.3.4" - json-rpc-error "^2.0.0" - json-stable-stringify "^1.0.1" - promise-to-callback "^1.0.0" - readable-stream "^2.2.9" - request "^2.85.0" - semaphore "^1.0.3" - ws "^5.1.1" - xhr "^2.2.0" - xtend "^4.0.1" - -web3-providers-http@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.2.11.tgz#1cd03442c61670572d40e4dcdf1faff8bd91e7c6" - integrity sha512-psh4hYGb1+ijWywfwpB2cvvOIMISlR44F/rJtYkRmQ5jMvG4FOCPlQJPiHQZo+2cc3HbktvvSJzIhkWQJdmvrA== - dependencies: - web3-core-helpers "1.2.11" - xhr2-cookies "1.1.0" - -web3-providers-ipc@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.11.tgz#d16d6c9be1be6e0b4f4536c4acc16b0f4f27ef21" - integrity sha512-yhc7Y/k8hBV/KlELxynWjJDzmgDEDjIjBzXK+e0rHBsYEhdCNdIH5Psa456c+l0qTEU2YzycF8VAjYpWfPnBpQ== - dependencies: - oboe "2.1.4" - underscore "1.9.1" - web3-core-helpers "1.2.11" - -web3-providers-ws@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.11.tgz#a1dfd6d9778d840561d9ec13dd453046451a96bb" - integrity sha512-ZxnjIY1Er8Ty+cE4migzr43zA/+72AF1myzsLaU5eVgdsfV7Jqx7Dix1hbevNZDKFlSoEyq/3j/jYalh3So1Zg== - dependencies: - eventemitter3 "4.0.4" - underscore "1.9.1" - web3-core-helpers "1.2.11" - websocket "^1.0.31" - -web3-shh@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.11.tgz#f5d086f9621c9a47e98d438010385b5f059fd88f" - integrity sha512-B3OrO3oG1L+bv3E1sTwCx66injW1A8hhwpknDUbV+sw3fehFazA06z9SGXUefuFI1kVs4q2vRi0n4oCcI4dZDg== - dependencies: - web3-core "1.2.11" - web3-core-method "1.2.11" - web3-core-subscriptions "1.2.11" - web3-net "1.2.11" - -web3-utils@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.11.tgz#af1942aead3fb166ae851a985bed8ef2c2d95a82" - integrity sha512-3Tq09izhD+ThqHEaWYX4VOT7dNPdZiO+c/1QMA0s5X2lDFKK/xHJb7cyTRRVzN2LvlHbR7baS1tmQhSua51TcQ== - dependencies: - bn.js "^4.11.9" - eth-lib "0.2.8" - ethereum-bloom-filters "^1.0.6" - ethjs-unit "0.1.6" - number-to-bn "1.7.0" - randombytes "^2.1.0" - underscore "1.9.1" - utf8 "3.0.0" - -web3-utils@^1.0.0-beta.31: - version "1.8.1" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.8.1.tgz#f2f7ca7eb65e6feb9f3d61056d0de6bbd57125ff" - integrity sha512-LgnM9p6V7rHHUGfpMZod+NST8cRfGzJ1BTXAyNo7A9cJX9LczBfSRxJp+U/GInYe9mby40t3v22AJdlELibnsQ== - dependencies: - bn.js "^5.2.1" - ethereum-bloom-filters "^1.0.6" - ethereumjs-util "^7.1.0" - ethjs-unit "0.1.6" - number-to-bn "1.7.0" - randombytes "^2.1.0" - utf8 "3.0.0" - -web3@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3/-/web3-1.2.11.tgz#50f458b2e8b11aa37302071c170ed61cff332975" - integrity sha512-mjQ8HeU41G6hgOYm1pmeH0mRAeNKJGnJEUzDMoerkpw7QUQT4exVREgF1MYPvL/z6vAshOXei25LE/t/Bxl8yQ== - dependencies: - web3-bzz "1.2.11" - web3-core "1.2.11" - web3-eth "1.2.11" - web3-eth-personal "1.2.11" - web3-net "1.2.11" - web3-shh "1.2.11" - web3-utils "1.2.11" - -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== - -websocket@1.0.32: - version "1.0.32" - resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.32.tgz#1f16ddab3a21a2d929dec1687ab21cfdc6d3dbb1" - integrity sha512-i4yhcllSP4wrpoPMU2N0TQ/q0O94LRG/eUQjEAamRltjQ1oT1PFFKOG4i877OlJgCG8rw6LrrowJp+TYCEWF7Q== - dependencies: - bufferutil "^4.0.1" - debug "^2.2.0" - es5-ext "^0.10.50" - typedarray-to-buffer "^3.1.5" - utf-8-validate "^5.0.2" - yaeti "^0.0.6" - -websocket@^1.0.31: - version "1.0.34" - resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" - integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== - dependencies: - bufferutil "^4.0.1" - debug "^2.2.0" - es5-ext "^0.10.50" - typedarray-to-buffer "^3.1.5" - utf-8-validate "^5.0.2" - yaeti "^0.0.6" - -whatwg-fetch@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" - integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== - -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== - dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" - -which-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" - integrity sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ== - -which-typed-array@^1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" - integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" - is-typed-array "^1.1.10" - -which@^1.2.9: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -window-size@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" - integrity sha512-UD7d8HFA2+PZsbKyaOCEy8gMh1oDtHgJh1LfgjQ4zVXmYjAT/kvz3PueITKuqDiIXQe7yzpPnxX3lNc+AhQMyw== - -wordwrapjs@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.1.tgz#d9790bccfb110a0fc7836b5ebce0937b37a8b98f" - integrity sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA== - dependencies: - reduce-flatten "^2.0.0" - typical "^5.2.0" - -workerpool@6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" - integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== - -wrap-ansi@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - integrity sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw== - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -ws@7.4.6: - version "7.4.6" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" - integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== - -ws@^3.0.0: - version "3.3.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" - integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== - dependencies: - async-limiter "~1.0.0" - safe-buffer "~5.1.0" - ultron "~1.1.0" - -ws@^5.1.1: - version "5.2.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.3.tgz#05541053414921bc29c63bee14b8b0dd50b07b3d" - integrity sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA== - dependencies: - async-limiter "~1.0.0" - -ws@^7.4.6: - version "7.5.9" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" - integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== - -xhr-request-promise@^0.1.2: - version "0.1.3" - resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz#2d5f4b16d8c6c893be97f1a62b0ed4cf3ca5f96c" - integrity sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg== - dependencies: - xhr-request "^1.1.0" - -xhr-request@^1.0.1, xhr-request@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/xhr-request/-/xhr-request-1.1.0.tgz#f4a7c1868b9f198723444d82dcae317643f2e2ed" - integrity sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA== - dependencies: - buffer-to-arraybuffer "^0.0.5" - object-assign "^4.1.1" - query-string "^5.0.1" - simple-get "^2.7.0" - timed-out "^4.0.1" - url-set-query "^1.0.0" - xhr "^2.0.4" - -xhr2-cookies@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" - integrity sha512-hjXUA6q+jl/bd8ADHcVfFsSPIf+tyLIjuO9TwJC9WI6JP2zKcS7C+p56I9kCLLsaCiNT035iYvEUUzdEFj/8+g== - dependencies: - cookiejar "^2.1.1" - -xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: - version "2.6.0" - resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.6.0.tgz#b69d4395e792b4173d6b7df077f0fc5e4e2b249d" - integrity sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA== - dependencies: - global "~4.4.0" - is-function "^1.0.1" - parse-headers "^2.0.0" - xtend "^4.0.0" - -xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -xtend@~2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" - integrity sha512-vMNKzr2rHP9Dp/e1NQFnLQlwlhp9L/LfvnsVdHxN1f+uggyVI3i08uD14GPvCToPkdsRfyPqIyYGmIk58V98ZQ== - dependencies: - object-keys "~0.4.0" - -y18n@^3.2.1: - version "3.2.2" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696" - integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ== - -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - -yaeti@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" - integrity sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug== - -yallist@^3.0.0, yallist@^3.0.2, yallist@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yaml@^1.10.2: - version "1.10.2" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" - integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== - -yargs-parser@20.2.4: - version "20.2.4" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" - integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== - -yargs-parser@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" - integrity sha512-9pIKIJhnI5tonzG6OnCFlz/yln8xHYcGl+pn3xR0Vzff0vzN1PbNRaelgfgRUwZ3s4i3jvxT9WhmUGL4whnasA== - dependencies: - camelcase "^3.0.0" - lodash.assign "^4.0.6" - -yargs-parser@^20.2.2: - version "20.2.9" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" - integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== - -yargs-unparser@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" - integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== - dependencies: - camelcase "^6.0.0" - decamelize "^4.0.0" - flat "^5.0.2" - is-plain-obj "^2.1.0" - -yargs@16.2.0: - version "16.2.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" - integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== - dependencies: - cliui "^7.0.2" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.0" - y18n "^5.0.5" - yargs-parser "^20.2.2" - -yargs@^4.7.1: - version "4.8.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0" - integrity sha512-LqodLrnIDM3IFT+Hf/5sxBnEGECrfdC1uIbgZeJmESCSo4HoCAaKEus8MylXHAkdacGc0ye+Qa+dpkuom8uVYA== - dependencies: - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - lodash.assign "^4.0.3" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^1.0.1" - which-module "^1.0.0" - window-size "^0.2.0" - y18n "^3.2.1" - yargs-parser "^2.4.1" - -yn@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" - integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== - -zksync-web3@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.8.1.tgz#db289d8f6caf61f4d5ddc471fa3448d93208dc14" - integrity sha512-1A4aHPQ3MyuGjpv5X/8pVEN+MdZqMjfVmiweQSRjOlklXYu65wT9BGEOtCmMs5d3gIvLp4ssfTeuR5OCKOD2kw== - -zod@^3.20.2: - version "3.20.2" - resolved "https://registry.yarnpkg.com/zod/-/zod-3.20.2.tgz#068606642c8f51b3333981f91c0a8ab37dfc2807" - integrity sha512-1MzNQdAvO+54H+EaK5YpyEy0T+Ejo/7YLHS93G3RnYWh5gaotGHwGeN/ZO687qEDU2y4CdStQYXVHIgrUl5UVQ== From bd32655d6d00609bf496361091578e4c5d672cba Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Fri, 27 Jan 2023 13:46:36 +1100 Subject: [PATCH 16/43] rename velo Velo IVelo --- contracts/Flow.sol | 4 +- contracts/Minter.sol | 4 +- contracts/VeArtProxy.sol | 2 +- contracts/VeloGovernor.sol | 2 +- contracts/Voter.sol | 2 +- contracts/interfaces/IFlow.sol | 2 +- contracts/redeem/MerkleClaim.sol | 6 +- contracts/redeem/RedemptionReceiver.sol | 4 +- deploy/00_velo.ts | 24 +- deploy/08_votingEscrow.ts | 30 +- deploy/13_redemptionReceiver.ts | 4 +- deploy/14_merkleClaim.ts | 4 +- deploy/15_init.ts | 10 +- deploy/16_whitelist.ts | 4 +- deploy/17_dist.ts | 10 +- .../{arbitrum => arbitrumOne}/.chainId | 0 .../.migrations.json | 0 .../BribeFactory.json | 0 .../GaugeFactory.json | 0 .../MerkleClaim.json | 0 .../{arbitrum => arbitrumOne}/Minter.json | 0 .../PairFactory.json | 0 .../RedemptionReceiver.json | 0 .../RewardsDistributor.json | 0 .../{arbitrum => arbitrumOne}/Router.json | 0 .../{arbitrum => arbitrumOne}/VeArtProxy.json | 0 .../{arbitrum => arbitrumOne}/Velo.json | 0 .../VeloGovernor.json | 0 .../VelodromeLibrary.json | 0 .../{arbitrum => arbitrumOne}/Voter.json | 0 .../VotingEscrow.json | 0 .../f93feb6db909c3f14d7eec3a3196fbbd.json | 0 dist/deploy/00_velo.js | 30 +- dist/deploy/08_votingEscrow.js | 34 +- dist/deploy/13_redemptionReceiver.js | 62 ++-- dist/deploy/14_merkleClaim.js | 46 +-- dist/deploy/15_init.js | 10 +- dist/deploy/16_whitelist.js | 46 +-- dist/tasks/deploy/arb.js | 300 ++++++++++------ dist/tasks/deploy/arbHardhat.js | 309 +++++++++------- dist/tasks/deploy/arbTest.js | 336 +++++++++++------- dist/tasks/deploy/op.js | 295 +++++++++------ hardhat.config.ts | 4 +- readme.md | 6 +- tasks/deploy/arb.ts | 32 +- tasks/deploy/arbHardhat.ts | 32 +- tasks/deploy/arbTest.ts | 46 +-- tasks/deploy/op.ts | 255 ++++++------- test/BaseTest.sol | 6 +- test/utils/TestOwner.sol | 2 +- 50 files changed, 1125 insertions(+), 838 deletions(-) rename deployments/{arbitrum => arbitrumOne}/.chainId (100%) rename deployments/{arbitrum => arbitrumOne}/.migrations.json (100%) rename deployments/{arbitrum => arbitrumOne}/BribeFactory.json (100%) rename deployments/{arbitrum => arbitrumOne}/GaugeFactory.json (100%) rename deployments/{arbitrum => arbitrumOne}/MerkleClaim.json (100%) rename deployments/{arbitrum => arbitrumOne}/Minter.json (100%) rename deployments/{arbitrum => arbitrumOne}/PairFactory.json (100%) rename deployments/{arbitrum => arbitrumOne}/RedemptionReceiver.json (100%) rename deployments/{arbitrum => arbitrumOne}/RewardsDistributor.json (100%) rename deployments/{arbitrum => arbitrumOne}/Router.json (100%) rename deployments/{arbitrum => arbitrumOne}/VeArtProxy.json (100%) rename deployments/{arbitrum => arbitrumOne}/Velo.json (100%) rename deployments/{arbitrum => arbitrumOne}/VeloGovernor.json (100%) rename deployments/{arbitrum => arbitrumOne}/VelodromeLibrary.json (100%) rename deployments/{arbitrum => arbitrumOne}/Voter.json (100%) rename deployments/{arbitrum => arbitrumOne}/VotingEscrow.json (100%) rename deployments/{arbitrum => arbitrumOne}/solcInputs/f93feb6db909c3f14d7eec3a3196fbbd.json (100%) diff --git a/contracts/Flow.sol b/contracts/Flow.sol index aae971a5..7a519e79 100644 --- a/contracts/Flow.sol +++ b/contracts/Flow.sol @@ -3,9 +3,9 @@ pragma solidity 0.8.13; import "contracts/interfaces/IFlow.sol"; -contract Velo is IVelo { +contract Flow is IFlow { - string public constant name = "Velodrome"; + string public constant name = "Velocimeter"; string public constant symbol = "FLOW"; uint8 public constant decimals = 18; uint public totalSupply = 0; diff --git a/contracts/Minter.sol b/contracts/Minter.sol index 72d0be09..f359f5a2 100644 --- a/contracts/Minter.sol +++ b/contracts/Minter.sol @@ -15,7 +15,7 @@ contract Minter is IMinter { uint256 internal constant EMISSION = 990; uint256 internal constant TAIL_EMISSION = 2; uint256 internal constant PRECISION = 1000; - IVelo public immutable _velo; + IFlow public immutable _velo; IVoter public immutable _voter; IVotingEscrow public immutable _ve; IRewardsDistributor public immutable _rewards_distributor; @@ -44,7 +44,7 @@ contract Minter is IMinter { initializer = msg.sender; team = msg.sender; teamRate = 30; // 30 bps = 0.03% - _velo = IVelo(IVotingEscrow(__ve).token()); + _velo = IFlow(IVotingEscrow(__ve).token()); _voter = IVoter(__voter); _ve = IVotingEscrow(__ve); _rewards_distributor = IRewardsDistributor(__rewards_distributor); diff --git a/contracts/VeArtProxy.sol b/contracts/VeArtProxy.sol index 505149ac..db5ee78a 100644 --- a/contracts/VeArtProxy.sol +++ b/contracts/VeArtProxy.sol @@ -33,7 +33,7 @@ contract VeArtProxy is IVeArtProxy { output = string(abi.encodePacked(output, "locked_end ", toString(_locked_end), '')); output = string(abi.encodePacked(output, "value ", toString(_value), '')); - string memory json = Base64.encode(bytes(string(abi.encodePacked('{"name": "lock #', toString(_tokenId), '", "description": "Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes", "image": "data:image/svg+xml;base64,', Base64.encode(bytes(output)), '"}')))); + string memory json = Base64.encode(bytes(string(abi.encodePacked('{"name": "lock #', toString(_tokenId), '", "description": "Velocimeter locks, can be used to boost gauge yields, vote on token emission, and receive bribes", "image": "data:image/svg+xml;base64,', Base64.encode(bytes(output)), '"}')))); output = string(abi.encodePacked('data:application/json;base64,', json)); } } diff --git a/contracts/VeloGovernor.sol b/contracts/VeloGovernor.sol index faa0804f..df67969d 100644 --- a/contracts/VeloGovernor.sol +++ b/contracts/VeloGovernor.sol @@ -21,7 +21,7 @@ contract VeloGovernor is uint256 public proposalNumerator = 2; // start at 0.02% constructor(IVotes _ve) - L2Governor("Velodrome Governor") + L2Governor("Velocimeter Governor") L2GovernorVotes(_ve) L2GovernorVotesQuorumFraction(4) // 4% { diff --git a/contracts/Voter.sol b/contracts/Voter.sol index 9f086005..e4353dde 100644 --- a/contracts/Voter.sol +++ b/contracts/Voter.sol @@ -221,7 +221,7 @@ contract Voter is IVoter { } } - if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs + if (msg.sender != governor) { // gov can create for any pool, even non-Velocimeter pairs require(isPair, "!_pool"); require(isWhitelisted[tokenA] && isWhitelisted[tokenB], "!whitelisted"); } diff --git a/contracts/interfaces/IFlow.sol b/contracts/interfaces/IFlow.sol index 8c8d1e33..ac81b10b 100644 --- a/contracts/interfaces/IFlow.sol +++ b/contracts/interfaces/IFlow.sol @@ -1,6 +1,6 @@ pragma solidity 0.8.13; -interface IVelo { +interface IFlow { function totalSupply() external view returns (uint); function balanceOf(address) external view returns (uint); function approve(address spender, uint value) external returns (bool); diff --git a/contracts/redeem/MerkleClaim.sol b/contracts/redeem/MerkleClaim.sol index 190119e2..495b4b88 100644 --- a/contracts/redeem/MerkleClaim.sol +++ b/contracts/redeem/MerkleClaim.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.13; /// ============ Imports ============ -import {IVelo} from "contracts/interfaces/IFlow.sol"; +import {IFlow} from "contracts/interfaces/IFlow.sol"; import {MerkleProof} from "openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol"; // OZ: MerkleProof /// @title MerkleClaim @@ -13,7 +13,7 @@ contract MerkleClaim { /// ============ Immutable storage ============ /// @notice FLOW token to claim - IVelo public immutable FLOW; + IFlow public immutable FLOW; /// @notice ERC20-claimee inclusion root bytes32 public immutable merkleRoot; @@ -28,7 +28,7 @@ contract MerkleClaim { /// @param _velo address /// @param _merkleRoot of claimees constructor(address _velo, bytes32 _merkleRoot) { - FLOW = IVelo(_velo); + FLOW = IFlow(_velo); merkleRoot = _merkleRoot; } diff --git a/contracts/redeem/RedemptionReceiver.sol b/contracts/redeem/RedemptionReceiver.sol index deb0ed22..73fe6a48 100644 --- a/contracts/redeem/RedemptionReceiver.sol +++ b/contracts/redeem/RedemptionReceiver.sol @@ -10,7 +10,7 @@ import "contracts/interfaces/IFlow.sol"; /// This contract is responsible for receiving the LZ message and distributing USDC + FLOW contract RedemptionReceiver is ILayerZeroReceiver { IERC20 public immutable USDC; - IVelo public immutable FLOW; + IFlow public immutable FLOW; uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet address public immutable endpoint; @@ -34,7 +34,7 @@ contract RedemptionReceiver is ILayerZeroReceiver { require(_fantomChainId == 12 || _fantomChainId == 10012, "CHAIN_ID_NOT_FTM"); USDC = IERC20(_usdc); - FLOW = IVelo(_velo); + FLOW = IFlow(_velo); fantomChainId = _fantomChainId; endpoint = _endpoint; diff --git a/deploy/00_velo.ts b/deploy/00_velo.ts index 2901cd93..7f96383f 100644 --- a/deploy/00_velo.ts +++ b/deploy/00_velo.ts @@ -1,19 +1,19 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments - const { deployer } = await getNamedAccounts(); + const { deployer } = await getNamedAccounts() - await deploy("Velo", { + await deploy('Flow', { from: deployer, args: [], log: true, - skipIfAlreadyDeployed: true, - }); -}; -export default func; -func.tags = ["Velo"]; -func.id = "velo"; + skipIfAlreadyDeployed: true + }) +} +export default func +func.tags = ['Flow'] +func.id = 'flow' diff --git a/deploy/08_votingEscrow.ts b/deploy/08_votingEscrow.ts index cdf71098..7a1392d7 100644 --- a/deploy/08_votingEscrow.ts +++ b/deploy/08_votingEscrow.ts @@ -1,22 +1,22 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments - const { deployer } = await getNamedAccounts(); + const { deployer } = await getNamedAccounts() - const velo = await deployments.get("Velo"); - const veArtProxy = await deployments.get("VeArtProxy"); + const flow = await deployments.get('Flow') + const veArtProxy = await deployments.get('VeArtProxy') - await deploy("VotingEscrow", { + await deploy('VotingEscrow', { from: deployer, - args: [velo.address, veArtProxy.address], + args: [flow.address, veArtProxy.address], log: true, - skipIfAlreadyDeployed: true, - }); -}; -export default func; -func.tags = ["VotingEscrow"]; -func.id = "votingEscrow"; \ No newline at end of file + skipIfAlreadyDeployed: true + }) +} +export default func +func.tags = ['VotingEscrow'] +func.id = 'votingEscrow' diff --git a/deploy/13_redemptionReceiver.ts b/deploy/13_redemptionReceiver.ts index 14ad1a5f..32e9f129 100644 --- a/deploy/13_redemptionReceiver.ts +++ b/deploy/13_redemptionReceiver.ts @@ -13,13 +13,13 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployer } = await getNamedAccounts() - const velo = await deployments.get('Velo') + const flow = await deployments.get('Flow') await deploy('RedemptionReceiver', { from: deployer, args: [ ARB_TEST_CONFIG.USDC, - velo.address, + flow.address, FTM_CONFIG.lzChainId, ARB_TEST_CONFIG.lzEndpoint ], diff --git a/deploy/14_merkleClaim.ts b/deploy/14_merkleClaim.ts index b680ea2e..0fe22e48 100644 --- a/deploy/14_merkleClaim.ts +++ b/deploy/14_merkleClaim.ts @@ -12,11 +12,11 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployer } = await getNamedAccounts() - const velo = await deployments.get('Velo') + const flow = await deployments.get('Flow') await deploy('MerkleClaim', { from: deployer, - args: [velo.address, ARB_TEST_CONFIG.merkleRoot], + args: [flow.address, ARB_TEST_CONFIG.merkleRoot], log: true, skipIfAlreadyDeployed: true }) diff --git a/deploy/15_init.ts b/deploy/15_init.ts index 3ddd28b4..919a06df 100644 --- a/deploy/15_init.ts +++ b/deploy/15_init.ts @@ -8,7 +8,7 @@ const ARB_TEST_CONFIG = arbHardhatConfig const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, ethers } = hre - const velo = await ethers.getContract('Velo') + const flow = await ethers.getContract('Flow') const pairFactory = await ethers.getContract('PairFactory') const escrow = await ethers.getContract('VotingEscrow') const voter = await ethers.getContract('Voter') @@ -20,16 +20,16 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const claim = await deployments.get('MerkleClaim') // Initialize - await velo.initialMint(ARB_TEST_CONFIG.teamEOA) + await flow.initialMint(ARB_TEST_CONFIG.teamEOA) console.log('Initial minted') - await velo.setRedemptionReceiver(receiver.address) + await flow.setRedemptionReceiver(receiver.address) console.log('RedemptionReceiver set') - await velo.setMerkleClaim(claim.address) + await flow.setMerkleClaim(claim.address) console.log('MerkleClaim set') - await velo.setMinter(minter.address) + await flow.setMinter(minter.address) console.log('Minter set') await pairFactory.setPauser(ARB_TEST_CONFIG.teamMultisig) diff --git a/deploy/16_whitelist.ts b/deploy/16_whitelist.ts index b448047c..f94df781 100644 --- a/deploy/16_whitelist.ts +++ b/deploy/16_whitelist.ts @@ -8,12 +8,12 @@ const ARB_TEST_CONFIG = arbTestnetConfig const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { ethers } = hre - const velo = await ethers.getContract('Velo') + const flow = await ethers.getContract('Flow') const voter = await ethers.getContract('Voter') const minter = await ethers.getContract('Minter') // Whitelist - const nativeToken = [velo.address] + const nativeToken = [flow.address] const tokenWhitelist = nativeToken.concat(ARB_TEST_CONFIG.tokenWhitelist) await voter.initialize(tokenWhitelist, minter.address) console.log('Whitelist set') diff --git a/deploy/17_dist.ts b/deploy/17_dist.ts index 6b99bb91..294d1678 100644 --- a/deploy/17_dist.ts +++ b/deploy/17_dist.ts @@ -16,7 +16,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployer } = await getNamedAccounts() - const velo = await deployments.get('Velo') + const flow = await deployments.get('Flow') // Initial veVELO distro await minter.initialize( @@ -33,16 +33,16 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { console.log('deployer', deployer) - // await velo.initialMint(ARB_CONFIG.teamEOA) + // await flow.initialMint(ARB_CONFIG.teamEOA) // console.log('Initial minted') - // await velo.setRedemptionReceiver(receiver.address) + // await flow.setRedemptionReceiver(receiver.address) // console.log('RedemptionReceiver set') - // await velo.setMerkleClaim(claim.address) + // await flow.setMerkleClaim(claim.address) // console.log('MerkleClaim set') - // await velo.setMinter(minter.address) + // await flow.setMinter(minter.address) // console.log('Minter set') // await pairFactory.setPauser(ARB_CONFIG.teamMultisig) diff --git a/deployments/arbitrum/.chainId b/deployments/arbitrumOne/.chainId similarity index 100% rename from deployments/arbitrum/.chainId rename to deployments/arbitrumOne/.chainId diff --git a/deployments/arbitrum/.migrations.json b/deployments/arbitrumOne/.migrations.json similarity index 100% rename from deployments/arbitrum/.migrations.json rename to deployments/arbitrumOne/.migrations.json diff --git a/deployments/arbitrum/BribeFactory.json b/deployments/arbitrumOne/BribeFactory.json similarity index 100% rename from deployments/arbitrum/BribeFactory.json rename to deployments/arbitrumOne/BribeFactory.json diff --git a/deployments/arbitrum/GaugeFactory.json b/deployments/arbitrumOne/GaugeFactory.json similarity index 100% rename from deployments/arbitrum/GaugeFactory.json rename to deployments/arbitrumOne/GaugeFactory.json diff --git a/deployments/arbitrum/MerkleClaim.json b/deployments/arbitrumOne/MerkleClaim.json similarity index 100% rename from deployments/arbitrum/MerkleClaim.json rename to deployments/arbitrumOne/MerkleClaim.json diff --git a/deployments/arbitrum/Minter.json b/deployments/arbitrumOne/Minter.json similarity index 100% rename from deployments/arbitrum/Minter.json rename to deployments/arbitrumOne/Minter.json diff --git a/deployments/arbitrum/PairFactory.json b/deployments/arbitrumOne/PairFactory.json similarity index 100% rename from deployments/arbitrum/PairFactory.json rename to deployments/arbitrumOne/PairFactory.json diff --git a/deployments/arbitrum/RedemptionReceiver.json b/deployments/arbitrumOne/RedemptionReceiver.json similarity index 100% rename from deployments/arbitrum/RedemptionReceiver.json rename to deployments/arbitrumOne/RedemptionReceiver.json diff --git a/deployments/arbitrum/RewardsDistributor.json b/deployments/arbitrumOne/RewardsDistributor.json similarity index 100% rename from deployments/arbitrum/RewardsDistributor.json rename to deployments/arbitrumOne/RewardsDistributor.json diff --git a/deployments/arbitrum/Router.json b/deployments/arbitrumOne/Router.json similarity index 100% rename from deployments/arbitrum/Router.json rename to deployments/arbitrumOne/Router.json diff --git a/deployments/arbitrum/VeArtProxy.json b/deployments/arbitrumOne/VeArtProxy.json similarity index 100% rename from deployments/arbitrum/VeArtProxy.json rename to deployments/arbitrumOne/VeArtProxy.json diff --git a/deployments/arbitrum/Velo.json b/deployments/arbitrumOne/Velo.json similarity index 100% rename from deployments/arbitrum/Velo.json rename to deployments/arbitrumOne/Velo.json diff --git a/deployments/arbitrum/VeloGovernor.json b/deployments/arbitrumOne/VeloGovernor.json similarity index 100% rename from deployments/arbitrum/VeloGovernor.json rename to deployments/arbitrumOne/VeloGovernor.json diff --git a/deployments/arbitrum/VelodromeLibrary.json b/deployments/arbitrumOne/VelodromeLibrary.json similarity index 100% rename from deployments/arbitrum/VelodromeLibrary.json rename to deployments/arbitrumOne/VelodromeLibrary.json diff --git a/deployments/arbitrum/Voter.json b/deployments/arbitrumOne/Voter.json similarity index 100% rename from deployments/arbitrum/Voter.json rename to deployments/arbitrumOne/Voter.json diff --git a/deployments/arbitrum/VotingEscrow.json b/deployments/arbitrumOne/VotingEscrow.json similarity index 100% rename from deployments/arbitrum/VotingEscrow.json rename to deployments/arbitrumOne/VotingEscrow.json diff --git a/deployments/arbitrum/solcInputs/f93feb6db909c3f14d7eec3a3196fbbd.json b/deployments/arbitrumOne/solcInputs/f93feb6db909c3f14d7eec3a3196fbbd.json similarity index 100% rename from deployments/arbitrum/solcInputs/f93feb6db909c3f14d7eec3a3196fbbd.json rename to deployments/arbitrumOne/solcInputs/f93feb6db909c3f14d7eec3a3196fbbd.json diff --git a/dist/deploy/00_velo.js b/dist/deploy/00_velo.js index abe1df7b..2824a37f 100644 --- a/dist/deploy/00_velo.js +++ b/dist/deploy/00_velo.js @@ -1,16 +1,16 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) const func = async function (hre) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; - const { deployer } = await getNamedAccounts(); - await deploy("Velo", { - from: deployer, - args: [], - log: true, - skipIfAlreadyDeployed: true, - }); -}; -exports.default = func; -func.tags = ["Velo"]; -func.id = "velo"; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments + const { deployer } = await getNamedAccounts() + await deploy('Flow', { + from: deployer, + args: [], + log: true, + skipIfAlreadyDeployed: true + }) +} +exports.default = func +func.tags = ['Flow'] +func.id = 'flow' diff --git a/dist/deploy/08_votingEscrow.js b/dist/deploy/08_votingEscrow.js index 77ee759c..24692084 100644 --- a/dist/deploy/08_votingEscrow.js +++ b/dist/deploy/08_votingEscrow.js @@ -1,18 +1,18 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) const func = async function (hre) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; - const { deployer } = await getNamedAccounts(); - const velo = await deployments.get("Velo"); - const veArtProxy = await deployments.get("VeArtProxy"); - await deploy("VotingEscrow", { - from: deployer, - args: [velo.address, veArtProxy.address], - log: true, - skipIfAlreadyDeployed: true, - }); -}; -exports.default = func; -func.tags = ["VotingEscrow"]; -func.id = "votingEscrow"; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments + const { deployer } = await getNamedAccounts() + const flow = await deployments.get('Flow') + const veArtProxy = await deployments.get('VeArtProxy') + await deploy('VotingEscrow', { + from: deployer, + args: [flow.address, veArtProxy.address], + log: true, + skipIfAlreadyDeployed: true + }) +} +exports.default = func +func.tags = ['VotingEscrow'] +func.id = 'votingEscrow' diff --git a/dist/deploy/13_redemptionReceiver.js b/dist/deploy/13_redemptionReceiver.js index c991aa49..c8eea4df 100644 --- a/dist/deploy/13_redemptionReceiver.js +++ b/dist/deploy/13_redemptionReceiver.js @@ -1,29 +1,35 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const arbTestnetConfig_1 = __importDefault(require("../tasks/deploy/constants/arbTestnetConfig")); -const testFantomConfig_1 = __importDefault(require("../tasks/deploy/constants/testFantomConfig")); -const ARB_TEST_CONFIG = arbTestnetConfig_1.default; -const FTM_CONFIG = testFantomConfig_1.default; +'use strict' +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod } + } +Object.defineProperty(exports, '__esModule', { value: true }) +const arbTestnetConfig_1 = __importDefault( + require('../tasks/deploy/constants/arbTestnetConfig') +) +const testFantomConfig_1 = __importDefault( + require('../tasks/deploy/constants/testFantomConfig') +) +const ARB_TEST_CONFIG = arbTestnetConfig_1.default +const FTM_CONFIG = testFantomConfig_1.default const func = async function (hre) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; - const { deployer } = await getNamedAccounts(); - const velo = await deployments.get("Velo"); - await deploy("RedemptionReceiver", { - from: deployer, - args: [ - ARB_TEST_CONFIG.USDC, - velo.address, - FTM_CONFIG.lzChainId, - ARB_TEST_CONFIG.lzEndpoint, - ], - log: true, - skipIfAlreadyDeployed: true, - }); -}; -exports.default = func; -func.tags = ["RedemptionReceiver"]; -func.id = "redemptionReceiver"; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments + const { deployer } = await getNamedAccounts() + const flow = await deployments.get('Flow') + await deploy('RedemptionReceiver', { + from: deployer, + args: [ + ARB_TEST_CONFIG.USDC, + flow.address, + FTM_CONFIG.lzChainId, + ARB_TEST_CONFIG.lzEndpoint + ], + log: true, + skipIfAlreadyDeployed: true + }) +} +exports.default = func +func.tags = ['RedemptionReceiver'] +func.id = 'redemptionReceiver' diff --git a/dist/deploy/14_merkleClaim.js b/dist/deploy/14_merkleClaim.js index 962094e9..de6a5ddb 100644 --- a/dist/deploy/14_merkleClaim.js +++ b/dist/deploy/14_merkleClaim.js @@ -1,22 +1,26 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const arbTestnetConfig_1 = __importDefault(require("../tasks/deploy/constants/arbTestnetConfig")); -const ARB_TEST_CONFIG = arbTestnetConfig_1.default; +'use strict' +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod } + } +Object.defineProperty(exports, '__esModule', { value: true }) +const arbTestnetConfig_1 = __importDefault( + require('../tasks/deploy/constants/arbTestnetConfig') +) +const ARB_TEST_CONFIG = arbTestnetConfig_1.default const func = async function (hre) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; - const { deployer } = await getNamedAccounts(); - const velo = await deployments.get("Velo"); - await deploy("MerkleClaim", { - from: deployer, - args: [velo.address, ARB_TEST_CONFIG.merkleRoot], - log: true, - skipIfAlreadyDeployed: true, - }); -}; -exports.default = func; -func.tags = ["MerkleClaim"]; -func.id = "merkleClaim"; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments + const { deployer } = await getNamedAccounts() + const flow = await deployments.get('Flow') + await deploy('MerkleClaim', { + from: deployer, + args: [flow.address, ARB_TEST_CONFIG.merkleRoot], + log: true, + skipIfAlreadyDeployed: true + }) +} +exports.default = func +func.tags = ['MerkleClaim'] +func.id = 'merkleClaim' diff --git a/dist/deploy/15_init.js b/dist/deploy/15_init.js index 53dbd798..aa5083f9 100644 --- a/dist/deploy/15_init.js +++ b/dist/deploy/15_init.js @@ -11,7 +11,7 @@ const arbTestnetConfig_1 = __importDefault( const ARB_TEST_CONFIG = arbTestnetConfig_1.default const func = async function (hre) { const { deployments, ethers } = hre - const velo = await ethers.getContract('Velo') + const flow = await ethers.getContract('Flow') const pairFactory = await ethers.getContract('PairFactory') const escrow = await ethers.getContract('VotingEscrow') const voter = await ethers.getContract('Voter') @@ -21,13 +21,13 @@ const func = async function (hre) { const receiver = await ethers.getContract('RedemptionReceiver') const claim = await deployments.get('MerkleClaim') // Initialize - await velo.initialMint(ARB_TEST_CONFIG.teamEOA) + await flow.initialMint(ARB_TEST_CONFIG.teamEOA) console.log('Initial minted') - await velo.setRedemptionReceiver(receiver.address) + await flow.setRedemptionReceiver(receiver.address) console.log('RedemptionReceiver set') - await velo.setMerkleClaim(claim.address) + await flow.setMerkleClaim(claim.address) console.log('MerkleClaim set') - await velo.setMinter(minter.address) + await flow.setMinter(minter.address) console.log('Minter set') await pairFactory.setPauser(ARB_TEST_CONFIG.teamMultisig) console.log('Pauser set') diff --git a/dist/deploy/16_whitelist.js b/dist/deploy/16_whitelist.js index 41fa82d1..50cd6bab 100644 --- a/dist/deploy/16_whitelist.js +++ b/dist/deploy/16_whitelist.js @@ -1,22 +1,26 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const arbTestnetConfig_1 = __importDefault(require("../tasks/deploy/constants/arbTestnetConfig")); -const ARB_TEST_CONFIG = arbTestnetConfig_1.default; +'use strict' +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod } + } +Object.defineProperty(exports, '__esModule', { value: true }) +const arbTestnetConfig_1 = __importDefault( + require('../tasks/deploy/constants/arbTestnetConfig') +) +const ARB_TEST_CONFIG = arbTestnetConfig_1.default const func = async function (hre) { - const { ethers } = hre; - const velo = await ethers.getContract("Velo"); - const voter = await ethers.getContract("Voter"); - const minter = await ethers.getContract("Minter"); - // Whitelist - const nativeToken = [velo.address]; - const tokenWhitelist = nativeToken.concat(ARB_TEST_CONFIG.tokenWhitelist); - await voter.initialize(tokenWhitelist, minter.address); - console.log("Whitelist set"); - return true; -}; -exports.default = func; -func.tags = ["whitelist"]; -func.id = "whitelist"; + const { ethers } = hre + const flow = await ethers.getContract('Flow') + const voter = await ethers.getContract('Voter') + const minter = await ethers.getContract('Minter') + // Whitelist + const nativeToken = [flow.address] + const tokenWhitelist = nativeToken.concat(ARB_TEST_CONFIG.tokenWhitelist) + await voter.initialize(tokenWhitelist, minter.address) + console.log('Whitelist set') + return true +} +exports.default = func +func.tags = ['whitelist'] +func.id = 'whitelist' diff --git a/dist/tasks/deploy/arb.js b/dist/tasks/deploy/arb.js index 1f3694b6..a16ed7dc 100644 --- a/dist/tasks/deploy/arb.js +++ b/dist/tasks/deploy/arb.js @@ -1,121 +1,189 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const config_1 = require("hardhat/config"); -const arbConfig_1 = __importDefault(require("./constants/arbConfig")); -const arbTestnetConfig_1 = __importDefault(require("./constants/arbTestnetConfig")); -const fantomConfig_1 = __importDefault(require("./constants/fantomConfig")); -const testFantomConfig_1 = __importDefault(require("./constants/testFantomConfig")); -(0, config_1.task)('deploy:arb', 'Deploys Arbitrum contracts').setAction(async function (taskArguments, { ethers }) { - const mainnet = true; - const ARB_CONFIG = mainnet ? arbConfig_1.default : arbTestnetConfig_1.default; - const FTM_CONFIG = mainnet ? fantomConfig_1.default : testFantomConfig_1.default; - console.log('ALCHEMY_MAINNET_ARBITRUM_API_KEY: ', process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY); +'use strict' +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod } + } +Object.defineProperty(exports, '__esModule', { value: true }) +const config_1 = require('hardhat/config') +const arbConfig_1 = __importDefault(require('./constants/arbConfig')) +const arbTestnetConfig_1 = __importDefault( + require('./constants/arbTestnetConfig') +) +const fantomConfig_1 = __importDefault(require('./constants/fantomConfig')) +const testFantomConfig_1 = __importDefault( + require('./constants/testFantomConfig') +) +;(0, config_1.task)('deploy:arb', 'Deploys Arbitrum contracts').setAction( + async function (taskArguments, { ethers }) { + const mainnet = true + const ARB_CONFIG = mainnet + ? arbConfig_1.default + : arbTestnetConfig_1.default + const FTM_CONFIG = mainnet + ? fantomConfig_1.default + : testFantomConfig_1.default + console.log( + 'ALCHEMY_MAINNET_ARBITRUM_API_KEY: ', + process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY + ) // Load - const [Velo, GaugeFactory, BribeFactory, PairFactory, Router, Library, VeArtProxy, VotingEscrow, RewardsDistributor, Voter, Minter, VeloGovernor, RedemptionReceiver, MerkleClaim] = await Promise.all([ - ethers.getContractFactory('Velo'), - ethers.getContractFactory('GaugeFactory'), - ethers.getContractFactory('BribeFactory'), - ethers.getContractFactory('PairFactory'), - ethers.getContractFactory('Router'), - ethers.getContractFactory('VelodromeLibrary'), - ethers.getContractFactory('VeArtProxy'), - ethers.getContractFactory('VotingEscrow'), - ethers.getContractFactory('RewardsDistributor'), - ethers.getContractFactory('Voter'), - ethers.getContractFactory('Minter'), - ethers.getContractFactory('VeloGovernor'), - ethers.getContractFactory('RedemptionReceiver'), - ethers.getContractFactory('MerkleClaim') - ]); - const velo = await Velo.deploy(); - await velo.deployed(); - console.log('Velo deployed to dunks: ', velo.address); - const gaugeFactory = await GaugeFactory.deploy(); - await gaugeFactory.deployed(); - console.log('GaugeFactory deployed to: ', gaugeFactory.address); - const bribeFactory = await BribeFactory.deploy(); - await bribeFactory.deployed(); - console.log('BribeFactory deployed to: ', bribeFactory.address); - const pairFactory = await PairFactory.deploy(); - await pairFactory.deployed(); - console.log('PairFactory deployed to: ', pairFactory.address); - const router = await Router.deploy(pairFactory.address, ARB_CONFIG.WETH); - await router.deployed(); - console.log('Router deployed to: ', router.address); - console.log('Args: ', pairFactory.address, ARB_CONFIG.WETH, '\n'); - const library = await Library.deploy(router.address); - await library.deployed(); - console.log('VelodromeLibrary deployed to: ', library.address); - console.log('Args: ', router.address, '\n'); - const artProxy = await VeArtProxy.deploy(); - await artProxy.deployed(); - console.log('VeArtProxy deployed to: ', artProxy.address); - const escrow = await VotingEscrow.deploy(velo.address, artProxy.address); - await escrow.deployed(); - console.log('VotingEscrow deployed to: ', escrow.address); - console.log('Args: ', velo.address, artProxy.address, '\n'); - const distributor = await RewardsDistributor.deploy(escrow.address); - await distributor.deployed(); - console.log('RewardsDistributor deployed to: ', distributor.address); - console.log('Args: ', escrow.address, '\n'); - const voter = await Voter.deploy(escrow.address, pairFactory.address, gaugeFactory.address, bribeFactory.address); - await voter.deployed(); - console.log('Voter deployed to: ', voter.address); - console.log('Args: ', escrow.address, pairFactory.address, gaugeFactory.address, bribeFactory.address, '\n'); - const minter = await Minter.deploy(voter.address, escrow.address, distributor.address); - await minter.deployed(); - console.log('Minter deployed to: ', minter.address); - console.log('Args: ', voter.address, escrow.address, distributor.address, '\n'); - const receiver = await RedemptionReceiver.deploy(ARB_CONFIG.USDC, velo.address, FTM_CONFIG.lzChainId, ARB_CONFIG.lzEndpoint); - await receiver.deployed(); - console.log('RedemptionReceiver deployed to: ', receiver.address); - console.log('Args: ', ARB_CONFIG.USDC, velo.address, FTM_CONFIG.lzChainId, ARB_CONFIG.lzEndpoint, '\n'); - const governor = await VeloGovernor.deploy(escrow.address); - await governor.deployed(); - console.log('VeloGovernor deployed to: ', governor.address); - console.log('Args: ', escrow.address, '\n'); + const [ + Flow, + GaugeFactory, + BribeFactory, + PairFactory, + Router, + Library, + VeArtProxy, + VotingEscrow, + RewardsDistributor, + Voter, + Minter, + VeloGovernor, + RedemptionReceiver, + MerkleClaim + ] = await Promise.all([ + ethers.getContractFactory('Flow'), + ethers.getContractFactory('GaugeFactory'), + ethers.getContractFactory('BribeFactory'), + ethers.getContractFactory('PairFactory'), + ethers.getContractFactory('Router'), + ethers.getContractFactory('VelodromeLibrary'), + ethers.getContractFactory('VeArtProxy'), + ethers.getContractFactory('VotingEscrow'), + ethers.getContractFactory('RewardsDistributor'), + ethers.getContractFactory('Voter'), + ethers.getContractFactory('Minter'), + ethers.getContractFactory('VeloGovernor'), + ethers.getContractFactory('RedemptionReceiver'), + ethers.getContractFactory('MerkleClaim') + ]) + const flow = await Flow.deploy() + await flow.deployed() + console.log('Flow deployed to dunks: ', flow.address) + const gaugeFactory = await GaugeFactory.deploy() + await gaugeFactory.deployed() + console.log('GaugeFactory deployed to: ', gaugeFactory.address) + const bribeFactory = await BribeFactory.deploy() + await bribeFactory.deployed() + console.log('BribeFactory deployed to: ', bribeFactory.address) + const pairFactory = await PairFactory.deploy() + await pairFactory.deployed() + console.log('PairFactory deployed to: ', pairFactory.address) + const router = await Router.deploy(pairFactory.address, ARB_CONFIG.WETH) + await router.deployed() + console.log('Router deployed to: ', router.address) + console.log('Args: ', pairFactory.address, ARB_CONFIG.WETH, '\n') + const library = await Library.deploy(router.address) + await library.deployed() + console.log('VelodromeLibrary deployed to: ', library.address) + console.log('Args: ', router.address, '\n') + const artProxy = await VeArtProxy.deploy() + await artProxy.deployed() + console.log('VeArtProxy deployed to: ', artProxy.address) + const escrow = await VotingEscrow.deploy(flow.address, artProxy.address) + await escrow.deployed() + console.log('VotingEscrow deployed to: ', escrow.address) + console.log('Args: ', flow.address, artProxy.address, '\n') + const distributor = await RewardsDistributor.deploy(escrow.address) + await distributor.deployed() + console.log('RewardsDistributor deployed to: ', distributor.address) + console.log('Args: ', escrow.address, '\n') + const voter = await Voter.deploy( + escrow.address, + pairFactory.address, + gaugeFactory.address, + bribeFactory.address + ) + await voter.deployed() + console.log('Voter deployed to: ', voter.address) + console.log( + 'Args: ', + escrow.address, + pairFactory.address, + gaugeFactory.address, + bribeFactory.address, + '\n' + ) + const minter = await Minter.deploy( + voter.address, + escrow.address, + distributor.address + ) + await minter.deployed() + console.log('Minter deployed to: ', minter.address) + console.log( + 'Args: ', + voter.address, + escrow.address, + distributor.address, + '\n' + ) + const receiver = await RedemptionReceiver.deploy( + ARB_CONFIG.USDC, + flow.address, + FTM_CONFIG.lzChainId, + ARB_CONFIG.lzEndpoint + ) + await receiver.deployed() + console.log('RedemptionReceiver deployed to: ', receiver.address) + console.log( + 'Args: ', + ARB_CONFIG.USDC, + flow.address, + FTM_CONFIG.lzChainId, + ARB_CONFIG.lzEndpoint, + '\n' + ) + const governor = await VeloGovernor.deploy(escrow.address) + await governor.deployed() + console.log('VeloGovernor deployed to: ', governor.address) + console.log('Args: ', escrow.address, '\n') // Airdrop - const claim = await MerkleClaim.deploy(velo.address, ARB_CONFIG.merkleRoot); - await claim.deployed(); - console.log('MerkleClaim deployed to: ', claim.address); - console.log('Args: ', velo.address, ARB_CONFIG.merkleRoot, '\n'); + const claim = await MerkleClaim.deploy(flow.address, ARB_CONFIG.merkleRoot) + await claim.deployed() + console.log('MerkleClaim deployed to: ', claim.address) + console.log('Args: ', flow.address, ARB_CONFIG.merkleRoot, '\n') // Initialize - await velo.initialMint(ARB_CONFIG.teamEOA); - console.log('Initial minted'); - await velo.setRedemptionReceiver(receiver.address); - console.log('RedemptionReceiver set'); - await velo.setMerkleClaim(claim.address); - console.log('MerkleClaim set'); - await velo.setMinter(minter.address); - console.log('Minter set'); - await pairFactory.setPauser(ARB_CONFIG.teamMultisig); - console.log('Pauser set'); - await escrow.setVoter(voter.address); - console.log('Voter set'); - await escrow.setTeam(ARB_CONFIG.teamMultisig); - console.log('Team set for escrow'); - await voter.setGovernor(ARB_CONFIG.teamMultisig); - console.log('Governor set'); - await voter.setEmergencyCouncil(ARB_CONFIG.teamMultisig); - console.log('Emergency Council set'); - await distributor.setDepositor(minter.address); - console.log('Depositor set'); - await receiver.setTeam(ARB_CONFIG.teamMultisig); - console.log('Team set for receiver'); - await governor.setTeam(ARB_CONFIG.teamMultisig); - console.log('Team set for governor'); + await flow.initialMint(ARB_CONFIG.teamEOA) + console.log('Initial minted') + await flow.setRedemptionReceiver(receiver.address) + console.log('RedemptionReceiver set') + await flow.setMerkleClaim(claim.address) + console.log('MerkleClaim set') + await flow.setMinter(minter.address) + console.log('Minter set') + await pairFactory.setPauser(ARB_CONFIG.teamMultisig) + console.log('Pauser set') + await escrow.setVoter(voter.address) + console.log('Voter set') + await escrow.setTeam(ARB_CONFIG.teamMultisig) + console.log('Team set for escrow') + await voter.setGovernor(ARB_CONFIG.teamMultisig) + console.log('Governor set') + await voter.setEmergencyCouncil(ARB_CONFIG.teamMultisig) + console.log('Emergency Council set') + await distributor.setDepositor(minter.address) + console.log('Depositor set') + await receiver.setTeam(ARB_CONFIG.teamMultisig) + console.log('Team set for receiver') + await governor.setTeam(ARB_CONFIG.teamMultisig) + console.log('Team set for governor') // Whitelist - const nativeToken = [velo.address]; - const tokenWhitelist = nativeToken.concat(ARB_CONFIG.tokenWhitelist); - await voter.initialize(tokenWhitelist, minter.address); - console.log('Whitelist set'); + const nativeToken = [flow.address] + const tokenWhitelist = nativeToken.concat(ARB_CONFIG.tokenWhitelist) + await voter.initialize(tokenWhitelist, minter.address) + console.log('Whitelist set') // Initial veVELO distro - await minter.initialize(ARB_CONFIG.partnerAddrs, ARB_CONFIG.partnerAmts, ARB_CONFIG.partnerMax); - console.log('veVELO distributed'); - await minter.setTeam(ARB_CONFIG.teamMultisig); - console.log('Team set for minter'); - console.log('Arbitrum contracts deployed'); -}); + await minter.initialize( + ARB_CONFIG.partnerAddrs, + ARB_CONFIG.partnerAmts, + ARB_CONFIG.partnerMax + ) + console.log('veVELO distributed') + await minter.setTeam(ARB_CONFIG.teamMultisig) + console.log('Team set for minter') + console.log('Arbitrum contracts deployed') + } +) diff --git a/dist/tasks/deploy/arbHardhat.js b/dist/tasks/deploy/arbHardhat.js index f3f593d2..2643f9f6 100644 --- a/dist/tasks/deploy/arbHardhat.js +++ b/dist/tasks/deploy/arbHardhat.js @@ -1,121 +1,188 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const config_1 = require("hardhat/config"); -const arbConfig_1 = __importDefault(require("./constants/arbConfig")); -const arbHardhatConfig_1 = __importDefault(require("./constants/arbHardhatConfig")); -const fantomConfig_1 = __importDefault(require("./constants/fantomConfig")); -const testFantomConfig_1 = __importDefault(require("./constants/testFantomConfig")); -(0, config_1.task)('deploy:arbHardhat', 'Deploys Arbitrum forked chain contracts').setAction(async function (taskArguments, { ethers }) { - const mainnet = false; - const ARB_CONFIG = mainnet ? arbConfig_1.default : arbHardhatConfig_1.default; - const FTM_CONFIG = mainnet ? fantomConfig_1.default : testFantomConfig_1.default; - console.log('ALCHEMY_MAINNET_ARBITRUM_API_KEY: ', process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY); - // Load - const [Velo, GaugeFactory, BribeFactory, PairFactory, Router, Library, VeArtProxy, VotingEscrow, RewardsDistributor, Voter, Minter, VeloGovernor, RedemptionReceiver, MerkleClaim] = await Promise.all([ - ethers.getContractFactory('Velo'), - ethers.getContractFactory('GaugeFactory'), - ethers.getContractFactory('BribeFactory'), - ethers.getContractFactory('PairFactory'), - ethers.getContractFactory('Router'), - ethers.getContractFactory('VelodromeLibrary'), - ethers.getContractFactory('VeArtProxy'), - ethers.getContractFactory('VotingEscrow'), - ethers.getContractFactory('RewardsDistributor'), - ethers.getContractFactory('Voter'), - ethers.getContractFactory('Minter'), - ethers.getContractFactory('VeloGovernor'), - ethers.getContractFactory('RedemptionReceiver'), - ethers.getContractFactory('MerkleClaim') - ]); - const velo = await Velo.deploy(); - await velo.deployed(); - console.log('Velo deployed to dunks: ', velo.address); - const gaugeFactory = await GaugeFactory.deploy(); - await gaugeFactory.deployed(); - console.log('GaugeFactory deployed to: ', gaugeFactory.address); - const bribeFactory = await BribeFactory.deploy(); - await bribeFactory.deployed(); - console.log('BribeFactory deployed to: ', bribeFactory.address); - const pairFactory = await PairFactory.deploy(); - await pairFactory.deployed(); - console.log('PairFactory deployed to: ', pairFactory.address); - const router = await Router.deploy(pairFactory.address, ARB_CONFIG.WETH); - await router.deployed(); - console.log('Router deployed to: ', router.address); - console.log('Args: ', pairFactory.address, ARB_CONFIG.WETH, '\n'); - const library = await Library.deploy(router.address); - await library.deployed(); - console.log('VelodromeLibrary deployed to: ', library.address); - console.log('Args: ', router.address, '\n'); - const artProxy = await VeArtProxy.deploy(); - await artProxy.deployed(); - console.log('VeArtProxy deployed to: ', artProxy.address); - const escrow = await VotingEscrow.deploy(velo.address, artProxy.address); - await escrow.deployed(); - console.log('VotingEscrow deployed to: ', escrow.address); - console.log('Args: ', velo.address, artProxy.address, '\n'); - const distributor = await RewardsDistributor.deploy(escrow.address); - await distributor.deployed(); - console.log('RewardsDistributor deployed to: ', distributor.address); - console.log('Args: ', escrow.address, '\n'); - const voter = await Voter.deploy(escrow.address, pairFactory.address, gaugeFactory.address, bribeFactory.address); - await voter.deployed(); - console.log('Voter deployed to: ', voter.address); - console.log('Args: ', escrow.address, pairFactory.address, gaugeFactory.address, bribeFactory.address, '\n'); - const minter = await Minter.deploy(voter.address, escrow.address, distributor.address); - await minter.deployed(); - console.log('Minter deployed to: ', minter.address); - console.log('Args: ', voter.address, escrow.address, distributor.address, '\n'); - const receiver = await RedemptionReceiver.deploy(ARB_CONFIG.USDC, velo.address, FTM_CONFIG.lzChainId, ARB_CONFIG.lzEndpoint); - await receiver.deployed(); - console.log('RedemptionReceiver deployed to: ', receiver.address); - console.log('Args: ', ARB_CONFIG.USDC, velo.address, FTM_CONFIG.lzChainId, ARB_CONFIG.lzEndpoint, '\n'); - const governor = await VeloGovernor.deploy(escrow.address); - await governor.deployed(); - console.log('VeloGovernor deployed to: ', governor.address); - console.log('Args: ', escrow.address, '\n'); - // Airdrop - const claim = await MerkleClaim.deploy(velo.address, ARB_CONFIG.merkleRoot); - await claim.deployed(); - console.log('MerkleClaim deployed to: ', claim.address); - console.log('Args: ', velo.address, ARB_CONFIG.merkleRoot, '\n'); - // Initialize - await velo.initialMint(ARB_CONFIG.teamEOA); - console.log('Initial minted'); - await velo.setRedemptionReceiver(receiver.address); - console.log('RedemptionReceiver set'); - await velo.setMerkleClaim(claim.address); - console.log('MerkleClaim set'); - await velo.setMinter(minter.address); - console.log('Minter set'); - await pairFactory.setPauser(ARB_CONFIG.teamMultisig); - console.log('Pauser set'); - await escrow.setVoter(voter.address); - console.log('Voter set'); - await escrow.setTeam(ARB_CONFIG.teamMultisig); - console.log('Team set for escrow'); - await voter.setGovernor(ARB_CONFIG.teamMultisig); - console.log('Governor set'); - await voter.setEmergencyCouncil(ARB_CONFIG.teamMultisig); - console.log('Emergency Council set'); - await distributor.setDepositor(minter.address); - console.log('Depositor set'); - await receiver.setTeam(ARB_CONFIG.teamMultisig); - console.log('Team set for receiver'); - await governor.setTeam(ARB_CONFIG.teamMultisig); - console.log('Team set for governor'); - // Whitelist - const nativeToken = [velo.address]; - const tokenWhitelist = nativeToken.concat(ARB_CONFIG.tokenWhitelist); - await voter.initialize(tokenWhitelist, minter.address); - console.log('Whitelist set'); - // Initial veVELO distro - await minter.initialize(ARB_CONFIG.partnerAddrs, ARB_CONFIG.partnerAmts, ARB_CONFIG.partnerMax); - console.log('veVELO distributed'); - await minter.setTeam(ARB_CONFIG.teamMultisig); - console.log('Team set for minter'); - console.log('Arbitrum Forked Chain contracts deployed'); -}); +'use strict' +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod } + } +Object.defineProperty(exports, '__esModule', { value: true }) +const config_1 = require('hardhat/config') +const arbConfig_1 = __importDefault(require('./constants/arbConfig')) +const arbHardhatConfig_1 = __importDefault( + require('./constants/arbHardhatConfig') +) +const fantomConfig_1 = __importDefault(require('./constants/fantomConfig')) +const testFantomConfig_1 = __importDefault( + require('./constants/testFantomConfig') +) +;(0, config_1.task)( + 'deploy:arbHardhat', + 'Deploys Arbitrum forked chain contracts' +).setAction(async function (taskArguments, { ethers }) { + const mainnet = false + const ARB_CONFIG = mainnet ? arbConfig_1.default : arbHardhatConfig_1.default + const FTM_CONFIG = mainnet + ? fantomConfig_1.default + : testFantomConfig_1.default + console.log( + 'ALCHEMY_MAINNET_ARBITRUM_API_KEY: ', + process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY + ) + // Load + const [ + Flow, + GaugeFactory, + BribeFactory, + PairFactory, + Router, + Library, + VeArtProxy, + VotingEscrow, + RewardsDistributor, + Voter, + Minter, + VeloGovernor, + RedemptionReceiver, + MerkleClaim + ] = await Promise.all([ + ethers.getContractFactory('Flow'), + ethers.getContractFactory('GaugeFactory'), + ethers.getContractFactory('BribeFactory'), + ethers.getContractFactory('PairFactory'), + ethers.getContractFactory('Router'), + ethers.getContractFactory('VelodromeLibrary'), + ethers.getContractFactory('VeArtProxy'), + ethers.getContractFactory('VotingEscrow'), + ethers.getContractFactory('RewardsDistributor'), + ethers.getContractFactory('Voter'), + ethers.getContractFactory('Minter'), + ethers.getContractFactory('VeloGovernor'), + ethers.getContractFactory('RedemptionReceiver'), + ethers.getContractFactory('MerkleClaim') + ]) + const flow = await Flow.deploy() + await flow.deployed() + console.log('Flow deployed to dunks: ', flow.address) + const gaugeFactory = await GaugeFactory.deploy() + await gaugeFactory.deployed() + console.log('GaugeFactory deployed to: ', gaugeFactory.address) + const bribeFactory = await BribeFactory.deploy() + await bribeFactory.deployed() + console.log('BribeFactory deployed to: ', bribeFactory.address) + const pairFactory = await PairFactory.deploy() + await pairFactory.deployed() + console.log('PairFactory deployed to: ', pairFactory.address) + const router = await Router.deploy(pairFactory.address, ARB_CONFIG.WETH) + await router.deployed() + console.log('Router deployed to: ', router.address) + console.log('Args: ', pairFactory.address, ARB_CONFIG.WETH, '\n') + const library = await Library.deploy(router.address) + await library.deployed() + console.log('VelodromeLibrary deployed to: ', library.address) + console.log('Args: ', router.address, '\n') + const artProxy = await VeArtProxy.deploy() + await artProxy.deployed() + console.log('VeArtProxy deployed to: ', artProxy.address) + const escrow = await VotingEscrow.deploy(flow.address, artProxy.address) + await escrow.deployed() + console.log('VotingEscrow deployed to: ', escrow.address) + console.log('Args: ', flow.address, artProxy.address, '\n') + const distributor = await RewardsDistributor.deploy(escrow.address) + await distributor.deployed() + console.log('RewardsDistributor deployed to: ', distributor.address) + console.log('Args: ', escrow.address, '\n') + const voter = await Voter.deploy( + escrow.address, + pairFactory.address, + gaugeFactory.address, + bribeFactory.address + ) + await voter.deployed() + console.log('Voter deployed to: ', voter.address) + console.log( + 'Args: ', + escrow.address, + pairFactory.address, + gaugeFactory.address, + bribeFactory.address, + '\n' + ) + const minter = await Minter.deploy( + voter.address, + escrow.address, + distributor.address + ) + await minter.deployed() + console.log('Minter deployed to: ', minter.address) + console.log( + 'Args: ', + voter.address, + escrow.address, + distributor.address, + '\n' + ) + const receiver = await RedemptionReceiver.deploy( + ARB_CONFIG.USDC, + flow.address, + FTM_CONFIG.lzChainId, + ARB_CONFIG.lzEndpoint + ) + await receiver.deployed() + console.log('RedemptionReceiver deployed to: ', receiver.address) + console.log( + 'Args: ', + ARB_CONFIG.USDC, + flow.address, + FTM_CONFIG.lzChainId, + ARB_CONFIG.lzEndpoint, + '\n' + ) + const governor = await VeloGovernor.deploy(escrow.address) + await governor.deployed() + console.log('VeloGovernor deployed to: ', governor.address) + console.log('Args: ', escrow.address, '\n') + // Airdrop + const claim = await MerkleClaim.deploy(flow.address, ARB_CONFIG.merkleRoot) + await claim.deployed() + console.log('MerkleClaim deployed to: ', claim.address) + console.log('Args: ', flow.address, ARB_CONFIG.merkleRoot, '\n') + // Initialize + await flow.initialMint(ARB_CONFIG.teamEOA) + console.log('Initial minted') + await flow.setRedemptionReceiver(receiver.address) + console.log('RedemptionReceiver set') + await flow.setMerkleClaim(claim.address) + console.log('MerkleClaim set') + await flow.setMinter(minter.address) + console.log('Minter set') + await pairFactory.setPauser(ARB_CONFIG.teamMultisig) + console.log('Pauser set') + await escrow.setVoter(voter.address) + console.log('Voter set') + await escrow.setTeam(ARB_CONFIG.teamMultisig) + console.log('Team set for escrow') + await voter.setGovernor(ARB_CONFIG.teamMultisig) + console.log('Governor set') + await voter.setEmergencyCouncil(ARB_CONFIG.teamMultisig) + console.log('Emergency Council set') + await distributor.setDepositor(minter.address) + console.log('Depositor set') + await receiver.setTeam(ARB_CONFIG.teamMultisig) + console.log('Team set for receiver') + await governor.setTeam(ARB_CONFIG.teamMultisig) + console.log('Team set for governor') + // Whitelist + const nativeToken = [flow.address] + const tokenWhitelist = nativeToken.concat(ARB_CONFIG.tokenWhitelist) + await voter.initialize(tokenWhitelist, minter.address) + console.log('Whitelist set') + // Initial veVELO distro + await minter.initialize( + ARB_CONFIG.partnerAddrs, + ARB_CONFIG.partnerAmts, + ARB_CONFIG.partnerMax + ) + console.log('veVELO distributed') + await minter.setTeam(ARB_CONFIG.teamMultisig) + console.log('Team set for minter') + console.log('Arbitrum Forked Chain contracts deployed') +}) diff --git a/dist/tasks/deploy/arbTest.js b/dist/tasks/deploy/arbTest.js index 9981b8df..c2c79915 100644 --- a/dist/tasks/deploy/arbTest.js +++ b/dist/tasks/deploy/arbTest.js @@ -1,35 +1,61 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const config_1 = require("hardhat/config"); -var fs = require('fs'); -const optimismConfig_1 = __importDefault(require("./constants/optimismConfig")); -const testOptimismConfig_1 = __importDefault(require("./constants/testOptimismConfig")); -const fantomConfig_1 = __importDefault(require("./constants/fantomConfig")); -const testFantomConfig_1 = __importDefault(require("./constants/testFantomConfig")); -(0, config_1.task)('deploy:arbTest', 'Deploys Optimism contracts').setAction(async function (taskArguments, { ethers }) { - const mainnet = false; - const OP_CONFIG = mainnet ? optimismConfig_1.default : testOptimismConfig_1.default; - const FTM_CONFIG = mainnet ? fantomConfig_1.default : testFantomConfig_1.default; +'use strict' +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod } + } +Object.defineProperty(exports, '__esModule', { value: true }) +const config_1 = require('hardhat/config') +var fs = require('fs') +const optimismConfig_1 = __importDefault(require('./constants/optimismConfig')) +const testOptimismConfig_1 = __importDefault( + require('./constants/testOptimismConfig') +) +const fantomConfig_1 = __importDefault(require('./constants/fantomConfig')) +const testFantomConfig_1 = __importDefault( + require('./constants/testFantomConfig') +) +;(0, config_1.task)('deploy:arbTest', 'Deploys Optimism contracts').setAction( + async function (taskArguments, { ethers }) { + const mainnet = false + const OP_CONFIG = mainnet + ? optimismConfig_1.default + : testOptimismConfig_1.default + const FTM_CONFIG = mainnet + ? fantomConfig_1.default + : testFantomConfig_1.default // Load - const [Velo, GaugeFactory, BribeFactory, PairFactory, Router, Library, VeArtProxy, VotingEscrow, RewardsDistributor, Voter, Minter, VeloGovernor, RedemptionReceiver, MerkleClaim] = await Promise.all([ - ethers.getContractFactory('Velo'), - ethers.getContractFactory('GaugeFactory'), - ethers.getContractFactory('BribeFactory'), - ethers.getContractFactory('PairFactory'), - ethers.getContractFactory('Router'), - ethers.getContractFactory('VelodromeLibrary'), - ethers.getContractFactory('VeArtProxy'), - ethers.getContractFactory('VotingEscrow'), - ethers.getContractFactory('RewardsDistributor'), - ethers.getContractFactory('Voter'), - ethers.getContractFactory('Minter'), - ethers.getContractFactory('VeloGovernor'), - ethers.getContractFactory('RedemptionReceiver'), - ethers.getContractFactory('MerkleClaim') - ]); + const [ + Flow, + GaugeFactory, + BribeFactory, + PairFactory, + Router, + Library, + VeArtProxy, + VotingEscrow, + RewardsDistributor, + Voter, + Minter, + VeloGovernor, + RedemptionReceiver, + MerkleClaim + ] = await Promise.all([ + ethers.getContractFactory('Flow'), + ethers.getContractFactory('GaugeFactory'), + ethers.getContractFactory('BribeFactory'), + ethers.getContractFactory('PairFactory'), + ethers.getContractFactory('Router'), + ethers.getContractFactory('VelodromeLibrary'), + ethers.getContractFactory('VeArtProxy'), + ethers.getContractFactory('VotingEscrow'), + ethers.getContractFactory('RewardsDistributor'), + ethers.getContractFactory('Voter'), + ethers.getContractFactory('Minter'), + ethers.getContractFactory('VeloGovernor'), + ethers.getContractFactory('RedemptionReceiver'), + ethers.getContractFactory('MerkleClaim') + ]) //WIP wait for 5 block transactions to ensure deployment before verifying // https://stackoverflow.com/questions/72916701/hardhat-compile-deploy-and-verify-in-a-single-script // https://github.com/profullstackdeveloper/contract-deploy-verify-hardhat @@ -37,40 +63,39 @@ const testFantomConfig_1 = __importDefault(require("./constants/testFantomConfig // await Promise.all.deployTransaction.wait(5) // //verify // await hre.run('verify:verify', { - // address: velo.address, - // contract: 'contracts/Velo.sol:MyContract', //Filename.sol:ClassName + // address: flow.address, + // contract: 'contracts/Flow.sol:MyContract', //Filename.sol:ClassName // constructorArguments: [arg1, arg2, arg3] // }) // WIP ^^ - const velo = await Velo.deploy(); - await velo.deployed(); - console.log('Velo deployed to: ', velo.address); + const flow = await Flow.deploy() + await flow.deployed() + console.log('Flow deployed to: ', flow.address) await hre.run('verify:verify', { - address: velo.address, - contract: 'contracts/Velo.sol:Velo', - constructorArguments: [] - }); - await velo.deployed(); - const name = await velo.name(); - console.log('dunksname: ', name); + address: flow.address, + contract: 'contracts/Flow.sol:Flow', + constructorArguments: [] + }) + await flow.deployed() + const name = await flow.name() + console.log('dunksname: ', name) const temp1 = { - [name]: velo.address - }; - const json1 = JSON.stringify(temp1); - console.log('result of json is ', json1); + [name]: flow.address + } + const json1 = JSON.stringify(temp1) + console.log('result of json is ', json1) fs.writeFileSync('contracts/deployments/veloAddress.json', json1, err => { - if (err) { - console.log('ERROR! while creating file: ', err); - } - else { - console.log('result is ', json1); - } - }); + if (err) { + console.log('ERROR! while creating file: ', err) + } else { + console.log('result is ', json1) + } + }) // repeat for gauge factory // update all the things... - const gaugeFactory = await GaugeFactory.deploy(); - await gaugeFactory.deployed(); - console.log('GaugeFactory deployed to: ', gaugeFactory.address); + const gaugeFactory = await GaugeFactory.deploy() + await gaugeFactory.deployed() + console.log('GaugeFactory deployed to: ', gaugeFactory.address) // await hre.run('verify:verify', { // address: gaugeFactory.address, // contract: 'contracts/factories/GaugeFactory.sol:GaugeFactory', //Filename.sol:ClassName @@ -91,86 +116,131 @@ const testFantomConfig_1 = __importDefault(require("./constants/testFantomConfig // console.log('result is ', json) // } // }) - const bribeFactory = await BribeFactory.deploy(); - await bribeFactory.deployed(); - console.log('BribeFactory deployed to: ', bribeFactory.address); - const pairFactory = await PairFactory.deploy(); - await pairFactory.deployed(); - console.log('PairFactory deployed to: ', pairFactory.address); - const router = await Router.deploy(pairFactory.address, OP_CONFIG.WETH); - await router.deployed(); - console.log('Router deployed to: ', router.address); - console.log('Args: ', pairFactory.address, OP_CONFIG.WETH, '\n'); - const library = await Library.deploy(router.address); - await library.deployed(); - console.log('VelodromeLibrary deployed to: ', library.address); - console.log('Args: ', router.address, '\n'); - const artProxy = await VeArtProxy.deploy(); - await artProxy.deployed(); - console.log('VeArtProxy deployed to: ', artProxy.address); - const escrow = await VotingEscrow.deploy(velo.address, artProxy.address); - await escrow.deployed(); - console.log('VotingEscrow deployed to: ', escrow.address); - console.log('Args: ', velo.address, artProxy.address, '\n'); - const distributor = await RewardsDistributor.deploy(escrow.address); - await distributor.deployed(); - console.log('RewardsDistributor deployed to: ', distributor.address); - console.log('Args: ', escrow.address, '\n'); - const voter = await Voter.deploy(escrow.address, pairFactory.address, gaugeFactory.address, bribeFactory.address); - await voter.deployed(); - console.log('Voter deployed to: ', voter.address); - console.log('Args: ', escrow.address, pairFactory.address, gaugeFactory.address, bribeFactory.address, '\n'); - const minter = await Minter.deploy(voter.address, escrow.address, distributor.address); - await minter.deployed(); - console.log('Minter deployed to: ', minter.address); - console.log('Args: ', voter.address, escrow.address, distributor.address, '\n'); - const receiver = await RedemptionReceiver.deploy(OP_CONFIG.USDC, velo.address, FTM_CONFIG.lzChainId, OP_CONFIG.lzEndpoint); - await receiver.deployed(); - console.log('RedemptionReceiver deployed to: ', receiver.address); - console.log('Args: ', OP_CONFIG.USDC, velo.address, FTM_CONFIG.lzChainId, OP_CONFIG.lzEndpoint, '\n'); - const governor = await VeloGovernor.deploy(escrow.address); - await governor.deployed(); - console.log('VeloGovernor deployed to: ', governor.address); - console.log('Args: ', escrow.address, '\n'); + const bribeFactory = await BribeFactory.deploy() + await bribeFactory.deployed() + console.log('BribeFactory deployed to: ', bribeFactory.address) + const pairFactory = await PairFactory.deploy() + await pairFactory.deployed() + console.log('PairFactory deployed to: ', pairFactory.address) + const router = await Router.deploy(pairFactory.address, OP_CONFIG.WETH) + await router.deployed() + console.log('Router deployed to: ', router.address) + console.log('Args: ', pairFactory.address, OP_CONFIG.WETH, '\n') + const library = await Library.deploy(router.address) + await library.deployed() + console.log('VelodromeLibrary deployed to: ', library.address) + console.log('Args: ', router.address, '\n') + const artProxy = await VeArtProxy.deploy() + await artProxy.deployed() + console.log('VeArtProxy deployed to: ', artProxy.address) + const escrow = await VotingEscrow.deploy(flow.address, artProxy.address) + await escrow.deployed() + console.log('VotingEscrow deployed to: ', escrow.address) + console.log('Args: ', flow.address, artProxy.address, '\n') + const distributor = await RewardsDistributor.deploy(escrow.address) + await distributor.deployed() + console.log('RewardsDistributor deployed to: ', distributor.address) + console.log('Args: ', escrow.address, '\n') + const voter = await Voter.deploy( + escrow.address, + pairFactory.address, + gaugeFactory.address, + bribeFactory.address + ) + await voter.deployed() + console.log('Voter deployed to: ', voter.address) + console.log( + 'Args: ', + escrow.address, + pairFactory.address, + gaugeFactory.address, + bribeFactory.address, + '\n' + ) + const minter = await Minter.deploy( + voter.address, + escrow.address, + distributor.address + ) + await minter.deployed() + console.log('Minter deployed to: ', minter.address) + console.log( + 'Args: ', + voter.address, + escrow.address, + distributor.address, + '\n' + ) + const receiver = await RedemptionReceiver.deploy( + OP_CONFIG.USDC, + flow.address, + FTM_CONFIG.lzChainId, + OP_CONFIG.lzEndpoint + ) + await receiver.deployed() + console.log('RedemptionReceiver deployed to: ', receiver.address) + console.log( + 'Args: ', + OP_CONFIG.USDC, + flow.address, + FTM_CONFIG.lzChainId, + OP_CONFIG.lzEndpoint, + '\n' + ) + const governor = await VeloGovernor.deploy(escrow.address) + await governor.deployed() + console.log('VeloGovernor deployed to: ', governor.address) + console.log('Args: ', escrow.address, '\n') // Airdrop - // const claim = await MerkleClaim.deploy(velo.address, OP_CONFIG.merkleRoot) + // const claim = await MerkleClaim.deploy(flow.address, OP_CONFIG.merkleRoot) // await claim.deployed() // console.log('MerkleClaim deployed to: ', claim.address) - // console.log('Args: ', velo.address, OP_CONFIG.merkleRoot, '\n') + // console.log('Args: ', flow.address, OP_CONFIG.merkleRoot, '\n') // Initialize - await velo.initialMint(OP_CONFIG.teamEOA); - console.log('Initial minted'); - await velo.setRedemptionReceiver(receiver.address); - console.log('RedemptionReceiver set'); - // await velo.setMerkleClaim(claim.address) + await flow.initialMint(OP_CONFIG.teamEOA) + console.log('Initial minted') + await flow.setRedemptionReceiver(receiver.address) + console.log('RedemptionReceiver set') + // await flow.setMerkleClaim(claim.address) // console.log('MerkleClaim set') - await velo.setMinter(minter.address); - console.log('Minter set'); - await pairFactory.setPauser(OP_CONFIG.teamMultisig); - console.log('Pauser set'); - await escrow.setVoter(voter.address); - console.log('Voter set', 'voter address: ', voter.address, 'escrow address: ', escrow.address); - await escrow.setTeam(OP_CONFIG.teamMultisig); - console.log('Team set for escrow'); - await voter.setGovernor(OP_CONFIG.teamMultisig); - console.log('Governor set'); - await voter.setEmergencyCouncil(OP_CONFIG.teamMultisig); - console.log('Emergency Council set'); - await distributor.setDepositor(minter.address); - console.log('Depositor set'); - await receiver.setTeam(OP_CONFIG.teamMultisig); - console.log('Team set for receiver'); - await governor.setTeam(OP_CONFIG.teamMultisig); - console.log('Team set for governor'); + await flow.setMinter(minter.address) + console.log('Minter set') + await pairFactory.setPauser(OP_CONFIG.teamMultisig) + console.log('Pauser set') + await escrow.setVoter(voter.address) + console.log( + 'Voter set', + 'voter address: ', + voter.address, + 'escrow address: ', + escrow.address + ) + await escrow.setTeam(OP_CONFIG.teamMultisig) + console.log('Team set for escrow') + await voter.setGovernor(OP_CONFIG.teamMultisig) + console.log('Governor set') + await voter.setEmergencyCouncil(OP_CONFIG.teamMultisig) + console.log('Emergency Council set') + await distributor.setDepositor(minter.address) + console.log('Depositor set') + await receiver.setTeam(OP_CONFIG.teamMultisig) + console.log('Team set for receiver') + await governor.setTeam(OP_CONFIG.teamMultisig) + console.log('Team set for governor') // Whitelist - const nativeToken = [velo.address]; - const tokenWhitelist = nativeToken.concat(OP_CONFIG.tokenWhitelist); - await voter.initialize(tokenWhitelist, minter.address); - console.log('Whitelist set'); + const nativeToken = [flow.address] + const tokenWhitelist = nativeToken.concat(OP_CONFIG.tokenWhitelist) + await voter.initialize(tokenWhitelist, minter.address) + console.log('Whitelist set') // Initial veVELO distro - await minter.initialize(OP_CONFIG.partnerAddrs, OP_CONFIG.partnerAmts, OP_CONFIG.partnerMax); - console.log('veVELO distributed'); - await minter.setTeam(OP_CONFIG.teamMultisig); - console.log('Team set for minter'); - console.log('Arbitrum Goerli Velocimeter Instruments deployed'); -}); + await minter.initialize( + OP_CONFIG.partnerAddrs, + OP_CONFIG.partnerAmts, + OP_CONFIG.partnerMax + ) + console.log('veVELO distributed') + await minter.setTeam(OP_CONFIG.teamMultisig) + console.log('Team set for minter') + console.log('Arbitrum Goerli Velocimeter Instruments deployed') + } +) diff --git a/dist/tasks/deploy/op.js b/dist/tasks/deploy/op.js index a09e3e9d..3f3e9ed3 100644 --- a/dist/tasks/deploy/op.js +++ b/dist/tasks/deploy/op.js @@ -1,120 +1,185 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const config_1 = require("hardhat/config"); -const optimismConfig_1 = __importDefault(require("./constants/optimismConfig")); -const testOptimismConfig_1 = __importDefault(require("./constants/testOptimismConfig")); -const fantomConfig_1 = __importDefault(require("./constants/fantomConfig")); -const testFantomConfig_1 = __importDefault(require("./constants/testFantomConfig")); -(0, config_1.task)("deploy:op", "Deploys Optimism contracts").setAction(async function (taskArguments, { ethers }) { - const mainnet = false; - const OP_CONFIG = mainnet ? optimismConfig_1.default : testOptimismConfig_1.default; - const FTM_CONFIG = mainnet ? fantomConfig_1.default : testFantomConfig_1.default; +'use strict' +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod } + } +Object.defineProperty(exports, '__esModule', { value: true }) +const config_1 = require('hardhat/config') +const optimismConfig_1 = __importDefault(require('./constants/optimismConfig')) +const testOptimismConfig_1 = __importDefault( + require('./constants/testOptimismConfig') +) +const fantomConfig_1 = __importDefault(require('./constants/fantomConfig')) +const testFantomConfig_1 = __importDefault( + require('./constants/testFantomConfig') +) +;(0, config_1.task)('deploy:op', 'Deploys Optimism contracts').setAction( + async function (taskArguments, { ethers }) { + const mainnet = false + const OP_CONFIG = mainnet + ? optimismConfig_1.default + : testOptimismConfig_1.default + const FTM_CONFIG = mainnet + ? fantomConfig_1.default + : testFantomConfig_1.default // Load - const [Velo, GaugeFactory, BribeFactory, PairFactory, Router, Library, VeArtProxy, VotingEscrow, RewardsDistributor, Voter, Minter, VeloGovernor, RedemptionReceiver, MerkleClaim,] = await Promise.all([ - ethers.getContractFactory("Velo"), - ethers.getContractFactory("GaugeFactory"), - ethers.getContractFactory("BribeFactory"), - ethers.getContractFactory("PairFactory"), - ethers.getContractFactory("Router"), - ethers.getContractFactory("VelodromeLibrary"), - ethers.getContractFactory("VeArtProxy"), - ethers.getContractFactory("VotingEscrow"), - ethers.getContractFactory("RewardsDistributor"), - ethers.getContractFactory("Voter"), - ethers.getContractFactory("Minter"), - ethers.getContractFactory("VeloGovernor"), - ethers.getContractFactory("RedemptionReceiver"), - ethers.getContractFactory("MerkleClaim"), - ]); - const velo = await Velo.deploy(); - await velo.deployed(); - console.log("Velo deployed to: ", velo.address); - const gaugeFactory = await GaugeFactory.deploy(); - await gaugeFactory.deployed(); - console.log("GaugeFactory deployed to: ", gaugeFactory.address); - const bribeFactory = await BribeFactory.deploy(); - await bribeFactory.deployed(); - console.log("BribeFactory deployed to: ", bribeFactory.address); - const pairFactory = await PairFactory.deploy(); - await pairFactory.deployed(); - console.log("PairFactory deployed to: ", pairFactory.address); - const router = await Router.deploy(pairFactory.address, OP_CONFIG.WETH); - await router.deployed(); - console.log("Router deployed to: ", router.address); - console.log("Args: ", pairFactory.address, OP_CONFIG.WETH, "\n"); - const library = await Library.deploy(router.address); - await library.deployed(); - console.log("VelodromeLibrary deployed to: ", library.address); - console.log("Args: ", router.address, "\n"); - const artProxy = await VeArtProxy.deploy(); - await artProxy.deployed(); - console.log("VeArtProxy deployed to: ", artProxy.address); - const escrow = await VotingEscrow.deploy(velo.address, artProxy.address); - await escrow.deployed(); - console.log("VotingEscrow deployed to: ", escrow.address); - console.log("Args: ", velo.address, artProxy.address, "\n"); - const distributor = await RewardsDistributor.deploy(escrow.address); - await distributor.deployed(); - console.log("RewardsDistributor deployed to: ", distributor.address); - console.log("Args: ", escrow.address, "\n"); - const voter = await Voter.deploy(escrow.address, pairFactory.address, gaugeFactory.address, bribeFactory.address); - await voter.deployed(); - console.log("Voter deployed to: ", voter.address); - console.log("Args: ", escrow.address, pairFactory.address, gaugeFactory.address, bribeFactory.address, "\n"); - const minter = await Minter.deploy(voter.address, escrow.address, distributor.address); - await minter.deployed(); - console.log("Minter deployed to: ", minter.address); - console.log("Args: ", voter.address, escrow.address, distributor.address, "\n"); - const receiver = await RedemptionReceiver.deploy(OP_CONFIG.USDC, velo.address, FTM_CONFIG.lzChainId, OP_CONFIG.lzEndpoint); - await receiver.deployed(); - console.log("RedemptionReceiver deployed to: ", receiver.address); - console.log("Args: ", OP_CONFIG.USDC, velo.address, FTM_CONFIG.lzChainId, OP_CONFIG.lzEndpoint, "\n"); - const governor = await VeloGovernor.deploy(escrow.address); - await governor.deployed(); - console.log("VeloGovernor deployed to: ", governor.address); - console.log("Args: ", escrow.address, "\n"); + const [ + Flow, + GaugeFactory, + BribeFactory, + PairFactory, + Router, + Library, + VeArtProxy, + VotingEscrow, + RewardsDistributor, + Voter, + Minter, + VeloGovernor, + RedemptionReceiver, + MerkleClaim + ] = await Promise.all([ + ethers.getContractFactory('Flow'), + ethers.getContractFactory('GaugeFactory'), + ethers.getContractFactory('BribeFactory'), + ethers.getContractFactory('PairFactory'), + ethers.getContractFactory('Router'), + ethers.getContractFactory('VelodromeLibrary'), + ethers.getContractFactory('VeArtProxy'), + ethers.getContractFactory('VotingEscrow'), + ethers.getContractFactory('RewardsDistributor'), + ethers.getContractFactory('Voter'), + ethers.getContractFactory('Minter'), + ethers.getContractFactory('VeloGovernor'), + ethers.getContractFactory('RedemptionReceiver'), + ethers.getContractFactory('MerkleClaim') + ]) + const flow = await Flow.deploy() + await flow.deployed() + console.log('Flow deployed to: ', flow.address) + const gaugeFactory = await GaugeFactory.deploy() + await gaugeFactory.deployed() + console.log('GaugeFactory deployed to: ', gaugeFactory.address) + const bribeFactory = await BribeFactory.deploy() + await bribeFactory.deployed() + console.log('BribeFactory deployed to: ', bribeFactory.address) + const pairFactory = await PairFactory.deploy() + await pairFactory.deployed() + console.log('PairFactory deployed to: ', pairFactory.address) + const router = await Router.deploy(pairFactory.address, OP_CONFIG.WETH) + await router.deployed() + console.log('Router deployed to: ', router.address) + console.log('Args: ', pairFactory.address, OP_CONFIG.WETH, '\n') + const library = await Library.deploy(router.address) + await library.deployed() + console.log('VelodromeLibrary deployed to: ', library.address) + console.log('Args: ', router.address, '\n') + const artProxy = await VeArtProxy.deploy() + await artProxy.deployed() + console.log('VeArtProxy deployed to: ', artProxy.address) + const escrow = await VotingEscrow.deploy(flow.address, artProxy.address) + await escrow.deployed() + console.log('VotingEscrow deployed to: ', escrow.address) + console.log('Args: ', flow.address, artProxy.address, '\n') + const distributor = await RewardsDistributor.deploy(escrow.address) + await distributor.deployed() + console.log('RewardsDistributor deployed to: ', distributor.address) + console.log('Args: ', escrow.address, '\n') + const voter = await Voter.deploy( + escrow.address, + pairFactory.address, + gaugeFactory.address, + bribeFactory.address + ) + await voter.deployed() + console.log('Voter deployed to: ', voter.address) + console.log( + 'Args: ', + escrow.address, + pairFactory.address, + gaugeFactory.address, + bribeFactory.address, + '\n' + ) + const minter = await Minter.deploy( + voter.address, + escrow.address, + distributor.address + ) + await minter.deployed() + console.log('Minter deployed to: ', minter.address) + console.log( + 'Args: ', + voter.address, + escrow.address, + distributor.address, + '\n' + ) + const receiver = await RedemptionReceiver.deploy( + OP_CONFIG.USDC, + flow.address, + FTM_CONFIG.lzChainId, + OP_CONFIG.lzEndpoint + ) + await receiver.deployed() + console.log('RedemptionReceiver deployed to: ', receiver.address) + console.log( + 'Args: ', + OP_CONFIG.USDC, + flow.address, + FTM_CONFIG.lzChainId, + OP_CONFIG.lzEndpoint, + '\n' + ) + const governor = await VeloGovernor.deploy(escrow.address) + await governor.deployed() + console.log('VeloGovernor deployed to: ', governor.address) + console.log('Args: ', escrow.address, '\n') // Airdrop - const claim = await MerkleClaim.deploy(velo.address, OP_CONFIG.merkleRoot); - await claim.deployed(); - console.log("MerkleClaim deployed to: ", claim.address); - console.log("Args: ", velo.address, OP_CONFIG.merkleRoot, "\n"); + const claim = await MerkleClaim.deploy(flow.address, OP_CONFIG.merkleRoot) + await claim.deployed() + console.log('MerkleClaim deployed to: ', claim.address) + console.log('Args: ', flow.address, OP_CONFIG.merkleRoot, '\n') // Initialize - await velo.initialMint(OP_CONFIG.teamEOA); - console.log("Initial minted"); - await velo.setRedemptionReceiver(receiver.address); - console.log("RedemptionReceiver set"); - await velo.setMerkleClaim(claim.address); - console.log("MerkleClaim set"); - await velo.setMinter(minter.address); - console.log("Minter set"); - await pairFactory.setPauser(OP_CONFIG.teamMultisig); - console.log("Pauser set"); - await escrow.setVoter(voter.address); - console.log("Voter set"); - await escrow.setTeam(OP_CONFIG.teamMultisig); - console.log("Team set for escrow"); - await voter.setGovernor(OP_CONFIG.teamMultisig); - console.log("Governor set"); - await voter.setEmergencyCouncil(OP_CONFIG.teamMultisig); - console.log("Emergency Council set"); - await distributor.setDepositor(minter.address); - console.log("Depositor set"); - await receiver.setTeam(OP_CONFIG.teamMultisig); - console.log("Team set for receiver"); - await governor.setTeam(OP_CONFIG.teamMultisig); - console.log("Team set for governor"); + await flow.initialMint(OP_CONFIG.teamEOA) + console.log('Initial minted') + await flow.setRedemptionReceiver(receiver.address) + console.log('RedemptionReceiver set') + await flow.setMerkleClaim(claim.address) + console.log('MerkleClaim set') + await flow.setMinter(minter.address) + console.log('Minter set') + await pairFactory.setPauser(OP_CONFIG.teamMultisig) + console.log('Pauser set') + await escrow.setVoter(voter.address) + console.log('Voter set') + await escrow.setTeam(OP_CONFIG.teamMultisig) + console.log('Team set for escrow') + await voter.setGovernor(OP_CONFIG.teamMultisig) + console.log('Governor set') + await voter.setEmergencyCouncil(OP_CONFIG.teamMultisig) + console.log('Emergency Council set') + await distributor.setDepositor(minter.address) + console.log('Depositor set') + await receiver.setTeam(OP_CONFIG.teamMultisig) + console.log('Team set for receiver') + await governor.setTeam(OP_CONFIG.teamMultisig) + console.log('Team set for governor') // Whitelist - const nativeToken = [velo.address]; - const tokenWhitelist = nativeToken.concat(OP_CONFIG.tokenWhitelist); - await voter.initialize(tokenWhitelist, minter.address); - console.log("Whitelist set"); + const nativeToken = [flow.address] + const tokenWhitelist = nativeToken.concat(OP_CONFIG.tokenWhitelist) + await voter.initialize(tokenWhitelist, minter.address) + console.log('Whitelist set') // Initial veVELO distro - await minter.initialize(OP_CONFIG.partnerAddrs, OP_CONFIG.partnerAmts, OP_CONFIG.partnerMax); - console.log("veVELO distributed"); - await minter.setTeam(OP_CONFIG.teamMultisig); - console.log("Team set for minter"); - console.log("Optimism contracts deployed"); -}); + await minter.initialize( + OP_CONFIG.partnerAddrs, + OP_CONFIG.partnerAmts, + OP_CONFIG.partnerMax + ) + console.log('veVELO distributed') + await minter.setTeam(OP_CONFIG.teamMultisig) + console.log('Team set for minter') + console.log('Optimism contracts deployed') + } +) diff --git a/hardhat.config.ts b/hardhat.config.ts index 8858281b..60675af1 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -36,7 +36,7 @@ const config: HardhatUserConfig = { url: 'https://rpc.fantom.network', accounts: [process.env.PRIVATE_KEY!] }, - arbitrum: { + arbitrumOne: { url: `https://arb-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY}`, accounts: [process.env.PRIVATE_KEY!], chainId: 42161, @@ -105,7 +105,7 @@ const config: HardhatUserConfig = { // ftmTestnet: process.env.FTM_SCAN_API_KEY!, // optimisticEthereum: process.env.OP_SCAN_API_KEY!, - arbitrum: process.env.ARB_SCAN_API_KEY!, + arbitrumOne: process.env.ARB_SCAN_API_KEY!, arbitrumGoerli: process.env.ARB_SCAN_API_KEY! } } diff --git a/readme.md b/readme.md index f23ca64f..7dfde675 100644 --- a/readme.md +++ b/readme.md @@ -23,7 +23,7 @@ npx hardhat --network arbitrumGoerli export --export ./exported.json RewardsDistributor: '0xc4b9295487B4C43C1929299076820D8f55BBf957', Router: '0x1B0aC6bf6f35E638f6cce8D69C6074561273dc52', VeArtProxy: '0x821B98D42D3AB509AF4F54205f0c52B019b9E2D5', - Velo: '0x84Ca387E7ede764A3284c67Ff8c68a305a9030a0', + Flow: '0x84Ca387E7ede764A3284c67Ff8c68a305a9030a0', VeloGovernor: '0x1a79b9daa3E741774bf67732F8a8B5820De8A53a', VelodromeLibrary: '0xcbE4714A95f866EB9C2eB50856F431f9E7353Ab6', Voter: '0x854086d39955d28317aE3856399312b8Edb1B473', @@ -61,14 +61,14 @@ Deployment contains 3 steps: ## Security -The Velodrome team engaged with Code 4rena for a security review. The results of that audit are available [here](https://code4rena.com/reports/2022-05-velodrome/). Our up-to-date security findings are located on our website [here](https://docs.velodrome.finance/security). +The Velocimeter team engaged with Code 4rena for a security review. The results of that audit are available [here](https://code4rena.com/reports/2022-05-velodrome/). Our up-to-date security findings are located on our website [here](https://docs.velodrome.finance/security). ## Contracts | Name | Address | | :----------------- | :------------------------------------------------------------------------------------------------------------------------------------ | | WETH | [0x4200000000000000000000000000000000000006](https://optimistic.etherscan.io/address/0x4200000000000000000000000000000000000006#code) | -| Velo | [0x3c8B650257cFb5f272f799F5e2b4e65093a11a05](https://optimistic.etherscan.io/address/0x3c8B650257cFb5f272f799F5e2b4e65093a11a05#code) | +| Flow | [0x3c8B650257cFb5f272f799F5e2b4e65093a11a05](https://optimistic.etherscan.io/address/0x3c8B650257cFb5f272f799F5e2b4e65093a11a05#code) | | MerkleClaim | [0x00D59BC35174C3b250Dd92a363495d38C8777a49](https://optimistic.etherscan.io/address/0x00D59BC35174C3b250Dd92a363495d38C8777a49#code) | | RedemptionSender | [0x9809fB94eED086F9529df00d6f125Bf25Ee84A93](https://ftmscan.com/address/0x9809fB94eED086F9529df00d6f125Bf25Ee84A93#code) | | RedemptionReceiver | [0x846e822e9a00669dcC647079d7d625d2cd25A951](https://optimistic.etherscan.io/address/0x846e822e9a00669dcC647079d7d625d2cd25A951#code) | diff --git a/tasks/deploy/arb.ts b/tasks/deploy/arb.ts index e61be7f7..b505b3f2 100644 --- a/tasks/deploy/arb.ts +++ b/tasks/deploy/arb.ts @@ -25,7 +25,7 @@ task('deploy:arb', 'Deploys Arbitrum contracts').setAction(async function ( // Load const [ - Velo, + Flow, GaugeFactory, BribeFactory, PairFactory, @@ -40,7 +40,7 @@ task('deploy:arb', 'Deploys Arbitrum contracts').setAction(async function ( RedemptionReceiver, MerkleClaim ] = await Promise.all([ - ethers.getContractFactory('Velo'), + ethers.getContractFactory('Flow'), ethers.getContractFactory('GaugeFactory'), ethers.getContractFactory('BribeFactory'), ethers.getContractFactory('PairFactory'), @@ -56,9 +56,9 @@ task('deploy:arb', 'Deploys Arbitrum contracts').setAction(async function ( ethers.getContractFactory('MerkleClaim') ]) - const velo = await Velo.deploy() - await velo.deployed() - console.log('Velo deployed to dunks: ', velo.address) + const flow = await Flow.deploy() + await flow.deployed() + console.log('Flow deployed to dunks: ', flow.address) const gaugeFactory = await GaugeFactory.deploy() await gaugeFactory.deployed() @@ -86,10 +86,10 @@ task('deploy:arb', 'Deploys Arbitrum contracts').setAction(async function ( await artProxy.deployed() console.log('VeArtProxy deployed to: ', artProxy.address) - const escrow = await VotingEscrow.deploy(velo.address, artProxy.address) + const escrow = await VotingEscrow.deploy(flow.address, artProxy.address) await escrow.deployed() console.log('VotingEscrow deployed to: ', escrow.address) - console.log('Args: ', velo.address, artProxy.address, '\n') + console.log('Args: ', flow.address, artProxy.address, '\n') const distributor = await RewardsDistributor.deploy(escrow.address) await distributor.deployed() @@ -130,7 +130,7 @@ task('deploy:arb', 'Deploys Arbitrum contracts').setAction(async function ( const receiver = await RedemptionReceiver.deploy( ARB_CONFIG.USDC, - velo.address, + flow.address, FTM_CONFIG.lzChainId, ARB_CONFIG.lzEndpoint ) @@ -139,7 +139,7 @@ task('deploy:arb', 'Deploys Arbitrum contracts').setAction(async function ( console.log( 'Args: ', ARB_CONFIG.USDC, - velo.address, + flow.address, FTM_CONFIG.lzChainId, ARB_CONFIG.lzEndpoint, '\n' @@ -151,22 +151,22 @@ task('deploy:arb', 'Deploys Arbitrum contracts').setAction(async function ( console.log('Args: ', escrow.address, '\n') // Airdrop - const claim = await MerkleClaim.deploy(velo.address, ARB_CONFIG.merkleRoot) + const claim = await MerkleClaim.deploy(flow.address, ARB_CONFIG.merkleRoot) await claim.deployed() console.log('MerkleClaim deployed to: ', claim.address) - console.log('Args: ', velo.address, ARB_CONFIG.merkleRoot, '\n') + console.log('Args: ', flow.address, ARB_CONFIG.merkleRoot, '\n') // Initialize - await velo.initialMint(ARB_CONFIG.teamEOA) + await flow.initialMint(ARB_CONFIG.teamEOA) console.log('Initial minted') - await velo.setRedemptionReceiver(receiver.address) + await flow.setRedemptionReceiver(receiver.address) console.log('RedemptionReceiver set') - await velo.setMerkleClaim(claim.address) + await flow.setMerkleClaim(claim.address) console.log('MerkleClaim set') - await velo.setMinter(minter.address) + await flow.setMinter(minter.address) console.log('Minter set') await pairFactory.setPauser(ARB_CONFIG.teamMultisig) @@ -194,7 +194,7 @@ task('deploy:arb', 'Deploys Arbitrum contracts').setAction(async function ( console.log('Team set for governor') // Whitelist - const nativeToken = [velo.address] + const nativeToken = [flow.address] const tokenWhitelist = nativeToken.concat(ARB_CONFIG.tokenWhitelist) await voter.initialize(tokenWhitelist, minter.address) console.log('Whitelist set') diff --git a/tasks/deploy/arbHardhat.ts b/tasks/deploy/arbHardhat.ts index 701ae98b..ab07603f 100644 --- a/tasks/deploy/arbHardhat.ts +++ b/tasks/deploy/arbHardhat.ts @@ -22,7 +22,7 @@ task('deploy:arbHardhat', 'Deploys Arbitrum forked chain contracts').setAction( // Load const [ - Velo, + Flow, GaugeFactory, BribeFactory, PairFactory, @@ -37,7 +37,7 @@ task('deploy:arbHardhat', 'Deploys Arbitrum forked chain contracts').setAction( RedemptionReceiver, MerkleClaim ] = await Promise.all([ - ethers.getContractFactory('Velo'), + ethers.getContractFactory('Flow'), ethers.getContractFactory('GaugeFactory'), ethers.getContractFactory('BribeFactory'), ethers.getContractFactory('PairFactory'), @@ -53,9 +53,9 @@ task('deploy:arbHardhat', 'Deploys Arbitrum forked chain contracts').setAction( ethers.getContractFactory('MerkleClaim') ]) - const velo = await Velo.deploy() - await velo.deployed() - console.log('Velo deployed to dunks: ', velo.address) + const flow = await Flow.deploy() + await flow.deployed() + console.log('Flow deployed to dunks: ', flow.address) const gaugeFactory = await GaugeFactory.deploy() await gaugeFactory.deployed() @@ -83,10 +83,10 @@ task('deploy:arbHardhat', 'Deploys Arbitrum forked chain contracts').setAction( await artProxy.deployed() console.log('VeArtProxy deployed to: ', artProxy.address) - const escrow = await VotingEscrow.deploy(velo.address, artProxy.address) + const escrow = await VotingEscrow.deploy(flow.address, artProxy.address) await escrow.deployed() console.log('VotingEscrow deployed to: ', escrow.address) - console.log('Args: ', velo.address, artProxy.address, '\n') + console.log('Args: ', flow.address, artProxy.address, '\n') const distributor = await RewardsDistributor.deploy(escrow.address) await distributor.deployed() @@ -127,7 +127,7 @@ task('deploy:arbHardhat', 'Deploys Arbitrum forked chain contracts').setAction( const receiver = await RedemptionReceiver.deploy( ARB_CONFIG.USDC, - velo.address, + flow.address, FTM_CONFIG.lzChainId, ARB_CONFIG.lzEndpoint ) @@ -136,7 +136,7 @@ task('deploy:arbHardhat', 'Deploys Arbitrum forked chain contracts').setAction( console.log( 'Args: ', ARB_CONFIG.USDC, - velo.address, + flow.address, FTM_CONFIG.lzChainId, ARB_CONFIG.lzEndpoint, '\n' @@ -148,22 +148,22 @@ task('deploy:arbHardhat', 'Deploys Arbitrum forked chain contracts').setAction( console.log('Args: ', escrow.address, '\n') // Airdrop - const claim = await MerkleClaim.deploy(velo.address, ARB_CONFIG.merkleRoot) + const claim = await MerkleClaim.deploy(flow.address, ARB_CONFIG.merkleRoot) await claim.deployed() console.log('MerkleClaim deployed to: ', claim.address) - console.log('Args: ', velo.address, ARB_CONFIG.merkleRoot, '\n') + console.log('Args: ', flow.address, ARB_CONFIG.merkleRoot, '\n') // Initialize - await velo.initialMint(ARB_CONFIG.teamEOA) + await flow.initialMint(ARB_CONFIG.teamEOA) console.log('Initial minted') - await velo.setRedemptionReceiver(receiver.address) + await flow.setRedemptionReceiver(receiver.address) console.log('RedemptionReceiver set') - await velo.setMerkleClaim(claim.address) + await flow.setMerkleClaim(claim.address) console.log('MerkleClaim set') - await velo.setMinter(minter.address) + await flow.setMinter(minter.address) console.log('Minter set') await pairFactory.setPauser(ARB_CONFIG.teamMultisig) @@ -191,7 +191,7 @@ task('deploy:arbHardhat', 'Deploys Arbitrum forked chain contracts').setAction( console.log('Team set for governor') // Whitelist - const nativeToken = [velo.address] + const nativeToken = [flow.address] const tokenWhitelist = nativeToken.concat(ARB_CONFIG.tokenWhitelist) await voter.initialize(tokenWhitelist, minter.address) console.log('Whitelist set') diff --git a/tasks/deploy/arbTest.ts b/tasks/deploy/arbTest.ts index e007848c..dd928cf8 100644 --- a/tasks/deploy/arbTest.ts +++ b/tasks/deploy/arbTest.ts @@ -19,7 +19,7 @@ task('deploy:arbTest', 'Deploys Optimism contracts').setAction(async function ( // Load const [ - Velo, + Flow, GaugeFactory, BribeFactory, PairFactory, @@ -34,7 +34,7 @@ task('deploy:arbTest', 'Deploys Optimism contracts').setAction(async function ( RedemptionReceiver, MerkleClaim ] = await Promise.all([ - ethers.getContractFactory('Velo'), + ethers.getContractFactory('Flow'), ethers.getContractFactory('GaugeFactory'), ethers.getContractFactory('BribeFactory'), ethers.getContractFactory('PairFactory'), @@ -59,29 +59,29 @@ task('deploy:arbTest', 'Deploys Optimism contracts').setAction(async function ( // //verify // await hre.run('verify:verify', { - // address: velo.address, - // contract: 'contracts/Velo.sol:MyContract', //Filename.sol:ClassName + // address: flow.address, + // contract: 'contracts/Flow.sol:MyContract', //Filename.sol:ClassName // constructorArguments: [arg1, arg2, arg3] // }) // WIP ^^ - const velo = await Velo.deploy() - await velo.deployed() - console.log('Velo deployed to: ', velo.address) + const flow = await Flow.deploy() + await flow.deployed() + console.log('Flow deployed to: ', flow.address) await hre.run('verify:verify', { - address: velo.address, - contract: 'contracts/Velo.sol:Velo', //Filename.sol:ClassName + address: flow.address, + contract: 'contracts/Flow.sol:Flow', //Filename.sol:ClassName constructorArguments: [] }) - await velo.deployed() - const name = await velo.name() + await flow.deployed() + const name = await flow.name() console.log('dunksname: ', name) const temp1 = { - [name]: velo.address + [name]: flow.address } const json1 = JSON.stringify(temp1) console.log('result of json is ', json1) @@ -145,10 +145,10 @@ task('deploy:arbTest', 'Deploys Optimism contracts').setAction(async function ( await artProxy.deployed() console.log('VeArtProxy deployed to: ', artProxy.address) - const escrow = await VotingEscrow.deploy(velo.address, artProxy.address) + const escrow = await VotingEscrow.deploy(flow.address, artProxy.address) await escrow.deployed() console.log('VotingEscrow deployed to: ', escrow.address) - console.log('Args: ', velo.address, artProxy.address, '\n') + console.log('Args: ', flow.address, artProxy.address, '\n') const distributor = await RewardsDistributor.deploy(escrow.address) await distributor.deployed() @@ -189,7 +189,7 @@ task('deploy:arbTest', 'Deploys Optimism contracts').setAction(async function ( const receiver = await RedemptionReceiver.deploy( OP_CONFIG.USDC, - velo.address, + flow.address, FTM_CONFIG.lzChainId, OP_CONFIG.lzEndpoint ) @@ -198,7 +198,7 @@ task('deploy:arbTest', 'Deploys Optimism contracts').setAction(async function ( console.log( 'Args: ', OP_CONFIG.USDC, - velo.address, + flow.address, FTM_CONFIG.lzChainId, OP_CONFIG.lzEndpoint, '\n' @@ -210,22 +210,22 @@ task('deploy:arbTest', 'Deploys Optimism contracts').setAction(async function ( console.log('Args: ', escrow.address, '\n') // Airdrop - // const claim = await MerkleClaim.deploy(velo.address, OP_CONFIG.merkleRoot) + // const claim = await MerkleClaim.deploy(flow.address, OP_CONFIG.merkleRoot) // await claim.deployed() // console.log('MerkleClaim deployed to: ', claim.address) - // console.log('Args: ', velo.address, OP_CONFIG.merkleRoot, '\n') + // console.log('Args: ', flow.address, OP_CONFIG.merkleRoot, '\n') // Initialize - await velo.initialMint(OP_CONFIG.teamEOA) + await flow.initialMint(OP_CONFIG.teamEOA) console.log('Initial minted') - await velo.setRedemptionReceiver(receiver.address) + await flow.setRedemptionReceiver(receiver.address) console.log('RedemptionReceiver set') - // await velo.setMerkleClaim(claim.address) + // await flow.setMerkleClaim(claim.address) // console.log('MerkleClaim set') - await velo.setMinter(minter.address) + await flow.setMinter(minter.address) console.log('Minter set') await pairFactory.setPauser(OP_CONFIG.teamMultisig) @@ -259,7 +259,7 @@ task('deploy:arbTest', 'Deploys Optimism contracts').setAction(async function ( console.log('Team set for governor') // Whitelist - const nativeToken = [velo.address] + const nativeToken = [flow.address] const tokenWhitelist = nativeToken.concat(OP_CONFIG.tokenWhitelist) await voter.initialize(tokenWhitelist, minter.address) console.log('Whitelist set') diff --git a/tasks/deploy/op.ts b/tasks/deploy/op.ts index e6fecd13..18ec5ac9 100644 --- a/tasks/deploy/op.ts +++ b/tasks/deploy/op.ts @@ -1,23 +1,23 @@ -import { task } from "hardhat/config"; +import { task } from 'hardhat/config' -import optimismConfig from "./constants/optimismConfig"; -import testOptimismConfig from "./constants/testOptimismConfig"; +import optimismConfig from './constants/optimismConfig' +import testOptimismConfig from './constants/testOptimismConfig' -import fantomConfig from "./constants/fantomConfig"; -import testFantomConfig from "./constants/testFantomConfig"; +import fantomConfig from './constants/fantomConfig' +import testFantomConfig from './constants/testFantomConfig' -task("deploy:op", "Deploys Optimism contracts").setAction(async function ( +task('deploy:op', 'Deploys Optimism contracts').setAction(async function ( taskArguments, { ethers } ) { - const mainnet = false; + const mainnet = false - const OP_CONFIG = mainnet ? optimismConfig : testOptimismConfig; - const FTM_CONFIG = mainnet ? fantomConfig : testFantomConfig; + const OP_CONFIG = mainnet ? optimismConfig : testOptimismConfig + const FTM_CONFIG = mainnet ? fantomConfig : testFantomConfig // Load const [ - Velo, + Flow, GaugeFactory, BribeFactory, PairFactory, @@ -30,174 +30,177 @@ task("deploy:op", "Deploys Optimism contracts").setAction(async function ( Minter, VeloGovernor, RedemptionReceiver, - MerkleClaim, + MerkleClaim ] = await Promise.all([ - ethers.getContractFactory("Velo"), - ethers.getContractFactory("GaugeFactory"), - ethers.getContractFactory("BribeFactory"), - ethers.getContractFactory("PairFactory"), - ethers.getContractFactory("Router"), - ethers.getContractFactory("VelodromeLibrary"), - ethers.getContractFactory("VeArtProxy"), - ethers.getContractFactory("VotingEscrow"), - ethers.getContractFactory("RewardsDistributor"), - ethers.getContractFactory("Voter"), - ethers.getContractFactory("Minter"), - ethers.getContractFactory("VeloGovernor"), - ethers.getContractFactory("RedemptionReceiver"), - ethers.getContractFactory("MerkleClaim"), - ]); - - const velo = await Velo.deploy(); - await velo.deployed(); - console.log("Velo deployed to: ", velo.address); - - const gaugeFactory = await GaugeFactory.deploy(); - await gaugeFactory.deployed(); - console.log("GaugeFactory deployed to: ", gaugeFactory.address); - - const bribeFactory = await BribeFactory.deploy(); - await bribeFactory.deployed(); - console.log("BribeFactory deployed to: ", bribeFactory.address); - - const pairFactory = await PairFactory.deploy(); - await pairFactory.deployed(); - console.log("PairFactory deployed to: ", pairFactory.address); - - const router = await Router.deploy(pairFactory.address, OP_CONFIG.WETH); - await router.deployed(); - console.log("Router deployed to: ", router.address); - console.log("Args: ", pairFactory.address, OP_CONFIG.WETH, "\n"); - - const library = await Library.deploy(router.address); - await library.deployed(); - console.log("VelodromeLibrary deployed to: ", library.address); - console.log("Args: ", router.address, "\n"); - - const artProxy = await VeArtProxy.deploy(); - await artProxy.deployed(); - console.log("VeArtProxy deployed to: ", artProxy.address); - - const escrow = await VotingEscrow.deploy(velo.address, artProxy.address); - await escrow.deployed(); - console.log("VotingEscrow deployed to: ", escrow.address); - console.log("Args: ", velo.address, artProxy.address, "\n"); - - const distributor = await RewardsDistributor.deploy(escrow.address); - await distributor.deployed(); - console.log("RewardsDistributor deployed to: ", distributor.address); - console.log("Args: ", escrow.address, "\n"); + ethers.getContractFactory('Flow'), + ethers.getContractFactory('GaugeFactory'), + ethers.getContractFactory('BribeFactory'), + ethers.getContractFactory('PairFactory'), + ethers.getContractFactory('Router'), + ethers.getContractFactory('VelodromeLibrary'), + ethers.getContractFactory('VeArtProxy'), + ethers.getContractFactory('VotingEscrow'), + ethers.getContractFactory('RewardsDistributor'), + ethers.getContractFactory('Voter'), + ethers.getContractFactory('Minter'), + ethers.getContractFactory('VeloGovernor'), + ethers.getContractFactory('RedemptionReceiver'), + ethers.getContractFactory('MerkleClaim') + ]) + + const flow = await Flow.deploy() + await flow.deployed() + console.log('Flow deployed to: ', flow.address) + + const gaugeFactory = await GaugeFactory.deploy() + await gaugeFactory.deployed() + console.log('GaugeFactory deployed to: ', gaugeFactory.address) + + const bribeFactory = await BribeFactory.deploy() + await bribeFactory.deployed() + console.log('BribeFactory deployed to: ', bribeFactory.address) + + const pairFactory = await PairFactory.deploy() + await pairFactory.deployed() + console.log('PairFactory deployed to: ', pairFactory.address) + + const router = await Router.deploy(pairFactory.address, OP_CONFIG.WETH) + await router.deployed() + console.log('Router deployed to: ', router.address) + console.log('Args: ', pairFactory.address, OP_CONFIG.WETH, '\n') + + const library = await Library.deploy(router.address) + await library.deployed() + console.log('VelodromeLibrary deployed to: ', library.address) + console.log('Args: ', router.address, '\n') + + const artProxy = await VeArtProxy.deploy() + await artProxy.deployed() + console.log('VeArtProxy deployed to: ', artProxy.address) + + const escrow = await VotingEscrow.deploy(flow.address, artProxy.address) + await escrow.deployed() + console.log('VotingEscrow deployed to: ', escrow.address) + console.log('Args: ', flow.address, artProxy.address, '\n') + + const distributor = await RewardsDistributor.deploy(escrow.address) + await distributor.deployed() + console.log('RewardsDistributor deployed to: ', distributor.address) + console.log('Args: ', escrow.address, '\n') const voter = await Voter.deploy( escrow.address, pairFactory.address, gaugeFactory.address, bribeFactory.address - ); - await voter.deployed(); - console.log("Voter deployed to: ", voter.address); - console.log("Args: ", + ) + await voter.deployed() + console.log('Voter deployed to: ', voter.address) + console.log( + 'Args: ', escrow.address, pairFactory.address, gaugeFactory.address, bribeFactory.address, - "\n" - ); + '\n' + ) const minter = await Minter.deploy( voter.address, escrow.address, distributor.address - ); - await minter.deployed(); - console.log("Minter deployed to: ", minter.address); - console.log("Args: ", + ) + await minter.deployed() + console.log('Minter deployed to: ', minter.address) + console.log( + 'Args: ', voter.address, escrow.address, distributor.address, - "\n" - ); + '\n' + ) const receiver = await RedemptionReceiver.deploy( OP_CONFIG.USDC, - velo.address, + flow.address, FTM_CONFIG.lzChainId, - OP_CONFIG.lzEndpoint, - ); - await receiver.deployed(); - console.log("RedemptionReceiver deployed to: ", receiver.address); - console.log("Args: ", + OP_CONFIG.lzEndpoint + ) + await receiver.deployed() + console.log('RedemptionReceiver deployed to: ', receiver.address) + console.log( + 'Args: ', OP_CONFIG.USDC, - velo.address, + flow.address, FTM_CONFIG.lzChainId, OP_CONFIG.lzEndpoint, - "\n" - ); + '\n' + ) - const governor = await VeloGovernor.deploy(escrow.address); - await governor.deployed(); - console.log("VeloGovernor deployed to: ", governor.address); - console.log("Args: ", escrow.address, "\n"); + const governor = await VeloGovernor.deploy(escrow.address) + await governor.deployed() + console.log('VeloGovernor deployed to: ', governor.address) + console.log('Args: ', escrow.address, '\n') // Airdrop - const claim = await MerkleClaim.deploy(velo.address, OP_CONFIG.merkleRoot); - await claim.deployed(); - console.log("MerkleClaim deployed to: ", claim.address); - console.log("Args: ", velo.address, OP_CONFIG.merkleRoot, "\n"); + const claim = await MerkleClaim.deploy(flow.address, OP_CONFIG.merkleRoot) + await claim.deployed() + console.log('MerkleClaim deployed to: ', claim.address) + console.log('Args: ', flow.address, OP_CONFIG.merkleRoot, '\n') // Initialize - await velo.initialMint(OP_CONFIG.teamEOA); - console.log("Initial minted"); + await flow.initialMint(OP_CONFIG.teamEOA) + console.log('Initial minted') - await velo.setRedemptionReceiver(receiver.address); - console.log("RedemptionReceiver set"); + await flow.setRedemptionReceiver(receiver.address) + console.log('RedemptionReceiver set') - await velo.setMerkleClaim(claim.address); - console.log("MerkleClaim set"); + await flow.setMerkleClaim(claim.address) + console.log('MerkleClaim set') - await velo.setMinter(minter.address); - console.log("Minter set"); + await flow.setMinter(minter.address) + console.log('Minter set') - await pairFactory.setPauser(OP_CONFIG.teamMultisig); - console.log("Pauser set"); + await pairFactory.setPauser(OP_CONFIG.teamMultisig) + console.log('Pauser set') - await escrow.setVoter(voter.address); - console.log("Voter set"); + await escrow.setVoter(voter.address) + console.log('Voter set') - await escrow.setTeam(OP_CONFIG.teamMultisig); - console.log("Team set for escrow"); + await escrow.setTeam(OP_CONFIG.teamMultisig) + console.log('Team set for escrow') - await voter.setGovernor(OP_CONFIG.teamMultisig); - console.log("Governor set"); + await voter.setGovernor(OP_CONFIG.teamMultisig) + console.log('Governor set') - await voter.setEmergencyCouncil(OP_CONFIG.teamMultisig); - console.log("Emergency Council set"); + await voter.setEmergencyCouncil(OP_CONFIG.teamMultisig) + console.log('Emergency Council set') - await distributor.setDepositor(minter.address); - console.log("Depositor set"); + await distributor.setDepositor(minter.address) + console.log('Depositor set') await receiver.setTeam(OP_CONFIG.teamMultisig) - console.log("Team set for receiver"); + console.log('Team set for receiver') await governor.setTeam(OP_CONFIG.teamMultisig) - console.log("Team set for governor"); + console.log('Team set for governor') // Whitelist - const nativeToken = [velo.address]; - const tokenWhitelist = nativeToken.concat(OP_CONFIG.tokenWhitelist); - await voter.initialize(tokenWhitelist, minter.address); - console.log("Whitelist set"); + const nativeToken = [flow.address] + const tokenWhitelist = nativeToken.concat(OP_CONFIG.tokenWhitelist) + await voter.initialize(tokenWhitelist, minter.address) + console.log('Whitelist set') // Initial veVELO distro await minter.initialize( OP_CONFIG.partnerAddrs, OP_CONFIG.partnerAmts, OP_CONFIG.partnerMax - ); - console.log("veVELO distributed"); + ) + console.log('veVELO distributed') await minter.setTeam(OP_CONFIG.teamMultisig) - console.log("Team set for minter"); + console.log('Team set for minter') - console.log("Optimism contracts deployed"); -}); + console.log('Optimism contracts deployed') +}) diff --git a/test/BaseTest.sol b/test/BaseTest.sol index a5629e70..66fc097e 100644 --- a/test/BaseTest.sol +++ b/test/BaseTest.sol @@ -17,7 +17,7 @@ import "contracts/Pair.sol"; import "contracts/PairFees.sol"; import "contracts/RewardsDistributor.sol"; import "contracts/Router.sol"; -import "contracts/Velo.sol"; +import "contracts/Flow.sol"; import "contracts/VelodromeLibrary.sol"; import "contracts/Voter.sol"; import "contracts/VeArtProxy.sol"; @@ -47,7 +47,7 @@ abstract contract BaseTest is Test, TestOwner { MockERC20 FRAX; MockERC20 DAI; TestWETH WETH; // Mock WETH token - Velo VELO; + Flow VELO; MockERC20 WEVE; MockERC20 LR; // late reward TestToken stake; // MockERC20 with claimFees() function that returns (0,0) @@ -72,7 +72,7 @@ abstract contract BaseTest is Test, TestOwner { USDC = new MockERC20("USDC", "USDC", 6); FRAX = new MockERC20("FRAX", "FRAX", 18); DAI = new MockERC20("DAI", "DAI", 18); - VELO = new Velo(); + VELO = new Flow(); WEVE = new MockERC20("WEVE", "WEVE", 18); LR = new MockERC20("LR", "LR", 18); WETH = new TestWETH(); diff --git a/test/utils/TestOwner.sol b/test/utils/TestOwner.sol index bd3510a7..ee90679f 100644 --- a/test/utils/TestOwner.sol +++ b/test/utils/TestOwner.sol @@ -6,7 +6,7 @@ import "contracts/Gauge.sol"; import "contracts/Minter.sol"; import "contracts/Pair.sol"; import "contracts/Router.sol"; -import "contracts/Velo.sol"; +import "contracts/Flow.sol"; import "contracts/VotingEscrow.sol"; import "utils/TestStakingRewards.sol"; import "utils/TestVotingEscrow.sol"; From bf65c59e12ac6320903b60bf999ea090762fc09b Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Fri, 27 Jan 2023 14:26:11 +1100 Subject: [PATCH 17/43] _velo _flow --- contractNameAndAddress.ts | 2 +- .../{VeloGovernor.sol => FlowGovernor.sol} | 0 contracts/Minter.sol | 26 +- ...romeLibrary.sol => VelocimeterLibrary.sol} | 2 +- contracts/redeem/MerkleClaim.sol | 6 +- contracts/redeem/RedemptionReceiver.sol | 4 +- deploy/00_velo.ts | 2 +- deploy/01_gaugeFactory.ts | 24 +- deploy/02_bribeFactory.ts | 24 +- deploy/04_pairFactory.ts | 24 +- deploy/05_router.ts | 2 +- deploy/06_library.ts | 26 +- deploy/07_veArtProxy.ts | 24 +- deploy/08_votingEscrow.ts | 2 +- deploy/09_rewardsDist.ts | 26 +- deploy/10_voter.ts | 34 +- deploy/11_minter.ts | 30 +- deploy/12_veloGovernor.ts | 26 +- deploy/13_redemptionReceiver.ts | 2 +- deploy/14_merkleClaim.ts | 2 +- deployments/arbitrumGoerli/Flow.json | 522 ++++++++++++++++++ .../d10aa8d28a580b2f5faf1ce0f5049c27.json | 238 ++++++++ dist/deploy/00_velo.js | 2 +- dist/deploy/01_gaugeFactory.js | 30 +- dist/deploy/02_bribeFactory.js | 30 +- dist/deploy/04_pairFactory.js | 30 +- dist/deploy/05_router.js | 46 +- dist/deploy/06_library.js | 32 +- dist/deploy/07_veArtProxy.js | 30 +- dist/deploy/08_votingEscrow.js | 2 +- dist/deploy/09_rewardsDist.js | 32 +- dist/deploy/10_voter.js | 48 +- dist/deploy/11_minter.js | 36 +- dist/deploy/12_veloGovernor.js | 32 +- dist/deploy/13_redemptionReceiver.js | 2 +- dist/deploy/14_merkleClaim.js | 2 +- dist/tasks/deploy/arb.js | 4 +- dist/tasks/deploy/arbHardhat.js | 4 +- dist/tasks/deploy/arbTest.js | 4 +- dist/tasks/deploy/init.js | 6 +- dist/tasks/deploy/op.js | 4 +- package.json | 5 +- readme.md | 2 +- tasks/deploy/arb.ts | 4 +- tasks/deploy/arbHardhat.ts | 4 +- tasks/deploy/arbTest.ts | 4 +- tasks/deploy/init.ts | 4 +- tasks/deploy/op.ts | 4 +- test/BaseTest.sol | 6 +- 49 files changed, 1111 insertions(+), 346 deletions(-) rename contracts/{VeloGovernor.sol => FlowGovernor.sol} (100%) rename contracts/{VelodromeLibrary.sol => VelocimeterLibrary.sol} (99%) create mode 100644 deployments/arbitrumGoerli/Flow.json create mode 100644 deployments/arbitrumGoerli/solcInputs/d10aa8d28a580b2f5faf1ce0f5049c27.json diff --git a/contractNameAndAddress.ts b/contractNameAndAddress.ts index 5a134846..2ad237cb 100644 --- a/contractNameAndAddress.ts +++ b/contractNameAndAddress.ts @@ -11,7 +11,7 @@ const func: GetContractNames = async function (hre: HardhatRuntimeEnvironment) { from: deployer, args: [], log: true, - skipIfAlreadyDeployed: true + skipIfAlreadyDeployed: false }) } export default func diff --git a/contracts/VeloGovernor.sol b/contracts/FlowGovernor.sol similarity index 100% rename from contracts/VeloGovernor.sol rename to contracts/FlowGovernor.sol diff --git a/contracts/Minter.sol b/contracts/Minter.sol index f359f5a2..a6ead9e6 100644 --- a/contracts/Minter.sol +++ b/contracts/Minter.sol @@ -15,7 +15,7 @@ contract Minter is IMinter { uint256 internal constant EMISSION = 990; uint256 internal constant TAIL_EMISSION = 2; uint256 internal constant PRECISION = 1000; - IFlow public immutable _velo; + IFlow public immutable _flow; IVoter public immutable _voter; IVotingEscrow public immutable _ve; IRewardsDistributor public immutable _rewards_distributor; @@ -44,7 +44,7 @@ contract Minter is IMinter { initializer = msg.sender; team = msg.sender; teamRate = 30; // 30 bps = 0.03% - _velo = IFlow(IVotingEscrow(__ve).token()); + _flow = IFlow(IVotingEscrow(__ve).token()); _voter = IVoter(__voter); _ve = IVotingEscrow(__ve); _rewards_distributor = IRewardsDistributor(__rewards_distributor); @@ -57,8 +57,8 @@ contract Minter is IMinter { uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m ) external { require(initializer == msg.sender); - _velo.mint(address(this), max); - _velo.approve(address(_ve), type(uint256).max); + _flow.mint(address(this), max); + _flow.approve(address(_ve), type(uint256).max); for (uint256 i = 0; i < claimants.length; i++) { _ve.create_lock_for(amounts[i], LOCK, claimants[i]); } @@ -84,7 +84,7 @@ contract Minter is IMinter { // calculate circulating supply as total token supply - locked supply function circulating_supply() public view returns (uint256) { - return _velo.totalSupply() - _ve.totalSupply(); + return _flow.totalSupply() - _ve.totalSupply(); } // emission calculation is 1% of available supply to mint adjusted by circulating / total supply @@ -105,11 +105,11 @@ contract Minter is IMinter { // calculate inflation and adjust ve balances accordingly function calculate_growth(uint256 _minted) public view returns (uint256) { uint256 _veTotal = _ve.totalSupply(); - uint256 _veloTotal = _velo.totalSupply(); + uint256 _flowTotal = _flow.totalSupply(); return - (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) * + (((((_minted * _veTotal) / _flowTotal) * _veTotal) / _flowTotal) * _veTotal) / - _veloTotal / + _flowTotal / 2; } @@ -126,17 +126,17 @@ contract Minter is IMinter { uint256 _teamEmissions = (teamRate * (_growth + weekly)) / (PRECISION - teamRate); uint256 _required = _growth + weekly + _teamEmissions; - uint256 _balanceOf = _velo.balanceOf(address(this)); + uint256 _balanceOf = _flow.balanceOf(address(this)); if (_balanceOf < _required) { - _velo.mint(address(this), _required - _balanceOf); + _flow.mint(address(this), _required - _balanceOf); } - require(_velo.transfer(team, _teamEmissions)); - require(_velo.transfer(address(_rewards_distributor), _growth)); + require(_flow.transfer(team, _teamEmissions)); + require(_flow.transfer(address(_rewards_distributor), _growth)); _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor _rewards_distributor.checkpoint_total_supply(); // checkpoint supply - _velo.approve(address(_voter), weekly); + _flow.approve(address(_voter), weekly); _voter.notifyRewardAmount(weekly); emit Mint( diff --git a/contracts/VelodromeLibrary.sol b/contracts/VelocimeterLibrary.sol similarity index 99% rename from contracts/VelodromeLibrary.sol rename to contracts/VelocimeterLibrary.sol index 9682faa5..99e883f8 100644 --- a/contracts/VelodromeLibrary.sol +++ b/contracts/VelocimeterLibrary.sol @@ -5,7 +5,7 @@ pragma solidity 0.8.13; import "contracts/interfaces/IPair.sol"; import "contracts/interfaces/IRouter.sol"; -contract VelodromeLibrary { +contract VelocimeterLibrary { IRouter internal immutable router; constructor(address _router) { diff --git a/contracts/redeem/MerkleClaim.sol b/contracts/redeem/MerkleClaim.sol index 495b4b88..6904237e 100644 --- a/contracts/redeem/MerkleClaim.sol +++ b/contracts/redeem/MerkleClaim.sol @@ -25,10 +25,10 @@ contract MerkleClaim { /// ============ Constructor ============ /// @notice Creates a new MerkleClaim contract - /// @param _velo address + /// @param _flow address /// @param _merkleRoot of claimees - constructor(address _velo, bytes32 _merkleRoot) { - FLOW = IFlow(_velo); + constructor(address _flow, bytes32 _merkleRoot) { + FLOW = IFlow(_flow); merkleRoot = _merkleRoot; } diff --git a/contracts/redeem/RedemptionReceiver.sol b/contracts/redeem/RedemptionReceiver.sol index 73fe6a48..2dc1c640 100644 --- a/contracts/redeem/RedemptionReceiver.sol +++ b/contracts/redeem/RedemptionReceiver.sol @@ -27,14 +27,14 @@ contract RedemptionReceiver is ILayerZeroReceiver { constructor( address _usdc, - address _velo, + address _flow, uint16 _fantomChainId, address _endpoint ) { require(_fantomChainId == 12 || _fantomChainId == 10012, "CHAIN_ID_NOT_FTM"); USDC = IERC20(_usdc); - FLOW = IFlow(_velo); + FLOW = IFlow(_flow); fantomChainId = _fantomChainId; endpoint = _endpoint; diff --git a/deploy/00_velo.ts b/deploy/00_velo.ts index 7f96383f..7e8c676e 100644 --- a/deploy/00_velo.ts +++ b/deploy/00_velo.ts @@ -11,7 +11,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { from: deployer, args: [], log: true, - skipIfAlreadyDeployed: true + skipIfAlreadyDeployed: false }) } export default func diff --git a/deploy/01_gaugeFactory.ts b/deploy/01_gaugeFactory.ts index 25e01c5a..9c2060c3 100644 --- a/deploy/01_gaugeFactory.ts +++ b/deploy/01_gaugeFactory.ts @@ -1,19 +1,19 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments - const { deployer } = await getNamedAccounts(); + const { deployer } = await getNamedAccounts() - await deploy("GaugeFactory", { + await deploy('GaugeFactory', { from: deployer, args: [], log: true, - skipIfAlreadyDeployed: true, - }); -}; -export default func; -func.tags = ["GaugeFactory"]; -func.id = "gaugeFactory"; + skipIfAlreadyDeployed: false + }) +} +export default func +func.tags = ['GaugeFactory'] +func.id = 'gaugeFactory' diff --git a/deploy/02_bribeFactory.ts b/deploy/02_bribeFactory.ts index eec353f8..48026f68 100644 --- a/deploy/02_bribeFactory.ts +++ b/deploy/02_bribeFactory.ts @@ -1,19 +1,19 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments - const { deployer } = await getNamedAccounts(); + const { deployer } = await getNamedAccounts() - await deploy("BribeFactory", { + await deploy('BribeFactory', { from: deployer, args: [], log: true, - skipIfAlreadyDeployed: true, - }); -}; -export default func; -func.tags = ["BribeFactory"]; -func.id = "bribeFactory"; + skipIfAlreadyDeployed: false + }) +} +export default func +func.tags = ['BribeFactory'] +func.id = 'bribeFactory' diff --git a/deploy/04_pairFactory.ts b/deploy/04_pairFactory.ts index 53efd4cb..ea1e4040 100644 --- a/deploy/04_pairFactory.ts +++ b/deploy/04_pairFactory.ts @@ -1,19 +1,19 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments - const { deployer } = await getNamedAccounts(); + const { deployer } = await getNamedAccounts() - await deploy("PairFactory", { + await deploy('PairFactory', { from: deployer, args: [], log: true, - skipIfAlreadyDeployed: true, - }); -}; -export default func; -func.tags = ["PairFactory"]; -func.id = "pairFactory"; \ No newline at end of file + skipIfAlreadyDeployed: false + }) +} +export default func +func.tags = ['PairFactory'] +func.id = 'pairFactory' diff --git a/deploy/05_router.ts b/deploy/05_router.ts index 526dd34b..33050b5b 100644 --- a/deploy/05_router.ts +++ b/deploy/05_router.ts @@ -16,7 +16,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { from: deployer, args: [pairFactory.address, ARB_TEST_CONFIG.WETH], log: true, - skipIfAlreadyDeployed: true + skipIfAlreadyDeployed: false }) } export default func diff --git a/deploy/06_library.ts b/deploy/06_library.ts index 159707a4..ec31a34d 100644 --- a/deploy/06_library.ts +++ b/deploy/06_library.ts @@ -1,21 +1,21 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments - const { deployer } = await getNamedAccounts(); + const { deployer } = await getNamedAccounts() - const router = await deployments.get("Router"); + const router = await deployments.get('Router') - await deploy("VelodromeLibrary", { + await deploy('VelocimeterLibrary', { from: deployer, args: [router.address], log: true, - skipIfAlreadyDeployed: true, - }); -}; -export default func; -func.tags = ["VelodromeLibrary"]; -func.id = "velodromeLibrary"; + skipIfAlreadyDeployed: false + }) +} +export default func +func.tags = ['VelocimeterLibrary'] +func.id = 'velodromeLibrary' diff --git a/deploy/07_veArtProxy.ts b/deploy/07_veArtProxy.ts index 39c61841..b1be7f86 100644 --- a/deploy/07_veArtProxy.ts +++ b/deploy/07_veArtProxy.ts @@ -1,19 +1,19 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments - const { deployer } = await getNamedAccounts(); + const { deployer } = await getNamedAccounts() - await deploy("VeArtProxy", { + await deploy('VeArtProxy', { from: deployer, args: [], log: true, - skipIfAlreadyDeployed: true, - }); -}; -export default func; -func.tags = ["VeArtProxy"]; -func.id = "veArtProxy"; + skipIfAlreadyDeployed: false + }) +} +export default func +func.tags = ['VeArtProxy'] +func.id = 'veArtProxy' diff --git a/deploy/08_votingEscrow.ts b/deploy/08_votingEscrow.ts index 7a1392d7..96215eb3 100644 --- a/deploy/08_votingEscrow.ts +++ b/deploy/08_votingEscrow.ts @@ -14,7 +14,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { from: deployer, args: [flow.address, veArtProxy.address], log: true, - skipIfAlreadyDeployed: true + skipIfAlreadyDeployed: false }) } export default func diff --git a/deploy/09_rewardsDist.ts b/deploy/09_rewardsDist.ts index bdc66b27..5a6541af 100644 --- a/deploy/09_rewardsDist.ts +++ b/deploy/09_rewardsDist.ts @@ -1,21 +1,21 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments - const { deployer } = await getNamedAccounts(); + const { deployer } = await getNamedAccounts() - const escrow = await deployments.get("VotingEscrow"); + const escrow = await deployments.get('VotingEscrow') - await deploy("RewardsDistributor", { + await deploy('RewardsDistributor', { from: deployer, args: [escrow.address], log: true, - skipIfAlreadyDeployed: true, - }); -}; -export default func; -func.tags = ["RewardsDistributor"]; -func.id = "rewardsDistributor"; + skipIfAlreadyDeployed: false + }) +} +export default func +func.tags = ['RewardsDistributor'] +func.id = 'rewardsDistributor' diff --git a/deploy/10_voter.ts b/deploy/10_voter.ts index a06fd976..d0e74956 100644 --- a/deploy/10_voter.ts +++ b/deploy/10_voter.ts @@ -1,29 +1,29 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments - const { deployer } = await getNamedAccounts(); + const { deployer } = await getNamedAccounts() - const escrow = await deployments.get("VotingEscrow"); - const pairFactory = await deployments.get("PairFactory"); - const gaugeFactory = await deployments.get("GaugeFactory"); - const bribeFactory = await deployments.get("BribeFactory"); + const escrow = await deployments.get('VotingEscrow') + const pairFactory = await deployments.get('PairFactory') + const gaugeFactory = await deployments.get('GaugeFactory') + const bribeFactory = await deployments.get('BribeFactory') - await deploy("Voter", { + await deploy('Voter', { from: deployer, args: [ escrow.address, pairFactory.address, gaugeFactory.address, - bribeFactory.address, + bribeFactory.address ], log: true, - skipIfAlreadyDeployed: true, - }); -}; -export default func; -func.tags = ["Voter"]; -func.id = "voter"; \ No newline at end of file + skipIfAlreadyDeployed: false + }) +} +export default func +func.tags = ['Voter'] +func.id = 'voter' diff --git a/deploy/11_minter.ts b/deploy/11_minter.ts index 87c11f5b..1c0a0ffd 100644 --- a/deploy/11_minter.ts +++ b/deploy/11_minter.ts @@ -1,23 +1,23 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments - const { deployer } = await getNamedAccounts(); + const { deployer } = await getNamedAccounts() - const escrow = await deployments.get("VotingEscrow"); - const voter = await deployments.get("Voter"); - const dist = await deployments.get("RewardsDistributor"); + const escrow = await deployments.get('VotingEscrow') + const voter = await deployments.get('Voter') + const dist = await deployments.get('RewardsDistributor') - await deploy("Minter", { + await deploy('Minter', { from: deployer, args: [voter.address, escrow.address, dist.address], log: true, - skipIfAlreadyDeployed: true, - }); -}; -export default func; -func.tags = ["Minter"]; -func.id = "minter"; \ No newline at end of file + skipIfAlreadyDeployed: false + }) +} +export default func +func.tags = ['Minter'] +func.id = 'minter' diff --git a/deploy/12_veloGovernor.ts b/deploy/12_veloGovernor.ts index 6e7a1d59..5462f7d6 100644 --- a/deploy/12_veloGovernor.ts +++ b/deploy/12_veloGovernor.ts @@ -1,21 +1,21 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments - const { deployer } = await getNamedAccounts(); + const { deployer } = await getNamedAccounts() - const escrow = await deployments.get("VotingEscrow"); + const escrow = await deployments.get('VotingEscrow') - await deploy("VeloGovernor", { + await deploy('VeloGovernor', { from: deployer, args: [escrow.address], log: true, - skipIfAlreadyDeployed: true, - }); -}; -export default func; -func.tags = ["VeloGovernor"]; -func.id = "veloGovernor"; \ No newline at end of file + skipIfAlreadyDeployed: false + }) +} +export default func +func.tags = ['VeloGovernor'] +func.id = 'veloGovernor' diff --git a/deploy/13_redemptionReceiver.ts b/deploy/13_redemptionReceiver.ts index 32e9f129..6ef22fa7 100644 --- a/deploy/13_redemptionReceiver.ts +++ b/deploy/13_redemptionReceiver.ts @@ -24,7 +24,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { ARB_TEST_CONFIG.lzEndpoint ], log: true, - skipIfAlreadyDeployed: true + skipIfAlreadyDeployed: false }) } export default func diff --git a/deploy/14_merkleClaim.ts b/deploy/14_merkleClaim.ts index 0fe22e48..b5e013b7 100644 --- a/deploy/14_merkleClaim.ts +++ b/deploy/14_merkleClaim.ts @@ -18,7 +18,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { from: deployer, args: [flow.address, ARB_TEST_CONFIG.merkleRoot], log: true, - skipIfAlreadyDeployed: true + skipIfAlreadyDeployed: false }) } export default func diff --git a/deployments/arbitrumGoerli/Flow.json b/deployments/arbitrumGoerli/Flow.json new file mode 100644 index 00000000..c0f55689 --- /dev/null +++ b/deployments/arbitrumGoerli/Flow.json @@ -0,0 +1,522 @@ +{ + "address": "0x10A3846b95Da6721A65b709df9586585B6d03AD4", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "claim", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_recipient", + "type": "address" + } + ], + "name": "initialMint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initialMinted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "merkleClaim", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "minter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "redemptionReceiver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_merkleClaim", + "type": "address" + } + ], + "name": "setMerkleClaim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_minter", + "type": "address" + } + ], + "name": "setMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_receiver", + "type": "address" + } + ], + "name": "setRedemptionReceiver", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x0258ba6c4313b48aedfc2a467a4dbc6eba74d9131dc4406734488b0e63bc1947", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x10A3846b95Da6721A65b709df9586585B6d03AD4", + "transactionIndex": 1, + "gasUsed": "537302", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000010000000000000040000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000002000000000000000000000000000000000000000000000000000020000000000000000000000000080000000000800000000000000000000000000400", + "blockHash": "0xbf7c19fef9e6dbd24085046dd0d3c7a50dfee2d1c120d63b84e50b4cce205f81", + "transactionHash": "0x0258ba6c4313b48aedfc2a467a4dbc6eba74d9131dc4406734488b0e63bc1947", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 5714776, + "transactionHash": "0x0258ba6c4313b48aedfc2a467a4dbc6eba74d9131dc4406734488b0e63bc1947", + "address": "0x10A3846b95Da6721A65b709df9586585B6d03AD4", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000053f3b51fd7f327e1ec4e6eaa3a049149cb2acad2" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000", + "logIndex": 0, + "blockHash": "0xbf7c19fef9e6dbd24085046dd0d3c7a50dfee2d1c120d63b84e50b4cce205f81" + } + ], + "blockNumber": 5714776, + "cumulativeGasUsed": "537302", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "d10aa8d28a580b2f5faf1ce0f5049c27", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"initialMint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialMinted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleClaim\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redemptionReceiver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_merkleClaim\",\"type\":\"address\"}],\"name\":\"setMerkleClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"setMinter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_receiver\",\"type\":\"address\"}],\"name\":\"setRedemptionReceiver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Flow.sol\":\"Flow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373837383339303038\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Flow.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\n\\ncontract Flow is IFlow {\\n\\n string public constant name = \\\"Velocimeter\\\";\\n string public constant symbol = \\\"FLOW\\\";\\n uint8 public constant decimals = 18;\\n uint public totalSupply = 0;\\n\\n mapping(address => uint) public balanceOf;\\n mapping(address => mapping(address => uint)) public allowance;\\n\\n bool public initialMinted;\\n address public minter;\\n address public redemptionReceiver;\\n address public merkleClaim;\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n\\n constructor() {\\n minter = msg.sender;\\n _mint(msg.sender, 0);\\n }\\n\\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\\n function setMinter(address _minter) external {\\n require(msg.sender == minter);\\n minter = _minter;\\n }\\n\\n function setRedemptionReceiver(address _receiver) external {\\n require(msg.sender == minter);\\n redemptionReceiver = _receiver;\\n }\\n\\n function setMerkleClaim(address _merkleClaim) external {\\n require(msg.sender == minter);\\n merkleClaim = _merkleClaim;\\n }\\n\\n // Initial mint: total 82M\\n // 4M for \\\"Genesis\\\" pools\\n // 30M for liquid team allocation (40M excl init veNFT)\\n // 48M for future partners\\n function initialMint(address _recipient) external {\\n require(msg.sender == minter && !initialMinted);\\n initialMinted = true;\\n _mint(_recipient, 82 * 1e6 * 1e18);\\n }\\n\\n function approve(address _spender, uint _value) external returns (bool) {\\n allowance[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n function _mint(address _to, uint _amount) internal returns (bool) {\\n totalSupply += _amount;\\n unchecked {\\n balanceOf[_to] += _amount;\\n }\\n emit Transfer(address(0x0), _to, _amount);\\n return true;\\n }\\n\\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\\n balanceOf[_from] -= _value;\\n unchecked {\\n balanceOf[_to] += _value;\\n }\\n emit Transfer(_from, _to, _value);\\n return true;\\n }\\n\\n function transfer(address _to, uint _value) external returns (bool) {\\n return _transfer(msg.sender, _to, _value);\\n }\\n\\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\\n uint allowed_from = allowance[_from][msg.sender];\\n if (allowed_from != type(uint).max) {\\n allowance[_from][msg.sender] -= _value;\\n }\\n return _transfer(_from, _to, _value);\\n }\\n\\n function mint(address account, uint amount) external returns (bool) {\\n require(msg.sender == minter);\\n _mint(account, amount);\\n return true;\\n }\\n\\n function claim(address account, uint amount) external returns (bool) {\\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\\n _mint(account, amount);\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x92c10665e9342078c1b4b7b7c74cc87eaf3e9a1eb58b7949776db8d3a2f37f3d\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"}},\"version\":1}", + "bytecode": "0x60806040526000805534801561001457600080fd5b5060038054610100600160a81b0319163361010081029190911790915561003c906000610042565b506100d9565b60008160008082825461005591906100b3565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a350600192915050565b600082198211156100d457634e487b7160e01b600052601160045260246000fd5b500190565b61082e806100e86000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ae578063dd62ed3e146102c1578063e752c44a146102ec578063ec676a25146102ff578063fca3b5aa1461031257600080fd5b806395d89b4114610243578063a9059cbb14610266578063aad3ec9614610279578063c268f9ba1461028c578063ca1c4de9146102a157600080fd5b806323b872dd116100f457806323b872dd146101d0578063313ce567146101e357806340c10f19146101fd5780635e05fe501461021057806370a082311461022357600080fd5b806306fdde03146101265780630754617214610166578063095ea7b31461019657806318160ddd146101b9575b600080fd5b6101506040518060400160405280600b81526020016a2b32b637b1b4b6b2ba32b960a91b81525081565b60405161015d919061068e565b60405180910390f35b60035461017e9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015d565b6101a96101a43660046106ff565b610325565b604051901515815260200161015d565b6101c260005481565b60405190815260200161015d565b6101a96101de366004610729565b610391565b6101eb601281565b60405160ff909116815260200161015d565b6101a961020b3660046106ff565b61040b565b60045461017e906001600160a01b031681565b6101c2610231366004610765565b60016020526000908152604090205481565b61015060405180604001604052806004815260200163464c4f5760e01b81525081565b6101a96102743660046106ff565b61043e565b6101a96102873660046106ff565b610452565b61029f61029a366004610765565b610481565b005b6003546101a99060ff1681565b61029f6102bc366004610765565b6104d2565b6101c26102cf366004610780565b600260209081526000928352604080842090915290825290205481565b60055461017e906001600160a01b031681565b61029f61030d366004610765565b610510565b61029f610320366004610765565b61054e565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103809086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f7576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103f19084906107c9565b90915550505b610402858585610592565b95945050505050565b60035460009061010090046001600160a01b0316331461042a57600080fd5b6104348383610629565b5060019392505050565b600061044b338484610592565b9392505050565b6004546000906001600160a01b031633148061047857506005546001600160a01b031633145b61042a57600080fd5b60035461010090046001600160a01b0316331480156104a3575060035460ff16155b6104ac57600080fd5b6003805460ff191660011790556104ce816a43d42ce83da41d92000000610629565b5050565b60035461010090046001600160a01b031633146104ee57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052c57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056a57600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105bc9084906107c9565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106179086815260200190565b60405180910390a35060019392505050565b60008160008082825461063c91906107e0565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610380565b600060208083528351808285015260005b818110156106bb5785810183015185820160400152820161069f565b818111156106cd576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106fa57600080fd5b919050565b6000806040838503121561071257600080fd5b61071b836106e3565b946020939093013593505050565b60008060006060848603121561073e57600080fd5b610747846106e3565b9250610755602085016106e3565b9150604084013590509250925092565b60006020828403121561077757600080fd5b61044b826106e3565b6000806040838503121561079357600080fd5b61079c836106e3565b91506107aa602084016106e3565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107db576107db6107b3565b500390565b600082198211156107f3576107f36107b3565b50019056fea26469706673582212207b4d8ddf7bd053136309187f2af3ffe1beab5257f646f1034096b0674ca6a59964736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ae578063dd62ed3e146102c1578063e752c44a146102ec578063ec676a25146102ff578063fca3b5aa1461031257600080fd5b806395d89b4114610243578063a9059cbb14610266578063aad3ec9614610279578063c268f9ba1461028c578063ca1c4de9146102a157600080fd5b806323b872dd116100f457806323b872dd146101d0578063313ce567146101e357806340c10f19146101fd5780635e05fe501461021057806370a082311461022357600080fd5b806306fdde03146101265780630754617214610166578063095ea7b31461019657806318160ddd146101b9575b600080fd5b6101506040518060400160405280600b81526020016a2b32b637b1b4b6b2ba32b960a91b81525081565b60405161015d919061068e565b60405180910390f35b60035461017e9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015d565b6101a96101a43660046106ff565b610325565b604051901515815260200161015d565b6101c260005481565b60405190815260200161015d565b6101a96101de366004610729565b610391565b6101eb601281565b60405160ff909116815260200161015d565b6101a961020b3660046106ff565b61040b565b60045461017e906001600160a01b031681565b6101c2610231366004610765565b60016020526000908152604090205481565b61015060405180604001604052806004815260200163464c4f5760e01b81525081565b6101a96102743660046106ff565b61043e565b6101a96102873660046106ff565b610452565b61029f61029a366004610765565b610481565b005b6003546101a99060ff1681565b61029f6102bc366004610765565b6104d2565b6101c26102cf366004610780565b600260209081526000928352604080842090915290825290205481565b60055461017e906001600160a01b031681565b61029f61030d366004610765565b610510565b61029f610320366004610765565b61054e565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103809086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f7576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103f19084906107c9565b90915550505b610402858585610592565b95945050505050565b60035460009061010090046001600160a01b0316331461042a57600080fd5b6104348383610629565b5060019392505050565b600061044b338484610592565b9392505050565b6004546000906001600160a01b031633148061047857506005546001600160a01b031633145b61042a57600080fd5b60035461010090046001600160a01b0316331480156104a3575060035460ff16155b6104ac57600080fd5b6003805460ff191660011790556104ce816a43d42ce83da41d92000000610629565b5050565b60035461010090046001600160a01b031633146104ee57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052c57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056a57600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105bc9084906107c9565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106179086815260200190565b60405180910390a35060019392505050565b60008160008082825461063c91906107e0565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610380565b600060208083528351808285015260005b818110156106bb5785810183015185820160400152820161069f565b818111156106cd576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106fa57600080fd5b919050565b6000806040838503121561071257600080fd5b61071b836106e3565b946020939093013593505050565b60008060006060848603121561073e57600080fd5b610747846106e3565b9250610755602085016106e3565b9150604084013590509250925092565b60006020828403121561077757600080fd5b61044b826106e3565b6000806040838503121561079357600080fd5b61079c836106e3565b91506107aa602084016106e3565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107db576107db6107b3565b500390565b600082198211156107f3576107f36107b3565b50019056fea26469706673582212207b4d8ddf7bd053136309187f2af3ffe1beab5257f646f1034096b0674ca6a59964736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 1342, + "contract": "contracts/Flow.sol:Flow", + "label": "totalSupply", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 1346, + "contract": "contracts/Flow.sol:Flow", + "label": "balanceOf", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 1352, + "contract": "contracts/Flow.sol:Flow", + "label": "allowance", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 1354, + "contract": "contracts/Flow.sol:Flow", + "label": "initialMinted", + "offset": 0, + "slot": "3", + "type": "t_bool" + }, + { + "astId": 1356, + "contract": "contracts/Flow.sol:Flow", + "label": "minter", + "offset": 1, + "slot": "3", + "type": "t_address" + }, + { + "astId": 1358, + "contract": "contracts/Flow.sol:Flow", + "label": "redemptionReceiver", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 1360, + "contract": "contracts/Flow.sol:Flow", + "label": "merkleClaim", + "offset": 0, + "slot": "5", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/d10aa8d28a580b2f5faf1ce0f5049c27.json b/deployments/arbitrumGoerli/solcInputs/d10aa8d28a580b2f5faf1ce0f5049c27.json new file mode 100644 index 00000000..68471bda --- /dev/null +++ b/deployments/arbitrumGoerli/solcInputs/d10aa8d28a580b2f5faf1ce0f5049c27.json @@ -0,0 +1,238 @@ +{ + "language": "Solidity", + "sources": { + "contracts/ExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/factories/BribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n\n// if this imports int and ext bribe why is the the gauge factory asking for those address as if they are deployed to an address.\n" + }, + "contracts/factories/GaugeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" + }, + "contracts/factories/PairFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" + }, + "contracts/factories/WrappedExternalBribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" + }, + "contracts/Flow.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IFlow.sol\";\n\ncontract Flow is IFlow {\n\n string public constant name = \"Velocimeter\";\n string public constant symbol = \"FLOW\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" + }, + "contracts/Gauge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/governance/L2Governor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" + }, + "contracts/governance/L2GovernorCountingSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" + }, + "contracts/governance/L2GovernorVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" + }, + "contracts/governance/L2GovernorVotesQuorumFraction.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" + }, + "contracts/interfaces/IBribe.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IBribeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IERC20.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" + }, + "contracts/interfaces/IFlow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IFlow {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" + }, + "contracts/interfaces/IGauge.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" + }, + "contracts/interfaces/IGaugeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IMinter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" + }, + "contracts/interfaces/IPair.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IPairCallee.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" + }, + "contracts/interfaces/IPairFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" + }, + "contracts/interfaces/IRewardsDistributor.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" + }, + "contracts/interfaces/IRouter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" + }, + "contracts/interfaces/IVeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" + }, + "contracts/interfaces/IVoter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" + }, + "contracts/interfaces/IVotingEscrow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" + }, + "contracts/interfaces/IWETH.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" + }, + "contracts/InternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/libraries/Base64.sol": { + "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" + }, + "contracts/libraries/Math.sol": { + "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" + }, + "contracts/Minter.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IFlow.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IFlow public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M FLOW (FLOW has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IFlow(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" + }, + "contracts/Pair.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/PairFees.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" + }, + "contracts/redeem/MerkleClaim.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IFlow} from \"contracts/interfaces/IFlow.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims FLOW for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice FLOW token to claim\n IFlow public immutable FLOW;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n FLOW = IFlow(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(FLOW.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" + }, + "contracts/redeem/RedemptionReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IFlow.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + FLOW\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IFlow public immutable FLOW;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableFLOW;\n uint256 public leftoverFLOW;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n FLOW = IFlow(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableFLOW);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableFLOW\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableFLOW = _redeemableFLOW;\n leftoverFLOW = _redeemableFLOW;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableFLOW);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfFLOW)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata FLOW\n shareOfFLOW = (amountWEVE * redeemableFLOW) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfFLOW) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverFLOW -= shareOfFLOW; // this will revert if underflows\n require(\n FLOW.claim(redemptionAddress, shareOfFLOW),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" + }, + "contracts/redeem/RedemptionSender.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" + }, + "contracts/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" + }, + "contracts/Router.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velocimeter locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" + }, + "contracts/VelodromeLibrary.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" + }, + "contracts/VeloGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velocimeter Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" + }, + "contracts/Voter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velocimeter pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VotingEscrow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `FLOW` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" + }, + "contracts/WrappedExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + }, + "libraries": { + "": { + "__CACHE_BREAKER__": "0x0000000000000031363734373837383339303038" + } + } + } +} \ No newline at end of file diff --git a/dist/deploy/00_velo.js b/dist/deploy/00_velo.js index 2824a37f..e5b7d4cb 100644 --- a/dist/deploy/00_velo.js +++ b/dist/deploy/00_velo.js @@ -8,7 +8,7 @@ const func = async function (hre) { from: deployer, args: [], log: true, - skipIfAlreadyDeployed: true + skipIfAlreadyDeployed: false }) } exports.default = func diff --git a/dist/deploy/01_gaugeFactory.js b/dist/deploy/01_gaugeFactory.js index b355c9fa..d930ff1a 100644 --- a/dist/deploy/01_gaugeFactory.js +++ b/dist/deploy/01_gaugeFactory.js @@ -1,16 +1,16 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) const func = async function (hre) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; - const { deployer } = await getNamedAccounts(); - await deploy("GaugeFactory", { - from: deployer, - args: [], - log: true, - skipIfAlreadyDeployed: true, - }); -}; -exports.default = func; -func.tags = ["GaugeFactory"]; -func.id = "gaugeFactory"; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments + const { deployer } = await getNamedAccounts() + await deploy('GaugeFactory', { + from: deployer, + args: [], + log: true, + skipIfAlreadyDeployed: false + }) +} +exports.default = func +func.tags = ['GaugeFactory'] +func.id = 'gaugeFactory' diff --git a/dist/deploy/02_bribeFactory.js b/dist/deploy/02_bribeFactory.js index cef38939..930c9c81 100644 --- a/dist/deploy/02_bribeFactory.js +++ b/dist/deploy/02_bribeFactory.js @@ -1,16 +1,16 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) const func = async function (hre) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; - const { deployer } = await getNamedAccounts(); - await deploy("BribeFactory", { - from: deployer, - args: [], - log: true, - skipIfAlreadyDeployed: true, - }); -}; -exports.default = func; -func.tags = ["BribeFactory"]; -func.id = "bribeFactory"; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments + const { deployer } = await getNamedAccounts() + await deploy('BribeFactory', { + from: deployer, + args: [], + log: true, + skipIfAlreadyDeployed: false + }) +} +exports.default = func +func.tags = ['BribeFactory'] +func.id = 'bribeFactory' diff --git a/dist/deploy/04_pairFactory.js b/dist/deploy/04_pairFactory.js index 2d8c7294..38d019b0 100644 --- a/dist/deploy/04_pairFactory.js +++ b/dist/deploy/04_pairFactory.js @@ -1,16 +1,16 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) const func = async function (hre) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; - const { deployer } = await getNamedAccounts(); - await deploy("PairFactory", { - from: deployer, - args: [], - log: true, - skipIfAlreadyDeployed: true, - }); -}; -exports.default = func; -func.tags = ["PairFactory"]; -func.id = "pairFactory"; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments + const { deployer } = await getNamedAccounts() + await deploy('PairFactory', { + from: deployer, + args: [], + log: true, + skipIfAlreadyDeployed: false + }) +} +exports.default = func +func.tags = ['PairFactory'] +func.id = 'pairFactory' diff --git a/dist/deploy/05_router.js b/dist/deploy/05_router.js index cfe59952..1f69cde6 100644 --- a/dist/deploy/05_router.js +++ b/dist/deploy/05_router.js @@ -1,22 +1,26 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const arbTestnetConfig_1 = __importDefault(require("../tasks/deploy/constants/arbTestnetConfig")); -const ARB_TEST_CONFIG = arbTestnetConfig_1.default; +'use strict' +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod } + } +Object.defineProperty(exports, '__esModule', { value: true }) +const arbTestnetConfig_1 = __importDefault( + require('../tasks/deploy/constants/arbTestnetConfig') +) +const ARB_TEST_CONFIG = arbTestnetConfig_1.default const func = async function (hre) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; - const { deployer } = await getNamedAccounts(); - const pairFactory = await deployments.get("PairFactory"); - await deploy("Router", { - from: deployer, - args: [pairFactory.address, ARB_TEST_CONFIG.WETH], - log: true, - skipIfAlreadyDeployed: true, - }); -}; -exports.default = func; -func.tags = ["Router"]; -func.id = "router"; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments + const { deployer } = await getNamedAccounts() + const pairFactory = await deployments.get('PairFactory') + await deploy('Router', { + from: deployer, + args: [pairFactory.address, ARB_TEST_CONFIG.WETH], + log: true, + skipIfAlreadyDeployed: false + }) +} +exports.default = func +func.tags = ['Router'] +func.id = 'router' diff --git a/dist/deploy/06_library.js b/dist/deploy/06_library.js index 90f0de52..536855d7 100644 --- a/dist/deploy/06_library.js +++ b/dist/deploy/06_library.js @@ -1,17 +1,17 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) const func = async function (hre) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; - const { deployer } = await getNamedAccounts(); - const router = await deployments.get("Router"); - await deploy("VelodromeLibrary", { - from: deployer, - args: [router.address], - log: true, - skipIfAlreadyDeployed: true, - }); -}; -exports.default = func; -func.tags = ["VelodromeLibrary"]; -func.id = "velodromeLibrary"; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments + const { deployer } = await getNamedAccounts() + const router = await deployments.get('Router') + await deploy('VelocimeterLibrary', { + from: deployer, + args: [router.address], + log: true, + skipIfAlreadyDeployed: false + }) +} +exports.default = func +func.tags = ['VelocimeterLibrary'] +func.id = 'velodromeLibrary' diff --git a/dist/deploy/07_veArtProxy.js b/dist/deploy/07_veArtProxy.js index 350c6d9f..46ed538b 100644 --- a/dist/deploy/07_veArtProxy.js +++ b/dist/deploy/07_veArtProxy.js @@ -1,16 +1,16 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) const func = async function (hre) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; - const { deployer } = await getNamedAccounts(); - await deploy("VeArtProxy", { - from: deployer, - args: [], - log: true, - skipIfAlreadyDeployed: true, - }); -}; -exports.default = func; -func.tags = ["VeArtProxy"]; -func.id = "veArtProxy"; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments + const { deployer } = await getNamedAccounts() + await deploy('VeArtProxy', { + from: deployer, + args: [], + log: true, + skipIfAlreadyDeployed: false + }) +} +exports.default = func +func.tags = ['VeArtProxy'] +func.id = 'veArtProxy' diff --git a/dist/deploy/08_votingEscrow.js b/dist/deploy/08_votingEscrow.js index 24692084..6033cd1a 100644 --- a/dist/deploy/08_votingEscrow.js +++ b/dist/deploy/08_votingEscrow.js @@ -10,7 +10,7 @@ const func = async function (hre) { from: deployer, args: [flow.address, veArtProxy.address], log: true, - skipIfAlreadyDeployed: true + skipIfAlreadyDeployed: false }) } exports.default = func diff --git a/dist/deploy/09_rewardsDist.js b/dist/deploy/09_rewardsDist.js index 6e4864d7..c41fcb9b 100644 --- a/dist/deploy/09_rewardsDist.js +++ b/dist/deploy/09_rewardsDist.js @@ -1,17 +1,17 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) const func = async function (hre) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; - const { deployer } = await getNamedAccounts(); - const escrow = await deployments.get("VotingEscrow"); - await deploy("RewardsDistributor", { - from: deployer, - args: [escrow.address], - log: true, - skipIfAlreadyDeployed: true, - }); -}; -exports.default = func; -func.tags = ["RewardsDistributor"]; -func.id = "rewardsDistributor"; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments + const { deployer } = await getNamedAccounts() + const escrow = await deployments.get('VotingEscrow') + await deploy('RewardsDistributor', { + from: deployer, + args: [escrow.address], + log: true, + skipIfAlreadyDeployed: false + }) +} +exports.default = func +func.tags = ['RewardsDistributor'] +func.id = 'rewardsDistributor' diff --git a/dist/deploy/10_voter.js b/dist/deploy/10_voter.js index f775df1c..ec3d36ba 100644 --- a/dist/deploy/10_voter.js +++ b/dist/deploy/10_voter.js @@ -1,25 +1,25 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) const func = async function (hre) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; - const { deployer } = await getNamedAccounts(); - const escrow = await deployments.get("VotingEscrow"); - const pairFactory = await deployments.get("PairFactory"); - const gaugeFactory = await deployments.get("GaugeFactory"); - const bribeFactory = await deployments.get("BribeFactory"); - await deploy("Voter", { - from: deployer, - args: [ - escrow.address, - pairFactory.address, - gaugeFactory.address, - bribeFactory.address, - ], - log: true, - skipIfAlreadyDeployed: true, - }); -}; -exports.default = func; -func.tags = ["Voter"]; -func.id = "voter"; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments + const { deployer } = await getNamedAccounts() + const escrow = await deployments.get('VotingEscrow') + const pairFactory = await deployments.get('PairFactory') + const gaugeFactory = await deployments.get('GaugeFactory') + const bribeFactory = await deployments.get('BribeFactory') + await deploy('Voter', { + from: deployer, + args: [ + escrow.address, + pairFactory.address, + gaugeFactory.address, + bribeFactory.address + ], + log: true, + skipIfAlreadyDeployed: false + }) +} +exports.default = func +func.tags = ['Voter'] +func.id = 'voter' diff --git a/dist/deploy/11_minter.js b/dist/deploy/11_minter.js index e6fc2686..4f5bddd7 100644 --- a/dist/deploy/11_minter.js +++ b/dist/deploy/11_minter.js @@ -1,19 +1,19 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) const func = async function (hre) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; - const { deployer } = await getNamedAccounts(); - const escrow = await deployments.get("VotingEscrow"); - const voter = await deployments.get("Voter"); - const dist = await deployments.get("RewardsDistributor"); - await deploy("Minter", { - from: deployer, - args: [voter.address, escrow.address, dist.address], - log: true, - skipIfAlreadyDeployed: true, - }); -}; -exports.default = func; -func.tags = ["Minter"]; -func.id = "minter"; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments + const { deployer } = await getNamedAccounts() + const escrow = await deployments.get('VotingEscrow') + const voter = await deployments.get('Voter') + const dist = await deployments.get('RewardsDistributor') + await deploy('Minter', { + from: deployer, + args: [voter.address, escrow.address, dist.address], + log: true, + skipIfAlreadyDeployed: false + }) +} +exports.default = func +func.tags = ['Minter'] +func.id = 'minter' diff --git a/dist/deploy/12_veloGovernor.js b/dist/deploy/12_veloGovernor.js index d38c5667..a8debabc 100644 --- a/dist/deploy/12_veloGovernor.js +++ b/dist/deploy/12_veloGovernor.js @@ -1,17 +1,17 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) const func = async function (hre) { - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; - const { deployer } = await getNamedAccounts(); - const escrow = await deployments.get("VotingEscrow"); - await deploy("VeloGovernor", { - from: deployer, - args: [escrow.address], - log: true, - skipIfAlreadyDeployed: true, - }); -}; -exports.default = func; -func.tags = ["VeloGovernor"]; -func.id = "veloGovernor"; + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments + const { deployer } = await getNamedAccounts() + const escrow = await deployments.get('VotingEscrow') + await deploy('VeloGovernor', { + from: deployer, + args: [escrow.address], + log: true, + skipIfAlreadyDeployed: false + }) +} +exports.default = func +func.tags = ['VeloGovernor'] +func.id = 'veloGovernor' diff --git a/dist/deploy/13_redemptionReceiver.js b/dist/deploy/13_redemptionReceiver.js index c8eea4df..762b26ea 100644 --- a/dist/deploy/13_redemptionReceiver.js +++ b/dist/deploy/13_redemptionReceiver.js @@ -27,7 +27,7 @@ const func = async function (hre) { ARB_TEST_CONFIG.lzEndpoint ], log: true, - skipIfAlreadyDeployed: true + skipIfAlreadyDeployed: false }) } exports.default = func diff --git a/dist/deploy/14_merkleClaim.js b/dist/deploy/14_merkleClaim.js index de6a5ddb..ed8a6f72 100644 --- a/dist/deploy/14_merkleClaim.js +++ b/dist/deploy/14_merkleClaim.js @@ -18,7 +18,7 @@ const func = async function (hre) { from: deployer, args: [flow.address, ARB_TEST_CONFIG.merkleRoot], log: true, - skipIfAlreadyDeployed: true + skipIfAlreadyDeployed: false }) } exports.default = func diff --git a/dist/tasks/deploy/arb.js b/dist/tasks/deploy/arb.js index a16ed7dc..8475fb62 100644 --- a/dist/tasks/deploy/arb.js +++ b/dist/tasks/deploy/arb.js @@ -49,7 +49,7 @@ const testFantomConfig_1 = __importDefault( ethers.getContractFactory('BribeFactory'), ethers.getContractFactory('PairFactory'), ethers.getContractFactory('Router'), - ethers.getContractFactory('VelodromeLibrary'), + ethers.getContractFactory('VelocimeterLibrary'), ethers.getContractFactory('VeArtProxy'), ethers.getContractFactory('VotingEscrow'), ethers.getContractFactory('RewardsDistributor'), @@ -77,7 +77,7 @@ const testFantomConfig_1 = __importDefault( console.log('Args: ', pairFactory.address, ARB_CONFIG.WETH, '\n') const library = await Library.deploy(router.address) await library.deployed() - console.log('VelodromeLibrary deployed to: ', library.address) + console.log('VelocimeterLibrary deployed to: ', library.address) console.log('Args: ', router.address, '\n') const artProxy = await VeArtProxy.deploy() await artProxy.deployed() diff --git a/dist/tasks/deploy/arbHardhat.js b/dist/tasks/deploy/arbHardhat.js index 2643f9f6..0720dd0e 100644 --- a/dist/tasks/deploy/arbHardhat.js +++ b/dist/tasks/deploy/arbHardhat.js @@ -49,7 +49,7 @@ const testFantomConfig_1 = __importDefault( ethers.getContractFactory('BribeFactory'), ethers.getContractFactory('PairFactory'), ethers.getContractFactory('Router'), - ethers.getContractFactory('VelodromeLibrary'), + ethers.getContractFactory('VelocimeterLibrary'), ethers.getContractFactory('VeArtProxy'), ethers.getContractFactory('VotingEscrow'), ethers.getContractFactory('RewardsDistributor'), @@ -77,7 +77,7 @@ const testFantomConfig_1 = __importDefault( console.log('Args: ', pairFactory.address, ARB_CONFIG.WETH, '\n') const library = await Library.deploy(router.address) await library.deployed() - console.log('VelodromeLibrary deployed to: ', library.address) + console.log('VelocimeterLibrary deployed to: ', library.address) console.log('Args: ', router.address, '\n') const artProxy = await VeArtProxy.deploy() await artProxy.deployed() diff --git a/dist/tasks/deploy/arbTest.js b/dist/tasks/deploy/arbTest.js index c2c79915..07566daa 100644 --- a/dist/tasks/deploy/arbTest.js +++ b/dist/tasks/deploy/arbTest.js @@ -46,7 +46,7 @@ const testFantomConfig_1 = __importDefault( ethers.getContractFactory('BribeFactory'), ethers.getContractFactory('PairFactory'), ethers.getContractFactory('Router'), - ethers.getContractFactory('VelodromeLibrary'), + ethers.getContractFactory('VelocimeterLibrary'), ethers.getContractFactory('VeArtProxy'), ethers.getContractFactory('VotingEscrow'), ethers.getContractFactory('RewardsDistributor'), @@ -128,7 +128,7 @@ const testFantomConfig_1 = __importDefault( console.log('Args: ', pairFactory.address, OP_CONFIG.WETH, '\n') const library = await Library.deploy(router.address) await library.deployed() - console.log('VelodromeLibrary deployed to: ', library.address) + console.log('VelocimeterLibrary deployed to: ', library.address) console.log('Args: ', router.address, '\n') const artProxy = await VeArtProxy.deploy() await artProxy.deployed() diff --git a/dist/tasks/deploy/init.js b/dist/tasks/deploy/init.js index e4ccaf8b..cf29a79a 100644 --- a/dist/tasks/deploy/init.js +++ b/dist/tasks/deploy/init.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict' // The tasks in this file should be called by the multisig // CURRENTLY OUTDATED // import { task } from "hardhat/config"; @@ -15,7 +15,7 @@ // const ELIGIBLE_WEVE = // ethers.BigNumber.from("375112540").mul(TOKEN_DECIMALS); // TODO fix rounding // const REDEEMABLE_USDC = ethers.BigNumber.from("0"); // TODO update -// const REDEEMABLE_VELO = +// const REDEEMABLE_flow = // ethers.BigNumber.from("108000000").mul(TOKEN_DECIMALS); // TODO fix rounding // // Load // const RedemptionReceiver = await ethers.getContractFactory( @@ -27,7 +27,7 @@ // deployed.fantomSender, // ELIGIBLE_WEVE, // REDEEMABLE_USDC, -// REDEEMABLE_VELO +// REDEEMABLE_flow // ); // console.log(`RedemptionSender at ${receiver.address} configured!`); // } diff --git a/dist/tasks/deploy/op.js b/dist/tasks/deploy/op.js index 3f3e9ed3..6de39dd8 100644 --- a/dist/tasks/deploy/op.js +++ b/dist/tasks/deploy/op.js @@ -45,7 +45,7 @@ const testFantomConfig_1 = __importDefault( ethers.getContractFactory('BribeFactory'), ethers.getContractFactory('PairFactory'), ethers.getContractFactory('Router'), - ethers.getContractFactory('VelodromeLibrary'), + ethers.getContractFactory('VelocimeterLibrary'), ethers.getContractFactory('VeArtProxy'), ethers.getContractFactory('VotingEscrow'), ethers.getContractFactory('RewardsDistributor'), @@ -73,7 +73,7 @@ const testFantomConfig_1 = __importDefault( console.log('Args: ', pairFactory.address, OP_CONFIG.WETH, '\n') const library = await Library.deploy(router.address) await library.deployed() - console.log('VelodromeLibrary deployed to: ', library.address) + console.log('VelocimeterLibrary deployed to: ', library.address) console.log('Args: ', router.address, '\n') const artProxy = await VeArtProxy.deploy() await artProxy.deployed() diff --git a/package.json b/package.json index 6377e94f..d8252e6b 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "verify": "npx hardhat --network arbitrumGoerli etherscan-verify --solc-input --sleep", "export": "npx hardhat --network arbitrumGoerli export --export ./exported.json", "exportMainnet": "npx hardhat --network arbitrum export --export ./mainnet-exported.json", - "deploy": "npx hardhat --network arbitrumGoerli", + "deploy": "npx hardhat deploy --network arbitrumGoerli", + "deployHardhat": "npx hardhat deploy --network hardhat", "verifyMainnet": "npx hardhat --network arbitrum etherscan-verify --solc-input --sleep" }, "devDependencies": { @@ -39,4 +40,4 @@ "zod": "^3.20.2" }, "packageManager": "yarn@3.3.1" -} +} \ No newline at end of file diff --git a/readme.md b/readme.md index 7dfde675..50bc4811 100644 --- a/readme.md +++ b/readme.md @@ -25,7 +25,7 @@ npx hardhat --network arbitrumGoerli export --export ./exported.json VeArtProxy: '0x821B98D42D3AB509AF4F54205f0c52B019b9E2D5', Flow: '0x84Ca387E7ede764A3284c67Ff8c68a305a9030a0', VeloGovernor: '0x1a79b9daa3E741774bf67732F8a8B5820De8A53a', - VelodromeLibrary: '0xcbE4714A95f866EB9C2eB50856F431f9E7353Ab6', + VelocimeterLibrary: '0xcbE4714A95f866EB9C2eB50856F431f9E7353Ab6', Voter: '0x854086d39955d28317aE3856399312b8Edb1B473', VotingEscrow: '0xBf05364D6cf1586852c18c6b1CbEe218E3e09885' } diff --git a/tasks/deploy/arb.ts b/tasks/deploy/arb.ts index b505b3f2..3958cd65 100644 --- a/tasks/deploy/arb.ts +++ b/tasks/deploy/arb.ts @@ -45,7 +45,7 @@ task('deploy:arb', 'Deploys Arbitrum contracts').setAction(async function ( ethers.getContractFactory('BribeFactory'), ethers.getContractFactory('PairFactory'), ethers.getContractFactory('Router'), - ethers.getContractFactory('VelodromeLibrary'), + ethers.getContractFactory('VelocimeterLibrary'), ethers.getContractFactory('VeArtProxy'), ethers.getContractFactory('VotingEscrow'), ethers.getContractFactory('RewardsDistributor'), @@ -79,7 +79,7 @@ task('deploy:arb', 'Deploys Arbitrum contracts').setAction(async function ( const library = await Library.deploy(router.address) await library.deployed() - console.log('VelodromeLibrary deployed to: ', library.address) + console.log('VelocimeterLibrary deployed to: ', library.address) console.log('Args: ', router.address, '\n') const artProxy = await VeArtProxy.deploy() diff --git a/tasks/deploy/arbHardhat.ts b/tasks/deploy/arbHardhat.ts index ab07603f..87b08b73 100644 --- a/tasks/deploy/arbHardhat.ts +++ b/tasks/deploy/arbHardhat.ts @@ -42,7 +42,7 @@ task('deploy:arbHardhat', 'Deploys Arbitrum forked chain contracts').setAction( ethers.getContractFactory('BribeFactory'), ethers.getContractFactory('PairFactory'), ethers.getContractFactory('Router'), - ethers.getContractFactory('VelodromeLibrary'), + ethers.getContractFactory('VelocimeterLibrary'), ethers.getContractFactory('VeArtProxy'), ethers.getContractFactory('VotingEscrow'), ethers.getContractFactory('RewardsDistributor'), @@ -76,7 +76,7 @@ task('deploy:arbHardhat', 'Deploys Arbitrum forked chain contracts').setAction( const library = await Library.deploy(router.address) await library.deployed() - console.log('VelodromeLibrary deployed to: ', library.address) + console.log('VelocimeterLibrary deployed to: ', library.address) console.log('Args: ', router.address, '\n') const artProxy = await VeArtProxy.deploy() diff --git a/tasks/deploy/arbTest.ts b/tasks/deploy/arbTest.ts index dd928cf8..d342c00c 100644 --- a/tasks/deploy/arbTest.ts +++ b/tasks/deploy/arbTest.ts @@ -39,7 +39,7 @@ task('deploy:arbTest', 'Deploys Optimism contracts').setAction(async function ( ethers.getContractFactory('BribeFactory'), ethers.getContractFactory('PairFactory'), ethers.getContractFactory('Router'), - ethers.getContractFactory('VelodromeLibrary'), + ethers.getContractFactory('VelocimeterLibrary'), ethers.getContractFactory('VeArtProxy'), ethers.getContractFactory('VotingEscrow'), ethers.getContractFactory('RewardsDistributor'), @@ -138,7 +138,7 @@ task('deploy:arbTest', 'Deploys Optimism contracts').setAction(async function ( const library = await Library.deploy(router.address) await library.deployed() - console.log('VelodromeLibrary deployed to: ', library.address) + console.log('VelocimeterLibrary deployed to: ', library.address) console.log('Args: ', router.address, '\n') const artProxy = await VeArtProxy.deploy() diff --git a/tasks/deploy/init.ts b/tasks/deploy/init.ts index 89d8fe44..8bbe6ea1 100644 --- a/tasks/deploy/init.ts +++ b/tasks/deploy/init.ts @@ -19,7 +19,7 @@ // ethers.BigNumber.from("375112540").mul(TOKEN_DECIMALS); // TODO fix rounding // const REDEEMABLE_USDC = ethers.BigNumber.from("0"); // TODO update -// const REDEEMABLE_VELO = +// const REDEEMABLE_flow = // ethers.BigNumber.from("108000000").mul(TOKEN_DECIMALS); // TODO fix rounding // // Load @@ -33,7 +33,7 @@ // deployed.fantomSender, // ELIGIBLE_WEVE, // REDEEMABLE_USDC, -// REDEEMABLE_VELO +// REDEEMABLE_flow // ); // console.log(`RedemptionSender at ${receiver.address} configured!`); // } diff --git a/tasks/deploy/op.ts b/tasks/deploy/op.ts index 18ec5ac9..d1042b90 100644 --- a/tasks/deploy/op.ts +++ b/tasks/deploy/op.ts @@ -37,7 +37,7 @@ task('deploy:op', 'Deploys Optimism contracts').setAction(async function ( ethers.getContractFactory('BribeFactory'), ethers.getContractFactory('PairFactory'), ethers.getContractFactory('Router'), - ethers.getContractFactory('VelodromeLibrary'), + ethers.getContractFactory('VelocimeterLibrary'), ethers.getContractFactory('VeArtProxy'), ethers.getContractFactory('VotingEscrow'), ethers.getContractFactory('RewardsDistributor'), @@ -71,7 +71,7 @@ task('deploy:op', 'Deploys Optimism contracts').setAction(async function ( const library = await Library.deploy(router.address) await library.deployed() - console.log('VelodromeLibrary deployed to: ', library.address) + console.log('VelocimeterLibrary deployed to: ', library.address) console.log('Args: ', router.address, '\n') const artProxy = await VeArtProxy.deploy() diff --git a/test/BaseTest.sol b/test/BaseTest.sol index 66fc097e..cd9bd973 100644 --- a/test/BaseTest.sol +++ b/test/BaseTest.sol @@ -18,7 +18,7 @@ import "contracts/PairFees.sol"; import "contracts/RewardsDistributor.sol"; import "contracts/Router.sol"; import "contracts/Flow.sol"; -import "contracts/VelodromeLibrary.sol"; +import "contracts/VelocimeterLibrary.sol"; import "contracts/Voter.sol"; import "contracts/VeArtProxy.sol"; import "contracts/VotingEscrow.sol"; @@ -53,7 +53,7 @@ abstract contract BaseTest is Test, TestOwner { TestToken stake; // MockERC20 with claimFees() function that returns (0,0) PairFactory factory; Router router; - VelodromeLibrary lib; + VelocimeterLibrary lib; Pair pair; Pair pair2; Pair pair3; @@ -124,7 +124,7 @@ abstract contract BaseTest is Test, TestOwner { factory.setFee(false, 1); router = new Router(address(factory), address(WETH)); assertEq(router.factory(), address(factory)); - lib = new VelodromeLibrary(address(router)); + lib = new VelocimeterLibrary(address(router)); } function deployPairWithOwner(address _owner) public { From 0fbea866c646ec217ced39d16270e9670760fea6 Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Fri, 27 Jan 2023 14:49:07 +1100 Subject: [PATCH 18/43] deployed to arbGoerli again --- contracts/Flow.sol | 2 +- contracts/Minter.sol | 2 +- contracts/RewardsDistributor.sol | 2 +- deploy/06_library.ts | 2 +- deployments/arbitrumGoerli/BribeFactory.json | 26 +- deployments/arbitrumGoerli/Flow.json | 32 +-- deployments/arbitrumGoerli/GaugeFactory.json | 26 +- deployments/arbitrumGoerli/MerkleClaim.json | 44 ++-- deployments/arbitrumGoerli/Minter.json | 56 ++--- deployments/arbitrumGoerli/PairFactory.json | 26 +- .../arbitrumGoerli/RedemptionReceiver.json | 56 ++--- .../arbitrumGoerli/RewardsDistributor.json | 64 ++--- deployments/arbitrumGoerli/Router.json | 28 +-- deployments/arbitrumGoerli/VeArtProxy.json | 26 +- deployments/arbitrumGoerli/VeloGovernor.json | 80 +++--- .../arbitrumGoerli/VelocimeterLibrary.json | 229 +++++++++++++++++ deployments/arbitrumGoerli/Voter.json | 34 +-- deployments/arbitrumGoerli/VotingEscrow.json | 54 ++-- .../4fb7d8e79af343f7b73620261b95024e.json | 238 ++++++++++++++++++ .../d1b0dfe2e40ce60c1a0cf04472752ec9.json | 238 ++++++++++++++++++ hardhat.config.ts | 2 +- package.json | 3 +- test/utils/TestToken.sol | 2 +- test/utils/TestVoter.sol | 2 +- test/utils/TestVotingEscrow.sol | 2 +- 25 files changed, 991 insertions(+), 285 deletions(-) create mode 100644 deployments/arbitrumGoerli/VelocimeterLibrary.json create mode 100644 deployments/arbitrumGoerli/solcInputs/4fb7d8e79af343f7b73620261b95024e.json create mode 100644 deployments/arbitrumGoerli/solcInputs/d1b0dfe2e40ce60c1a0cf04472752ec9.json diff --git a/contracts/Flow.sol b/contracts/Flow.sol index 7a519e79..9b77a5bc 100644 --- a/contracts/Flow.sol +++ b/contracts/Flow.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-License-Identifier: MIT pragma solidity 0.8.13; import "contracts/interfaces/IFlow.sol"; diff --git a/contracts/Minter.sol b/contracts/Minter.sol index a6ead9e6..37ba78c1 100644 --- a/contracts/Minter.sol +++ b/contracts/Minter.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-License-Identifier: MIT pragma solidity 0.8.13; import "contracts/libraries/Math.sol"; diff --git a/contracts/RewardsDistributor.sol b/contracts/RewardsDistributor.sol index f742d719..768e5e30 100644 --- a/contracts/RewardsDistributor.sol +++ b/contracts/RewardsDistributor.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-License-Identifier: MIT pragma solidity 0.8.13; import "contracts/libraries/Math.sol"; diff --git a/deploy/06_library.ts b/deploy/06_library.ts index ec31a34d..ec1250ad 100644 --- a/deploy/06_library.ts +++ b/deploy/06_library.ts @@ -18,4 +18,4 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { } export default func func.tags = ['VelocimeterLibrary'] -func.id = 'velodromeLibrary' +func.id = 'velocimeterLibrary' diff --git a/deployments/arbitrumGoerli/BribeFactory.json b/deployments/arbitrumGoerli/BribeFactory.json index 83ea468e..1a613f49 100644 --- a/deployments/arbitrumGoerli/BribeFactory.json +++ b/deployments/arbitrumGoerli/BribeFactory.json @@ -1,5 +1,5 @@ { - "address": "0x560b401d9F28F80980451d8582DEe903dD5295c3", + "address": "0x5cD2336a80E72bf0480ae704df021e4531A09671", "abi": [ { "inputs": [ @@ -66,28 +66,28 @@ "type": "function" } ], - "transactionHash": "0xd2bfb0f6387a38f7c85ef125fd2de4c612b006f39b3e581ebddeda5e2e285d08", + "transactionHash": "0x77a94f275b395e421f082a3cfabcf1927db848226adbfc12e4f39282af163148", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x560b401d9F28F80980451d8582DEe903dD5295c3", + "contractAddress": "0x5cD2336a80E72bf0480ae704df021e4531A09671", "transactionIndex": 1, - "gasUsed": "4416403", + "gasUsed": "4288891", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x69af5ecd4fae07b0786e4a2336921c49af0545a2268d3bfc1ddcb4b9ae5fcd6d", - "transactionHash": "0xd2bfb0f6387a38f7c85ef125fd2de4c612b006f39b3e581ebddeda5e2e285d08", + "blockHash": "0xaccbf40c13ccf9a9f1c88e673ba78a7a891d8c74f1db7dc2fc95b6306b3938d3", + "transactionHash": "0x77a94f275b395e421f082a3cfabcf1927db848226adbfc12e4f39282af163148", "logs": [], - "blockNumber": 4455872, - "cumulativeGasUsed": "4416403", + "blockNumber": 5716710, + "cumulativeGasUsed": "4288891", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createExternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createInternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_external_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_internal_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/BribeFactory.sol\":\"BribeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/ExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract ExternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve; // \\u5929\\u4f7f\\u306e\\u305f\\u307e\\u3054\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balanceOf;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n _prevSupply = supplyCheckpoints[\\n getPriorSupplyIndex(_nextEpochStart + DURATION)\\n ].supply;\\n prevRewards.balanceOf =\\n (cp0.balanceOf *\\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (block.timestamp > _lastEpochEnd) {\\n reward +=\\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\\n }\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0xfe1e53dea8a63ce448c5856a740ed73038ad29a9dcd0f2a2752049b146bb4eb0\",\"license\":\"MIT\"},\"contracts/InternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract InternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve;\\n\\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 public constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n mapping(address => mapping(uint256 => uint256))\\n public userRewardPerTokenStored;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (totalSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / totalSupply);\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\\n _startTimestamp = endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][tokenId],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][tokenId]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n require(isReward[token]);\\n\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2dc302de5dfd95018d1fba7a3a1916d2c1fcf32859d19d38648767f13422a694\",\"license\":\"MIT\"},\"contracts/factories/BribeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IBribeFactory.sol\\\";\\nimport 'contracts/InternalBribe.sol';\\nimport 'contracts/ExternalBribe.sol';\\n\\ncontract BribeFactory is IBribeFactory {\\n address public last_internal_bribe;\\n address public last_external_bribe;\\n\\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\\n return last_internal_bribe;\\n }\\n\\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\\n return last_external_bribe;\\n }\\n}\\n\",\"keccak256\":\"0x30d69b5733c01d1d27e8af06e6217200709721fb84ee8458ee50269bf2ce7ed8\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50614cca806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea2646970667358221220efd2286df364745c6a561267c0e080a96fe1607b9ca8c59dd88db8449c06e2f064736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea264697066735822122032807a5a4af2a7e09f287a189f7d41c0fe80bf7ded450a48d6c047e50d355fae64736f6c634300080d0033a2646970667358221220ddd5a8c80f6c4f13aaec10b17f47da405d95cf2e069d0b5875cb77c5276bb85064736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea2646970667358221220efd2286df364745c6a561267c0e080a96fe1607b9ca8c59dd88db8449c06e2f064736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea264697066735822122032807a5a4af2a7e09f287a189f7d41c0fe80bf7ded450a48d6c047e50d355fae64736f6c634300080d0033a2646970667358221220ddd5a8c80f6c4f13aaec10b17f47da405d95cf2e069d0b5875cb77c5276bb85064736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createExternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createInternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_external_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_internal_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/BribeFactory.sol\":\"BribeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/ExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract ExternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve; // \\u5929\\u4f7f\\u306e\\u305f\\u307e\\u3054\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balanceOf;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n _prevSupply = supplyCheckpoints[\\n getPriorSupplyIndex(_nextEpochStart + DURATION)\\n ].supply;\\n prevRewards.balanceOf =\\n (cp0.balanceOf *\\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (block.timestamp > _lastEpochEnd) {\\n reward +=\\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\\n }\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0xfe1e53dea8a63ce448c5856a740ed73038ad29a9dcd0f2a2752049b146bb4eb0\",\"license\":\"MIT\"},\"contracts/InternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract InternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve;\\n\\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 public constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n mapping(address => mapping(uint256 => uint256))\\n public userRewardPerTokenStored;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (totalSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / totalSupply);\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\\n _startTimestamp = endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][tokenId],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][tokenId]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n require(isReward[token]);\\n\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2dc302de5dfd95018d1fba7a3a1916d2c1fcf32859d19d38648767f13422a694\",\"license\":\"MIT\"},\"contracts/factories/BribeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IBribeFactory.sol\\\";\\nimport 'contracts/InternalBribe.sol';\\nimport 'contracts/ExternalBribe.sol';\\n\\ncontract BribeFactory is IBribeFactory {\\n address public last_internal_bribe;\\n address public last_external_bribe;\\n\\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\\n return last_internal_bribe;\\n }\\n\\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\\n return last_external_bribe;\\n }\\n}\\n\\n// if this imports int and ext bribe why is the the gauge factory asking for those address as if they are deployed to an address.\\n\",\"keccak256\":\"0xd107fb5a520bae9b655bec4ad2eb11d598e74d0eeda0db547e2526a907dea7ec\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50614cca806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea26469706673582212208f809014e1be8a684b75e7a6caaac3aae9d2d6082521efe651fdef5245aa62c364736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea26469706673582212200ac3824bebc233077a386d729739b930145f110bb778ad11e43e1b6a5453856364736f6c634300080d0033a2646970667358221220822b550e682635bdd856a9670b0ae5f85deb16da9b775f7411a7b2b69c291e5164736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea26469706673582212208f809014e1be8a684b75e7a6caaac3aae9d2d6082521efe651fdef5245aa62c364736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea26469706673582212200ac3824bebc233077a386d729739b930145f110bb778ad11e43e1b6a5453856364736f6c634300080d0033a2646970667358221220822b550e682635bdd856a9670b0ae5f85deb16da9b775f7411a7b2b69c291e5164736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/Flow.json b/deployments/arbitrumGoerli/Flow.json index c0f55689..cf30e482 100644 --- a/deployments/arbitrumGoerli/Flow.json +++ b/deployments/arbitrumGoerli/Flow.json @@ -1,5 +1,5 @@ { - "address": "0x10A3846b95Da6721A65b709df9586585B6d03AD4", + "address": "0xf5A53c1b4072425DF6eC082f0A48B4652bc4188C", "abi": [ { "inputs": [], @@ -381,22 +381,22 @@ "type": "function" } ], - "transactionHash": "0x0258ba6c4313b48aedfc2a467a4dbc6eba74d9131dc4406734488b0e63bc1947", + "transactionHash": "0x31ab3451d3d9dce5b823a7fb929a52936a64aa3cb1c2c0f3970404573aa38605", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x10A3846b95Da6721A65b709df9586585B6d03AD4", + "contractAddress": "0xf5A53c1b4072425DF6eC082f0A48B4652bc4188C", "transactionIndex": 1, "gasUsed": "537302", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000010000000000000040000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000002000000000000000000000000000000000000000000000000000020000000000000000000000000080000000000800000000000000000000000000400", - "blockHash": "0xbf7c19fef9e6dbd24085046dd0d3c7a50dfee2d1c120d63b84e50b4cce205f81", - "transactionHash": "0x0258ba6c4313b48aedfc2a467a4dbc6eba74d9131dc4406734488b0e63bc1947", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000010000000000000000000040000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000400000000004000000000000002000000000000000000000800000000000000000000000000000020000000000000000000000000080000000000000000000000000000000000000000", + "blockHash": "0xc1c1d58e5d1ad27f96d332fe52913cefdeb32e6f1bc25ff56b4919739d03031b", + "transactionHash": "0x31ab3451d3d9dce5b823a7fb929a52936a64aa3cb1c2c0f3970404573aa38605", "logs": [ { "transactionIndex": 1, - "blockNumber": 5714776, - "transactionHash": "0x0258ba6c4313b48aedfc2a467a4dbc6eba74d9131dc4406734488b0e63bc1947", - "address": "0x10A3846b95Da6721A65b709df9586585B6d03AD4", + "blockNumber": 5716700, + "transactionHash": "0x31ab3451d3d9dce5b823a7fb929a52936a64aa3cb1c2c0f3970404573aa38605", + "address": "0xf5A53c1b4072425DF6eC082f0A48B4652bc4188C", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x0000000000000000000000000000000000000000000000000000000000000000", @@ -404,20 +404,20 @@ ], "data": "0x0000000000000000000000000000000000000000000000000000000000000000", "logIndex": 0, - "blockHash": "0xbf7c19fef9e6dbd24085046dd0d3c7a50dfee2d1c120d63b84e50b4cce205f81" + "blockHash": "0xc1c1d58e5d1ad27f96d332fe52913cefdeb32e6f1bc25ff56b4919739d03031b" } ], - "blockNumber": 5714776, + "blockNumber": 5716700, "cumulativeGasUsed": "537302", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "d10aa8d28a580b2f5faf1ce0f5049c27", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"initialMint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialMinted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleClaim\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redemptionReceiver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_merkleClaim\",\"type\":\"address\"}],\"name\":\"setMerkleClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"setMinter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_receiver\",\"type\":\"address\"}],\"name\":\"setRedemptionReceiver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Flow.sol\":\"Flow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373837383339303038\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Flow.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\n\\ncontract Flow is IFlow {\\n\\n string public constant name = \\\"Velocimeter\\\";\\n string public constant symbol = \\\"FLOW\\\";\\n uint8 public constant decimals = 18;\\n uint public totalSupply = 0;\\n\\n mapping(address => uint) public balanceOf;\\n mapping(address => mapping(address => uint)) public allowance;\\n\\n bool public initialMinted;\\n address public minter;\\n address public redemptionReceiver;\\n address public merkleClaim;\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n\\n constructor() {\\n minter = msg.sender;\\n _mint(msg.sender, 0);\\n }\\n\\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\\n function setMinter(address _minter) external {\\n require(msg.sender == minter);\\n minter = _minter;\\n }\\n\\n function setRedemptionReceiver(address _receiver) external {\\n require(msg.sender == minter);\\n redemptionReceiver = _receiver;\\n }\\n\\n function setMerkleClaim(address _merkleClaim) external {\\n require(msg.sender == minter);\\n merkleClaim = _merkleClaim;\\n }\\n\\n // Initial mint: total 82M\\n // 4M for \\\"Genesis\\\" pools\\n // 30M for liquid team allocation (40M excl init veNFT)\\n // 48M for future partners\\n function initialMint(address _recipient) external {\\n require(msg.sender == minter && !initialMinted);\\n initialMinted = true;\\n _mint(_recipient, 82 * 1e6 * 1e18);\\n }\\n\\n function approve(address _spender, uint _value) external returns (bool) {\\n allowance[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n function _mint(address _to, uint _amount) internal returns (bool) {\\n totalSupply += _amount;\\n unchecked {\\n balanceOf[_to] += _amount;\\n }\\n emit Transfer(address(0x0), _to, _amount);\\n return true;\\n }\\n\\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\\n balanceOf[_from] -= _value;\\n unchecked {\\n balanceOf[_to] += _value;\\n }\\n emit Transfer(_from, _to, _value);\\n return true;\\n }\\n\\n function transfer(address _to, uint _value) external returns (bool) {\\n return _transfer(msg.sender, _to, _value);\\n }\\n\\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\\n uint allowed_from = allowance[_from][msg.sender];\\n if (allowed_from != type(uint).max) {\\n allowance[_from][msg.sender] -= _value;\\n }\\n return _transfer(_from, _to, _value);\\n }\\n\\n function mint(address account, uint amount) external returns (bool) {\\n require(msg.sender == minter);\\n _mint(account, amount);\\n return true;\\n }\\n\\n function claim(address account, uint amount) external returns (bool) {\\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\\n _mint(account, amount);\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x92c10665e9342078c1b4b7b7c74cc87eaf3e9a1eb58b7949776db8d3a2f37f3d\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"}},\"version\":1}", - "bytecode": "0x60806040526000805534801561001457600080fd5b5060038054610100600160a81b0319163361010081029190911790915561003c906000610042565b506100d9565b60008160008082825461005591906100b3565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a350600192915050565b600082198211156100d457634e487b7160e01b600052601160045260246000fd5b500190565b61082e806100e86000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ae578063dd62ed3e146102c1578063e752c44a146102ec578063ec676a25146102ff578063fca3b5aa1461031257600080fd5b806395d89b4114610243578063a9059cbb14610266578063aad3ec9614610279578063c268f9ba1461028c578063ca1c4de9146102a157600080fd5b806323b872dd116100f457806323b872dd146101d0578063313ce567146101e357806340c10f19146101fd5780635e05fe501461021057806370a082311461022357600080fd5b806306fdde03146101265780630754617214610166578063095ea7b31461019657806318160ddd146101b9575b600080fd5b6101506040518060400160405280600b81526020016a2b32b637b1b4b6b2ba32b960a91b81525081565b60405161015d919061068e565b60405180910390f35b60035461017e9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015d565b6101a96101a43660046106ff565b610325565b604051901515815260200161015d565b6101c260005481565b60405190815260200161015d565b6101a96101de366004610729565b610391565b6101eb601281565b60405160ff909116815260200161015d565b6101a961020b3660046106ff565b61040b565b60045461017e906001600160a01b031681565b6101c2610231366004610765565b60016020526000908152604090205481565b61015060405180604001604052806004815260200163464c4f5760e01b81525081565b6101a96102743660046106ff565b61043e565b6101a96102873660046106ff565b610452565b61029f61029a366004610765565b610481565b005b6003546101a99060ff1681565b61029f6102bc366004610765565b6104d2565b6101c26102cf366004610780565b600260209081526000928352604080842090915290825290205481565b60055461017e906001600160a01b031681565b61029f61030d366004610765565b610510565b61029f610320366004610765565b61054e565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103809086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f7576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103f19084906107c9565b90915550505b610402858585610592565b95945050505050565b60035460009061010090046001600160a01b0316331461042a57600080fd5b6104348383610629565b5060019392505050565b600061044b338484610592565b9392505050565b6004546000906001600160a01b031633148061047857506005546001600160a01b031633145b61042a57600080fd5b60035461010090046001600160a01b0316331480156104a3575060035460ff16155b6104ac57600080fd5b6003805460ff191660011790556104ce816a43d42ce83da41d92000000610629565b5050565b60035461010090046001600160a01b031633146104ee57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052c57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056a57600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105bc9084906107c9565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106179086815260200190565b60405180910390a35060019392505050565b60008160008082825461063c91906107e0565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610380565b600060208083528351808285015260005b818110156106bb5785810183015185820160400152820161069f565b818111156106cd576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106fa57600080fd5b919050565b6000806040838503121561071257600080fd5b61071b836106e3565b946020939093013593505050565b60008060006060848603121561073e57600080fd5b610747846106e3565b9250610755602085016106e3565b9150604084013590509250925092565b60006020828403121561077757600080fd5b61044b826106e3565b6000806040838503121561079357600080fd5b61079c836106e3565b91506107aa602084016106e3565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107db576107db6107b3565b500390565b600082198211156107f3576107f36107b3565b50019056fea26469706673582212207b4d8ddf7bd053136309187f2af3ffe1beab5257f646f1034096b0674ca6a59964736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ae578063dd62ed3e146102c1578063e752c44a146102ec578063ec676a25146102ff578063fca3b5aa1461031257600080fd5b806395d89b4114610243578063a9059cbb14610266578063aad3ec9614610279578063c268f9ba1461028c578063ca1c4de9146102a157600080fd5b806323b872dd116100f457806323b872dd146101d0578063313ce567146101e357806340c10f19146101fd5780635e05fe501461021057806370a082311461022357600080fd5b806306fdde03146101265780630754617214610166578063095ea7b31461019657806318160ddd146101b9575b600080fd5b6101506040518060400160405280600b81526020016a2b32b637b1b4b6b2ba32b960a91b81525081565b60405161015d919061068e565b60405180910390f35b60035461017e9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015d565b6101a96101a43660046106ff565b610325565b604051901515815260200161015d565b6101c260005481565b60405190815260200161015d565b6101a96101de366004610729565b610391565b6101eb601281565b60405160ff909116815260200161015d565b6101a961020b3660046106ff565b61040b565b60045461017e906001600160a01b031681565b6101c2610231366004610765565b60016020526000908152604090205481565b61015060405180604001604052806004815260200163464c4f5760e01b81525081565b6101a96102743660046106ff565b61043e565b6101a96102873660046106ff565b610452565b61029f61029a366004610765565b610481565b005b6003546101a99060ff1681565b61029f6102bc366004610765565b6104d2565b6101c26102cf366004610780565b600260209081526000928352604080842090915290825290205481565b60055461017e906001600160a01b031681565b61029f61030d366004610765565b610510565b61029f610320366004610765565b61054e565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103809086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f7576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103f19084906107c9565b90915550505b610402858585610592565b95945050505050565b60035460009061010090046001600160a01b0316331461042a57600080fd5b6104348383610629565b5060019392505050565b600061044b338484610592565b9392505050565b6004546000906001600160a01b031633148061047857506005546001600160a01b031633145b61042a57600080fd5b60035461010090046001600160a01b0316331480156104a3575060035460ff16155b6104ac57600080fd5b6003805460ff191660011790556104ce816a43d42ce83da41d92000000610629565b5050565b60035461010090046001600160a01b031633146104ee57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052c57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056a57600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105bc9084906107c9565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106179086815260200190565b60405180910390a35060019392505050565b60008160008082825461063c91906107e0565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610380565b600060208083528351808285015260005b818110156106bb5785810183015185820160400152820161069f565b818111156106cd576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106fa57600080fd5b919050565b6000806040838503121561071257600080fd5b61071b836106e3565b946020939093013593505050565b60008060006060848603121561073e57600080fd5b610747846106e3565b9250610755602085016106e3565b9150604084013590509250925092565b60006020828403121561077757600080fd5b61044b826106e3565b6000806040838503121561079357600080fd5b61079c836106e3565b91506107aa602084016106e3565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107db576107db6107b3565b500390565b600082198211156107f3576107f36107b3565b50019056fea26469706673582212207b4d8ddf7bd053136309187f2af3ffe1beab5257f646f1034096b0674ca6a59964736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"initialMint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialMinted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleClaim\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redemptionReceiver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_merkleClaim\",\"type\":\"address\"}],\"name\":\"setMerkleClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"setMinter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_receiver\",\"type\":\"address\"}],\"name\":\"setRedemptionReceiver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Flow.sol\":\"Flow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Flow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\n\\ncontract Flow is IFlow {\\n\\n string public constant name = \\\"Velocimeter\\\";\\n string public constant symbol = \\\"FLOW\\\";\\n uint8 public constant decimals = 18;\\n uint public totalSupply = 0;\\n\\n mapping(address => uint) public balanceOf;\\n mapping(address => mapping(address => uint)) public allowance;\\n\\n bool public initialMinted;\\n address public minter;\\n address public redemptionReceiver;\\n address public merkleClaim;\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n\\n constructor() {\\n minter = msg.sender;\\n _mint(msg.sender, 0);\\n }\\n\\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\\n function setMinter(address _minter) external {\\n require(msg.sender == minter);\\n minter = _minter;\\n }\\n\\n function setRedemptionReceiver(address _receiver) external {\\n require(msg.sender == minter);\\n redemptionReceiver = _receiver;\\n }\\n\\n function setMerkleClaim(address _merkleClaim) external {\\n require(msg.sender == minter);\\n merkleClaim = _merkleClaim;\\n }\\n\\n // Initial mint: total 82M\\n // 4M for \\\"Genesis\\\" pools\\n // 30M for liquid team allocation (40M excl init veNFT)\\n // 48M for future partners\\n function initialMint(address _recipient) external {\\n require(msg.sender == minter && !initialMinted);\\n initialMinted = true;\\n _mint(_recipient, 82 * 1e6 * 1e18);\\n }\\n\\n function approve(address _spender, uint _value) external returns (bool) {\\n allowance[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n function _mint(address _to, uint _amount) internal returns (bool) {\\n totalSupply += _amount;\\n unchecked {\\n balanceOf[_to] += _amount;\\n }\\n emit Transfer(address(0x0), _to, _amount);\\n return true;\\n }\\n\\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\\n balanceOf[_from] -= _value;\\n unchecked {\\n balanceOf[_to] += _value;\\n }\\n emit Transfer(_from, _to, _value);\\n return true;\\n }\\n\\n function transfer(address _to, uint _value) external returns (bool) {\\n return _transfer(msg.sender, _to, _value);\\n }\\n\\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\\n uint allowed_from = allowance[_from][msg.sender];\\n if (allowed_from != type(uint).max) {\\n allowance[_from][msg.sender] -= _value;\\n }\\n return _transfer(_from, _to, _value);\\n }\\n\\n function mint(address account, uint amount) external returns (bool) {\\n require(msg.sender == minter);\\n _mint(account, amount);\\n return true;\\n }\\n\\n function claim(address account, uint amount) external returns (bool) {\\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\\n _mint(account, amount);\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xe98c291786f74c8f02edb3673870ba99d6b9adac299bbe42f1df42c740d737ac\",\"license\":\"MIT\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"}},\"version\":1}", + "bytecode": "0x60806040526000805534801561001457600080fd5b5060038054610100600160a81b0319163361010081029190911790915561003c906000610042565b506100d9565b60008160008082825461005591906100b3565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a350600192915050565b600082198211156100d457634e487b7160e01b600052601160045260246000fd5b500190565b61082e806100e86000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ae578063dd62ed3e146102c1578063e752c44a146102ec578063ec676a25146102ff578063fca3b5aa1461031257600080fd5b806395d89b4114610243578063a9059cbb14610266578063aad3ec9614610279578063c268f9ba1461028c578063ca1c4de9146102a157600080fd5b806323b872dd116100f457806323b872dd146101d0578063313ce567146101e357806340c10f19146101fd5780635e05fe501461021057806370a082311461022357600080fd5b806306fdde03146101265780630754617214610166578063095ea7b31461019657806318160ddd146101b9575b600080fd5b6101506040518060400160405280600b81526020016a2b32b637b1b4b6b2ba32b960a91b81525081565b60405161015d919061068e565b60405180910390f35b60035461017e9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015d565b6101a96101a43660046106ff565b610325565b604051901515815260200161015d565b6101c260005481565b60405190815260200161015d565b6101a96101de366004610729565b610391565b6101eb601281565b60405160ff909116815260200161015d565b6101a961020b3660046106ff565b61040b565b60045461017e906001600160a01b031681565b6101c2610231366004610765565b60016020526000908152604090205481565b61015060405180604001604052806004815260200163464c4f5760e01b81525081565b6101a96102743660046106ff565b61043e565b6101a96102873660046106ff565b610452565b61029f61029a366004610765565b610481565b005b6003546101a99060ff1681565b61029f6102bc366004610765565b6104d2565b6101c26102cf366004610780565b600260209081526000928352604080842090915290825290205481565b60055461017e906001600160a01b031681565b61029f61030d366004610765565b610510565b61029f610320366004610765565b61054e565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103809086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f7576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103f19084906107c9565b90915550505b610402858585610592565b95945050505050565b60035460009061010090046001600160a01b0316331461042a57600080fd5b6104348383610629565b5060019392505050565b600061044b338484610592565b9392505050565b6004546000906001600160a01b031633148061047857506005546001600160a01b031633145b61042a57600080fd5b60035461010090046001600160a01b0316331480156104a3575060035460ff16155b6104ac57600080fd5b6003805460ff191660011790556104ce816a43d42ce83da41d92000000610629565b5050565b60035461010090046001600160a01b031633146104ee57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052c57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056a57600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105bc9084906107c9565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106179086815260200190565b60405180910390a35060019392505050565b60008160008082825461063c91906107e0565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610380565b600060208083528351808285015260005b818110156106bb5785810183015185820160400152820161069f565b818111156106cd576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106fa57600080fd5b919050565b6000806040838503121561071257600080fd5b61071b836106e3565b946020939093013593505050565b60008060006060848603121561073e57600080fd5b610747846106e3565b9250610755602085016106e3565b9150604084013590509250925092565b60006020828403121561077757600080fd5b61044b826106e3565b6000806040838503121561079357600080fd5b61079c836106e3565b91506107aa602084016106e3565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107db576107db6107b3565b500390565b600082198211156107f3576107f36107b3565b50019056fea26469706673582212202aa872e848c1e34938f3ed63a66bc6d089c78d27e13a03d66d1a7c12ab495dbd64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ae578063dd62ed3e146102c1578063e752c44a146102ec578063ec676a25146102ff578063fca3b5aa1461031257600080fd5b806395d89b4114610243578063a9059cbb14610266578063aad3ec9614610279578063c268f9ba1461028c578063ca1c4de9146102a157600080fd5b806323b872dd116100f457806323b872dd146101d0578063313ce567146101e357806340c10f19146101fd5780635e05fe501461021057806370a082311461022357600080fd5b806306fdde03146101265780630754617214610166578063095ea7b31461019657806318160ddd146101b9575b600080fd5b6101506040518060400160405280600b81526020016a2b32b637b1b4b6b2ba32b960a91b81525081565b60405161015d919061068e565b60405180910390f35b60035461017e9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015d565b6101a96101a43660046106ff565b610325565b604051901515815260200161015d565b6101c260005481565b60405190815260200161015d565b6101a96101de366004610729565b610391565b6101eb601281565b60405160ff909116815260200161015d565b6101a961020b3660046106ff565b61040b565b60045461017e906001600160a01b031681565b6101c2610231366004610765565b60016020526000908152604090205481565b61015060405180604001604052806004815260200163464c4f5760e01b81525081565b6101a96102743660046106ff565b61043e565b6101a96102873660046106ff565b610452565b61029f61029a366004610765565b610481565b005b6003546101a99060ff1681565b61029f6102bc366004610765565b6104d2565b6101c26102cf366004610780565b600260209081526000928352604080842090915290825290205481565b60055461017e906001600160a01b031681565b61029f61030d366004610765565b610510565b61029f610320366004610765565b61054e565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103809086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f7576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103f19084906107c9565b90915550505b610402858585610592565b95945050505050565b60035460009061010090046001600160a01b0316331461042a57600080fd5b6104348383610629565b5060019392505050565b600061044b338484610592565b9392505050565b6004546000906001600160a01b031633148061047857506005546001600160a01b031633145b61042a57600080fd5b60035461010090046001600160a01b0316331480156104a3575060035460ff16155b6104ac57600080fd5b6003805460ff191660011790556104ce816a43d42ce83da41d92000000610629565b5050565b60035461010090046001600160a01b031633146104ee57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052c57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056a57600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105bc9084906107c9565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106179086815260200190565b60405180910390a35060019392505050565b60008160008082825461063c91906107e0565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610380565b600060208083528351808285015260005b818110156106bb5785810183015185820160400152820161069f565b818111156106cd576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106fa57600080fd5b919050565b6000806040838503121561071257600080fd5b61071b836106e3565b946020939093013593505050565b60008060006060848603121561073e57600080fd5b610747846106e3565b9250610755602085016106e3565b9150604084013590509250925092565b60006020828403121561077757600080fd5b61044b826106e3565b6000806040838503121561079357600080fd5b61079c836106e3565b91506107aa602084016106e3565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107db576107db6107b3565b500390565b600082198211156107f3576107f36107b3565b50019056fea26469706673582212202aa872e848c1e34938f3ed63a66bc6d089c78d27e13a03d66d1a7c12ab495dbd64736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/GaugeFactory.json b/deployments/arbitrumGoerli/GaugeFactory.json index 3d6d3445..2dcc2896 100644 --- a/deployments/arbitrumGoerli/GaugeFactory.json +++ b/deployments/arbitrumGoerli/GaugeFactory.json @@ -1,5 +1,5 @@ { - "address": "0xeAA8Ebb77A7e3b7AE2d8090E7A1c2F9B605dc919", + "address": "0xA957E3958C7ed4590a28C5564438E89238b34EC1", "abi": [ { "inputs": [ @@ -59,28 +59,28 @@ "type": "function" } ], - "transactionHash": "0x7f6f1ecc83b06c652e8bdf68f0802c149d6aadb43ac2bb12ef73f667f92d06ba", + "transactionHash": "0x85efc32d1e1f57ec2317ea7f06e5066c523fb0ce28325e1755e390d2d7046ca8", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xeAA8Ebb77A7e3b7AE2d8090E7A1c2F9B605dc919", + "contractAddress": "0xA957E3958C7ed4590a28C5564438E89238b34EC1", "transactionIndex": 1, - "gasUsed": "3419689", + "gasUsed": "3308285", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc356f50eca13e49b083bbae272055a0a02168086bb9188bb487bec9d9f2e1bef", - "transactionHash": "0x7f6f1ecc83b06c652e8bdf68f0802c149d6aadb43ac2bb12ef73f667f92d06ba", + "blockHash": "0x0c70caef0b5b20139b77a153f56d8b52ac092b78130d749353ec2eb408f34b17", + "transactionHash": "0x85efc32d1e1f57ec2317ea7f06e5066c523fb0ce28325e1755e390d2d7046ca8", "logs": [], - "blockNumber": 4455868, - "cumulativeGasUsed": "3419689", + "blockNumber": 5716706, + "cumulativeGasUsed": "3308285", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_internal_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_external_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_ve\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isPair\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_gauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/GaugeFactory.sol\":\"GaugeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Gauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\\ncontract Gauge is IGauge {\\n address public immutable stake; // the LP token that needs to be staked for rewards\\n address public immutable _ve; // the ve token used for gauges\\n address public immutable internal_bribe;\\n address public immutable external_bribe;\\n address public immutable voter;\\n\\n uint256 public derivedSupply;\\n mapping(address => uint256) public derivedBalances;\\n\\n bool public isForPair;\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 internal constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(address => uint256)) public lastEarn;\\n mapping(address => mapping(address => uint256))\\n public userRewardPerTokenStored;\\n\\n mapping(address => uint256) public tokenIds;\\n\\n uint256 public totalSupply;\\n mapping(address => uint256) public balanceOf;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n uint256 public fees0;\\n uint256 public fees1;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(\\n address _stake,\\n address _internal_bribe,\\n address _external_bribe,\\n address __ve,\\n address _voter,\\n bool _forPair,\\n address[] memory _allowedRewardTokens\\n ) {\\n stake = _stake;\\n internal_bribe = _internal_bribe;\\n external_bribe = _external_bribe;\\n _ve = __ve;\\n voter = _voter;\\n isForPair = _forPair;\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function claimFees()\\n external\\n lock\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n return _claimFees();\\n }\\n\\n function _claimFees()\\n internal\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n if (!isForPair) {\\n return (0, 0);\\n }\\n (claimed0, claimed1) = IPair(stake).claimFees();\\n if (claimed0 > 0 || claimed1 > 0) {\\n uint256 _fees0 = fees0 + claimed0;\\n uint256 _fees1 = fees1 + claimed1;\\n (address _token0, address _token1) = IPair(stake).tokens();\\n if (\\n _fees0 > IBribe(internal_bribe).left(_token0) &&\\n _fees0 / DURATION > 0\\n ) {\\n fees0 = 0;\\n _safeApprove(_token0, internal_bribe, _fees0);\\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\\n } else {\\n fees0 = _fees0;\\n }\\n if (\\n _fees1 > IBribe(internal_bribe).left(_token1) &&\\n _fees1 / DURATION > 0\\n ) {\\n fees1 = 0;\\n _safeApprove(_token1, internal_bribe, _fees1);\\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\\n } else {\\n fees1 = _fees1;\\n }\\n\\n emit ClaimFees(msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(address account, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(address account, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[account][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[account] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n derivedSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n function getReward(address account, address[] memory tokens) external lock {\\n require(msg.sender == account || msg.sender == voter);\\n _unlocked = 1;\\n IVoter(voter).distribute(address(this));\\n _unlocked = 2;\\n\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], account);\\n lastEarn[tokens[i]][account] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n\\n uint256 _derivedBalance = derivedBalances[account];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(account);\\n derivedBalances[account] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(account, derivedBalances[account]);\\n _writeSupplyCheckpoint();\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (derivedSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / derivedSupply);\\n }\\n\\n function derivedBalance(address account) public view returns (uint256) {\\n return balanceOf[account];\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\\n function earned(address token, address account)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][account],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[account] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[account] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[account][i];\\n Checkpoint memory cp1 = checkpoints[account][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[account][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][account]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n function depositAll(uint256 tokenId) external {\\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\\n }\\n\\n function deposit(uint256 amount, uint256 tokenId) public lock {\\n require(amount > 0);\\n _updateRewardForAllTokens();\\n\\n _safeTransferFrom(stake, msg.sender, address(this), amount);\\n totalSupply += amount;\\n balanceOf[msg.sender] += amount;\\n\\n if (tokenId > 0) {\\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\\n if (tokenIds[msg.sender] == 0) {\\n tokenIds[msg.sender] = tokenId;\\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\\n }\\n require(tokenIds[msg.sender] == tokenId);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, _derivedBalance);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function withdrawAll() external {\\n withdraw(balanceOf[msg.sender]);\\n }\\n\\n function withdraw(uint256 amount) public {\\n uint256 tokenId = 0;\\n if (amount == balanceOf[msg.sender]) {\\n tokenId = tokenIds[msg.sender];\\n }\\n withdrawToken(amount, tokenId);\\n }\\n\\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[msg.sender] -= amount;\\n _safeTransfer(stake, msg.sender, amount);\\n\\n if (tokenId > 0) {\\n require(tokenId == tokenIds[msg.sender]);\\n tokenIds[msg.sender] = 0;\\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(token != stake);\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"rewards tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n _claimFees();\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeApprove(\\n address token,\\n address spender,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x38cc0284dd60d8a1418d9c34e6be84911ca4a1b479dc129f19b9027e4c670e1f\",\"license\":\"MIT\"},\"contracts/factories/GaugeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/Gauge.sol';\\n\\ncontract GaugeFactory is IGaugeFactory {\\n address public last_gauge;\\n\\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\\n return last_gauge;\\n }\\n}\\n\",\"keccak256\":\"0x34f6ac4bdace9ef01d8cffda9b45842efae88b519230c67759b9936aee6acc9b\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50613b19806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea2646970667358221220c06381d31029b69e5bf80856b47bc2c6fb3bf68a222f6443485012f0d1a029f464736f6c634300080d0033a264697066735822122049fcf5d52ddf2c6e544d113d8ad438616e0a0479cc9116cd6e1d5d4f0ccb7b2364736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea2646970667358221220c06381d31029b69e5bf80856b47bc2c6fb3bf68a222f6443485012f0d1a029f464736f6c634300080d0033a264697066735822122049fcf5d52ddf2c6e544d113d8ad438616e0a0479cc9116cd6e1d5d4f0ccb7b2364736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_internal_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_external_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_ve\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isPair\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_gauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/GaugeFactory.sol\":\"GaugeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Gauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\\ncontract Gauge is IGauge {\\n address public immutable stake; // the LP token that needs to be staked for rewards\\n address public immutable _ve; // the ve token used for gauges\\n address public immutable internal_bribe;\\n address public immutable external_bribe;\\n address public immutable voter;\\n\\n uint256 public derivedSupply;\\n mapping(address => uint256) public derivedBalances;\\n\\n bool public isForPair;\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 internal constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(address => uint256)) public lastEarn;\\n mapping(address => mapping(address => uint256))\\n public userRewardPerTokenStored;\\n\\n mapping(address => uint256) public tokenIds;\\n\\n uint256 public totalSupply;\\n mapping(address => uint256) public balanceOf;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n uint256 public fees0;\\n uint256 public fees1;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(\\n address _stake,\\n address _internal_bribe,\\n address _external_bribe,\\n address __ve,\\n address _voter,\\n bool _forPair,\\n address[] memory _allowedRewardTokens\\n ) {\\n stake = _stake;\\n internal_bribe = _internal_bribe;\\n external_bribe = _external_bribe;\\n _ve = __ve;\\n voter = _voter;\\n isForPair = _forPair;\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function claimFees()\\n external\\n lock\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n return _claimFees();\\n }\\n\\n function _claimFees()\\n internal\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n if (!isForPair) {\\n return (0, 0);\\n }\\n (claimed0, claimed1) = IPair(stake).claimFees();\\n if (claimed0 > 0 || claimed1 > 0) {\\n uint256 _fees0 = fees0 + claimed0;\\n uint256 _fees1 = fees1 + claimed1;\\n (address _token0, address _token1) = IPair(stake).tokens();\\n if (\\n _fees0 > IBribe(internal_bribe).left(_token0) &&\\n _fees0 / DURATION > 0\\n ) {\\n fees0 = 0;\\n _safeApprove(_token0, internal_bribe, _fees0);\\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\\n } else {\\n fees0 = _fees0;\\n }\\n if (\\n _fees1 > IBribe(internal_bribe).left(_token1) &&\\n _fees1 / DURATION > 0\\n ) {\\n fees1 = 0;\\n _safeApprove(_token1, internal_bribe, _fees1);\\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\\n } else {\\n fees1 = _fees1;\\n }\\n\\n emit ClaimFees(msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(address account, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(address account, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[account][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[account] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n derivedSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n function getReward(address account, address[] memory tokens) external lock {\\n require(msg.sender == account || msg.sender == voter);\\n _unlocked = 1;\\n IVoter(voter).distribute(address(this));\\n _unlocked = 2;\\n\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], account);\\n lastEarn[tokens[i]][account] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n\\n uint256 _derivedBalance = derivedBalances[account];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(account);\\n derivedBalances[account] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(account, derivedBalances[account]);\\n _writeSupplyCheckpoint();\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (derivedSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / derivedSupply);\\n }\\n\\n function derivedBalance(address account) public view returns (uint256) {\\n return balanceOf[account];\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\\n function earned(address token, address account)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][account],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[account] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[account] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[account][i];\\n Checkpoint memory cp1 = checkpoints[account][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[account][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][account]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n function depositAll(uint256 tokenId) external {\\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\\n }\\n\\n function deposit(uint256 amount, uint256 tokenId) public lock {\\n require(amount > 0);\\n _updateRewardForAllTokens();\\n\\n _safeTransferFrom(stake, msg.sender, address(this), amount);\\n totalSupply += amount;\\n balanceOf[msg.sender] += amount;\\n\\n if (tokenId > 0) {\\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\\n if (tokenIds[msg.sender] == 0) {\\n tokenIds[msg.sender] = tokenId;\\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\\n }\\n require(tokenIds[msg.sender] == tokenId);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, _derivedBalance);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function withdrawAll() external {\\n withdraw(balanceOf[msg.sender]);\\n }\\n\\n function withdraw(uint256 amount) public {\\n uint256 tokenId = 0;\\n if (amount == balanceOf[msg.sender]) {\\n tokenId = tokenIds[msg.sender];\\n }\\n withdrawToken(amount, tokenId);\\n }\\n\\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[msg.sender] -= amount;\\n _safeTransfer(stake, msg.sender, amount);\\n\\n if (tokenId > 0) {\\n require(tokenId == tokenIds[msg.sender]);\\n tokenIds[msg.sender] = 0;\\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(token != stake);\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"rewards tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n _claimFees();\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeApprove(\\n address token,\\n address spender,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x38cc0284dd60d8a1418d9c34e6be84911ca4a1b479dc129f19b9027e4c670e1f\",\"license\":\"MIT\"},\"contracts/factories/GaugeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/Gauge.sol';\\n\\ncontract GaugeFactory is IGaugeFactory {\\n address public last_gauge;\\n\\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\\n return last_gauge;\\n }\\n}\\n\",\"keccak256\":\"0x34f6ac4bdace9ef01d8cffda9b45842efae88b519230c67759b9936aee6acc9b\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50613b19806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea26469706673582212208a503e90ec86652bffaad1a8a72d166d5f800a64e217b3ae0e9e2239815ddf4a64736f6c634300080d0033a264697066735822122090d33148904466ef33139c1a9443e5d4726004bb8187f8f4e03966c135b5f79664736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea26469706673582212208a503e90ec86652bffaad1a8a72d166d5f800a64e217b3ae0e9e2239815ddf4a64736f6c634300080d0033a264697066735822122090d33148904466ef33139c1a9443e5d4726004bb8187f8f4e03966c135b5f79664736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/MerkleClaim.json b/deployments/arbitrumGoerli/MerkleClaim.json index c92eedd1..a73c3a19 100644 --- a/deployments/arbitrumGoerli/MerkleClaim.json +++ b/deployments/arbitrumGoerli/MerkleClaim.json @@ -1,11 +1,11 @@ { - "address": "0x92eB499DBC33446Ace4f84Fba84E3A230370858D", + "address": "0x7F86f722a510CACb2cCD880a41dfE64773bfb371", "abi": [ { "inputs": [ { "internalType": "address", - "name": "_velo", + "name": "_flow", "type": "address" }, { @@ -38,10 +38,10 @@ }, { "inputs": [], - "name": "VELO", + "name": "FLOW", "outputs": [ { - "internalType": "contract IVelo", + "internalType": "contract IFlow", "name": "", "type": "address" } @@ -105,31 +105,31 @@ "type": "function" } ], - "transactionHash": "0xed2995ce6e0f251ecae7787f47c3e63c7e9c678465cac23506f04fdce77d5610", + "transactionHash": "0x9eee7514b364ed8b59f8f853c7122f3ed4b8a7e443e8239db2ab7c64b9166f33", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x92eB499DBC33446Ace4f84Fba84E3A230370858D", + "contractAddress": "0x7F86f722a510CACb2cCD880a41dfE64773bfb371", "transactionIndex": 1, - "gasUsed": "376375", + "gasUsed": "356954", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xcaac342c509bedceb64053d523bc7af000a2ee9954e10f8a0e0d6f855186c0b1", - "transactionHash": "0xed2995ce6e0f251ecae7787f47c3e63c7e9c678465cac23506f04fdce77d5610", + "blockHash": "0x4c9918bfc3679e56c838bebb22d8cf7149af2bda2952f5d05a87188926c6b1a4", + "transactionHash": "0x9eee7514b364ed8b59f8f853c7122f3ed4b8a7e443e8239db2ab7c64b9166f33", "logs": [], - "blockNumber": 4455902, - "cumulativeGasUsed": "376375", + "blockNumber": 5716760, + "cumulativeGasUsed": "356954", "status": 1, "byzantium": true }, "args": [ - "0x84Ca387E7ede764A3284c67Ff8c68a305a9030a0", + "0xf5A53c1b4072425DF6eC082f0A48B4652bc4188C", "0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f" ], - "numDeployments": 1, - "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_velo\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"_merkleRoot\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Claim\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"VELO\",\"outputs\":[{\"internalType\":\"contract IVelo\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"hasClaimed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\",\"events\":{\"Claim(address,uint256)\":{\"params\":{\"amount\":\"of tokens claimed\",\"to\":\"recipient of claim\"}}},\"kind\":\"dev\",\"methods\":{\"claim(address,uint256,bytes32[])\":{\"params\":{\"amount\":\"of tokens owed to claimee\",\"proof\":\"merkle proof to prove address and amount are in tree\",\"to\":\"address of claimee\"}},\"constructor\":{\"params\":{\"_merkleRoot\":\"of claimees\",\"_velo\":\"address\"}}},\"title\":\"MerkleClaim\",\"version\":1},\"userdoc\":{\"events\":{\"Claim(address,uint256)\":{\"notice\":\"Emitted after a successful token claim\"}},\"kind\":\"user\",\"methods\":{\"VELO()\":{\"notice\":\"VELO token to claim\"},\"claim(address,uint256,bytes32[])\":{\"notice\":\"Allows claiming tokens if address is part of merkle tree\"},\"constructor\":{\"notice\":\"Creates a new MerkleClaim contract\"},\"hasClaimed(address)\":{\"notice\":\"Mapping of addresses who have claimed tokens\"},\"merkleRoot()\":{\"notice\":\"ERC20-claimee inclusion root\"}},\"notice\":\"Claims VELO for members of a merkle tree\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/MerkleClaim.sol\":\"MerkleClaim\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"},\"contracts/redeem/MerkleClaim.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity 0.8.13;\\n\\n/// ============ Imports ============\\n\\nimport {IVelo} from \\\"contracts/interfaces/IVelo.sol\\\";\\nimport {MerkleProof} from \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\\\"; // OZ: MerkleProof\\n\\n/// @title MerkleClaim\\n/// @notice Claims VELO for members of a merkle tree\\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\\ncontract MerkleClaim {\\n /// ============ Immutable storage ============\\n\\n /// @notice VELO token to claim\\n IVelo public immutable VELO;\\n /// @notice ERC20-claimee inclusion root\\n bytes32 public immutable merkleRoot;\\n\\n /// ============ Mutable storage ============\\n\\n /// @notice Mapping of addresses who have claimed tokens\\n mapping(address => bool) public hasClaimed;\\n\\n /// ============ Constructor ============\\n\\n /// @notice Creates a new MerkleClaim contract\\n /// @param _velo address\\n /// @param _merkleRoot of claimees\\n constructor(address _velo, bytes32 _merkleRoot) {\\n VELO = IVelo(_velo);\\n merkleRoot = _merkleRoot;\\n }\\n\\n /// ============ Events ============\\n\\n /// @notice Emitted after a successful token claim\\n /// @param to recipient of claim\\n /// @param amount of tokens claimed\\n event Claim(address indexed to, uint256 amount);\\n\\n /// ============ Functions ============\\n\\n /// @notice Allows claiming tokens if address is part of merkle tree\\n /// @param to address of claimee\\n /// @param amount of tokens owed to claimee\\n /// @param proof merkle proof to prove address and amount are in tree\\n function claim(\\n address to,\\n uint256 amount,\\n bytes32[] calldata proof\\n ) external {\\n // Throw if address has already claimed tokens\\n require(!hasClaimed[to], \\\"ALREADY_CLAIMED\\\");\\n\\n // Verify merkle proof, or revert if not in tree\\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\\n require(isValidLeaf, \\\"NOT_IN_MERKLE\\\");\\n\\n // Set address to claimed\\n hasClaimed[to] = true;\\n\\n // Claim tokens for address\\n require(VELO.claim(to, amount), \\\"CLAIM_FAILED\\\");\\n\\n // Emit claim event\\n emit Claim(to, amount);\\n }\\n}\\n\",\"keccak256\":\"0xb4724b0f4bf1f8a9f5ef9147e834b2d85ae61005ffc1d6b261f911c093f38270\",\"license\":\"AGPL-3.0-only\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev These functions deal with verification of Merkle Tree proofs.\\n *\\n * The tree and the proofs can be generated using our\\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\\n * You will find a quickstart guide in the readme.\\n *\\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\\n * hashing, or use a hash function other than keccak256 for hashing leaves.\\n * This is because the concatenation of a sorted pair of internal nodes in\\n * the merkle tree could be reinterpreted as a leaf value.\\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\\n * against this attack out of the box.\\n */\\nlibrary MerkleProof {\\n /**\\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\\n * defined by `root`. For this, a `proof` must be provided, containing\\n * sibling hashes on the branch from the leaf to the root of the tree. Each\\n * pair of leaves and each pair of pre-images are assumed to be sorted.\\n */\\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProof(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {verify}\\n *\\n * _Available since v4.7._\\n */\\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProofCalldata(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\\n * hash matches the root of the tree. When processing the proof, the pairs\\n * of leafs & pre-images are assumed to be sorted.\\n *\\n * _Available since v4.4._\\n */\\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Calldata version of {processProof}\\n *\\n * _Available since v4.7._\\n */\\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerify(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProof(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {multiProofVerify}\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerifyCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\\n * respectively.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProof(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n /**\\n * @dev Calldata version of {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProofCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\\n }\\n\\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x00, a)\\n mstore(0x20, b)\\n value := keccak256(0x00, 0x40)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcc76dbe53154a5bbd12fdd1613a73f73f3dc7c63d813be36f7ee606f52d6a7b3\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60c060405234801561001057600080fd5b5060405161062638038061062683398101604081905261002f91610045565b6001600160a01b0390911660805260a05261007f565b6000806040838503121561005857600080fd5b82516001600160a01b038116811461006f57600080fd5b6020939093015192949293505050565b60805160a0516105766100b060003960008181605601526101ea01526000818160d8015261029601526105766000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633d13f8741461008b57806373b2e80e146100a0578063a0eeb39a146100d3575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61009e61009936600461043c565b610112565b005b6100c36100ae3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6100fa7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220c4a1bab597730e466dcb169625a9837504c5e0af82acc632d411e8517a3ed02964736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633d13f8741461008b57806373b2e80e146100a0578063a0eeb39a146100d3575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61009e61009936600461043c565b610112565b005b6100c36100ae3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6100fa7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220c4a1bab597730e466dcb169625a9837504c5e0af82acc632d411e8517a3ed02964736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_flow\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"_merkleRoot\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Claim\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FLOW\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"hasClaimed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\",\"events\":{\"Claim(address,uint256)\":{\"params\":{\"amount\":\"of tokens claimed\",\"to\":\"recipient of claim\"}}},\"kind\":\"dev\",\"methods\":{\"claim(address,uint256,bytes32[])\":{\"params\":{\"amount\":\"of tokens owed to claimee\",\"proof\":\"merkle proof to prove address and amount are in tree\",\"to\":\"address of claimee\"}},\"constructor\":{\"params\":{\"_flow\":\"address\",\"_merkleRoot\":\"of claimees\"}}},\"title\":\"MerkleClaim\",\"version\":1},\"userdoc\":{\"events\":{\"Claim(address,uint256)\":{\"notice\":\"Emitted after a successful token claim\"}},\"kind\":\"user\",\"methods\":{\"FLOW()\":{\"notice\":\"FLOW token to claim\"},\"claim(address,uint256,bytes32[])\":{\"notice\":\"Allows claiming tokens if address is part of merkle tree\"},\"constructor\":{\"notice\":\"Creates a new MerkleClaim contract\"},\"hasClaimed(address)\":{\"notice\":\"Mapping of addresses who have claimed tokens\"},\"merkleRoot()\":{\"notice\":\"ERC20-claimee inclusion root\"}},\"notice\":\"Claims FLOW for members of a merkle tree\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/MerkleClaim.sol\":\"MerkleClaim\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/redeem/MerkleClaim.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity 0.8.13;\\n\\n/// ============ Imports ============\\n\\nimport {IFlow} from \\\"contracts/interfaces/IFlow.sol\\\";\\nimport {MerkleProof} from \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\\\"; // OZ: MerkleProof\\n\\n/// @title MerkleClaim\\n/// @notice Claims FLOW for members of a merkle tree\\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\\ncontract MerkleClaim {\\n /// ============ Immutable storage ============\\n\\n /// @notice FLOW token to claim\\n IFlow public immutable FLOW;\\n /// @notice ERC20-claimee inclusion root\\n bytes32 public immutable merkleRoot;\\n\\n /// ============ Mutable storage ============\\n\\n /// @notice Mapping of addresses who have claimed tokens\\n mapping(address => bool) public hasClaimed;\\n\\n /// ============ Constructor ============\\n\\n /// @notice Creates a new MerkleClaim contract\\n /// @param _flow address\\n /// @param _merkleRoot of claimees\\n constructor(address _flow, bytes32 _merkleRoot) {\\n FLOW = IFlow(_flow);\\n merkleRoot = _merkleRoot;\\n }\\n\\n /// ============ Events ============\\n\\n /// @notice Emitted after a successful token claim\\n /// @param to recipient of claim\\n /// @param amount of tokens claimed\\n event Claim(address indexed to, uint256 amount);\\n\\n /// ============ Functions ============\\n\\n /// @notice Allows claiming tokens if address is part of merkle tree\\n /// @param to address of claimee\\n /// @param amount of tokens owed to claimee\\n /// @param proof merkle proof to prove address and amount are in tree\\n function claim(\\n address to,\\n uint256 amount,\\n bytes32[] calldata proof\\n ) external {\\n // Throw if address has already claimed tokens\\n require(!hasClaimed[to], \\\"ALREADY_CLAIMED\\\");\\n\\n // Verify merkle proof, or revert if not in tree\\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\\n require(isValidLeaf, \\\"NOT_IN_MERKLE\\\");\\n\\n // Set address to claimed\\n hasClaimed[to] = true;\\n\\n // Claim tokens for address\\n require(FLOW.claim(to, amount), \\\"CLAIM_FAILED\\\");\\n\\n // Emit claim event\\n emit Claim(to, amount);\\n }\\n}\\n\",\"keccak256\":\"0xf169ba9559c5c39dc79b2281410b09fd92f200a3b0489b32e28ce08a00a98826\",\"license\":\"AGPL-3.0-only\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev These functions deal with verification of Merkle Tree proofs.\\n *\\n * The tree and the proofs can be generated using our\\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\\n * You will find a quickstart guide in the readme.\\n *\\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\\n * hashing, or use a hash function other than keccak256 for hashing leaves.\\n * This is because the concatenation of a sorted pair of internal nodes in\\n * the merkle tree could be reinterpreted as a leaf value.\\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\\n * against this attack out of the box.\\n */\\nlibrary MerkleProof {\\n /**\\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\\n * defined by `root`. For this, a `proof` must be provided, containing\\n * sibling hashes on the branch from the leaf to the root of the tree. Each\\n * pair of leaves and each pair of pre-images are assumed to be sorted.\\n */\\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProof(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {verify}\\n *\\n * _Available since v4.7._\\n */\\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProofCalldata(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\\n * hash matches the root of the tree. When processing the proof, the pairs\\n * of leafs & pre-images are assumed to be sorted.\\n *\\n * _Available since v4.4._\\n */\\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Calldata version of {processProof}\\n *\\n * _Available since v4.7._\\n */\\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerify(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProof(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {multiProofVerify}\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerifyCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\\n * respectively.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProof(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n /**\\n * @dev Calldata version of {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProofCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\\n }\\n\\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x00, a)\\n mstore(0x20, b)\\n value := keccak256(0x00, 0x40)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcc76dbe53154a5bbd12fdd1613a73f73f3dc7c63d813be36f7ee606f52d6a7b3\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c060405234801561001057600080fd5b5060405161062638038061062683398101604081905261002f91610045565b6001600160a01b0390911660805260a05261007f565b6000806040838503121561005857600080fd5b82516001600160a01b038116811461006f57600080fd5b6020939093015192949293505050565b60805160a0516105766100b060003960008181605601526101ea0152600081816090015261029601526105766000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633189097b1461008b5780633d13f874146100ca57806373b2e80e146100df575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6100b27f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6100dd6100d836600461043c565b610112565b005b6101026100ed3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea26469706673582212209c52c6d8a33927001b183ce0a24bb8ee0b37d362594a46e4cb302c90ea5c7f7564736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633189097b1461008b5780633d13f874146100ca57806373b2e80e146100df575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6100b27f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6100dd6100d836600461043c565b610112565b005b6101026100ed3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea26469706673582212209c52c6d8a33927001b183ce0a24bb8ee0b37d362594a46e4cb302c90ea5c7f7564736f6c634300080d0033", "devdoc": { "author": "Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)", "events": { @@ -151,8 +151,8 @@ }, "constructor": { "params": { - "_merkleRoot": "of claimees", - "_velo": "address" + "_flow": "address", + "_merkleRoot": "of claimees" } } }, @@ -167,8 +167,8 @@ }, "kind": "user", "methods": { - "VELO()": { - "notice": "VELO token to claim" + "FLOW()": { + "notice": "FLOW token to claim" }, "claim(address,uint256,bytes32[])": { "notice": "Allows claiming tokens if address is part of merkle tree" @@ -183,7 +183,7 @@ "notice": "ERC20-claimee inclusion root" } }, - "notice": "Claims VELO for members of a merkle tree", + "notice": "Claims FLOW for members of a merkle tree", "version": 1 }, "storageLayout": { diff --git a/deployments/arbitrumGoerli/Minter.json b/deployments/arbitrumGoerli/Minter.json index 0c8d2150..cfeb83bb 100644 --- a/deployments/arbitrumGoerli/Minter.json +++ b/deployments/arbitrumGoerli/Minter.json @@ -1,5 +1,5 @@ { - "address": "0x402f3c314149F252144EE4Ca8646b4a215ACD6aC", + "address": "0x388c6C5e6D27E3b6fa40eb98e0ef573D9E8e037E", "abi": [ { "inputs": [ @@ -68,10 +68,10 @@ }, { "inputs": [], - "name": "_rewards_distributor", + "name": "_flow", "outputs": [ { - "internalType": "contract IRewardsDistributor", + "internalType": "contract IFlow", "name": "", "type": "address" } @@ -81,10 +81,10 @@ }, { "inputs": [], - "name": "_ve", + "name": "_rewards_distributor", "outputs": [ { - "internalType": "contract IVotingEscrow", + "internalType": "contract IRewardsDistributor", "name": "", "type": "address" } @@ -94,10 +94,10 @@ }, { "inputs": [], - "name": "_velo", + "name": "_ve", "outputs": [ { - "internalType": "contract IVelo", + "internalType": "contract IVotingEscrow", "name": "", "type": "address" } @@ -324,32 +324,32 @@ "type": "function" } ], - "transactionHash": "0xb286b07d5b396515e46cc6a6b8babba627980fcd79ca741b914e28f95cc766ca", + "transactionHash": "0x356a312c4d8f1b2798a49b56e2fd152d6e032bc3d634fed3f3476aa062cd8e57", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x402f3c314149F252144EE4Ca8646b4a215ACD6aC", + "contractAddress": "0x388c6C5e6D27E3b6fa40eb98e0ef573D9E8e037E", "transactionIndex": 1, - "gasUsed": "1240030", + "gasUsed": "1199219", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x98ac4f1cbbf01c907d9eeee29aedb2ab604deaadef1812effe4eeb52f1aed6e4", - "transactionHash": "0xb286b07d5b396515e46cc6a6b8babba627980fcd79ca741b914e28f95cc766ca", + "blockHash": "0xd0490e4f90eee1e815840ca4c6032d9c26121484c5251a3cd90102f8dfaaac32", + "transactionHash": "0x356a312c4d8f1b2798a49b56e2fd152d6e032bc3d634fed3f3476aa062cd8e57", "logs": [], - "blockNumber": 4455893, - "cumulativeGasUsed": "1240030", + "blockNumber": 5716740, + "cumulativeGasUsed": "1199219", "status": 1, "byzantium": true }, "args": [ - "0x854086d39955d28317aE3856399312b8Edb1B473", - "0xBf05364D6cf1586852c18c6b1CbEe218E3e09885", - "0xc4b9295487B4C43C1929299076820D8f55BBf957" + "0x362502b7139761937067cf81a73Dc18D315f10A0", + "0xC43f6EbF97f9D99FF8a3aFe1413599e8DEc2aDB3", + "0xEED0deFB831F96fC45B5e0ACb477F517F186496F" ], - "numDeployments": 1, - "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__voter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__rewards_distributor\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weekly\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_supply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_emission\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_TEAM_RATE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_rewards_distributor\",\"outputs\":[{\"internalType\":\"contract IRewardsDistributor\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"contract IVotingEscrow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_velo\",\"outputs\":[{\"internalType\":\"contract IVelo\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_voter\",\"outputs\":[{\"internalType\":\"contract IVoter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"active_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"calculate_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minted\",\"type\":\"uint256\"}],\"name\":\"calculate_growth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"claimants\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingTeam\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_teamRate\",\"type\":\"uint256\"}],\"name\":\"setTeamRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"teamRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"update_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Minter.sol\":\"Minter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Minter.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IMinter.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVelo.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\\n\\ncontract Minter is IMinter {\\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\\n uint256 internal constant EMISSION = 990;\\n uint256 internal constant TAIL_EMISSION = 2;\\n uint256 internal constant PRECISION = 1000;\\n IVelo public immutable _velo;\\n IVoter public immutable _voter;\\n IVotingEscrow public immutable _ve;\\n IRewardsDistributor public immutable _rewards_distributor;\\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\\n uint256 public active_period;\\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\\n\\n address internal initializer;\\n address public team;\\n address public pendingTeam;\\n uint256 public teamRate;\\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\\n\\n event Mint(\\n address indexed sender,\\n uint256 weekly,\\n uint256 circulating_supply,\\n uint256 circulating_emission\\n );\\n\\n constructor(\\n address __voter, // the voting & distribution system\\n address __ve, // the ve(3,3) system that will be locked into\\n address __rewards_distributor // the distribution system that ensures users aren't diluted\\n ) {\\n initializer = msg.sender;\\n team = msg.sender;\\n teamRate = 30; // 30 bps = 0.03%\\n _velo = IVelo(IVotingEscrow(__ve).token());\\n _voter = IVoter(__voter);\\n _ve = IVotingEscrow(__ve);\\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\\n }\\n\\n function initialize(\\n address[] memory claimants,\\n uint256[] memory amounts,\\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\\n ) external {\\n require(initializer == msg.sender);\\n _velo.mint(address(this), max);\\n _velo.approve(address(_ve), type(uint256).max);\\n for (uint256 i = 0; i < claimants.length; i++) {\\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\\n }\\n initializer = address(0);\\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\\n }\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team, \\\"not team\\\");\\n pendingTeam = _team;\\n }\\n\\n function acceptTeam() external {\\n require(msg.sender == pendingTeam, \\\"not pending team\\\");\\n team = pendingTeam;\\n }\\n\\n function setTeamRate(uint256 _teamRate) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(_teamRate <= MAX_TEAM_RATE, \\\"rate too high\\\");\\n teamRate = _teamRate;\\n }\\n\\n // calculate circulating supply as total token supply - locked supply\\n function circulating_supply() public view returns (uint256) {\\n return _velo.totalSupply() - _ve.totalSupply();\\n }\\n\\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\\n function calculate_emission() public view returns (uint256) {\\n return (weekly * EMISSION) / PRECISION;\\n }\\n\\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\\n function weekly_emission() public view returns (uint256) {\\n return MathDunks.max(calculate_emission(), circulating_emission());\\n }\\n\\n // calculates tail end (infinity) emissions as 0.2% of total supply\\n function circulating_emission() public view returns (uint256) {\\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\\n }\\n\\n // calculate inflation and adjust ve balances accordingly\\n function calculate_growth(uint256 _minted) public view returns (uint256) {\\n uint256 _veTotal = _ve.totalSupply();\\n uint256 _veloTotal = _velo.totalSupply();\\n return\\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\\n _veTotal) /\\n _veloTotal /\\n 2;\\n }\\n\\n // update period can only be called once per cycle (1 week)\\n function update_period() external returns (uint256) {\\n uint256 _period = active_period;\\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\\n // only trigger if new week\\n _period = (block.timestamp / WEEK) * WEEK;\\n active_period = _period;\\n weekly = weekly_emission();\\n\\n uint256 _growth = calculate_growth(weekly);\\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\\n (PRECISION - teamRate);\\n uint256 _required = _growth + weekly + _teamEmissions;\\n uint256 _balanceOf = _velo.balanceOf(address(this));\\n if (_balanceOf < _required) {\\n _velo.mint(address(this), _required - _balanceOf);\\n }\\n\\n require(_velo.transfer(team, _teamEmissions));\\n require(_velo.transfer(address(_rewards_distributor), _growth));\\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\\n\\n _velo.approve(address(_voter), weekly);\\n _voter.notifyRewardAmount(weekly);\\n\\n emit Mint(\\n msg.sender,\\n weekly,\\n circulating_supply(),\\n circulating_emission()\\n );\\n }\\n return _period;\\n }\\n}\\n\",\"keccak256\":\"0x8dce50c09815e53982006f9ddc46cd52cf7ac86b0c1b7bb15c817f86fb990580\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x6101006040526a0c685fa11e01ec6f0000006000553480156200002157600080fd5b506040516200158938038062001589833981016040819052620000449162000156565b60028054336001600160a01b03199182168117909255600380549091169091179055601e60055560408051637e062a3560e11b815290516001600160a01b0384169163fc0c546a9160048083019260209291908290030181865afa158015620000b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d79190620001a0565b6001600160a01b0390811660805283811660a05282811660c052811660e05262093a808062000108816002620001db565b620001149042620001fd565b62000120919062000218565b6200012c9190620001db565b600155506200023b915050565b80516001600160a01b03811681146200015157600080fd5b919050565b6000806000606084860312156200016c57600080fd5b620001778462000139565b9250620001876020850162000139565b9150620001976040850162000139565b90509250925092565b600060208284031215620001b357600080fd5b620001be8262000139565b9392505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620001f857620001f8620001c5565b500290565b60008219821115620002135762000213620001c5565b500190565b6000826200023657634e487b7160e01b600052601260045260246000fd5b500490565b60805160a05160c05160e051611296620002f3600039600081816101f801528181610c3701528181610cde0152610d51015260008181610261015281816104b30152818161055f0152818161068901526108750152600081816101d101528181610e090152610ea301526000818161015101528181610426015281816104e30152818161070f015281816108f701528181610a5f01528181610ade01528181610ba801528181610c660152610dda01526112966000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c806378ef7f02116100ad578063b5cc143a11610071578063b5cc143a14610296578063cfc6c8ff1461029e578063d1399608146102a6578063e038c75a146102af578063ed29fc11146102b757600080fd5b806378ef7f021461022d578063851708131461023657806385f2aef2146102495780638dd598fb1461025c5780638e01fbfa1461028357600080fd5b80632e8f7b1f116100f45780632e8f7b1f146101b157806336d96faf146101c45780633db9b42a146101cc5780634b1cd5da146101f357806359d46ffc1461021a57600080fd5b806301c8e6fd1461013157806308aa44581461014c578063095cf5c61461018b5780631eebae80146101a057806326cfc17b146101a8575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b61019e610199366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61019e6101bf366004610fb8565b610353565b6101396103de565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b600454610173906001600160a01b031681565b61013960055481565b61019e6102443660046110a7565b6103f3565b600354610173906001600160a01b031681565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b610139610291366004610fb8565b610684565b61019e6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea26469706673582212206fa40733fc0460202dd7acad8836bc192a7e6f0195a1ba5004b64c08f206af0564736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c806378ef7f02116100ad578063b5cc143a11610071578063b5cc143a14610296578063cfc6c8ff1461029e578063d1399608146102a6578063e038c75a146102af578063ed29fc11146102b757600080fd5b806378ef7f021461022d578063851708131461023657806385f2aef2146102495780638dd598fb1461025c5780638e01fbfa1461028357600080fd5b80632e8f7b1f116100f45780632e8f7b1f146101b157806336d96faf146101c45780633db9b42a146101cc5780634b1cd5da146101f357806359d46ffc1461021a57600080fd5b806301c8e6fd1461013157806308aa44581461014c578063095cf5c61461018b5780631eebae80146101a057806326cfc17b146101a8575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b61019e610199366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61019e6101bf366004610fb8565b610353565b6101396103de565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b600454610173906001600160a01b031681565b61013960055481565b61019e6102443660046110a7565b6103f3565b600354610173906001600160a01b031681565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b610139610291366004610fb8565b610684565b61019e6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea26469706673582212206fa40733fc0460202dd7acad8836bc192a7e6f0195a1ba5004b64c08f206af0564736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__voter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__rewards_distributor\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weekly\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_supply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_emission\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_TEAM_RATE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_flow\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_rewards_distributor\",\"outputs\":[{\"internalType\":\"contract IRewardsDistributor\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"contract IVotingEscrow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_voter\",\"outputs\":[{\"internalType\":\"contract IVoter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"active_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"calculate_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minted\",\"type\":\"uint256\"}],\"name\":\"calculate_growth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"claimants\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingTeam\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_teamRate\",\"type\":\"uint256\"}],\"name\":\"setTeamRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"teamRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"update_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Minter.sol\":\"Minter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Minter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IMinter.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\\n\\ncontract Minter is IMinter {\\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\\n uint256 internal constant EMISSION = 990;\\n uint256 internal constant TAIL_EMISSION = 2;\\n uint256 internal constant PRECISION = 1000;\\n IFlow public immutable _flow;\\n IVoter public immutable _voter;\\n IVotingEscrow public immutable _ve;\\n IRewardsDistributor public immutable _rewards_distributor;\\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M FLOW (FLOW has 18 decimals)\\n uint256 public active_period;\\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\\n\\n address internal initializer;\\n address public team;\\n address public pendingTeam;\\n uint256 public teamRate;\\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\\n\\n event Mint(\\n address indexed sender,\\n uint256 weekly,\\n uint256 circulating_supply,\\n uint256 circulating_emission\\n );\\n\\n constructor(\\n address __voter, // the voting & distribution system\\n address __ve, // the ve(3,3) system that will be locked into\\n address __rewards_distributor // the distribution system that ensures users aren't diluted\\n ) {\\n initializer = msg.sender;\\n team = msg.sender;\\n teamRate = 30; // 30 bps = 0.03%\\n _flow = IFlow(IVotingEscrow(__ve).token());\\n _voter = IVoter(__voter);\\n _ve = IVotingEscrow(__ve);\\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\\n }\\n\\n function initialize(\\n address[] memory claimants,\\n uint256[] memory amounts,\\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\\n ) external {\\n require(initializer == msg.sender);\\n _flow.mint(address(this), max);\\n _flow.approve(address(_ve), type(uint256).max);\\n for (uint256 i = 0; i < claimants.length; i++) {\\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\\n }\\n initializer = address(0);\\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\\n }\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team, \\\"not team\\\");\\n pendingTeam = _team;\\n }\\n\\n function acceptTeam() external {\\n require(msg.sender == pendingTeam, \\\"not pending team\\\");\\n team = pendingTeam;\\n }\\n\\n function setTeamRate(uint256 _teamRate) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(_teamRate <= MAX_TEAM_RATE, \\\"rate too high\\\");\\n teamRate = _teamRate;\\n }\\n\\n // calculate circulating supply as total token supply - locked supply\\n function circulating_supply() public view returns (uint256) {\\n return _flow.totalSupply() - _ve.totalSupply();\\n }\\n\\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\\n function calculate_emission() public view returns (uint256) {\\n return (weekly * EMISSION) / PRECISION;\\n }\\n\\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\\n function weekly_emission() public view returns (uint256) {\\n return MathDunks.max(calculate_emission(), circulating_emission());\\n }\\n\\n // calculates tail end (infinity) emissions as 0.2% of total supply\\n function circulating_emission() public view returns (uint256) {\\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\\n }\\n\\n // calculate inflation and adjust ve balances accordingly\\n function calculate_growth(uint256 _minted) public view returns (uint256) {\\n uint256 _veTotal = _ve.totalSupply();\\n uint256 _flowTotal = _flow.totalSupply();\\n return\\n (((((_minted * _veTotal) / _flowTotal) * _veTotal) / _flowTotal) *\\n _veTotal) /\\n _flowTotal /\\n 2;\\n }\\n\\n // update period can only be called once per cycle (1 week)\\n function update_period() external returns (uint256) {\\n uint256 _period = active_period;\\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\\n // only trigger if new week\\n _period = (block.timestamp / WEEK) * WEEK;\\n active_period = _period;\\n weekly = weekly_emission();\\n\\n uint256 _growth = calculate_growth(weekly);\\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\\n (PRECISION - teamRate);\\n uint256 _required = _growth + weekly + _teamEmissions;\\n uint256 _balanceOf = _flow.balanceOf(address(this));\\n if (_balanceOf < _required) {\\n _flow.mint(address(this), _required - _balanceOf);\\n }\\n\\n require(_flow.transfer(team, _teamEmissions));\\n require(_flow.transfer(address(_rewards_distributor), _growth));\\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\\n\\n _flow.approve(address(_voter), weekly);\\n _voter.notifyRewardAmount(weekly);\\n\\n emit Mint(\\n msg.sender,\\n weekly,\\n circulating_supply(),\\n circulating_emission()\\n );\\n }\\n return _period;\\n }\\n}\\n\",\"keccak256\":\"0xc661046dd2b90d93e4f057d2497b137703b4f0c3caccfe846f1a81906a2e1961\",\"license\":\"MIT\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x6101006040526a0c685fa11e01ec6f0000006000553480156200002157600080fd5b506040516200158938038062001589833981016040819052620000449162000156565b60028054336001600160a01b03199182168117909255600380549091169091179055601e60055560408051637e062a3560e11b815290516001600160a01b0384169163fc0c546a9160048083019260209291908290030181865afa158015620000b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d79190620001a0565b6001600160a01b0390811660805283811660a05282811660c052811660e05262093a808062000108816002620001db565b620001149042620001fd565b62000120919062000218565b6200012c9190620001db565b600155506200023b915050565b80516001600160a01b03811681146200015157600080fd5b919050565b6000806000606084860312156200016c57600080fd5b620001778462000139565b9250620001876020850162000139565b9150620001976040850162000139565b90509250925092565b600060208284031215620001b357600080fd5b620001be8262000139565b9392505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620001f857620001f8620001c5565b500290565b60008219821115620002135762000213620001c5565b500190565b6000826200023657634e487b7160e01b600052601260045260246000fd5b500490565b60805160a05160c05160e051611296620002f3600039600081816101d101528181610c3701528181610cde0152610d5101526000818161023a015281816104b30152818161055f01528181610689015261087501526000818161019201528181610e090152610ea301526000818161029d01528181610426015281816104e30152818161070f015281816108f701528181610a5f01528181610ade01528181610ba801528181610c660152610dda01526112966000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c806385170813116100ad578063cfc6c8ff11610071578063cfc6c8ff14610277578063d13996081461027f578063e038c75a14610288578063ed29fc1114610290578063fe75cac51461029857600080fd5b8063851708131461020f57806385f2aef2146102225780638dd598fb146102355780638e01fbfa1461025c578063b5cc143a1461026f57600080fd5b806336d96faf116100f457806336d96faf146101855780633db9b42a1461018d5780634b1cd5da146101cc57806359d46ffc146101f357806378ef7f021461020657600080fd5b806301c8e6fd14610131578063095cf5c61461014c5780631eebae801461016157806326cfc17b146101695780632e8f7b1f14610172575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b61015f61015a366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61015f610180366004610fb8565b610353565b6101396103de565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6004546101b4906001600160a01b031681565b61013960055481565b61015f61021d3660046110a7565b6103f3565b6003546101b4906001600160a01b031681565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b61013961026a366004610fb8565b610684565b61015f6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea2646970667358221220fd177bce5ff2a20e0ff464c75ae7fa0fb1787a1d805a0ee0ff24890d9985a70164736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c806385170813116100ad578063cfc6c8ff11610071578063cfc6c8ff14610277578063d13996081461027f578063e038c75a14610288578063ed29fc1114610290578063fe75cac51461029857600080fd5b8063851708131461020f57806385f2aef2146102225780638dd598fb146102355780638e01fbfa1461025c578063b5cc143a1461026f57600080fd5b806336d96faf116100f457806336d96faf146101855780633db9b42a1461018d5780634b1cd5da146101cc57806359d46ffc146101f357806378ef7f021461020657600080fd5b806301c8e6fd14610131578063095cf5c61461014c5780631eebae801461016157806326cfc17b146101695780632e8f7b1f14610172575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b61015f61015a366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61015f610180366004610fb8565b610353565b6101396103de565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6004546101b4906001600160a01b031681565b61013960055481565b61015f61021d3660046110a7565b6103f3565b6003546101b4906001600160a01b031681565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b61013961026a366004610fb8565b610684565b61015f6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea2646970667358221220fd177bce5ff2a20e0ff464c75ae7fa0fb1787a1d805a0ee0ff24890d9985a70164736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, @@ -363,7 +363,7 @@ "storageLayout": { "storage": [ { - "astId": 6187, + "astId": 6679, "contract": "contracts/Minter.sol:Minter", "label": "weekly", "offset": 0, @@ -371,7 +371,7 @@ "type": "t_uint256" }, { - "astId": 6189, + "astId": 6681, "contract": "contracts/Minter.sol:Minter", "label": "active_period", "offset": 0, @@ -379,7 +379,7 @@ "type": "t_uint256" }, { - "astId": 6200, + "astId": 6692, "contract": "contracts/Minter.sol:Minter", "label": "initializer", "offset": 0, @@ -387,7 +387,7 @@ "type": "t_address" }, { - "astId": 6202, + "astId": 6694, "contract": "contracts/Minter.sol:Minter", "label": "team", "offset": 0, @@ -395,7 +395,7 @@ "type": "t_address" }, { - "astId": 6204, + "astId": 6696, "contract": "contracts/Minter.sol:Minter", "label": "pendingTeam", "offset": 0, @@ -403,7 +403,7 @@ "type": "t_address" }, { - "astId": 6206, + "astId": 6698, "contract": "contracts/Minter.sol:Minter", "label": "teamRate", "offset": 0, diff --git a/deployments/arbitrumGoerli/PairFactory.json b/deployments/arbitrumGoerli/PairFactory.json index c72dff2f..5d5c0292 100644 --- a/deployments/arbitrumGoerli/PairFactory.json +++ b/deployments/arbitrumGoerli/PairFactory.json @@ -1,5 +1,5 @@ { - "address": "0x6389e934d35fC9e066FAb549C8DBc9FddaC10e0D", + "address": "0xddadFF10D1C9eb062180a870150D11673FFf7ad6", "abi": [ { "inputs": [], @@ -383,28 +383,28 @@ "type": "function" } ], - "transactionHash": "0x6ed74c056b5b7bd5c74422c6a7f3bcdb0c8f660e5036b0e602ecad2bf3c7069b", + "transactionHash": "0x8dc1c3a31146015f6268ba5bd7c44d4a6119d330d0160a5281b3f24d551df73b", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x6389e934d35fC9e066FAb549C8DBc9FddaC10e0D", + "contractAddress": "0xddadFF10D1C9eb062180a870150D11673FFf7ad6", "transactionIndex": 1, - "gasUsed": "4777620", + "gasUsed": "4628154", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x15d0ab42df0563378e2406c0d098da299916fce4242aa1646a01591688fa367a", - "transactionHash": "0x6ed74c056b5b7bd5c74422c6a7f3bcdb0c8f660e5036b0e602ecad2bf3c7069b", + "blockHash": "0x4838e8d0987d654b382fa3c6380dd10c976bd9abf020f9e33ed688f05cbcdb1c", + "transactionHash": "0x8dc1c3a31146015f6268ba5bd7c44d4a6119d330d0160a5281b3f24d551df73b", "logs": [], - "blockNumber": 4455874, - "cumulativeGasUsed": "4777620", + "blockNumber": 5716716, + "cumulativeGasUsed": "4628154", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"PairCreated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_FEE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allPairs\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"allPairsLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"createPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getInitializable\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"name\":\"getPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pairCodeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingFeeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingPauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_feeManager\",\"type\":\"address\"}],\"name\":\"setFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_state\",\"type\":\"bool\"}],\"name\":\"setPause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pauser\",\"type\":\"address\"}],\"name\":\"setPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stableFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"volatileFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/PairFactory.sol\":\"PairFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Pair.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairCallee.sol\\\";\\nimport \\\"contracts/factories/PairFactory.sol\\\";\\nimport \\\"contracts/PairFees.sol\\\";\\n\\n// The base pair of pools, either stable or volatile\\ncontract Pair is IPair {\\n string public name;\\n string public symbol;\\n uint8 public constant decimals = 18;\\n\\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\\n bool public immutable stable;\\n\\n uint256 public totalSupply = 0;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n mapping(address => uint256) public balanceOf;\\n\\n bytes32 internal DOMAIN_SEPARATOR;\\n // keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 internal constant PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n mapping(address => uint256) public nonces;\\n\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n\\n address public immutable token0;\\n address public immutable token1;\\n address public immutable fees;\\n address immutable factory;\\n\\n // Structure to capture time period obervations every 30 minutes, used for local oracles\\n struct Observation {\\n uint256 timestamp;\\n uint256 reserve0Cumulative;\\n uint256 reserve1Cumulative;\\n }\\n\\n // Capture oracle reading every 30 minutes\\n uint256 constant periodSize = 1800;\\n\\n Observation[] public observations;\\n\\n uint256 internal immutable decimals0;\\n uint256 internal immutable decimals1;\\n\\n uint256 public reserve0;\\n uint256 public reserve1;\\n uint256 public blockTimestampLast;\\n\\n uint256 public reserve0CumulativeLast;\\n uint256 public reserve1CumulativeLast;\\n\\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \\\"clean\\\"\\n // this further allows LP holders to easily claim fees for tokens they have/staked\\n uint256 public index0 = 0;\\n uint256 public index1 = 0;\\n\\n // position assigned to each LP to track their current index0 & index1 vs the global position\\n mapping(address => uint256) public supplyIndex0;\\n mapping(address => uint256) public supplyIndex1;\\n\\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\\n mapping(address => uint256) public claimable0;\\n mapping(address => uint256) public claimable1;\\n\\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\\n event Burn(\\n address indexed sender,\\n uint256 amount0,\\n uint256 amount1,\\n address indexed to\\n );\\n event Swap(\\n address indexed sender,\\n uint256 amount0In,\\n uint256 amount1In,\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address indexed to\\n );\\n event Sync(uint256 reserve0, uint256 reserve1);\\n event Claim(\\n address indexed sender,\\n address indexed recipient,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 amount\\n );\\n\\n constructor() {\\n factory = msg.sender;\\n (address _token0, address _token1, bool _stable) = PairFactory(\\n msg.sender\\n ).getInitializable();\\n (token0, token1, stable) = (_token0, _token1, _stable);\\n fees = address(new PairFees(_token0, _token1));\\n if (_stable) {\\n name = string(\\n abi.encodePacked(\\n \\\"StableV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"sAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n } else {\\n name = string(\\n abi.encodePacked(\\n \\\"VolatileV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"vAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n }\\n\\n decimals0 = 10**IERC20(_token0).decimals();\\n decimals1 = 10**IERC20(_token1).decimals();\\n\\n observations.push(Observation(block.timestamp, 0, 0));\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function observationLength() external view returns (uint256) {\\n return observations.length;\\n }\\n\\n function lastObservation() public view returns (Observation memory) {\\n return observations[observations.length - 1];\\n }\\n\\n function metadata()\\n external\\n view\\n returns (\\n uint256 dec0,\\n uint256 dec1,\\n uint256 r0,\\n uint256 r1,\\n bool st,\\n address t0,\\n address t1\\n )\\n {\\n return (\\n decimals0,\\n decimals1,\\n reserve0,\\n reserve1,\\n stable,\\n token0,\\n token1\\n );\\n }\\n\\n function tokens() external view returns (address, address) {\\n return (token0, token1);\\n }\\n\\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\\n _updateFor(msg.sender);\\n\\n claimed0 = claimable0[msg.sender];\\n claimed1 = claimable1[msg.sender];\\n\\n if (claimed0 > 0 || claimed1 > 0) {\\n claimable0[msg.sender] = 0;\\n claimable1[msg.sender] = 0;\\n\\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\\n\\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n // Accrue fees on token0\\n function _update0(uint256 amount) internal {\\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index0 += _ratio;\\n }\\n emit Fees(msg.sender, amount, 0);\\n }\\n\\n // Accrue fees on token1\\n function _update1(uint256 amount) internal {\\n _safeTransfer(token1, fees, amount);\\n uint256 _ratio = (amount * 1e18) / totalSupply;\\n if (_ratio > 0) {\\n index1 += _ratio;\\n }\\n emit Fees(msg.sender, 0, amount);\\n }\\n\\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\\n // Fees are segregated from core funds, so fees can never put liquidity at risk\\n function _updateFor(address recipient) internal {\\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\\n if (_supplied > 0) {\\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\\n uint256 _supplyIndex1 = supplyIndex1[recipient];\\n uint256 _index0 = index0; // get global index0 for accumulated fees\\n uint256 _index1 = index1;\\n supplyIndex0[recipient] = _index0; // update user current position to global position\\n supplyIndex1[recipient] = _index1;\\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\\n uint256 _delta1 = _index1 - _supplyIndex1;\\n if (_delta0 > 0) {\\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\\n claimable0[recipient] += _share;\\n }\\n if (_delta1 > 0) {\\n uint256 _share = (_supplied * _delta1) / 1e18;\\n claimable1[recipient] += _share;\\n }\\n } else {\\n supplyIndex0[recipient] = index0; // new users are set to the default global state\\n supplyIndex1[recipient] = index1;\\n }\\n }\\n\\n function getReserves()\\n public\\n view\\n returns (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n )\\n {\\n _reserve0 = reserve0;\\n _reserve1 = reserve1;\\n _blockTimestampLast = blockTimestampLast;\\n }\\n\\n // update reserves and, on the first call per block, price accumulators\\n function _update(\\n uint256 balance0,\\n uint256 balance1,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal {\\n uint256 blockTimestamp = block.timestamp;\\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\\n reserve0CumulativeLast += _reserve0 * timeElapsed;\\n reserve1CumulativeLast += _reserve1 * timeElapsed;\\n }\\n\\n Observation memory _point = lastObservation();\\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\\n if (timeElapsed > periodSize) {\\n observations.push(\\n Observation(\\n blockTimestamp,\\n reserve0CumulativeLast,\\n reserve1CumulativeLast\\n )\\n );\\n }\\n reserve0 = balance0;\\n reserve1 = balance1;\\n blockTimestampLast = blockTimestamp;\\n emit Sync(reserve0, reserve1);\\n }\\n\\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\\n function currentCumulativePrices()\\n public\\n view\\n returns (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n uint256 blockTimestamp\\n )\\n {\\n blockTimestamp = block.timestamp;\\n reserve0Cumulative = reserve0CumulativeLast;\\n reserve1Cumulative = reserve1CumulativeLast;\\n\\n // if time has elapsed since the last update on the pair, mock the accumulated price values\\n (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n ) = getReserves();\\n if (_blockTimestampLast != blockTimestamp) {\\n // subtraction overflow is desired\\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\\n reserve0Cumulative += _reserve0 * timeElapsed;\\n reserve1Cumulative += _reserve1 * timeElapsed;\\n }\\n }\\n\\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\\n function current(address tokenIn, uint256 amountIn)\\n external\\n view\\n returns (uint256 amountOut)\\n {\\n Observation memory _observation = lastObservation();\\n (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n\\n ) = currentCumulativePrices();\\n if (block.timestamp == _observation.timestamp) {\\n _observation = observations[observations.length - 2];\\n }\\n\\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\\n uint256 _reserve0 = (reserve0Cumulative -\\n _observation.reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (reserve1Cumulative -\\n _observation.reserve1Cumulative) / timeElapsed;\\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n // as per `current`, however allows user configured granularity, up to the full window size\\n function quote(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 granularity\\n ) external view returns (uint256 amountOut) {\\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\\n uint256 priceAverageCumulative;\\n for (uint256 i = 0; i < _prices.length; i++) {\\n priceAverageCumulative += _prices[i];\\n }\\n return priceAverageCumulative / granularity;\\n }\\n\\n // returns a memory set of twap prices\\n function prices(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points\\n ) external view returns (uint256[] memory) {\\n return sample(tokenIn, amountIn, points, 1);\\n }\\n\\n function sample(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points,\\n uint256 window\\n ) public view returns (uint256[] memory) {\\n uint256[] memory _prices = new uint256[](points);\\n\\n uint256 length = observations.length - 1;\\n uint256 i = length - (points * window);\\n uint256 nextIndex = 0;\\n uint256 index = 0;\\n\\n for (; i < length; i += window) {\\n nextIndex = i + window;\\n uint256 timeElapsed = observations[nextIndex].timestamp -\\n observations[i].timestamp;\\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\\n observations[i].reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\\n observations[i].reserve1Cumulative) / timeElapsed;\\n _prices[index] = _getAmountOut(\\n amountIn,\\n tokenIn,\\n _reserve0,\\n _reserve1\\n );\\n // index < length; length cannot overflow\\n unchecked {\\n index = index + 1;\\n }\\n }\\n return _prices;\\n }\\n\\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\\n // standard uniswap v2 implementation\\n function mint(address to) external lock returns (uint256 liquidity) {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\\n uint256 _amount0 = _balance0 - _reserve0;\\n uint256 _amount1 = _balance1 - _reserve1;\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n if (_totalSupply == 0) {\\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\\n } else {\\n liquidity = MathDunks.min(\\n (_amount0 * _totalSupply) / _reserve0,\\n (_amount1 * _totalSupply) / _reserve1\\n );\\n }\\n require(liquidity > 0, \\\"ILM\\\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\\n _mint(to, liquidity);\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Mint(msg.sender, _amount0, _amount1);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n // standard uniswap v2 implementation\\n function burn(address to)\\n external\\n lock\\n returns (uint256 amount0, uint256 amount1)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n (address _token0, address _token1) = (token0, token1);\\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\\n uint256 _liquidity = balanceOf[address(this)];\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\\n require(amount0 > 0 && amount1 > 0, \\\"ILB\\\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\\n _burn(address(this), _liquidity);\\n _safeTransfer(_token0, to, amount0);\\n _safeTransfer(_token1, to, amount1);\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Burn(msg.sender, amount0, amount1, to);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n function swap(\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address to,\\n bytes calldata data\\n ) external lock {\\n require(!PairFactory(factory).isPaused());\\n require(amount0Out > 0 || amount1Out > 0, \\\"IOA\\\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \\\"IL\\\"); // Pair: INSUFFICIENT_LIQUIDITY\\n\\n uint256 _balance0;\\n uint256 _balance1;\\n {\\n // scope for _token{0,1}, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n require(to != _token0 && to != _token1, \\\"IT\\\"); // Pair: INVALID_TO\\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\\n if (data.length > 0)\\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n }\\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\\n ? _balance0 - (_reserve0 - amount0Out)\\n : 0;\\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\\n ? _balance1 - (_reserve1 - amount1Out)\\n : 0;\\n require(amount0In > 0 || amount1In > 0, \\\"IIA\\\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\\n {\\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n if (amount0In > 0)\\n _update0(\\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token0 and move them out of pool\\n if (amount1In > 0)\\n _update1(\\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token1 and move them out of pool\\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \\\"K\\\"); // Pair: K\\n }\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\\n }\\n\\n // force balances to match reserves\\n function skim(address to) external lock {\\n (address _token0, address _token1) = (token0, token1);\\n _safeTransfer(\\n _token0,\\n to,\\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\\n );\\n _safeTransfer(\\n _token1,\\n to,\\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\\n );\\n }\\n\\n // force reserves to match balances\\n function sync() external lock {\\n _update(\\n IERC20(token0).balanceOf(address(this)),\\n IERC20(token1).balanceOf(address(this)),\\n reserve0,\\n reserve1\\n );\\n }\\n\\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\\n 1e18 +\\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\\n 1e18;\\n }\\n\\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (3 * x0 * ((y * y) / 1e18)) /\\n 1e18 +\\n ((((x0 * x0) / 1e18) * x0) / 1e18);\\n }\\n\\n function _get_y(\\n uint256 x0,\\n uint256 xy,\\n uint256 y\\n ) internal pure returns (uint256) {\\n for (uint256 i = 0; i < 255; i++) {\\n uint256 y_prev = y;\\n uint256 k = _f(x0, y);\\n if (k < xy) {\\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\\n y = y + dy;\\n } else {\\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getAmountOut(uint256 amountIn, address tokenIn)\\n external\\n view\\n returns (uint256)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n function _getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal view returns (uint256) {\\n if (stable) {\\n uint256 xy = _k(_reserve0, _reserve1);\\n _reserve0 = (_reserve0 * 1e18) / decimals0;\\n _reserve1 = (_reserve1 * 1e18) / decimals1;\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0\\n ? (amountIn * 1e18) / decimals0\\n : (amountIn * 1e18) / decimals1;\\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\\n } else {\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n return (amountIn * reserveB) / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\\n if (stable) {\\n uint256 _x = (x * 1e18) / decimals0;\\n uint256 _y = (y * 1e18) / decimals1;\\n uint256 _a = (_x * _y) / 1e18;\\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return (_a * _b) / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n\\n function _mint(address dst, uint256 amount) internal {\\n _updateFor(dst); // balances must be updated on mint/burn/transfer\\n totalSupply += amount;\\n balanceOf[dst] += amount;\\n emit Transfer(address(0), dst, amount);\\n }\\n\\n function _burn(address dst, uint256 amount) internal {\\n _updateFor(dst);\\n totalSupply -= amount;\\n balanceOf[dst] -= amount;\\n emit Transfer(dst, address(0), amount);\\n }\\n\\n function approve(address spender, uint256 amount) external returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external {\\n require(deadline >= block.timestamp, \\\"Pair: EXPIRED\\\");\\n DOMAIN_SEPARATOR = keccak256(\\n abi.encode(\\n keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n ),\\n keccak256(bytes(name)),\\n keccak256(bytes(\\\"1\\\")),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR,\\n keccak256(\\n abi.encode(\\n PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n );\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n require(\\n recoveredAddress != address(0) && recoveredAddress == owner,\\n \\\"Pair: INVALID_SIGNATURE\\\"\\n );\\n allowance[owner][spender] = value;\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function transfer(address dst, uint256 amount) external returns (bool) {\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 amount\\n ) external returns (bool) {\\n address spender = msg.sender;\\n uint256 spenderAllowance = allowance[src][spender];\\n\\n if (spender != src && spenderAllowance != type(uint256).max) {\\n uint256 newAllowance = spenderAllowance - amount;\\n allowance[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n function _transferTokens(\\n address src,\\n address dst,\\n uint256 amount\\n ) internal {\\n _updateFor(src); // update fee position for src\\n _updateFor(dst); // update fee position for dst\\n\\n balanceOf[src] -= amount;\\n balanceOf[dst] += amount;\\n\\n emit Transfer(src, dst, amount);\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x4f508747645f4480e0b0f23d952fa9b82af1d9bc60b15b8cd1f542ee136043d1\",\"license\":\"MIT\"},\"contracts/PairFees.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IERC20.sol';\\n\\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\\ncontract PairFees {\\n\\n address internal immutable pair; // The pair it is bonded to\\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\\n\\n constructor(address _token0, address _token1) {\\n pair = msg.sender;\\n token0 = _token0;\\n token1 = _token1;\\n }\\n\\n function _safeTransfer(address token,address to,uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n // Allow the pair to transfer fees to users\\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\\n require(msg.sender == pair);\\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\\n }\\n\\n}\\n\",\"keccak256\":\"0xb772e192bab353f8642e89a95ef4ef0255d1caef08444101d7fe34469c1000ca\",\"license\":\"MIT\"},\"contracts/factories/PairFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/Pair.sol';\\n\\ncontract PairFactory is IPairFactory {\\n\\n bool public isPaused;\\n address public pauser;\\n address public pendingPauser;\\n\\n uint256 public stableFee;\\n uint256 public volatileFee;\\n uint256 public constant MAX_FEE = 5; // 0.05%\\n address public feeManager;\\n address public pendingFeeManager;\\n\\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\\n address[] public allPairs;\\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\\n\\n address internal _temp0;\\n address internal _temp1;\\n bool internal _temp;\\n\\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\\n\\n constructor() {\\n pauser = msg.sender;\\n isPaused = false;\\n feeManager = msg.sender;\\n stableFee = 2; // 0.02%\\n volatileFee = 2;\\n }\\n\\n function allPairsLength() external view returns (uint) {\\n return allPairs.length;\\n }\\n\\n function setPauser(address _pauser) external {\\n require(msg.sender == pauser);\\n pendingPauser = _pauser;\\n }\\n\\n function acceptPauser() external {\\n require(msg.sender == pendingPauser);\\n pauser = pendingPauser;\\n }\\n\\n function setPause(bool _state) external {\\n require(msg.sender == pauser);\\n isPaused = _state;\\n }\\n\\n function setFeeManager(address _feeManager) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n pendingFeeManager = _feeManager;\\n }\\n\\n function acceptFeeManager() external {\\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\\n feeManager = pendingFeeManager;\\n }\\n\\n function setFee(bool _stable, uint256 _fee) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n require(_fee <= MAX_FEE, 'fee too high');\\n require(_fee != 0, 'fee must be nonzero');\\n if (_stable) {\\n stableFee = _fee;\\n } else {\\n volatileFee = _fee;\\n }\\n }\\n\\n function getFee(bool _stable) public view returns(uint256) {\\n return _stable ? stableFee : volatileFee;\\n }\\n\\n function pairCodeHash() external pure returns (bytes32) {\\n return keccak256(type(Pair).creationCode);\\n }\\n\\n function getInitializable() external view returns (address, address, bool) {\\n return (_temp0, _temp1, _temp);\\n }\\n\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\\n (_temp0, _temp1, _temp) = (token0, token1, stable);\\n pair = address(new Pair{salt:salt}());\\n getPair[token0][token1][stable] = pair;\\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\\n allPairs.push(pair);\\n isPair[pair] = true;\\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\\n }\\n}\\n\",\"keccak256\":\"0x9b7984117a5a32188aa9ddf42b6cff024240579ab30f3776f7a201285d813e4f\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairCallee.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairCallee {\\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x3ac2de2c7a08bf59fd1006e4d108b247916369de15fbd048b72ca2b7814023ca\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50600080546001600160a81b03191633610100810260ff1916919091178255600480546001600160a01b0319169091179055600280805560035561519190819061005a90396000f3fe60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea2646970667358221220a6c1c49d2a02bc4a24e84a9e991bd58346313938bf594eb65d535709e7b46ac764736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea264697066735822122087f6444299d02580bffcb97ca1adfcbaae5d5dcd5007567b6722534a74b6bd3f64736f6c634300080d0033a2646970667358221220f93a0275ff0f5bd6a16554956d45f62614b3d89703e3c9d92f48df4c3d70a4b964736f6c634300080d0033", - "deployedBytecode": "0x60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea2646970667358221220a6c1c49d2a02bc4a24e84a9e991bd58346313938bf594eb65d535709e7b46ac764736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea264697066735822122087f6444299d02580bffcb97ca1adfcbaae5d5dcd5007567b6722534a74b6bd3f64736f6c634300080d0033a2646970667358221220f93a0275ff0f5bd6a16554956d45f62614b3d89703e3c9d92f48df4c3d70a4b964736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"PairCreated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_FEE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allPairs\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"allPairsLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"createPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getInitializable\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"name\":\"getPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pairCodeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingFeeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingPauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_feeManager\",\"type\":\"address\"}],\"name\":\"setFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_state\",\"type\":\"bool\"}],\"name\":\"setPause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pauser\",\"type\":\"address\"}],\"name\":\"setPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stableFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"volatileFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/PairFactory.sol\":\"PairFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Pair.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairCallee.sol\\\";\\nimport \\\"contracts/factories/PairFactory.sol\\\";\\nimport \\\"contracts/PairFees.sol\\\";\\n\\n// The base pair of pools, either stable or volatile\\ncontract Pair is IPair {\\n string public name;\\n string public symbol;\\n uint8 public constant decimals = 18;\\n\\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\\n bool public immutable stable;\\n\\n uint256 public totalSupply = 0;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n mapping(address => uint256) public balanceOf;\\n\\n bytes32 internal DOMAIN_SEPARATOR;\\n // keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 internal constant PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n mapping(address => uint256) public nonces;\\n\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n\\n address public immutable token0;\\n address public immutable token1;\\n address public immutable fees;\\n address immutable factory;\\n\\n // Structure to capture time period obervations every 30 minutes, used for local oracles\\n struct Observation {\\n uint256 timestamp;\\n uint256 reserve0Cumulative;\\n uint256 reserve1Cumulative;\\n }\\n\\n // Capture oracle reading every 30 minutes\\n uint256 constant periodSize = 1800;\\n\\n Observation[] public observations;\\n\\n uint256 internal immutable decimals0;\\n uint256 internal immutable decimals1;\\n\\n uint256 public reserve0;\\n uint256 public reserve1;\\n uint256 public blockTimestampLast;\\n\\n uint256 public reserve0CumulativeLast;\\n uint256 public reserve1CumulativeLast;\\n\\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \\\"clean\\\"\\n // this further allows LP holders to easily claim fees for tokens they have/staked\\n uint256 public index0 = 0;\\n uint256 public index1 = 0;\\n\\n // position assigned to each LP to track their current index0 & index1 vs the global position\\n mapping(address => uint256) public supplyIndex0;\\n mapping(address => uint256) public supplyIndex1;\\n\\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\\n mapping(address => uint256) public claimable0;\\n mapping(address => uint256) public claimable1;\\n\\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\\n event Burn(\\n address indexed sender,\\n uint256 amount0,\\n uint256 amount1,\\n address indexed to\\n );\\n event Swap(\\n address indexed sender,\\n uint256 amount0In,\\n uint256 amount1In,\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address indexed to\\n );\\n event Sync(uint256 reserve0, uint256 reserve1);\\n event Claim(\\n address indexed sender,\\n address indexed recipient,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 amount\\n );\\n\\n constructor() {\\n factory = msg.sender;\\n (address _token0, address _token1, bool _stable) = PairFactory(\\n msg.sender\\n ).getInitializable();\\n (token0, token1, stable) = (_token0, _token1, _stable);\\n fees = address(new PairFees(_token0, _token1));\\n if (_stable) {\\n name = string(\\n abi.encodePacked(\\n \\\"StableV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"sAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n } else {\\n name = string(\\n abi.encodePacked(\\n \\\"VolatileV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"vAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n }\\n\\n decimals0 = 10**IERC20(_token0).decimals();\\n decimals1 = 10**IERC20(_token1).decimals();\\n\\n observations.push(Observation(block.timestamp, 0, 0));\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function observationLength() external view returns (uint256) {\\n return observations.length;\\n }\\n\\n function lastObservation() public view returns (Observation memory) {\\n return observations[observations.length - 1];\\n }\\n\\n function metadata()\\n external\\n view\\n returns (\\n uint256 dec0,\\n uint256 dec1,\\n uint256 r0,\\n uint256 r1,\\n bool st,\\n address t0,\\n address t1\\n )\\n {\\n return (\\n decimals0,\\n decimals1,\\n reserve0,\\n reserve1,\\n stable,\\n token0,\\n token1\\n );\\n }\\n\\n function tokens() external view returns (address, address) {\\n return (token0, token1);\\n }\\n\\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\\n _updateFor(msg.sender);\\n\\n claimed0 = claimable0[msg.sender];\\n claimed1 = claimable1[msg.sender];\\n\\n if (claimed0 > 0 || claimed1 > 0) {\\n claimable0[msg.sender] = 0;\\n claimable1[msg.sender] = 0;\\n\\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\\n\\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n // Accrue fees on token0\\n function _update0(uint256 amount) internal {\\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index0 += _ratio;\\n }\\n emit Fees(msg.sender, amount, 0);\\n }\\n\\n // Accrue fees on token1\\n function _update1(uint256 amount) internal {\\n _safeTransfer(token1, fees, amount);\\n uint256 _ratio = (amount * 1e18) / totalSupply;\\n if (_ratio > 0) {\\n index1 += _ratio;\\n }\\n emit Fees(msg.sender, 0, amount);\\n }\\n\\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\\n // Fees are segregated from core funds, so fees can never put liquidity at risk\\n function _updateFor(address recipient) internal {\\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\\n if (_supplied > 0) {\\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\\n uint256 _supplyIndex1 = supplyIndex1[recipient];\\n uint256 _index0 = index0; // get global index0 for accumulated fees\\n uint256 _index1 = index1;\\n supplyIndex0[recipient] = _index0; // update user current position to global position\\n supplyIndex1[recipient] = _index1;\\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\\n uint256 _delta1 = _index1 - _supplyIndex1;\\n if (_delta0 > 0) {\\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\\n claimable0[recipient] += _share;\\n }\\n if (_delta1 > 0) {\\n uint256 _share = (_supplied * _delta1) / 1e18;\\n claimable1[recipient] += _share;\\n }\\n } else {\\n supplyIndex0[recipient] = index0; // new users are set to the default global state\\n supplyIndex1[recipient] = index1;\\n }\\n }\\n\\n function getReserves()\\n public\\n view\\n returns (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n )\\n {\\n _reserve0 = reserve0;\\n _reserve1 = reserve1;\\n _blockTimestampLast = blockTimestampLast;\\n }\\n\\n // update reserves and, on the first call per block, price accumulators\\n function _update(\\n uint256 balance0,\\n uint256 balance1,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal {\\n uint256 blockTimestamp = block.timestamp;\\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\\n reserve0CumulativeLast += _reserve0 * timeElapsed;\\n reserve1CumulativeLast += _reserve1 * timeElapsed;\\n }\\n\\n Observation memory _point = lastObservation();\\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\\n if (timeElapsed > periodSize) {\\n observations.push(\\n Observation(\\n blockTimestamp,\\n reserve0CumulativeLast,\\n reserve1CumulativeLast\\n )\\n );\\n }\\n reserve0 = balance0;\\n reserve1 = balance1;\\n blockTimestampLast = blockTimestamp;\\n emit Sync(reserve0, reserve1);\\n }\\n\\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\\n function currentCumulativePrices()\\n public\\n view\\n returns (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n uint256 blockTimestamp\\n )\\n {\\n blockTimestamp = block.timestamp;\\n reserve0Cumulative = reserve0CumulativeLast;\\n reserve1Cumulative = reserve1CumulativeLast;\\n\\n // if time has elapsed since the last update on the pair, mock the accumulated price values\\n (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n ) = getReserves();\\n if (_blockTimestampLast != blockTimestamp) {\\n // subtraction overflow is desired\\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\\n reserve0Cumulative += _reserve0 * timeElapsed;\\n reserve1Cumulative += _reserve1 * timeElapsed;\\n }\\n }\\n\\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\\n function current(address tokenIn, uint256 amountIn)\\n external\\n view\\n returns (uint256 amountOut)\\n {\\n Observation memory _observation = lastObservation();\\n (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n\\n ) = currentCumulativePrices();\\n if (block.timestamp == _observation.timestamp) {\\n _observation = observations[observations.length - 2];\\n }\\n\\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\\n uint256 _reserve0 = (reserve0Cumulative -\\n _observation.reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (reserve1Cumulative -\\n _observation.reserve1Cumulative) / timeElapsed;\\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n // as per `current`, however allows user configured granularity, up to the full window size\\n function quote(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 granularity\\n ) external view returns (uint256 amountOut) {\\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\\n uint256 priceAverageCumulative;\\n for (uint256 i = 0; i < _prices.length; i++) {\\n priceAverageCumulative += _prices[i];\\n }\\n return priceAverageCumulative / granularity;\\n }\\n\\n // returns a memory set of twap prices\\n function prices(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points\\n ) external view returns (uint256[] memory) {\\n return sample(tokenIn, amountIn, points, 1);\\n }\\n\\n function sample(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points,\\n uint256 window\\n ) public view returns (uint256[] memory) {\\n uint256[] memory _prices = new uint256[](points);\\n\\n uint256 length = observations.length - 1;\\n uint256 i = length - (points * window);\\n uint256 nextIndex = 0;\\n uint256 index = 0;\\n\\n for (; i < length; i += window) {\\n nextIndex = i + window;\\n uint256 timeElapsed = observations[nextIndex].timestamp -\\n observations[i].timestamp;\\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\\n observations[i].reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\\n observations[i].reserve1Cumulative) / timeElapsed;\\n _prices[index] = _getAmountOut(\\n amountIn,\\n tokenIn,\\n _reserve0,\\n _reserve1\\n );\\n // index < length; length cannot overflow\\n unchecked {\\n index = index + 1;\\n }\\n }\\n return _prices;\\n }\\n\\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\\n // standard uniswap v2 implementation\\n function mint(address to) external lock returns (uint256 liquidity) {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\\n uint256 _amount0 = _balance0 - _reserve0;\\n uint256 _amount1 = _balance1 - _reserve1;\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n if (_totalSupply == 0) {\\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\\n } else {\\n liquidity = MathDunks.min(\\n (_amount0 * _totalSupply) / _reserve0,\\n (_amount1 * _totalSupply) / _reserve1\\n );\\n }\\n require(liquidity > 0, \\\"ILM\\\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\\n _mint(to, liquidity);\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Mint(msg.sender, _amount0, _amount1);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n // standard uniswap v2 implementation\\n function burn(address to)\\n external\\n lock\\n returns (uint256 amount0, uint256 amount1)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n (address _token0, address _token1) = (token0, token1);\\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\\n uint256 _liquidity = balanceOf[address(this)];\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\\n require(amount0 > 0 && amount1 > 0, \\\"ILB\\\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\\n _burn(address(this), _liquidity);\\n _safeTransfer(_token0, to, amount0);\\n _safeTransfer(_token1, to, amount1);\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Burn(msg.sender, amount0, amount1, to);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n function swap(\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address to,\\n bytes calldata data\\n ) external lock {\\n require(!PairFactory(factory).isPaused());\\n require(amount0Out > 0 || amount1Out > 0, \\\"IOA\\\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \\\"IL\\\"); // Pair: INSUFFICIENT_LIQUIDITY\\n\\n uint256 _balance0;\\n uint256 _balance1;\\n {\\n // scope for _token{0,1}, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n require(to != _token0 && to != _token1, \\\"IT\\\"); // Pair: INVALID_TO\\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\\n if (data.length > 0)\\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n }\\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\\n ? _balance0 - (_reserve0 - amount0Out)\\n : 0;\\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\\n ? _balance1 - (_reserve1 - amount1Out)\\n : 0;\\n require(amount0In > 0 || amount1In > 0, \\\"IIA\\\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\\n {\\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n if (amount0In > 0)\\n _update0(\\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token0 and move them out of pool\\n if (amount1In > 0)\\n _update1(\\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token1 and move them out of pool\\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \\\"K\\\"); // Pair: K\\n }\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\\n }\\n\\n // force balances to match reserves\\n function skim(address to) external lock {\\n (address _token0, address _token1) = (token0, token1);\\n _safeTransfer(\\n _token0,\\n to,\\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\\n );\\n _safeTransfer(\\n _token1,\\n to,\\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\\n );\\n }\\n\\n // force reserves to match balances\\n function sync() external lock {\\n _update(\\n IERC20(token0).balanceOf(address(this)),\\n IERC20(token1).balanceOf(address(this)),\\n reserve0,\\n reserve1\\n );\\n }\\n\\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\\n 1e18 +\\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\\n 1e18;\\n }\\n\\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (3 * x0 * ((y * y) / 1e18)) /\\n 1e18 +\\n ((((x0 * x0) / 1e18) * x0) / 1e18);\\n }\\n\\n function _get_y(\\n uint256 x0,\\n uint256 xy,\\n uint256 y\\n ) internal pure returns (uint256) {\\n for (uint256 i = 0; i < 255; i++) {\\n uint256 y_prev = y;\\n uint256 k = _f(x0, y);\\n if (k < xy) {\\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\\n y = y + dy;\\n } else {\\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getAmountOut(uint256 amountIn, address tokenIn)\\n external\\n view\\n returns (uint256)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n function _getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal view returns (uint256) {\\n if (stable) {\\n uint256 xy = _k(_reserve0, _reserve1);\\n _reserve0 = (_reserve0 * 1e18) / decimals0;\\n _reserve1 = (_reserve1 * 1e18) / decimals1;\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0\\n ? (amountIn * 1e18) / decimals0\\n : (amountIn * 1e18) / decimals1;\\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\\n } else {\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n return (amountIn * reserveB) / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\\n if (stable) {\\n uint256 _x = (x * 1e18) / decimals0;\\n uint256 _y = (y * 1e18) / decimals1;\\n uint256 _a = (_x * _y) / 1e18;\\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return (_a * _b) / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n\\n function _mint(address dst, uint256 amount) internal {\\n _updateFor(dst); // balances must be updated on mint/burn/transfer\\n totalSupply += amount;\\n balanceOf[dst] += amount;\\n emit Transfer(address(0), dst, amount);\\n }\\n\\n function _burn(address dst, uint256 amount) internal {\\n _updateFor(dst);\\n totalSupply -= amount;\\n balanceOf[dst] -= amount;\\n emit Transfer(dst, address(0), amount);\\n }\\n\\n function approve(address spender, uint256 amount) external returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external {\\n require(deadline >= block.timestamp, \\\"Pair: EXPIRED\\\");\\n DOMAIN_SEPARATOR = keccak256(\\n abi.encode(\\n keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n ),\\n keccak256(bytes(name)),\\n keccak256(bytes(\\\"1\\\")),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR,\\n keccak256(\\n abi.encode(\\n PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n );\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n require(\\n recoveredAddress != address(0) && recoveredAddress == owner,\\n \\\"Pair: INVALID_SIGNATURE\\\"\\n );\\n allowance[owner][spender] = value;\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function transfer(address dst, uint256 amount) external returns (bool) {\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 amount\\n ) external returns (bool) {\\n address spender = msg.sender;\\n uint256 spenderAllowance = allowance[src][spender];\\n\\n if (spender != src && spenderAllowance != type(uint256).max) {\\n uint256 newAllowance = spenderAllowance - amount;\\n allowance[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n function _transferTokens(\\n address src,\\n address dst,\\n uint256 amount\\n ) internal {\\n _updateFor(src); // update fee position for src\\n _updateFor(dst); // update fee position for dst\\n\\n balanceOf[src] -= amount;\\n balanceOf[dst] += amount;\\n\\n emit Transfer(src, dst, amount);\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x4f508747645f4480e0b0f23d952fa9b82af1d9bc60b15b8cd1f542ee136043d1\",\"license\":\"MIT\"},\"contracts/PairFees.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IERC20.sol';\\n\\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\\ncontract PairFees {\\n\\n address internal immutable pair; // The pair it is bonded to\\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\\n\\n constructor(address _token0, address _token1) {\\n pair = msg.sender;\\n token0 = _token0;\\n token1 = _token1;\\n }\\n\\n function _safeTransfer(address token,address to,uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n // Allow the pair to transfer fees to users\\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\\n require(msg.sender == pair);\\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\\n }\\n\\n}\\n\",\"keccak256\":\"0xb772e192bab353f8642e89a95ef4ef0255d1caef08444101d7fe34469c1000ca\",\"license\":\"MIT\"},\"contracts/factories/PairFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/Pair.sol';\\n\\ncontract PairFactory is IPairFactory {\\n\\n bool public isPaused;\\n address public pauser;\\n address public pendingPauser;\\n\\n uint256 public stableFee;\\n uint256 public volatileFee;\\n uint256 public constant MAX_FEE = 5; // 0.05%\\n address public feeManager;\\n address public pendingFeeManager;\\n\\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\\n address[] public allPairs;\\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\\n\\n address internal _temp0;\\n address internal _temp1;\\n bool internal _temp;\\n\\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\\n\\n constructor() {\\n pauser = msg.sender;\\n isPaused = false;\\n feeManager = msg.sender;\\n stableFee = 2; // 0.02%\\n volatileFee = 2;\\n }\\n\\n function allPairsLength() external view returns (uint) {\\n return allPairs.length;\\n }\\n\\n function setPauser(address _pauser) external {\\n require(msg.sender == pauser);\\n pendingPauser = _pauser;\\n }\\n\\n function acceptPauser() external {\\n require(msg.sender == pendingPauser);\\n pauser = pendingPauser;\\n }\\n\\n function setPause(bool _state) external {\\n require(msg.sender == pauser);\\n isPaused = _state;\\n }\\n\\n function setFeeManager(address _feeManager) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n pendingFeeManager = _feeManager;\\n }\\n\\n function acceptFeeManager() external {\\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\\n feeManager = pendingFeeManager;\\n }\\n\\n function setFee(bool _stable, uint256 _fee) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n require(_fee <= MAX_FEE, 'fee too high');\\n require(_fee != 0, 'fee must be nonzero');\\n if (_stable) {\\n stableFee = _fee;\\n } else {\\n volatileFee = _fee;\\n }\\n }\\n\\n function getFee(bool _stable) public view returns(uint256) {\\n return _stable ? stableFee : volatileFee;\\n }\\n\\n function pairCodeHash() external pure returns (bytes32) {\\n return keccak256(type(Pair).creationCode);\\n }\\n\\n function getInitializable() external view returns (address, address, bool) {\\n return (_temp0, _temp1, _temp);\\n }\\n\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\\n (_temp0, _temp1, _temp) = (token0, token1, stable);\\n pair = address(new Pair{salt:salt}());\\n getPair[token0][token1][stable] = pair;\\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\\n allPairs.push(pair);\\n isPair[pair] = true;\\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\\n }\\n}\\n\",\"keccak256\":\"0x9b7984117a5a32188aa9ddf42b6cff024240579ab30f3776f7a201285d813e4f\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairCallee.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairCallee {\\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x3ac2de2c7a08bf59fd1006e4d108b247916369de15fbd048b72ca2b7814023ca\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50600080546001600160a81b03191633610100810260ff1916919091178255600480546001600160a01b0319169091179055600280805560035561519190819061005a90396000f3fe60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea2646970667358221220c096b5b8eff492cfa56eca7766bf438a7772873d9d55ac3fb8495fc6e91048df64736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea26469706673582212203b862e6743be8a92d1eec9a88fc2f68597ac055d6ad2133ccb634ef6a70ed04764736f6c634300080d0033a2646970667358221220cba5a1771a35b11c991d6154f51a9021074ad34c96b2d242ead8321a39d961cb64736f6c634300080d0033", + "deployedBytecode": "0x60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea2646970667358221220c096b5b8eff492cfa56eca7766bf438a7772873d9d55ac3fb8495fc6e91048df64736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea26469706673582212203b862e6743be8a92d1eec9a88fc2f68597ac055d6ad2133ccb634ef6a70ed04764736f6c634300080d0033a2646970667358221220cba5a1771a35b11c991d6154f51a9021074ad34c96b2d242ead8321a39d961cb64736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/RedemptionReceiver.json b/deployments/arbitrumGoerli/RedemptionReceiver.json index da744b76..d3f792e7 100644 --- a/deployments/arbitrumGoerli/RedemptionReceiver.json +++ b/deployments/arbitrumGoerli/RedemptionReceiver.json @@ -1,5 +1,5 @@ { - "address": "0x52018E83E84ebe30ac6923F3747c7aE503923aaB", + "address": "0x552dD2458Ac8Fb7bC83a2BFF16e57e44Aa30cd4F", "abi": [ { "inputs": [ @@ -10,7 +10,7 @@ }, { "internalType": "address", - "name": "_velo", + "name": "_flow", "type": "address" }, { @@ -45,7 +45,7 @@ { "indexed": false, "internalType": "uint256", - "name": "redeemableVELO", + "name": "redeemableFLOW", "type": "uint256" } ], @@ -67,10 +67,10 @@ }, { "inputs": [], - "name": "USDC", + "name": "FLOW", "outputs": [ { - "internalType": "contract IERC20", + "internalType": "contract IFlow", "name": "", "type": "address" } @@ -80,10 +80,10 @@ }, { "inputs": [], - "name": "VELO", + "name": "USDC", "outputs": [ { - "internalType": "contract IVelo", + "internalType": "contract IERC20", "name": "", "type": "address" } @@ -183,7 +183,7 @@ }, { "internalType": "uint256", - "name": "_redeemableVELO", + "name": "_redeemableFLOW", "type": "uint256" } ], @@ -194,7 +194,7 @@ }, { "inputs": [], - "name": "leftoverVELO", + "name": "leftoverFLOW", "outputs": [ { "internalType": "uint256", @@ -250,7 +250,7 @@ }, { "internalType": "uint256", - "name": "shareOfVELO", + "name": "shareOfFLOW", "type": "uint256" } ], @@ -259,7 +259,7 @@ }, { "inputs": [], - "name": "redeemableUSDC", + "name": "redeemableFLOW", "outputs": [ { "internalType": "uint256", @@ -272,7 +272,7 @@ }, { "inputs": [], - "name": "redeemableVELO", + "name": "redeemableUSDC", "outputs": [ { "internalType": "uint256", @@ -323,33 +323,33 @@ "type": "function" } ], - "transactionHash": "0xb92890feb62248533088d4adc0e25235f6ff55e33118157ec87b5f5273eaec09", + "transactionHash": "0x16c49dd70b141dc4df3888393a02418744bd2a6dbb0b864af1a7ba82a1847f6b", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x52018E83E84ebe30ac6923F3747c7aE503923aaB", + "contractAddress": "0x552dD2458Ac8Fb7bC83a2BFF16e57e44Aa30cd4F", "transactionIndex": 1, - "gasUsed": "878312", + "gasUsed": "841985", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x3e266eb2e4f8dffba63778f5c9dd4db42d5da8660e567116b6ed09c3fa43333c", - "transactionHash": "0xb92890feb62248533088d4adc0e25235f6ff55e33118157ec87b5f5273eaec09", + "blockHash": "0xd1753b9b7f09a0dd4dea81afdf1f617e8f0224c4dd3ca1436e14cc1c85b6c03d", + "transactionHash": "0x16c49dd70b141dc4df3888393a02418744bd2a6dbb0b864af1a7ba82a1847f6b", "logs": [], - "blockNumber": 4455899, - "cumulativeGasUsed": "878312", + "blockNumber": 5716750, + "cumulativeGasUsed": "841985", "status": 1, "byzantium": true }, "args": [ "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8", - "0x84Ca387E7ede764A3284c67Ff8c68a305a9030a0", + "0xf5A53c1b4072425DF6eC082f0A48B4652bc4188C", 10012, "0x3c2269811836af69497E5F486A85D7316753cf62" ], - "numDeployments": 1, - "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_usdc\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_velo\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"_fantomChainId\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"_endpoint\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fantomSender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableUSDC\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableVELO\",\"type\":\"uint256\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ELIGIBLE_WEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"USDC\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VELO\",\"outputs\":[{\"internalType\":\"contract IVelo\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"toAddressBytes\",\"type\":\"bytes\"}],\"name\":\"addressFromPackedBytes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimLeftovers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endpoint\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomChainId\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_fantomSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableVELO\",\"type\":\"uint256\"}],\"name\":\"initializeReceiverWith\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"leftoverVELO\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"srcChainId\",\"type\":\"uint16\"},{\"internalType\":\"bytes\",\"name\":\"srcAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"lzReceive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountWEVE\",\"type\":\"uint256\"}],\"name\":\"previewRedeem\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"shareOfUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shareOfVELO\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableUSDC\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableVELO\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemedWEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process This contract is responsible for receiving the LZ message and distributing USDC + VELO\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/RedemptionReceiver.sol\":\"RedemptionReceiver\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"},\"contracts/redeem/RedemptionReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\\\";\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IVelo.sol\\\";\\n\\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\\ncontract RedemptionReceiver is ILayerZeroReceiver {\\n IERC20 public immutable USDC;\\n IVelo public immutable VELO;\\n\\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\\n address public immutable endpoint;\\n\\n address public team;\\n uint256 public immutable deployed;\\n\\n address public fantomSender;\\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\\n uint256 public redeemedWEVE;\\n uint256 public redeemableUSDC;\\n uint256 public redeemableVELO;\\n uint256 public leftoverVELO;\\n\\n constructor(\\n address _usdc,\\n address _velo,\\n uint16 _fantomChainId,\\n address _endpoint\\n ) {\\n require(_fantomChainId == 12 || _fantomChainId == 10012, \\\"CHAIN_ID_NOT_FTM\\\");\\n\\n USDC = IERC20(_usdc);\\n VELO = IVelo(_velo);\\n\\n fantomChainId = _fantomChainId;\\n endpoint = _endpoint;\\n\\n team = msg.sender;\\n deployed = block.timestamp;\\n }\\n\\n modifier onlyTeam() {\\n require(msg.sender == team, \\\"ONLY_TEAM\\\");\\n _;\\n }\\n\\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\\n\\n function initializeReceiverWith(\\n address _fantomSender,\\n uint256 _redeemableUSDC,\\n uint256 _redeemableVELO\\n ) external onlyTeam {\\n require(fantomSender == address(0), \\\"ALREADY_INITIALIZED\\\");\\n require(\\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n fantomSender = _fantomSender;\\n redeemableUSDC = _redeemableUSDC;\\n redeemableVELO = _redeemableVELO;\\n leftoverVELO = _redeemableVELO;\\n\\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\\n }\\n\\n function setTeam(address _team) external onlyTeam {\\n team = _team;\\n }\\n\\n function previewRedeem(uint256 amountWEVE)\\n public\\n view\\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\\n {\\n // pro rata USDC\\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\\n // pro rata VELO\\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\\n }\\n\\n function lzReceive(\\n uint16 srcChainId,\\n bytes memory srcAddress,\\n uint64,\\n bytes memory payload\\n ) external override {\\n require(fantomSender != address(0), \\\"NOT_INITIALIZED\\\");\\n require(\\n msg.sender == endpoint &&\\n srcChainId == fantomChainId &&\\n addressFromPackedBytes(srcAddress) == fantomSender,\\n \\\"UNAUTHORIZED_CALLER\\\"\\n );\\n\\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\\n payload,\\n (address, uint256)\\n );\\n\\n require(\\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\\n \\\"cannot redeem more than eligible\\\"\\n );\\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\\n\\n require(\\n USDC.transfer(redemptionAddress, shareOfUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n leftoverVELO -= shareOfVELO; // this will revert if underflows\\n require(\\n VELO.claim(redemptionAddress, shareOfVELO),\\n \\\"CLAIM_FAILED\\\"\\n );\\n }\\n\\n function addressFromPackedBytes(bytes memory toAddressBytes)\\n public\\n pure\\n returns (address toAddress)\\n {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n toAddress := mload(add(toAddressBytes, 20))\\n }\\n }\\n\\n function claimLeftovers() external onlyTeam {\\n require(block.timestamp >= deployed + 30 days, \\\"LEFTOVERS_NOT_CLAIMABLE\\\");\\n require(\\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n }\\n}\\n\",\"keccak256\":\"0xb5c76f083e5076206e2713b64eed8bfc782715c19f6993ac8e97b1db898ae304\",\"license\":\"MIT\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\nimport \\\"./ILayerZeroUserApplicationConfig.sol\\\";\\n\\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\\n // @param _dstChainId - the destination chain identifier\\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\\n // @param _payload - a custom bytes payload to send to the destination contract\\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\\n\\n // @notice used by the messaging library to publish verified payload\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source contract (as bytes) at the source chain\\n // @param _dstAddress - the address on destination chain\\n // @param _nonce - the unbound message ordering nonce\\n // @param _gasLimit - the gas limit for external contract execution\\n // @param _payload - verified payload to send to the destination contract\\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\\n\\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\\n\\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\\n // @param _srcAddress - the source chain contract address\\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\\n\\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\\n // @param _dstChainId - the destination chain identifier\\n // @param _userApplication - the user app address on this EVM chain\\n // @param _payload - the custom message to send over LayerZero\\n // @param _payInZRO - if false, user app pays the protocol fee in native token\\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\\n\\n // @notice get this Endpoint's immutable source identifier\\n function getChainId() external view returns (uint16);\\n\\n // @notice the interface to retry failed message on this Endpoint destination\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n // @param _payload - the payload to be retried\\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\\n\\n // @notice query if any STORED payload (message blocking) at the endpoint.\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\\n\\n // @notice query if the _libraryAddress is valid for sending msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getSendLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the _libraryAddress is valid for receiving msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the non-reentrancy guard for send() is on\\n // @return true if the guard is on. false otherwise\\n function isSendingPayload() external view returns (bool);\\n\\n // @notice query if the non-reentrancy guard for receive() is on\\n // @return true if the guard is on. false otherwise\\n function isReceivingPayload() external view returns (bool);\\n\\n // @notice get the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _userApplication - the contract address of the user application\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\\n\\n // @notice get the send() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getSendVersion(address _userApplication) external view returns (uint16);\\n\\n // @notice get the lzReceive() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getReceiveVersion(address _userApplication) external view returns (uint16);\\n}\\n\",\"keccak256\":\"0xbc2e0022d4d53d136830aa90037be2ed7a0966f5fd1b409bf5986185984c495f\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroReceiver {\\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\\n // @param _srcChainId - the source endpoint identifier\\n // @param _srcAddress - the source sending contract address from the source chain\\n // @param _nonce - the ordered message nonce\\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\\n}\\n\",\"keccak256\":\"0xd1617e455d90d41556bba636bc440627d301ec481de16ff04fbd520333c3c6f3\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroUserApplicationConfig {\\n // @notice set the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n // @param _config - configuration in the bytes. can encode arbitrary content.\\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\\n\\n // @notice set the send() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setSendVersion(uint16 _version) external;\\n\\n // @notice set the lzReceive() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setReceiveVersion(uint16 _version) external;\\n\\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\\n // @param _srcChainId - the chainId of the source chain\\n // @param _srcAddress - the contract address of the source contract at the source chain\\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\\n}\\n\",\"keccak256\":\"0xdc7e072cf3064081a8edf4a286ca43ddecc24330f2923d96f416f9d3f6538447\",\"license\":\"BUSL-1.1\"}},\"version\":1}", - "bytecode": "0x61012060405234801561001157600080fd5b50604051610f81380380610f81833981016040819052610030916100e2565b8161ffff16600c148061004857508161ffff1661271c145b61008b5760405162461bcd60e51b815260206004820152601060248201526f434841494e5f49445f4e4f545f46544d60801b604482015260640160405180910390fd5b6001600160a01b0393841660805291831660a05261ffff1660c0521660e052600080546001600160a01b03191633179055426101005261013f565b80516001600160a01b03811681146100dd57600080fd5b919050565b600080600080608085870312156100f857600080fd5b610101856100c6565b935061010f602086016100c6565b9250604085015161ffff8116811461012657600080fd5b9150610134606086016100c6565b905092959194509250565b60805160a05160c05160e05161010051610dcd6101b4600039600081816102d601526108c00152600081816101940152610352015260008181610245015261037c01526000818161027f015261059f01526000818161021e015281816104d70152818161078e015261094c0152610dcd6000f3fe608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a0eeb39a11610071578063a0eeb39a1461027a578063a408bb4c146102a1578063aaa8f2ef146102a9578063b8ea6281146102bc578063f905c15a146102d157600080fd5b80636bfd23a7146101fd57806385f2aef21461020657806389a3027114610219578063997a03b71461024057600080fd5b80634cdad506116100e95780634cdad506146101675780635e280f111461018f57806363b4eb8d146101ce57806368ecc6bc146101e15780636ac55083146101f457600080fd5b80621d35671461011a578063095cf5c61461012f578063221798ad1461014257806347db1a6a1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60045481565b6040519081526020015b60405180910390f35b61014b60035481565b61017a610175366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b6001546101b6906001600160a01b031681565b61012d6101ef366004610be5565b6106f3565b61014b60055481565b61014b60025481565b6000546101b6906001600160a01b031681565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6102677f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101b66102ca366004610c1a565b6014015190565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea2646970667358221220b598fc2bd4de791cc9775861ae06595f700bc013f87600fbf2bdb67f21fed1a764736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a0eeb39a11610071578063a0eeb39a1461027a578063a408bb4c146102a1578063aaa8f2ef146102a9578063b8ea6281146102bc578063f905c15a146102d157600080fd5b80636bfd23a7146101fd57806385f2aef21461020657806389a3027114610219578063997a03b71461024057600080fd5b80634cdad506116100e95780634cdad506146101675780635e280f111461018f57806363b4eb8d146101ce57806368ecc6bc146101e15780636ac55083146101f457600080fd5b80621d35671461011a578063095cf5c61461012f578063221798ad1461014257806347db1a6a1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60045481565b6040519081526020015b60405180910390f35b61014b60035481565b61017a610175366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b6001546101b6906001600160a01b031681565b61012d6101ef366004610be5565b6106f3565b61014b60055481565b61014b60025481565b6000546101b6906001600160a01b031681565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b6102677f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b6101b67f000000000000000000000000000000000000000000000000000000000000000081565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101b66102ca366004610c1a565b6014015190565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea2646970667358221220b598fc2bd4de791cc9775861ae06595f700bc013f87600fbf2bdb67f21fed1a764736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_usdc\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_flow\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"_fantomChainId\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"_endpoint\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fantomSender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableUSDC\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableFLOW\",\"type\":\"uint256\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ELIGIBLE_WEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FLOW\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"USDC\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"toAddressBytes\",\"type\":\"bytes\"}],\"name\":\"addressFromPackedBytes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimLeftovers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endpoint\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomChainId\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_fantomSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableFLOW\",\"type\":\"uint256\"}],\"name\":\"initializeReceiverWith\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"leftoverFLOW\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"srcChainId\",\"type\":\"uint16\"},{\"internalType\":\"bytes\",\"name\":\"srcAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"lzReceive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountWEVE\",\"type\":\"uint256\"}],\"name\":\"previewRedeem\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"shareOfUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shareOfFLOW\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableFLOW\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableUSDC\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemedWEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process This contract is responsible for receiving the LZ message and distributing USDC + FLOW\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/RedemptionReceiver.sol\":\"RedemptionReceiver\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/redeem/RedemptionReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\\\";\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\n\\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\\n/// This contract is responsible for receiving the LZ message and distributing USDC + FLOW\\ncontract RedemptionReceiver is ILayerZeroReceiver {\\n IERC20 public immutable USDC;\\n IFlow public immutable FLOW;\\n\\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\\n address public immutable endpoint;\\n\\n address public team;\\n uint256 public immutable deployed;\\n\\n address public fantomSender;\\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\\n uint256 public redeemedWEVE;\\n uint256 public redeemableUSDC;\\n uint256 public redeemableFLOW;\\n uint256 public leftoverFLOW;\\n\\n constructor(\\n address _usdc,\\n address _flow,\\n uint16 _fantomChainId,\\n address _endpoint\\n ) {\\n require(_fantomChainId == 12 || _fantomChainId == 10012, \\\"CHAIN_ID_NOT_FTM\\\");\\n\\n USDC = IERC20(_usdc);\\n FLOW = IFlow(_flow);\\n\\n fantomChainId = _fantomChainId;\\n endpoint = _endpoint;\\n\\n team = msg.sender;\\n deployed = block.timestamp;\\n }\\n\\n modifier onlyTeam() {\\n require(msg.sender == team, \\\"ONLY_TEAM\\\");\\n _;\\n }\\n\\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableFLOW);\\n\\n function initializeReceiverWith(\\n address _fantomSender,\\n uint256 _redeemableUSDC,\\n uint256 _redeemableFLOW\\n ) external onlyTeam {\\n require(fantomSender == address(0), \\\"ALREADY_INITIALIZED\\\");\\n require(\\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n fantomSender = _fantomSender;\\n redeemableUSDC = _redeemableUSDC;\\n redeemableFLOW = _redeemableFLOW;\\n leftoverFLOW = _redeemableFLOW;\\n\\n emit Initialized(fantomSender, redeemableUSDC, redeemableFLOW);\\n }\\n\\n function setTeam(address _team) external onlyTeam {\\n team = _team;\\n }\\n\\n function previewRedeem(uint256 amountWEVE)\\n public\\n view\\n returns (uint256 shareOfUSDC, uint256 shareOfFLOW)\\n {\\n // pro rata USDC\\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\\n // pro rata FLOW\\n shareOfFLOW = (amountWEVE * redeemableFLOW) / ELIGIBLE_WEVE;\\n }\\n\\n function lzReceive(\\n uint16 srcChainId,\\n bytes memory srcAddress,\\n uint64,\\n bytes memory payload\\n ) external override {\\n require(fantomSender != address(0), \\\"NOT_INITIALIZED\\\");\\n require(\\n msg.sender == endpoint &&\\n srcChainId == fantomChainId &&\\n addressFromPackedBytes(srcAddress) == fantomSender,\\n \\\"UNAUTHORIZED_CALLER\\\"\\n );\\n\\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\\n payload,\\n (address, uint256)\\n );\\n\\n require(\\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\\n \\\"cannot redeem more than eligible\\\"\\n );\\n (uint256 shareOfUSDC, uint256 shareOfFLOW) = previewRedeem(amountWEVE);\\n\\n require(\\n USDC.transfer(redemptionAddress, shareOfUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n leftoverFLOW -= shareOfFLOW; // this will revert if underflows\\n require(\\n FLOW.claim(redemptionAddress, shareOfFLOW),\\n \\\"CLAIM_FAILED\\\"\\n );\\n }\\n\\n function addressFromPackedBytes(bytes memory toAddressBytes)\\n public\\n pure\\n returns (address toAddress)\\n {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n toAddress := mload(add(toAddressBytes, 20))\\n }\\n }\\n\\n function claimLeftovers() external onlyTeam {\\n require(block.timestamp >= deployed + 30 days, \\\"LEFTOVERS_NOT_CLAIMABLE\\\");\\n require(\\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n }\\n}\\n\",\"keccak256\":\"0x582d45a8db937fe4a965056bcbe7d1427f71be66e8071bb1cae76d5f36c6c314\",\"license\":\"MIT\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\nimport \\\"./ILayerZeroUserApplicationConfig.sol\\\";\\n\\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\\n // @param _dstChainId - the destination chain identifier\\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\\n // @param _payload - a custom bytes payload to send to the destination contract\\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\\n\\n // @notice used by the messaging library to publish verified payload\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source contract (as bytes) at the source chain\\n // @param _dstAddress - the address on destination chain\\n // @param _nonce - the unbound message ordering nonce\\n // @param _gasLimit - the gas limit for external contract execution\\n // @param _payload - verified payload to send to the destination contract\\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\\n\\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\\n\\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\\n // @param _srcAddress - the source chain contract address\\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\\n\\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\\n // @param _dstChainId - the destination chain identifier\\n // @param _userApplication - the user app address on this EVM chain\\n // @param _payload - the custom message to send over LayerZero\\n // @param _payInZRO - if false, user app pays the protocol fee in native token\\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\\n\\n // @notice get this Endpoint's immutable source identifier\\n function getChainId() external view returns (uint16);\\n\\n // @notice the interface to retry failed message on this Endpoint destination\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n // @param _payload - the payload to be retried\\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\\n\\n // @notice query if any STORED payload (message blocking) at the endpoint.\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\\n\\n // @notice query if the _libraryAddress is valid for sending msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getSendLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the _libraryAddress is valid for receiving msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the non-reentrancy guard for send() is on\\n // @return true if the guard is on. false otherwise\\n function isSendingPayload() external view returns (bool);\\n\\n // @notice query if the non-reentrancy guard for receive() is on\\n // @return true if the guard is on. false otherwise\\n function isReceivingPayload() external view returns (bool);\\n\\n // @notice get the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _userApplication - the contract address of the user application\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\\n\\n // @notice get the send() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getSendVersion(address _userApplication) external view returns (uint16);\\n\\n // @notice get the lzReceive() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getReceiveVersion(address _userApplication) external view returns (uint16);\\n}\\n\",\"keccak256\":\"0xbc2e0022d4d53d136830aa90037be2ed7a0966f5fd1b409bf5986185984c495f\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroReceiver {\\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\\n // @param _srcChainId - the source endpoint identifier\\n // @param _srcAddress - the source sending contract address from the source chain\\n // @param _nonce - the ordered message nonce\\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\\n}\\n\",\"keccak256\":\"0xd1617e455d90d41556bba636bc440627d301ec481de16ff04fbd520333c3c6f3\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroUserApplicationConfig {\\n // @notice set the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n // @param _config - configuration in the bytes. can encode arbitrary content.\\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\\n\\n // @notice set the send() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setSendVersion(uint16 _version) external;\\n\\n // @notice set the lzReceive() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setReceiveVersion(uint16 _version) external;\\n\\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\\n // @param _srcChainId - the chainId of the source chain\\n // @param _srcAddress - the contract address of the source contract at the source chain\\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\\n}\\n\",\"keccak256\":\"0xdc7e072cf3064081a8edf4a286ca43ddecc24330f2923d96f416f9d3f6538447\",\"license\":\"BUSL-1.1\"}},\"version\":1}", + "bytecode": "0x61012060405234801561001157600080fd5b50604051610f81380380610f81833981016040819052610030916100e2565b8161ffff16600c148061004857508161ffff1661271c145b61008b5760405162461bcd60e51b815260206004820152601060248201526f434841494e5f49445f4e4f545f46544d60801b604482015260640160405180910390fd5b6001600160a01b0393841660805291831660a05261ffff1660c0521660e052600080546001600160a01b03191633179055426101005261013f565b80516001600160a01b03811681146100dd57600080fd5b919050565b600080600080608085870312156100f857600080fd5b610101856100c6565b935061010f602086016100c6565b9250604085015161ffff8116811461012657600080fd5b9150610134606086016100c6565b905092959194509250565b60805160a05160c05160e05161010051610dcd6101b4600039600081816102d601526108c00152600081816101d30152610352015260008181610263015261037c015260008181610163015261059f01526000818161023c015281816104d70152818161078e015261094c0152610dcd6000f3fe608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a408bb4c11610071578063a408bb4c14610298578063aaa8f2ef146102a0578063b8ea6281146102b3578063caccb667146102c8578063f905c15a146102d157600080fd5b80636bfd23a71461021b57806385f2aef21461022457806389a3027114610237578063997a03b71461025e57600080fd5b806347db1a6a116100e957806347db1a6a1461019d5780634cdad506146101a65780635e280f11146101ce57806363b4eb8d146101f557806368ecc6bc1461020857600080fd5b80621d35671461011a578063095cf5c61461012f5780631308db08146101425780633189097b1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60055481565b6040519081526020015b60405180910390f35b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b61014b60035481565b6101b96101b4366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b600154610185906001600160a01b031681565b61012d610216366004610be5565b6106f3565b61014b60025481565b600054610185906001600160a01b031681565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6102857f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101856102c1366004610c1a565b6014015190565b61014b60045481565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea26469706673582212207993ac0a14cefc113df5ea974ec076ad2ab5958e591d373203e387ffd15e8c1564736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a408bb4c11610071578063a408bb4c14610298578063aaa8f2ef146102a0578063b8ea6281146102b3578063caccb667146102c8578063f905c15a146102d157600080fd5b80636bfd23a71461021b57806385f2aef21461022457806389a3027114610237578063997a03b71461025e57600080fd5b806347db1a6a116100e957806347db1a6a1461019d5780634cdad506146101a65780635e280f11146101ce57806363b4eb8d146101f557806368ecc6bc1461020857600080fd5b80621d35671461011a578063095cf5c61461012f5780631308db08146101425780633189097b1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60055481565b6040519081526020015b60405180910390f35b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b61014b60035481565b6101b96101b4366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b600154610185906001600160a01b031681565b61012d610216366004610be5565b6106f3565b61014b60025481565b600054610185906001600160a01b031681565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6102857f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101856102c1366004610c1a565b6014015190565b61014b60045481565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea26469706673582212207993ac0a14cefc113df5ea974ec076ad2ab5958e591d373203e387ffd15e8c1564736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, @@ -358,7 +358,7 @@ "userdoc": { "kind": "user", "methods": {}, - "notice": "Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process This contract is responsible for receiving the LZ message and distributing USDC + VELO", + "notice": "Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process This contract is responsible for receiving the LZ message and distributing USDC + FLOW", "version": 1 }, "storageLayout": { @@ -398,7 +398,7 @@ { "astId": 24599, "contract": "contracts/redeem/RedemptionReceiver.sol:RedemptionReceiver", - "label": "redeemableVELO", + "label": "redeemableFLOW", "offset": 0, "slot": "4", "type": "t_uint256" @@ -406,7 +406,7 @@ { "astId": 24601, "contract": "contracts/redeem/RedemptionReceiver.sol:RedemptionReceiver", - "label": "leftoverVELO", + "label": "leftoverFLOW", "offset": 0, "slot": "5", "type": "t_uint256" diff --git a/deployments/arbitrumGoerli/RewardsDistributor.json b/deployments/arbitrumGoerli/RewardsDistributor.json index b4112b3c..a53a14d8 100644 --- a/deployments/arbitrumGoerli/RewardsDistributor.json +++ b/deployments/arbitrumGoerli/RewardsDistributor.json @@ -1,5 +1,5 @@ { - "address": "0xc4b9295487B4C43C1929299076820D8f55BBf957", + "address": "0xEED0deFB831F96fC45B5e0ACb477F517F186496F", "abi": [ { "inputs": [ @@ -351,45 +351,45 @@ "type": "function" } ], - "transactionHash": "0x3da7f01a909390d938a1b55c6711edc4e51b5b5d3759e23a79db10a86ccc298f", + "transactionHash": "0x75de4aad94bdd3ccf1a3abd009b69267523d51a5286ffe92105aeb7bf4e3a5c8", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xc4b9295487B4C43C1929299076820D8f55BBf957", + "contractAddress": "0xEED0deFB831F96fC45B5e0ACb477F517F186496F", "transactionIndex": 1, - "gasUsed": "1676854", - "logsBloom": "0x00000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000002000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020001000000008000000000000000000008000000000000000000000200000000000000000000000000000000000000000002000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x533fb1fbc52cac7b9ef364882a21aacb70fa93316760ea3f3c347796628e89e5", - "transactionHash": "0x3da7f01a909390d938a1b55c6711edc4e51b5b5d3759e23a79db10a86ccc298f", + "gasUsed": "1623336", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000008000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000004000000000000000040000000000000000000000000000000000000000000000000000021000400000000000000000000000000000000000000400000000000000000000000000000000000000000000000800000000000000000000000000000000000010000000000000008000000000000000000000000000000000000000000000", + "blockHash": "0xc23e9a698a2fa91f639179617c0d79aa34767237d3ccc6d87b31ede6dd02be02", + "transactionHash": "0x75de4aad94bdd3ccf1a3abd009b69267523d51a5286ffe92105aeb7bf4e3a5c8", "logs": [ { "transactionIndex": 1, - "blockNumber": 4455886, - "transactionHash": "0x3da7f01a909390d938a1b55c6711edc4e51b5b5d3759e23a79db10a86ccc298f", - "address": "0x84Ca387E7ede764A3284c67Ff8c68a305a9030a0", + "blockNumber": 5716732, + "transactionHash": "0x75de4aad94bdd3ccf1a3abd009b69267523d51a5286ffe92105aeb7bf4e3a5c8", + "address": "0xf5A53c1b4072425DF6eC082f0A48B4652bc4188C", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000c4b9295487b4c43c1929299076820d8f55bbf957", - "0x000000000000000000000000bf05364d6cf1586852c18c6b1cbee218e3e09885" + "0x000000000000000000000000eed0defb831f96fc45b5e0acb477f517f186496f", + "0x000000000000000000000000c43f6ebf97f9d99ff8a3afe1413599e8dec2adb3" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "logIndex": 0, - "blockHash": "0x533fb1fbc52cac7b9ef364882a21aacb70fa93316760ea3f3c347796628e89e5" + "blockHash": "0xc23e9a698a2fa91f639179617c0d79aa34767237d3ccc6d87b31ede6dd02be02" } ], - "blockNumber": 4455886, - "cumulativeGasUsed": "1676854", + "blockNumber": 5716732, + "cumulativeGasUsed": "1623336", "status": 1, "byzantium": true }, "args": [ - "0xBf05364D6cf1586852c18c6b1CbEe218E3e09885" + "0xC43f6EbF97f9D99FF8a3aFe1413599e8DEc2aDB3" ], - "numDeployments": 1, - "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voting_escrow\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"time\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"CheckpointToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"claim_epoch\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"max_epoch\",\"type\":\"uint256\"}],\"name\":\"Claimed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"checkpoint_token\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint_total_supply\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"_tokenIds\",\"type\":\"uint256[]\"}],\"name\":\"claim_many\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_token_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"}],\"name\":\"setDepositor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"start_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"time_cursor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"time_cursor_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token_last_balance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"tokens_per_week\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_epoch_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"ve_for_at\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ve_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voting_escrow\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RewardsDistributor.sol\":\"RewardsDistributor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/*\\n\\n@title Curve Fee Distribution modified for ve(3,3) emissions\\n@author Curve Finance, andrecronje\\n@license MIT\\n\\n*/\\n\\ncontract RewardsDistributor is IRewardsDistributor {\\n event CheckpointToken(uint256 time, uint256 tokens);\\n\\n event Claimed(\\n uint256 tokenId,\\n uint256 amount,\\n uint256 claim_epoch,\\n uint256 max_epoch\\n );\\n\\n uint256 constant WEEK = 7 * 86400;\\n\\n uint256 public start_time;\\n uint256 public time_cursor;\\n mapping(uint256 => uint256) public time_cursor_of;\\n mapping(uint256 => uint256) public user_epoch_of;\\n\\n uint256 public last_token_time;\\n uint256[1000000000000000] public tokens_per_week;\\n\\n address public voting_escrow;\\n address public token;\\n uint256 public token_last_balance;\\n\\n uint256[1000000000000000] public ve_supply;\\n\\n address public depositor;\\n\\n constructor(address _voting_escrow) {\\n uint256 _t = (block.timestamp / WEEK) * WEEK;\\n start_time = _t;\\n last_token_time = _t;\\n time_cursor = _t;\\n address _token = IVotingEscrow(_voting_escrow).token();\\n token = _token;\\n voting_escrow = _voting_escrow;\\n depositor = msg.sender;\\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\\n }\\n\\n function timestamp() external view returns (uint256) {\\n return (block.timestamp / WEEK) * WEEK;\\n }\\n\\n function _checkpoint_token() internal {\\n uint256 token_balance = IERC20(token).balanceOf(address(this));\\n uint256 to_distribute = token_balance - token_last_balance;\\n token_last_balance = token_balance;\\n\\n uint256 t = last_token_time;\\n uint256 since_last = block.timestamp - t;\\n last_token_time = block.timestamp;\\n uint256 this_week = (t / WEEK) * WEEK;\\n uint256 next_week = 0;\\n\\n for (uint256 i = 0; i < 20; i++) {\\n next_week = this_week + WEEK;\\n if (block.timestamp < next_week) {\\n if (since_last == 0 && block.timestamp == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (block.timestamp - t)) /\\n since_last;\\n }\\n break;\\n } else {\\n if (since_last == 0 && next_week == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (next_week - t)) /\\n since_last;\\n }\\n }\\n t = next_week;\\n this_week = next_week;\\n }\\n emit CheckpointToken(block.timestamp, to_distribute);\\n }\\n\\n function checkpoint_token() external {\\n assert(msg.sender == depositor);\\n _checkpoint_token();\\n }\\n\\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\\n internal\\n view\\n returns (uint256)\\n {\\n uint256 _min = 0;\\n uint256 _max = IVotingEscrow(ve).epoch();\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n _mid\\n );\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function _find_timestamp_user_epoch(\\n address ve,\\n uint256 tokenId,\\n uint256 _timestamp,\\n uint256 max_user_epoch\\n ) internal view returns (uint256) {\\n uint256 _min = 0;\\n uint256 _max = max_user_epoch;\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\\n .user_point_history(tokenId, _mid);\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\\n external\\n view\\n returns (uint256)\\n {\\n address ve = voting_escrow;\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _timestamp,\\n max_user_epoch\\n );\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n epoch\\n );\\n return\\n MathDunks.max(\\n uint256(\\n int256(\\n pt.bias -\\n pt.slope *\\n (int128(int256(_timestamp - pt.ts)))\\n )\\n ),\\n 0\\n );\\n }\\n\\n function _checkpoint_total_supply() internal {\\n address ve = voting_escrow;\\n uint256 t = time_cursor;\\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\\n IVotingEscrow(ve).checkpoint();\\n\\n for (uint256 i = 0; i < 20; i++) {\\n if (t > rounded_timestamp) {\\n break;\\n } else {\\n uint256 epoch = _find_timestamp_epoch(ve, t);\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n epoch\\n );\\n int128 dt = 0;\\n if (t > pt.ts) {\\n dt = int128(int256(t - pt.ts));\\n }\\n ve_supply[t] = MathDunks.max(\\n uint256(int256(pt.bias - pt.slope * dt)),\\n 0\\n );\\n }\\n t += WEEK;\\n }\\n time_cursor = t;\\n }\\n\\n function checkpoint_total_supply() external {\\n _checkpoint_total_supply();\\n }\\n\\n function _claim(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\\n user_epoch_of[_tokenId] = user_epoch;\\n time_cursor_of[_tokenId] = week_cursor;\\n\\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\\n\\n return to_distribute;\\n }\\n\\n function _claimable(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal view returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n return to_distribute;\\n }\\n\\n function claimable(uint256 _tokenId) external view returns (uint256) {\\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\\n return _claimable(_tokenId, voting_escrow, _last_token_time);\\n }\\n\\n function claim(uint256 _tokenId) external returns (uint256) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\\n token_last_balance -= amount;\\n }\\n return amount;\\n }\\n\\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n address _voting_escrow = voting_escrow;\\n uint256 total = 0;\\n\\n for (uint256 i = 0; i < _tokenIds.length; i++) {\\n uint256 _tokenId = _tokenIds[i];\\n if (_tokenId == 0) break;\\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\\n total += amount;\\n }\\n }\\n if (total != 0) {\\n token_last_balance -= total;\\n }\\n\\n return true;\\n }\\n\\n // Once off event on contract initialize\\n function setDepositor(address _depositor) external {\\n require(msg.sender == depositor);\\n depositor = _depositor;\\n }\\n}\\n\",\"keccak256\":\"0xdbcfb11d65c6ca7d63baba42fb2f1222478c6ca78d8e81970032eff5e034e09b\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b5060405162001b9f38038062001b9f83398101604081905262000034916200019f565b600062093a80620000468142620001d1565b620000529190620001f4565b90508060008190555080600481905550806001819055506000826001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000aa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d091906200019f565b66038d7ea4c6800680546001600160a01b038381166001600160a01b0319928316811790935566038d7ea4c6800580549188169183168217905566071afd498d00088054909216331790915560405163095ea7b360e01b8152600481019190915260001960248201529192509063095ea7b3906044016020604051808303816000875af115801562000166573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200018c919062000222565b6200019657600080fd5b50505062000246565b600060208284031215620001b257600080fd5b81516001600160a01b0381168114620001ca57600080fd5b9392505050565b600082620001ef57634e487b7160e01b600052601260045260246000fd5b500490565b60008160001904831182151516156200021d57634e487b7160e01b600052601160045260246000fd5b500290565b6000602082840312156200023557600080fd5b81518015158114620001ca57600080fd5b61194980620002566000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea26469706673582212203106563b3fbc12e10f6737c5ef908828c2a3f356862c6c472cb078657f47140b64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea26469706673582212203106563b3fbc12e10f6737c5ef908828c2a3f356862c6c472cb078657f47140b64736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voting_escrow\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"time\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"CheckpointToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"claim_epoch\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"max_epoch\",\"type\":\"uint256\"}],\"name\":\"Claimed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"checkpoint_token\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint_total_supply\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"_tokenIds\",\"type\":\"uint256[]\"}],\"name\":\"claim_many\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_token_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"}],\"name\":\"setDepositor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"start_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"time_cursor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"time_cursor_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token_last_balance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"tokens_per_week\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_epoch_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"ve_for_at\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ve_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voting_escrow\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RewardsDistributor.sol\":\"RewardsDistributor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/*\\n\\n@title Curve Fee Distribution modified for ve(3,3) emissions\\n@author Curve Finance, andrecronje\\n@license MIT\\n\\n*/\\n\\ncontract RewardsDistributor is IRewardsDistributor {\\n event CheckpointToken(uint256 time, uint256 tokens);\\n\\n event Claimed(\\n uint256 tokenId,\\n uint256 amount,\\n uint256 claim_epoch,\\n uint256 max_epoch\\n );\\n\\n uint256 constant WEEK = 7 * 86400;\\n\\n uint256 public start_time;\\n uint256 public time_cursor;\\n mapping(uint256 => uint256) public time_cursor_of;\\n mapping(uint256 => uint256) public user_epoch_of;\\n\\n uint256 public last_token_time;\\n uint256[1000000000000000] public tokens_per_week;\\n\\n address public voting_escrow;\\n address public token;\\n uint256 public token_last_balance;\\n\\n uint256[1000000000000000] public ve_supply;\\n\\n address public depositor;\\n\\n constructor(address _voting_escrow) {\\n uint256 _t = (block.timestamp / WEEK) * WEEK;\\n start_time = _t;\\n last_token_time = _t;\\n time_cursor = _t;\\n address _token = IVotingEscrow(_voting_escrow).token();\\n token = _token;\\n voting_escrow = _voting_escrow;\\n depositor = msg.sender;\\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\\n }\\n\\n function timestamp() external view returns (uint256) {\\n return (block.timestamp / WEEK) * WEEK;\\n }\\n\\n function _checkpoint_token() internal {\\n uint256 token_balance = IERC20(token).balanceOf(address(this));\\n uint256 to_distribute = token_balance - token_last_balance;\\n token_last_balance = token_balance;\\n\\n uint256 t = last_token_time;\\n uint256 since_last = block.timestamp - t;\\n last_token_time = block.timestamp;\\n uint256 this_week = (t / WEEK) * WEEK;\\n uint256 next_week = 0;\\n\\n for (uint256 i = 0; i < 20; i++) {\\n next_week = this_week + WEEK;\\n if (block.timestamp < next_week) {\\n if (since_last == 0 && block.timestamp == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (block.timestamp - t)) /\\n since_last;\\n }\\n break;\\n } else {\\n if (since_last == 0 && next_week == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (next_week - t)) /\\n since_last;\\n }\\n }\\n t = next_week;\\n this_week = next_week;\\n }\\n emit CheckpointToken(block.timestamp, to_distribute);\\n }\\n\\n function checkpoint_token() external {\\n assert(msg.sender == depositor);\\n _checkpoint_token();\\n }\\n\\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\\n internal\\n view\\n returns (uint256)\\n {\\n uint256 _min = 0;\\n uint256 _max = IVotingEscrow(ve).epoch();\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n _mid\\n );\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function _find_timestamp_user_epoch(\\n address ve,\\n uint256 tokenId,\\n uint256 _timestamp,\\n uint256 max_user_epoch\\n ) internal view returns (uint256) {\\n uint256 _min = 0;\\n uint256 _max = max_user_epoch;\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\\n .user_point_history(tokenId, _mid);\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\\n external\\n view\\n returns (uint256)\\n {\\n address ve = voting_escrow;\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _timestamp,\\n max_user_epoch\\n );\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n epoch\\n );\\n return\\n MathDunks.max(\\n uint256(\\n int256(\\n pt.bias -\\n pt.slope *\\n (int128(int256(_timestamp - pt.ts)))\\n )\\n ),\\n 0\\n );\\n }\\n\\n function _checkpoint_total_supply() internal {\\n address ve = voting_escrow;\\n uint256 t = time_cursor;\\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\\n IVotingEscrow(ve).checkpoint();\\n\\n for (uint256 i = 0; i < 20; i++) {\\n if (t > rounded_timestamp) {\\n break;\\n } else {\\n uint256 epoch = _find_timestamp_epoch(ve, t);\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n epoch\\n );\\n int128 dt = 0;\\n if (t > pt.ts) {\\n dt = int128(int256(t - pt.ts));\\n }\\n ve_supply[t] = MathDunks.max(\\n uint256(int256(pt.bias - pt.slope * dt)),\\n 0\\n );\\n }\\n t += WEEK;\\n }\\n time_cursor = t;\\n }\\n\\n function checkpoint_total_supply() external {\\n _checkpoint_total_supply();\\n }\\n\\n function _claim(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\\n user_epoch_of[_tokenId] = user_epoch;\\n time_cursor_of[_tokenId] = week_cursor;\\n\\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\\n\\n return to_distribute;\\n }\\n\\n function _claimable(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal view returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n return to_distribute;\\n }\\n\\n function claimable(uint256 _tokenId) external view returns (uint256) {\\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\\n return _claimable(_tokenId, voting_escrow, _last_token_time);\\n }\\n\\n function claim(uint256 _tokenId) external returns (uint256) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\\n token_last_balance -= amount;\\n }\\n return amount;\\n }\\n\\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n address _voting_escrow = voting_escrow;\\n uint256 total = 0;\\n\\n for (uint256 i = 0; i < _tokenIds.length; i++) {\\n uint256 _tokenId = _tokenIds[i];\\n if (_tokenId == 0) break;\\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\\n total += amount;\\n }\\n }\\n if (total != 0) {\\n token_last_balance -= total;\\n }\\n\\n return true;\\n }\\n\\n // Once off event on contract initialize\\n function setDepositor(address _depositor) external {\\n require(msg.sender == depositor);\\n depositor = _depositor;\\n }\\n}\\n\",\"keccak256\":\"0xc3e7c3c7944974ce250313d2794fbfa3a98786e2040c685dc250c71ff9002829\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b5060405162001b9f38038062001b9f83398101604081905262000034916200019f565b600062093a80620000468142620001d1565b620000529190620001f4565b90508060008190555080600481905550806001819055506000826001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000aa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d091906200019f565b66038d7ea4c6800680546001600160a01b038381166001600160a01b0319928316811790935566038d7ea4c6800580549188169183168217905566071afd498d00088054909216331790915560405163095ea7b360e01b8152600481019190915260001960248201529192509063095ea7b3906044016020604051808303816000875af115801562000166573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200018c919062000222565b6200019657600080fd5b50505062000246565b600060208284031215620001b257600080fd5b81516001600160a01b0381168114620001ca57600080fd5b9392505050565b600082620001ef57634e487b7160e01b600052601260045260246000fd5b500490565b60008160001904831182151516156200021d57634e487b7160e01b600052601160045260246000fd5b500290565b6000602082840312156200023557600080fd5b81518015158114620001ca57600080fd5b61194980620002566000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea26469706673582212201e6c535ac80bdcc2173028ba4f75663baac29d307f03145fc4e6429a070cb05564736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea26469706673582212201e6c535ac80bdcc2173028ba4f75663baac29d307f03145fc4e6429a070cb05564736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, @@ -403,7 +403,7 @@ "storageLayout": { "storage": [ { - "astId": 9410, + "astId": 9902, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "start_time", "offset": 0, @@ -411,7 +411,7 @@ "type": "t_uint256" }, { - "astId": 9412, + "astId": 9904, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "time_cursor", "offset": 0, @@ -419,7 +419,7 @@ "type": "t_uint256" }, { - "astId": 9416, + "astId": 9908, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "time_cursor_of", "offset": 0, @@ -427,7 +427,7 @@ "type": "t_mapping(t_uint256,t_uint256)" }, { - "astId": 9420, + "astId": 9912, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "user_epoch_of", "offset": 0, @@ -435,7 +435,7 @@ "type": "t_mapping(t_uint256,t_uint256)" }, { - "astId": 9422, + "astId": 9914, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "last_token_time", "offset": 0, @@ -443,7 +443,7 @@ "type": "t_uint256" }, { - "astId": 9426, + "astId": 9918, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "tokens_per_week", "offset": 0, @@ -451,7 +451,7 @@ "type": "t_array(t_uint256)1000000000000000_storage" }, { - "astId": 9428, + "astId": 9920, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "voting_escrow", "offset": 0, @@ -459,7 +459,7 @@ "type": "t_address" }, { - "astId": 9430, + "astId": 9922, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "token", "offset": 0, @@ -467,7 +467,7 @@ "type": "t_address" }, { - "astId": 9432, + "astId": 9924, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "token_last_balance", "offset": 0, @@ -475,7 +475,7 @@ "type": "t_uint256" }, { - "astId": 9436, + "astId": 9928, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "ve_supply", "offset": 0, @@ -483,7 +483,7 @@ "type": "t_array(t_uint256)1000000000000000_storage" }, { - "astId": 9438, + "astId": 9930, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "depositor", "offset": 0, diff --git a/deployments/arbitrumGoerli/Router.json b/deployments/arbitrumGoerli/Router.json index f3f674c3..2000bb1e 100644 --- a/deployments/arbitrumGoerli/Router.json +++ b/deployments/arbitrumGoerli/Router.json @@ -1,5 +1,5 @@ { - "address": "0x1B0aC6bf6f35E638f6cce8D69C6074561273dc52", + "address": "0x49fb251F8Ff60bcd975D2018D0011D7a6065000B", "abi": [ { "inputs": [ @@ -979,31 +979,31 @@ "type": "receive" } ], - "transactionHash": "0x95ae820faec784f4c39345361659f4d3f37f6a02c6e723fa105c1e985e303832", + "transactionHash": "0x6610f670be71188a6b66792b771e60520f5f7e7e91ee0c273e4306edfe22e182", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x1B0aC6bf6f35E638f6cce8D69C6074561273dc52", + "contractAddress": "0x49fb251F8Ff60bcd975D2018D0011D7a6065000B", "transactionIndex": 1, - "gasUsed": "3250410", + "gasUsed": "3145971", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x6b332b331cd45f4e5ea7479d9ec5e8eab1dc518626ee7ca06fcb07ca0742c4f6", - "transactionHash": "0x95ae820faec784f4c39345361659f4d3f37f6a02c6e723fa105c1e985e303832", + "blockHash": "0xcc92dd426bfe64c858819df3de6b6b806cca0f9c9e6aed184ca13cf3e58e4707", + "transactionHash": "0x6610f670be71188a6b66792b771e60520f5f7e7e91ee0c273e4306edfe22e182", "logs": [], - "blockNumber": 4455877, - "cumulativeGasUsed": "3250410", + "blockNumber": 5716719, + "cumulativeGasUsed": "3145971", "status": 1, "byzantium": true }, "args": [ - "0x6389e934d35fC9e066FAb549C8DBc9FddaC10e0D", + "0xddadFF10D1C9eb062180a870150D11673FFf7ad6", "0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83" ], - "numDeployments": 1, - "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_weth\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"UNSAFE_swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"}],\"name\":\"getAmountsOut\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reserveA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"pairFor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"}],\"name\":\"quoteAddLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"name\":\"quoteRemoveLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityETHWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"}],\"name\":\"sortTokens\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactETHForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForETH\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenFrom\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenTo\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokensSimple\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weth\",\"outputs\":[{\"internalType\":\"contract IWETH\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Router.sol\":\"Router\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Router.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairFactory.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\nimport \\\"contracts/interfaces/IWETH.sol\\\";\\n\\ncontract Router is IRouter {\\n struct route {\\n address from;\\n address to;\\n bool stable;\\n }\\n\\n address public immutable factory;\\n IWETH public immutable weth;\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n bytes32 immutable pairCodeHash;\\n\\n modifier ensure(uint256 deadline) {\\n require(deadline >= block.timestamp, \\\"Router: EXPIRED\\\");\\n _;\\n }\\n\\n constructor(address _factory, address _weth) {\\n factory = _factory;\\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\\n weth = IWETH(_weth);\\n }\\n\\n receive() external payable {\\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\\n }\\n\\n function sortTokens(address tokenA, address tokenB)\\n public\\n pure\\n returns (address token0, address token1)\\n {\\n require(tokenA != tokenB, \\\"Router: IDENTICAL_ADDRESSES\\\");\\n (token0, token1) = tokenA < tokenB\\n ? (tokenA, tokenB)\\n : (tokenB, tokenA);\\n require(token0 != address(0), \\\"Router: ZERO_ADDRESS\\\");\\n }\\n\\n // calculates the CREATE2 address for a pair without making any external calls\\n function pairFor(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (address pair) {\\n (address token0, address token1) = sortTokens(tokenA, tokenB);\\n pair = address(\\n uint160(\\n uint256(\\n keccak256(\\n abi.encodePacked(\\n hex\\\"ff\\\",\\n factory,\\n keccak256(abi.encodePacked(token0, token1, stable)),\\n pairCodeHash // init code hash\\n )\\n )\\n )\\n )\\n );\\n }\\n\\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\\n function quoteLiquidity(\\n uint256 amountA,\\n uint256 reserveA,\\n uint256 reserveB\\n ) internal pure returns (uint256 amountB) {\\n require(amountA > 0, \\\"Router: INSUFFICIENT_AMOUNT\\\");\\n require(reserveA > 0 && reserveB > 0, \\\"Router: INSUFFICIENT_LIQUIDITY\\\");\\n amountB = (amountA * reserveB) / reserveA;\\n }\\n\\n // fetches and sorts the reserves for a pair\\n function getReserves(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (uint256 reserveA, uint256 reserveB) {\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (uint256 reserve0, uint256 reserve1, ) = IPair(\\n pairFor(tokenA, tokenB, stable)\\n ).getReserves();\\n (reserveA, reserveB) = tokenA == token0\\n ? (reserve0, reserve1)\\n : (reserve1, reserve0);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n address tokenOut\\n ) external view returns (uint256 amount, bool stable) {\\n address pair = pairFor(tokenIn, tokenOut, true);\\n uint256 amountStable;\\n uint256 amountVolatile;\\n if (IPairFactory(factory).isPair(pair)) {\\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n pair = pairFor(tokenIn, tokenOut, false);\\n if (IPairFactory(factory).isPair(pair)) {\\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n return\\n amountStable > amountVolatile\\n ? (amountStable, true)\\n : (amountVolatile, false);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountsOut(uint256 amountIn, route[] memory routes)\\n public\\n view\\n returns (uint256[] memory amounts)\\n {\\n require(routes.length >= 1, \\\"Router: INVALID_PATH\\\");\\n amounts = new uint256[](routes.length + 1);\\n amounts[0] = amountIn;\\n for (uint256 i = 0; i < routes.length; i++) {\\n address pair = pairFor(\\n routes[i].from,\\n routes[i].to,\\n routes[i].stable\\n );\\n if (IPairFactory(factory).isPair(pair)) {\\n amounts[i + 1] = IPair(pair).getAmountOut(\\n amounts[i],\\n routes[i].from\\n );\\n }\\n }\\n }\\n\\n function isPair(address pair) external view returns (bool) {\\n return IPairFactory(factory).isPair(pair);\\n }\\n\\n function quoteAddLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired\\n )\\n external\\n view\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n (uint256 reserveA, uint256 reserveB) = (0, 0);\\n uint256 _totalSupply = 0;\\n if (_pair != address(0)) {\\n _totalSupply = IERC20(_pair).totalSupply();\\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\\n }\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n }\\n }\\n }\\n\\n function quoteRemoveLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity\\n ) external view returns (uint256 amountA, uint256 amountB) {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n\\n if (_pair == address(0)) {\\n return (0, 0);\\n }\\n\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n uint256 _totalSupply = IERC20(_pair).totalSupply();\\n\\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\\n }\\n\\n function _addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin\\n ) internal returns (uint256 amountA, uint256 amountB) {\\n require(amountADesired >= amountAMin);\\n require(amountBDesired >= amountBMin);\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n if (_pair == address(0)) {\\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\\n }\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n require(\\n amountBOptimal >= amountBMin,\\n \\\"Router: INSUFFICIENT_B_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n assert(amountAOptimal <= amountADesired);\\n require(\\n amountAOptimal >= amountAMin,\\n \\\"Router: INSUFFICIENT_A_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n }\\n }\\n }\\n\\n function addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n ensure(deadline)\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n (amountA, amountB) = _addLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n amountADesired,\\n amountBDesired,\\n amountAMin,\\n amountBMin\\n );\\n address pair = pairFor(tokenA, tokenB, stable);\\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\\n liquidity = IPair(pair).mint(to);\\n }\\n\\n function addLiquidityETH(\\n address token,\\n bool stable,\\n uint256 amountTokenDesired,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n payable\\n ensure(deadline)\\n returns (\\n uint256 amountToken,\\n uint256 amountETH,\\n uint256 liquidity\\n )\\n {\\n (amountToken, amountETH) = _addLiquidity(\\n token,\\n address(weth),\\n stable,\\n amountTokenDesired,\\n msg.value,\\n amountTokenMin,\\n amountETHMin\\n );\\n address pair = pairFor(token, address(weth), stable);\\n _safeTransferFrom(token, msg.sender, pair, amountToken);\\n weth.deposit{value: amountETH}();\\n assert(weth.transfer(pair, amountETH));\\n liquidity = IPair(pair).mint(to);\\n // refund dust eth, if any\\n if (msg.value > amountETH)\\n _safeTransferETH(msg.sender, msg.value - amountETH);\\n }\\n\\n // **** REMOVE LIQUIDITY ****\\n function removeLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (amountA, amountB) = tokenA == token0\\n ? (amount0, amount1)\\n : (amount1, amount0);\\n require(amountA >= amountAMin, \\\"Router: INSUFFICIENT_A_AMOUNT\\\");\\n require(amountB >= amountBMin, \\\"Router: INSUFFICIENT_B_AMOUNT\\\");\\n }\\n\\n function removeLiquidityETH(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\\n (amountToken, amountETH) = removeLiquidity(\\n token,\\n address(weth),\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n address(this),\\n deadline\\n );\\n _safeTransfer(token, to, amountToken);\\n weth.withdraw(amountETH);\\n _safeTransferETH(to, amountETH);\\n }\\n\\n function removeLiquidityWithPermit(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n {\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(\\n msg.sender,\\n address(this),\\n value,\\n deadline,\\n v,\\n r,\\n s\\n );\\n }\\n\\n (amountA, amountB) = removeLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n liquidity,\\n amountAMin,\\n amountBMin,\\n to,\\n deadline\\n );\\n }\\n\\n function removeLiquidityETHWithPermit(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountToken, uint256 amountETH) {\\n address pair = pairFor(token, address(weth), stable);\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\\n (amountToken, amountETH) = removeLiquidityETH(\\n token,\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n to,\\n deadline\\n );\\n }\\n\\n // **** SWAP ****\\n // requires the initial amount to have already been sent to the first pair\\n function _swap(\\n uint256[] memory amounts,\\n route[] memory routes,\\n address _to\\n ) internal virtual {\\n for (uint256 i = 0; i < routes.length; i++) {\\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\\n uint256 amountOut = amounts[i + 1];\\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\\n ? (uint256(0), amountOut)\\n : (amountOut, uint256(0));\\n address to = i < routes.length - 1\\n ? pairFor(\\n routes[i + 1].from,\\n routes[i + 1].to,\\n routes[i + 1].stable\\n )\\n : _to;\\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\\n amount0Out,\\n amount1Out,\\n to,\\n new bytes(0)\\n );\\n }\\n }\\n\\n function swapExactTokensForTokensSimple(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n address tokenFrom,\\n address tokenTo,\\n bool stable,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n route[] memory routes = new route[](1);\\n routes[0].from = tokenFrom;\\n routes[0].to = tokenTo;\\n routes[0].stable = stable;\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForTokens(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactETHForTokens(\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\\n require(routes[0].from == address(weth), \\\"Router: INVALID_PATH\\\");\\n amounts = getAmountsOut(msg.value, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n weth.deposit{value: amounts[0]}();\\n assert(\\n weth.transfer(\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n )\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForETH(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n require(\\n routes[routes.length - 1].to == address(weth),\\n \\\"Router: INVALID_PATH\\\"\\n );\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, address(this));\\n weth.withdraw(amounts[amounts.length - 1]);\\n _safeTransferETH(to, amounts[amounts.length - 1]);\\n }\\n\\n function UNSAFE_swapExactTokensForTokens(\\n uint256[] memory amounts,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory) {\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n return amounts;\\n }\\n\\n function _safeTransferETH(address to, uint256 value) internal {\\n (bool success, ) = to.call{value: value}(new bytes(0));\\n require(success, \\\"TransferHelper: ETH_TRANSFER_FAILED\\\");\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x3d84c846129d645eec66c37a493bb7fb401a2524497f450eaced155088305ead\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"},\"contracts/interfaces/IWETH.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n function transfer(address to, uint256 value) external returns (bool);\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0x20ad0b3a319a36e3430f0d8512ee3755de8f85a80effe78d06f333f5326ee3d7\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x60e06040523480156200001157600080fd5b50604051620039bc380380620039bc8339810160408190526200003491620000d8565b6001600160a01b038216608081905260408051631355724960e31b81529051639aab9248916004808201926020929091908290030181865afa1580156200007f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000a5919062000110565b60c0526001600160a01b031660a052506200012a565b80516001600160a01b0381168114620000d357600080fd5b919050565b60008060408385031215620000ec57600080fd5b620000f783620000bb565b91506200010760208401620000bb565b90509250929050565b6000602082840312156200012357600080fd5b5051919050565b60805160a05160c0516137c8620001f46000396000610ef901526000818161013e0152818161020b0152818161091901528181610b5801528181610da901528181611470015281816115830152818161161101528181611de901528181611e1f01528181611e5401528181611ee901528181612028015261207801526000818161042d01528181610c3e01528181610ebe015281816111770152818161128b0152818161199601528181611b0a01528181612115015281816126ff01526127a001526137c86000f3fe60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea2646970667358221220f2ee1975729b6186adceb8b9288ee74fe51d172125a95d24ef2076061558626e64736f6c634300080d0033", - "deployedBytecode": "0x60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea2646970667358221220f2ee1975729b6186adceb8b9288ee74fe51d172125a95d24ef2076061558626e64736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_weth\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"UNSAFE_swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"}],\"name\":\"getAmountsOut\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reserveA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"pairFor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"}],\"name\":\"quoteAddLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"name\":\"quoteRemoveLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityETHWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"}],\"name\":\"sortTokens\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactETHForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForETH\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenFrom\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenTo\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokensSimple\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weth\",\"outputs\":[{\"internalType\":\"contract IWETH\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Router.sol\":\"Router\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Router.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairFactory.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\nimport \\\"contracts/interfaces/IWETH.sol\\\";\\n\\ncontract Router is IRouter {\\n struct route {\\n address from;\\n address to;\\n bool stable;\\n }\\n\\n address public immutable factory;\\n IWETH public immutable weth;\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n bytes32 immutable pairCodeHash;\\n\\n modifier ensure(uint256 deadline) {\\n require(deadline >= block.timestamp, \\\"Router: EXPIRED\\\");\\n _;\\n }\\n\\n constructor(address _factory, address _weth) {\\n factory = _factory;\\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\\n weth = IWETH(_weth);\\n }\\n\\n receive() external payable {\\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\\n }\\n\\n function sortTokens(address tokenA, address tokenB)\\n public\\n pure\\n returns (address token0, address token1)\\n {\\n require(tokenA != tokenB, \\\"Router: IDENTICAL_ADDRESSES\\\");\\n (token0, token1) = tokenA < tokenB\\n ? (tokenA, tokenB)\\n : (tokenB, tokenA);\\n require(token0 != address(0), \\\"Router: ZERO_ADDRESS\\\");\\n }\\n\\n // calculates the CREATE2 address for a pair without making any external calls\\n function pairFor(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (address pair) {\\n (address token0, address token1) = sortTokens(tokenA, tokenB);\\n pair = address(\\n uint160(\\n uint256(\\n keccak256(\\n abi.encodePacked(\\n hex\\\"ff\\\",\\n factory,\\n keccak256(abi.encodePacked(token0, token1, stable)),\\n pairCodeHash // init code hash\\n )\\n )\\n )\\n )\\n );\\n }\\n\\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\\n function quoteLiquidity(\\n uint256 amountA,\\n uint256 reserveA,\\n uint256 reserveB\\n ) internal pure returns (uint256 amountB) {\\n require(amountA > 0, \\\"Router: INSUFFICIENT_AMOUNT\\\");\\n require(reserveA > 0 && reserveB > 0, \\\"Router: INSUFFICIENT_LIQUIDITY\\\");\\n amountB = (amountA * reserveB) / reserveA;\\n }\\n\\n // fetches and sorts the reserves for a pair\\n function getReserves(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (uint256 reserveA, uint256 reserveB) {\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (uint256 reserve0, uint256 reserve1, ) = IPair(\\n pairFor(tokenA, tokenB, stable)\\n ).getReserves();\\n (reserveA, reserveB) = tokenA == token0\\n ? (reserve0, reserve1)\\n : (reserve1, reserve0);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n address tokenOut\\n ) external view returns (uint256 amount, bool stable) {\\n address pair = pairFor(tokenIn, tokenOut, true);\\n uint256 amountStable;\\n uint256 amountVolatile;\\n if (IPairFactory(factory).isPair(pair)) {\\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n pair = pairFor(tokenIn, tokenOut, false);\\n if (IPairFactory(factory).isPair(pair)) {\\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n return\\n amountStable > amountVolatile\\n ? (amountStable, true)\\n : (amountVolatile, false);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountsOut(uint256 amountIn, route[] memory routes)\\n public\\n view\\n returns (uint256[] memory amounts)\\n {\\n require(routes.length >= 1, \\\"Router: INVALID_PATH\\\");\\n amounts = new uint256[](routes.length + 1);\\n amounts[0] = amountIn;\\n for (uint256 i = 0; i < routes.length; i++) {\\n address pair = pairFor(\\n routes[i].from,\\n routes[i].to,\\n routes[i].stable\\n );\\n if (IPairFactory(factory).isPair(pair)) {\\n amounts[i + 1] = IPair(pair).getAmountOut(\\n amounts[i],\\n routes[i].from\\n );\\n }\\n }\\n }\\n\\n function isPair(address pair) external view returns (bool) {\\n return IPairFactory(factory).isPair(pair);\\n }\\n\\n function quoteAddLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired\\n )\\n external\\n view\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n (uint256 reserveA, uint256 reserveB) = (0, 0);\\n uint256 _totalSupply = 0;\\n if (_pair != address(0)) {\\n _totalSupply = IERC20(_pair).totalSupply();\\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\\n }\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n }\\n }\\n }\\n\\n function quoteRemoveLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity\\n ) external view returns (uint256 amountA, uint256 amountB) {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n\\n if (_pair == address(0)) {\\n return (0, 0);\\n }\\n\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n uint256 _totalSupply = IERC20(_pair).totalSupply();\\n\\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\\n }\\n\\n function _addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin\\n ) internal returns (uint256 amountA, uint256 amountB) {\\n require(amountADesired >= amountAMin);\\n require(amountBDesired >= amountBMin);\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n if (_pair == address(0)) {\\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\\n }\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n require(\\n amountBOptimal >= amountBMin,\\n \\\"Router: INSUFFICIENT_B_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n assert(amountAOptimal <= amountADesired);\\n require(\\n amountAOptimal >= amountAMin,\\n \\\"Router: INSUFFICIENT_A_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n }\\n }\\n }\\n\\n function addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n ensure(deadline)\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n (amountA, amountB) = _addLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n amountADesired,\\n amountBDesired,\\n amountAMin,\\n amountBMin\\n );\\n address pair = pairFor(tokenA, tokenB, stable);\\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\\n liquidity = IPair(pair).mint(to);\\n }\\n\\n function addLiquidityETH(\\n address token,\\n bool stable,\\n uint256 amountTokenDesired,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n payable\\n ensure(deadline)\\n returns (\\n uint256 amountToken,\\n uint256 amountETH,\\n uint256 liquidity\\n )\\n {\\n (amountToken, amountETH) = _addLiquidity(\\n token,\\n address(weth),\\n stable,\\n amountTokenDesired,\\n msg.value,\\n amountTokenMin,\\n amountETHMin\\n );\\n address pair = pairFor(token, address(weth), stable);\\n _safeTransferFrom(token, msg.sender, pair, amountToken);\\n weth.deposit{value: amountETH}();\\n assert(weth.transfer(pair, amountETH));\\n liquidity = IPair(pair).mint(to);\\n // refund dust eth, if any\\n if (msg.value > amountETH)\\n _safeTransferETH(msg.sender, msg.value - amountETH);\\n }\\n\\n // **** REMOVE LIQUIDITY ****\\n function removeLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (amountA, amountB) = tokenA == token0\\n ? (amount0, amount1)\\n : (amount1, amount0);\\n require(amountA >= amountAMin, \\\"Router: INSUFFICIENT_A_AMOUNT\\\");\\n require(amountB >= amountBMin, \\\"Router: INSUFFICIENT_B_AMOUNT\\\");\\n }\\n\\n function removeLiquidityETH(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\\n (amountToken, amountETH) = removeLiquidity(\\n token,\\n address(weth),\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n address(this),\\n deadline\\n );\\n _safeTransfer(token, to, amountToken);\\n weth.withdraw(amountETH);\\n _safeTransferETH(to, amountETH);\\n }\\n\\n function removeLiquidityWithPermit(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n {\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(\\n msg.sender,\\n address(this),\\n value,\\n deadline,\\n v,\\n r,\\n s\\n );\\n }\\n\\n (amountA, amountB) = removeLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n liquidity,\\n amountAMin,\\n amountBMin,\\n to,\\n deadline\\n );\\n }\\n\\n function removeLiquidityETHWithPermit(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountToken, uint256 amountETH) {\\n address pair = pairFor(token, address(weth), stable);\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\\n (amountToken, amountETH) = removeLiquidityETH(\\n token,\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n to,\\n deadline\\n );\\n }\\n\\n // **** SWAP ****\\n // requires the initial amount to have already been sent to the first pair\\n function _swap(\\n uint256[] memory amounts,\\n route[] memory routes,\\n address _to\\n ) internal virtual {\\n for (uint256 i = 0; i < routes.length; i++) {\\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\\n uint256 amountOut = amounts[i + 1];\\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\\n ? (uint256(0), amountOut)\\n : (amountOut, uint256(0));\\n address to = i < routes.length - 1\\n ? pairFor(\\n routes[i + 1].from,\\n routes[i + 1].to,\\n routes[i + 1].stable\\n )\\n : _to;\\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\\n amount0Out,\\n amount1Out,\\n to,\\n new bytes(0)\\n );\\n }\\n }\\n\\n function swapExactTokensForTokensSimple(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n address tokenFrom,\\n address tokenTo,\\n bool stable,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n route[] memory routes = new route[](1);\\n routes[0].from = tokenFrom;\\n routes[0].to = tokenTo;\\n routes[0].stable = stable;\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForTokens(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactETHForTokens(\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\\n require(routes[0].from == address(weth), \\\"Router: INVALID_PATH\\\");\\n amounts = getAmountsOut(msg.value, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n weth.deposit{value: amounts[0]}();\\n assert(\\n weth.transfer(\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n )\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForETH(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n require(\\n routes[routes.length - 1].to == address(weth),\\n \\\"Router: INVALID_PATH\\\"\\n );\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, address(this));\\n weth.withdraw(amounts[amounts.length - 1]);\\n _safeTransferETH(to, amounts[amounts.length - 1]);\\n }\\n\\n function UNSAFE_swapExactTokensForTokens(\\n uint256[] memory amounts,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory) {\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n return amounts;\\n }\\n\\n function _safeTransferETH(address to, uint256 value) internal {\\n (bool success, ) = to.call{value: value}(new bytes(0));\\n require(success, \\\"TransferHelper: ETH_TRANSFER_FAILED\\\");\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x3d84c846129d645eec66c37a493bb7fb401a2524497f450eaced155088305ead\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"},\"contracts/interfaces/IWETH.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n function transfer(address to, uint256 value) external returns (bool);\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0x20ad0b3a319a36e3430f0d8512ee3755de8f85a80effe78d06f333f5326ee3d7\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x60e06040523480156200001157600080fd5b50604051620039bc380380620039bc8339810160408190526200003491620000d8565b6001600160a01b038216608081905260408051631355724960e31b81529051639aab9248916004808201926020929091908290030181865afa1580156200007f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000a5919062000110565b60c0526001600160a01b031660a052506200012a565b80516001600160a01b0381168114620000d357600080fd5b919050565b60008060408385031215620000ec57600080fd5b620000f783620000bb565b91506200010760208401620000bb565b90509250929050565b6000602082840312156200012357600080fd5b5051919050565b60805160a05160c0516137c8620001f46000396000610ef901526000818161013e0152818161020b0152818161091901528181610b5801528181610da901528181611470015281816115830152818161161101528181611de901528181611e1f01528181611e5401528181611ee901528181612028015261207801526000818161042d01528181610c3e01528181610ebe015281816111770152818161128b0152818161199601528181611b0a01528181612115015281816126ff01526127a001526137c86000f3fe60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea26469706673582212207f76fe8e2aef1f06aeeb37f313c0f0f346548f28b5ac3c1f1e24c72c7e4bab4764736f6c634300080d0033", + "deployedBytecode": "0x60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea26469706673582212207f76fe8e2aef1f06aeeb37f313c0f0f346548f28b5ac3c1f1e24c72c7e4bab4764736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/VeArtProxy.json b/deployments/arbitrumGoerli/VeArtProxy.json index 93a3c3be..52e58bed 100644 --- a/deployments/arbitrumGoerli/VeArtProxy.json +++ b/deployments/arbitrumGoerli/VeArtProxy.json @@ -1,5 +1,5 @@ { - "address": "0x821B98D42D3AB509AF4F54205f0c52B019b9E2D5", + "address": "0xDe032908A79276B257d1ae80f0C0A2c070eDa1F4", "abi": [ { "inputs": [ @@ -36,28 +36,28 @@ "type": "function" } ], - "transactionHash": "0x54e3314db01e3cabc091054c4928e7e5ddc5bc219384cdbc0bb493b8009cf015", + "transactionHash": "0xab177b1c3f70b542f397bafe504efd889bd5359783e389177712edeedef956a9", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x821B98D42D3AB509AF4F54205f0c52B019b9E2D5", + "contractAddress": "0xDe032908A79276B257d1ae80f0C0A2c070eDa1F4", "transactionIndex": 1, - "gasUsed": "644260", + "gasUsed": "615440", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x4f111813d8e4e78801f82168c4bec40866a898791e08a4fd8d4984f5f60e200b", - "transactionHash": "0x54e3314db01e3cabc091054c4928e7e5ddc5bc219384cdbc0bb493b8009cf015", + "blockHash": "0xf86a5efdf9931e00138c17d04166a3294ec57a48e574d95f13403048937ea8f0", + "transactionHash": "0xab177b1c3f70b542f397bafe504efd889bd5359783e389177712edeedef956a9", "logs": [], - "blockNumber": 4455883, - "cumulativeGasUsed": "644260", + "blockNumber": 5716723, + "cumulativeGasUsed": "615440", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_locked_end\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"_tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"output\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VeArtProxy.sol\":\"VeArtProxy\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\nimport {Base64} from \\\"contracts/libraries/Base64.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\n\\ncontract VeArtProxy is IVeArtProxy {\\n function toString(uint value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT license\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint temp = value;\\n uint digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\\n output = '';\\n output = string(abi.encodePacked(output, \\\"token \\\", toString(_tokenId), ''));\\n output = string(abi.encodePacked(output, \\\"balanceOf \\\", toString(_balanceOf), ''));\\n output = string(abi.encodePacked(output, \\\"locked_end \\\", toString(_locked_end), ''));\\n output = string(abi.encodePacked(output, \\\"value \\\", toString(_value), ''));\\n\\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\\\"name\\\": \\\"lock #', toString(_tokenId), '\\\", \\\"description\\\": \\\"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\\\", \\\"image\\\": \\\"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\\\"}'))));\\n output = string(abi.encodePacked('data:application/json;base64,', json));\\n }\\n}\\n\",\"keccak256\":\"0x8757d8095922dcad7af8c6820415049fd7d5af61a5580719210e5e91a31d80b1\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/libraries/Base64.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n/// [MIT License]\\n/// @title Base64\\n/// @notice Provides a function for encoding some bytes in base64\\n/// @author Brecht Devos \\nlibrary Base64 {\\n bytes internal constant TABLE = \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\";\\n\\n /// @notice Encodes some bytes to the base64 representation\\n function encode(bytes memory data) internal pure returns (string memory) {\\n uint len = data.length;\\n if (len == 0) return \\\"\\\";\\n\\n // multiply by 4/3 rounded up\\n uint encodedLen = 4 * ((len + 2) / 3);\\n\\n // Add some extra buffer at the end\\n bytes memory result = new bytes(encodedLen + 32);\\n\\n bytes memory table = TABLE;\\n\\n assembly {\\n let tablePtr := add(table, 1)\\n let resultPtr := add(result, 32)\\n\\n for {\\n let i := 0\\n } lt(i, len) {\\n\\n } {\\n i := add(i, 3)\\n let input := and(mload(add(data, i)), 0xffffff)\\n\\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\\n out := shl(224, out)\\n\\n mstore(resultPtr, out)\\n\\n resultPtr := add(resultPtr, 4)\\n }\\n\\n switch mod(len, 3)\\n case 1 {\\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\\n }\\n case 2 {\\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\\n }\\n\\n mstore(result, encodedLen)\\n }\\n\\n return string(result);\\n }\\n}\\n\",\"keccak256\":\"0x55535e1e0a14bbac370fe5f25df23aa88c678b915af53517672130f9a54f7e3e\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50610a2b806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f64726f6d65206c6f636010918401918201527f6b732c2063616e206265207573656420746f20626f6f7374206761756765207960308201527f69656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c206160508201527f6e64207265636569766520627269626573222c2022696d616765223a2022646160708201527f74613a696d6167652f7376672b786d6c3b6261736536342c0000000000000000609082015283516107718160a8840160208801610435565b61227d60f01b60a8929091019182015260aa01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220af1f8cc7181d18ce7e9f4d26a0b55e87cfad516b6b2bf21dc6cebe86c06fb7bf64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f64726f6d65206c6f636010918401918201527f6b732c2063616e206265207573656420746f20626f6f7374206761756765207960308201527f69656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c206160508201527f6e64207265636569766520627269626573222c2022696d616765223a2022646160708201527f74613a696d6167652f7376672b786d6c3b6261736536342c0000000000000000609082015283516107718160a8840160208801610435565b61227d60f01b60a8929091019182015260aa01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220af1f8cc7181d18ce7e9f4d26a0b55e87cfad516b6b2bf21dc6cebe86c06fb7bf64736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_locked_end\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"_tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"output\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VeArtProxy.sol\":\"VeArtProxy\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\nimport {Base64} from \\\"contracts/libraries/Base64.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\n\\ncontract VeArtProxy is IVeArtProxy {\\n function toString(uint value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT license\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint temp = value;\\n uint digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\\n output = '';\\n output = string(abi.encodePacked(output, \\\"token \\\", toString(_tokenId), ''));\\n output = string(abi.encodePacked(output, \\\"balanceOf \\\", toString(_balanceOf), ''));\\n output = string(abi.encodePacked(output, \\\"locked_end \\\", toString(_locked_end), ''));\\n output = string(abi.encodePacked(output, \\\"value \\\", toString(_value), ''));\\n\\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\\\"name\\\": \\\"lock #', toString(_tokenId), '\\\", \\\"description\\\": \\\"Velocimeter locks, can be used to boost gauge yields, vote on token emission, and receive bribes\\\", \\\"image\\\": \\\"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\\\"}'))));\\n output = string(abi.encodePacked('data:application/json;base64,', json));\\n }\\n}\\n\",\"keccak256\":\"0xc526ae7232c93412d664837d1171f1bf5d231a4ea33bcc7a8d0b4e3fa6a9e227\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/libraries/Base64.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n/// [MIT License]\\n/// @title Base64\\n/// @notice Provides a function for encoding some bytes in base64\\n/// @author Brecht Devos \\nlibrary Base64 {\\n bytes internal constant TABLE = \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\";\\n\\n /// @notice Encodes some bytes to the base64 representation\\n function encode(bytes memory data) internal pure returns (string memory) {\\n uint len = data.length;\\n if (len == 0) return \\\"\\\";\\n\\n // multiply by 4/3 rounded up\\n uint encodedLen = 4 * ((len + 2) / 3);\\n\\n // Add some extra buffer at the end\\n bytes memory result = new bytes(encodedLen + 32);\\n\\n bytes memory table = TABLE;\\n\\n assembly {\\n let tablePtr := add(table, 1)\\n let resultPtr := add(result, 32)\\n\\n for {\\n let i := 0\\n } lt(i, len) {\\n\\n } {\\n i := add(i, 3)\\n let input := and(mload(add(data, i)), 0xffffff)\\n\\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\\n out := shl(224, out)\\n\\n mstore(resultPtr, out)\\n\\n resultPtr := add(resultPtr, 4)\\n }\\n\\n switch mod(len, 3)\\n case 1 {\\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\\n }\\n case 2 {\\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\\n }\\n\\n mstore(result, encodedLen)\\n }\\n\\n return string(result);\\n }\\n}\\n\",\"keccak256\":\"0x55535e1e0a14bbac370fe5f25df23aa88c678b915af53517672130f9a54f7e3e\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610a2b806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f63696d65746572206c6010918401918201527f6f636b732c2063616e206265207573656420746f20626f6f737420676175676560308201527f207969656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c60508201527f20616e64207265636569766520627269626573222c2022696d616765223a202260708201527f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000609082015283516107718160aa840160208801610435565b61227d60f01b60aa929091019182015260ac01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa264697066735822122060ab03393b15ef9eba3bfe6f65af595952a170fe24d2e6f613a8448a0eb4d69364736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f63696d65746572206c6010918401918201527f6f636b732c2063616e206265207573656420746f20626f6f737420676175676560308201527f207969656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c60508201527f20616e64207265636569766520627269626573222c2022696d616765223a202260708201527f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000609082015283516107718160aa840160208801610435565b61227d60f01b60aa929091019182015260ac01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa264697066735822122060ab03393b15ef9eba3bfe6f65af595952a170fe24d2e6f613a8448a0eb4d69364736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/VeloGovernor.json b/deployments/arbitrumGoerli/VeloGovernor.json index 063cc4b2..a147e7e6 100644 --- a/deployments/arbitrumGoerli/VeloGovernor.json +++ b/deployments/arbitrumGoerli/VeloGovernor.json @@ -1,5 +1,5 @@ { - "address": "0x1a79b9daa3E741774bf67732F8a8B5820De8A53a", + "address": "0xB843444d08bee4f79f571Bd34D13Ec71D4194b40", "abi": [ { "inputs": [ @@ -1055,43 +1055,43 @@ "type": "receive" } ], - "transactionHash": "0x4a643f6407d24899d49ae4c8f4f8af6c638991636267c8c19c51db19d58c16f1", + "transactionHash": "0x374952c327cc474cb69c07f492ddeac4cd2ccac618e6fe1b132e7c295c1d8513", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x1a79b9daa3E741774bf67732F8a8B5820De8A53a", + "contractAddress": "0xB843444d08bee4f79f571Bd34D13Ec71D4194b40", "transactionIndex": 1, - "gasUsed": "2851602", - "logsBloom": "0x00000000000000000100000000001000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xa613ccf9c1c4459e5c227f665c806c3d46ea612c1a333a7f75a76f498e952898", - "transactionHash": "0x4a643f6407d24899d49ae4c8f4f8af6c638991636267c8c19c51db19d58c16f1", + "gasUsed": "2742890", + "logsBloom": "0x00000000000000000100000000001000040000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000080000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xbda9204981d328ee926ac35a2c718d8177974cd4bd8a94c4e2acc571cc1c6c11", + "transactionHash": "0x374952c327cc474cb69c07f492ddeac4cd2ccac618e6fe1b132e7c295c1d8513", "logs": [ { "transactionIndex": 1, - "blockNumber": 4455895, - "transactionHash": "0x4a643f6407d24899d49ae4c8f4f8af6c638991636267c8c19c51db19d58c16f1", - "address": "0x1a79b9daa3E741774bf67732F8a8B5820De8A53a", + "blockNumber": 5716742, + "transactionHash": "0x374952c327cc474cb69c07f492ddeac4cd2ccac618e6fe1b132e7c295c1d8513", + "address": "0xB843444d08bee4f79f571Bd34D13Ec71D4194b40", "topics": [ "0x0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997" ], "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004", "logIndex": 0, - "blockHash": "0xa613ccf9c1c4459e5c227f665c806c3d46ea612c1a333a7f75a76f498e952898" + "blockHash": "0xbda9204981d328ee926ac35a2c718d8177974cd4bd8a94c4e2acc571cc1c6c11" } ], - "blockNumber": 4455895, - "cumulativeGasUsed": "2851602", + "blockNumber": 5716742, + "cumulativeGasUsed": "2742890", "status": 1, "byzantium": true }, "args": [ - "0xBf05364D6cf1586852c18c6b1CbEe218E3e09885" + "0xC43f6EbF97f9D99FF8a3aFe1413599e8DEc2aDB3" ], - "numDeployments": 1, - "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"_ve\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"Empty\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"proposer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"string[]\",\"name\":\"signatures\",\"type\":\"string[]\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"ProposalCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldQuorumNumerator\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"QuorumNumeratorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"VoteCast\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"VoteCastWithParams\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"COUNTING_MODE\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EXTENDED_BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_PROPOSAL_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROPOSAL_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"}],\"name\":\"castVote\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"castVoteWithReason\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"castVoteWithReasonAndParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteWithReasonAndParamsBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"execute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"getVotesWithParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasVoted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"hashProposal\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalDeadline\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalSnapshot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"againstVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"forVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"abstainVotes\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"propose\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"quorum\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumDenominator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"}],\"name\":\"setProposalNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTeam\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"state\",\"outputs\":[{\"internalType\":\"enum IGovernor.ProposalState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"updateQuorumNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"Empty()\":[{\"details\":\"An operation (e.g. {front}) couldn't be completed due to the queue being empty.\"}]},\"kind\":\"dev\",\"methods\":{\"COUNTING_MODE()\":{\"details\":\"See {IGovernor-COUNTING_MODE}.\"},\"castVote(uint256,uint8)\":{\"details\":\"See {IGovernor-castVote}.\"},\"castVoteBySig(uint256,uint8,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteBySig}.\"},\"castVoteWithReason(uint256,uint8,string)\":{\"details\":\"See {IGovernor-castVoteWithReason}.\"},\"castVoteWithReasonAndParams(uint256,uint8,string,bytes)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParams}.\"},\"castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParamsBySig}.\"},\"execute(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-execute}.\"},\"getVotes(address,uint256)\":{\"details\":\"See {IGovernor-getVotes}.\"},\"getVotesWithParams(address,uint256,bytes)\":{\"details\":\"See {IGovernor-getVotesWithParams}.\"},\"hasVoted(uint256,address)\":{\"details\":\"See {IGovernor-hasVoted}.\"},\"hashProposal(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-hashProposal}. The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in advance, before the proposal is submitted. Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the same proposal (with same operation and same description) will have the same id if submitted on multiple governors across multiple networks. This also means that in order to execute the same operation twice (on the same governor) the proposer will have to change the description in order to avoid proposal id conflicts.\"},\"name()\":{\"details\":\"See {IGovernor-name}.\"},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155BatchReceived}.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155Received}.\"},\"onERC721Received(address,address,uint256,bytes)\":{\"details\":\"See {IERC721Receiver-onERC721Received}.\"},\"proposalDeadline(uint256)\":{\"details\":\"See {IGovernor-proposalDeadline}.\"},\"proposalSnapshot(uint256)\":{\"details\":\"See {IGovernor-proposalSnapshot}.\"},\"proposalThreshold()\":{\"details\":\"Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\"},\"proposalVotes(uint256)\":{\"details\":\"Accessor to the internal vote counts.\"},\"propose(address[],uint256[],bytes[],string)\":{\"details\":\"See {IGovernor-propose}.\"},\"quorum(uint256)\":{\"details\":\"Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\"},\"quorumDenominator()\":{\"details\":\"Returns the quorum denominator. Defaults to 100, but may be overridden.\"},\"quorumNumerator()\":{\"details\":\"Returns the current quorum numerator. See {quorumDenominator}.\"},\"relay(address,uint256,bytes)\":{\"details\":\"Relays a transaction or function call to an arbitrary target. In cases where the governance executor is some contract other than the governor itself, like when using a timelock, this function can be invoked in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake. Note that if the executor is simply the governor itself, use of `relay` is redundant.\"},\"state(uint256)\":{\"details\":\"See {IGovernor-state}.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"updateQuorumNumerator(uint256)\":{\"details\":\"Changes the quorum numerator. Emits a {QuorumNumeratorUpdated} event. Requirements: - Must be called through a governance proposal. - New numerator must be smaller or equal to the denominator.\"},\"version()\":{\"details\":\"See {IGovernor-version}.\"},\"votingDelay()\":{\"details\":\"Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\"},\"votingPeriod()\":{\"details\":\"Delay, in number of blocks, between the vote start and vote ends. NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting duration compared to the voting delay.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"votingDelay()\":{\"notice\":\"module:user-config\"},\"votingPeriod()\":{\"notice\":\"module:user-config\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VeloGovernor.sol\":\"VeloGovernor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VeloGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IGovernor} from \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\nimport {L2GovernorCountingSimple} from \\\"contracts/governance/L2GovernorCountingSimple.sol\\\";\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\nimport {L2GovernorVotesQuorumFraction} from \\\"contracts/governance/L2GovernorVotesQuorumFraction.sol\\\";\\n\\ncontract VeloGovernor is\\n L2Governor,\\n L2GovernorCountingSimple,\\n L2GovernorVotes,\\n L2GovernorVotesQuorumFraction\\n{\\n address public team;\\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\\n uint256 public proposalNumerator = 2; // start at 0.02%\\n\\n constructor(IVotes _ve)\\n L2Governor(\\\"Velodrome Governor\\\")\\n L2GovernorVotes(_ve)\\n L2GovernorVotesQuorumFraction(4) // 4%\\n {\\n team = msg.sender;\\n }\\n\\n function votingDelay() public pure override(IGovernor) returns (uint256) {\\n return 15 minutes; // 1 block\\n }\\n\\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\\n return 1 weeks;\\n }\\n\\n function setTeam(address newTeam) external {\\n require(msg.sender == team, \\\"not team\\\");\\n team = newTeam;\\n }\\n\\n function setProposalNumerator(uint256 numerator) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \\\"numerator too high\\\");\\n proposalNumerator = numerator;\\n }\\n\\n function proposalThreshold()\\n public\\n view\\n override(L2Governor)\\n returns (uint256)\\n {\\n return\\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\\n PROPOSAL_DENOMINATOR;\\n }\\n}\\n\",\"keccak256\":\"0xbdbc34fd1c78fdffb528f7a2f450e75457cb089369204f4671ec241aa0eb3a7e\",\"license\":\"MIT\"},\"contracts/governance/L2Governor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Address.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Context.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\\n *\\n * @dev Core of the governance system, designed to be extended though various modules.\\n *\\n * This contract is abstract and requires several function to be implemented in various modules:\\n *\\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\\n * - A voting module must implement {_getVotes}\\n * - Additionanly, the {votingPeriod} must also be implemented\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\\n using SafeCast for uint256;\\n using Timers for Timers.Timestamp;\\n\\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\\\"Ballot(uint256 proposalId,uint8 support)\\\");\\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\\n keccak256(\\\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\\\");\\n\\n struct ProposalCore {\\n Timers.Timestamp voteStart;\\n Timers.Timestamp voteEnd;\\n bool executed;\\n bool canceled;\\n }\\n\\n string private _name;\\n\\n mapping(uint256 => ProposalCore) private _proposals;\\n\\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\\n\\n /**\\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\\n * parameter setters in {GovernorSettings} are protected using this modifier.\\n *\\n * The governance executing address may be different from the Governor's own address, for example it could be a\\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\\n * for example, additional timelock proposers are not able to change governance parameters without going through the\\n * governance protocol (since v4.6).\\n */\\n modifier onlyGovernance() {\\n require(_msgSender() == _executor(), \\\"Governor: onlyGovernance\\\");\\n if (_executor() != address(this)) {\\n bytes32 msgDataHash = keccak256(_msgData());\\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\\n while (_governanceCall.popFront() != msgDataHash) {}\\n }\\n _;\\n }\\n\\n /**\\n * @dev Sets the value for {name} and {version}\\n */\\n constructor(string memory name_) EIP712(name_, version()) {\\n _name = name_;\\n }\\n\\n /**\\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\\n */\\n receive() external payable virtual {\\n require(_executor() == address(this));\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\\n // include the castVoteWithReasonAndParams() function as standard\\n return\\n interfaceId ==\\n (type(IGovernor).interfaceId ^\\n this.castVoteWithReasonAndParams.selector ^\\n this.castVoteWithReasonAndParamsBySig.selector ^\\n this.getVotesWithParams.selector) ||\\n interfaceId == type(IGovernor).interfaceId ||\\n interfaceId == type(IERC1155Receiver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IGovernor-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IGovernor-version}.\\n */\\n function version() public view virtual override returns (string memory) {\\n return \\\"1\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hashProposal}.\\n *\\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\\n * advance, before the proposal is submitted.\\n *\\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual override returns (uint256) {\\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\\n }\\n\\n /**\\n * @dev See {IGovernor-state}.\\n */\\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n\\n if (proposal.executed) {\\n return ProposalState.Executed;\\n }\\n\\n if (proposal.canceled) {\\n return ProposalState.Canceled;\\n }\\n\\n uint256 start = proposalSnapshot(proposalId);\\n\\n if (start == 0) {\\n revert(\\\"Governor: unknown proposal id\\\");\\n }\\n\\n if (start >= block.timestamp) {\\n return ProposalState.Pending;\\n }\\n\\n uint256 deadline = proposalDeadline(proposalId);\\n\\n if (deadline >= block.timestamp) {\\n return ProposalState.Active;\\n }\\n\\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\\n return ProposalState.Succeeded;\\n } else {\\n return ProposalState.Defeated;\\n }\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalSnapshot}.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteStart.getDeadline();\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalDeadline}.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteEnd.getDeadline();\\n }\\n\\n /**\\n * @dev Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\\n */\\n function proposalThreshold() public view virtual returns (uint256) {\\n return 0;\\n }\\n\\n /**\\n * @dev Amount of votes already cast passes the threshold limit.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Is the proposal successful or not.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) internal view virtual returns (uint256);\\n\\n /**\\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\\n *\\n * Note: Support is generic and can represent various things depending on the voting system used.\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory params\\n ) internal virtual;\\n\\n /**\\n * @dev Default additional encoded parameters used by castVote methods that don't include them\\n *\\n * Note: Should be overridden by specific implementations to use an appropriate value, the\\n * meaning of the additional params, in the context of that implementation\\n */\\n function _defaultParams() internal view virtual returns (bytes memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-propose}.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual override returns (uint256) {\\n require(\\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\\n \\\"Governor: proposer votes below proposal threshold\\\"\\n );\\n\\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\\n\\n require(targets.length == values.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length == calldatas.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length > 0, \\\"Governor: empty proposal\\\");\\n\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(proposal.voteStart.isUnset(), \\\"Governor: proposal already exists\\\");\\n\\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\\n uint64 deadline = start + votingPeriod().toUint64();\\n\\n proposal.voteStart.setDeadline(start);\\n proposal.voteEnd.setDeadline(deadline);\\n\\n emit ProposalCreated(\\n proposalId,\\n _msgSender(),\\n targets,\\n values,\\n new string[](targets.length),\\n calldatas,\\n start,\\n deadline,\\n description\\n );\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-execute}.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual override returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n\\n ProposalState status = state(proposalId);\\n require(\\n status == ProposalState.Succeeded || status == ProposalState.Queued,\\n \\\"Governor: proposal not successful\\\"\\n );\\n _proposals[proposalId].executed = true;\\n\\n emit ProposalExecuted(proposalId);\\n\\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\\n _execute(proposalId, targets, values, calldatas, descriptionHash);\\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\\n */\\n function _execute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n string memory errorMessage = \\\"Governor: call reverted without message\\\";\\n for (uint256 i = 0; i < targets.length; ++i) {\\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\\n Address.verifyCallResult(success, returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Hook before execution is triggered.\\n */\\n function _beforeExecute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory, /* values */\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n for (uint256 i = 0; i < targets.length; ++i) {\\n if (targets[i] == address(this)) {\\n _governanceCall.pushBack(keccak256(calldatas[i]));\\n }\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook after execution is triggered.\\n */\\n function _afterExecute(\\n uint256, /* proposalId */\\n address[] memory, /* targets */\\n uint256[] memory, /* values */\\n bytes[] memory, /* calldatas */\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n if (!_governanceCall.empty()) {\\n _governanceCall.clear();\\n }\\n }\\n }\\n\\n /**\\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\\n * canceled to allow distinguishing it from executed proposals.\\n *\\n * Emits a {IGovernor-ProposalCanceled} event.\\n */\\n function _cancel(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) internal virtual returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n ProposalState status = state(proposalId);\\n\\n require(\\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\\n \\\"Governor: proposal not active\\\"\\n );\\n _proposals[proposalId].canceled = true;\\n\\n emit ProposalCanceled(proposalId);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotes}.\\n */\\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, _defaultParams());\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotesWithParams}.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVote}.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReason}.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteBySig}.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\\n v,\\n r,\\n s\\n );\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(\\n keccak256(\\n abi.encode(\\n EXTENDED_BALLOT_TYPEHASH,\\n proposalId,\\n support,\\n keccak256(bytes(reason)),\\n keccak256(params)\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason\\n ) internal virtual returns (uint256) {\\n return _castVote(proposalId, account, support, reason, _defaultParams());\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason,\\n bytes memory params\\n ) internal virtual returns (uint256) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(state(proposalId) == ProposalState.Active, \\\"Governor: vote not currently active\\\");\\n\\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\\n _countVote(proposalId, account, support, weight, params);\\n\\n if (params.length == 0) {\\n emit VoteCast(account, proposalId, support, weight, reason);\\n } else {\\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\\n }\\n\\n return weight;\\n }\\n\\n /**\\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\\n */\\n function relay(\\n address target,\\n uint256 value,\\n bytes calldata data\\n ) external virtual onlyGovernance {\\n Address.functionCallWithValue(target, data, value);\\n }\\n\\n /**\\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\\n * through another contract such as a timelock.\\n */\\n function _executor() internal view virtual returns (address) {\\n return address(this);\\n }\\n\\n /**\\n * @dev See {IERC721Receiver-onERC721Received}.\\n */\\n function onERC721Received(\\n address,\\n address,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155Received}.\\n */\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\\n */\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] memory,\\n uint256[] memory,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155BatchReceived.selector;\\n }\\n}\\n\",\"keccak256\":\"0xa2846313b89a871807cdebd0225b0bf8f23b17505ab8b3288549ec54a5a4a71b\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorCountingSimple.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\\n *\\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorCountingSimple is L2Governor {\\n /**\\n * @dev Supported vote types. Matches Governor Bravo ordering.\\n */\\n enum VoteType {\\n Against,\\n For,\\n Abstain\\n }\\n\\n struct ProposalVote {\\n uint256 againstVotes;\\n uint256 forVotes;\\n uint256 abstainVotes;\\n mapping(address => bool) hasVoted;\\n }\\n\\n mapping(uint256 => ProposalVote) private _proposalVotes;\\n\\n /**\\n * @dev See {IGovernor-COUNTING_MODE}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual override returns (string memory) {\\n return \\\"support=bravo&quorum=for,abstain\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hasVoted}.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\\n return _proposalVotes[proposalId].hasVoted[account];\\n }\\n\\n /**\\n * @dev Accessor to the internal vote counts.\\n */\\n function proposalVotes(uint256 proposalId)\\n public\\n view\\n virtual\\n returns (\\n uint256 againstVotes,\\n uint256 forVotes,\\n uint256 abstainVotes\\n )\\n {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\\n }\\n\\n /**\\n * @dev See {Governor-_quorumReached}.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return proposalvote.forVotes > proposalvote.againstVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory // params\\n ) internal virtual override {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n require(!proposalvote.hasVoted[account], \\\"GovernorVotingSimple: vote already cast\\\");\\n proposalvote.hasVoted[account] = true;\\n\\n if (support == uint8(VoteType.Against)) {\\n proposalvote.againstVotes += weight;\\n } else if (support == uint8(VoteType.For)) {\\n proposalvote.forVotes += weight;\\n } else if (support == uint8(VoteType.Abstain)) {\\n proposalvote.abstainVotes += weight;\\n } else {\\n revert(\\\"GovernorVotingSimple: invalid value for enum VoteType\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xdc37daa24118a6e6ba5208b4abefa1632af2ff340135ca6c6d7237f70102d5db\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotes is L2Governor {\\n IVotes public immutable token;\\n\\n constructor(IVotes tokenAddress) {\\n token = tokenAddress;\\n }\\n\\n /**\\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory /*params*/\\n ) internal view virtual override returns (uint256) {\\n return token.getPastVotes(account, blockTimestamp);\\n }\\n}\\n\",\"keccak256\":\"0x605a7de71228dda3cb8fd878cac313a86bc5841fd34d7344214346ba46e63af1\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotesQuorumFraction.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\\n * fraction of the total supply.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\\n uint256 private _quorumNumerator;\\n\\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\\n\\n /**\\n * @dev Initialize quorum as a fraction of the token's total supply.\\n *\\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\\n * customized by overriding {quorumDenominator}.\\n */\\n constructor(uint256 quorumNumeratorValue) {\\n _updateQuorumNumerator(quorumNumeratorValue);\\n }\\n\\n /**\\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\\n */\\n function quorumNumerator() public view virtual returns (uint256) {\\n return _quorumNumerator;\\n }\\n\\n /**\\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\\n */\\n function quorumDenominator() public view virtual returns (uint256) {\\n return 100;\\n }\\n\\n /**\\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\\n */\\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - Must be called through a governance proposal.\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\\n _updateQuorumNumerator(newQuorumNumerator);\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\\n require(\\n newQuorumNumerator <= quorumDenominator(),\\n \\\"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\\\"\\n );\\n\\n uint256 oldQuorumNumerator = _quorumNumerator;\\n _quorumNumerator = newQuorumNumerator;\\n\\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\\n }\\n}\\n\",\"keccak256\":\"0xe66d29c0ffd2274de933d80e11d68891f3acc3f078be4560a2b493b7d88dcb7f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Interface of the {Governor} core.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract IGovernor is IERC165 {\\n enum ProposalState {\\n Pending,\\n Active,\\n Canceled,\\n Defeated,\\n Succeeded,\\n Queued,\\n Expired,\\n Executed\\n }\\n\\n /**\\n * @dev Emitted when a proposal is created.\\n */\\n event ProposalCreated(\\n uint256 proposalId,\\n address proposer,\\n address[] targets,\\n uint256[] values,\\n string[] signatures,\\n bytes[] calldatas,\\n uint256 startBlock,\\n uint256 endBlock,\\n string description\\n );\\n\\n /**\\n * @dev Emitted when a proposal is canceled.\\n */\\n event ProposalCanceled(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a proposal is executed.\\n */\\n event ProposalExecuted(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a vote is cast without params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n */\\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\\n\\n /**\\n * @dev Emitted when a vote is cast with params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\\n */\\n event VoteCastWithParams(\\n address indexed voter,\\n uint256 proposalId,\\n uint8 support,\\n uint256 weight,\\n string reason,\\n bytes params\\n );\\n\\n /**\\n * @notice module:core\\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\\n */\\n function name() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \\\"1\\\"\\n */\\n function version() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:voting\\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\\n *\\n * There are 2 standard keys: `support` and `quorum`.\\n *\\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\\n * - `quorum=bravo` means that only For votes are counted towards quorum.\\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\\n *\\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\\n * name that describes the behavior. For example:\\n *\\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\\n *\\n * NOTE: The string can be decoded by the standard\\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\\n * JavaScript class.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Current state of a proposal, following Compound's convention\\n */\\n function state(uint256 proposalId) public view virtual returns (ProposalState);\\n\\n /**\\n * @notice module:core\\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\\n * beginning of the following block.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\\n * during this block.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\\n */\\n function votingDelay() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of blocks, between the vote start and vote ends.\\n *\\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\\n * duration compared to the voting delay.\\n */\\n function votingPeriod() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Minimum number of cast voted required for a proposal to be successful.\\n *\\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\\n */\\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber`.\\n *\\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\\n * multiple), {ERC20Votes} tokens.\\n */\\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockNumber,\\n bytes memory params\\n ) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:voting\\n * @dev Returns whether `account` has cast a vote on `proposalId`.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\\n\\n /**\\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\\n * {IGovernor-votingPeriod} blocks after the voting starts.\\n *\\n * Emits a {ProposalCreated} event.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\\n * deadline to be reached.\\n *\\n * Emits a {ProposalExecuted} event.\\n *\\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Cast a vote\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xa52d593ff06a2353f78fa149da31f2ca94f03d1eff99bde41977fa2fe985a92f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2e53602b96c1bf97c731ed3e2a981b4f85e23a9410a5ebd36e549a4cc93340dc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x2626d8ab3dfdad0fad630c212ad146d59473d0f48b771784c61a7c1dbbea1f3f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Tooling for timepoints, timers and delays\\n */\\nlibrary Timers {\\n struct Timestamp {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(Timestamp storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(Timestamp memory timer) internal view returns (bool) {\\n return timer._deadline > block.timestamp;\\n }\\n\\n function isExpired(Timestamp memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.timestamp;\\n }\\n\\n struct BlockNumber {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(BlockNumber storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(BlockNumber memory timer) internal view returns (bool) {\\n return timer._deadline > block.number;\\n }\\n\\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.number;\\n }\\n}\\n\",\"keccak256\":\"0x29791a62950a7983e02a673639c1a781d1e448691800456c2ce4b99715391b14\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS,\\n InvalidSignatureV // Deprecated in v4.8\\n }\\n\\n function _throwError(RecoverError error) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert(\\\"ECDSA: invalid signature\\\");\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert(\\\"ECDSA: invalid signature 's' value\\\");\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature` or error string. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\\n if (signature.length == 65) {\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n /// @solidity memory-safe-assembly\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n return tryRecover(hash, v, r, s);\\n } else {\\n return (address(0), RecoverError.InvalidSignatureLength);\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, signature);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n *\\n * _Available since v4.2._\\n */\\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature);\\n }\\n\\n return (signer, RecoverError.NoError);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from `s`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", Strings.toString(s.length), s));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Typed Data, created from a\\n * `domainSeparator` and a `structHash`. This produces hash corresponding\\n * to the one signed with the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\\n * JSON-RPC method as part of EIP-712.\\n *\\n * See {recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n }\\n}\\n\",\"keccak256\":\"0x54ee424bfc83ce63b2a918b9a1efb5090a0fb68dbd1de3b10bc667776885dd4f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ECDSA.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n /* solhint-disable var-name-mixedcase */\\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n // invalidate the cached domain separator if the chain id changes.\\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n uint256 private immutable _CACHED_CHAIN_ID;\\n address private immutable _CACHED_THIS;\\n\\n bytes32 private immutable _HASHED_NAME;\\n bytes32 private immutable _HASHED_VERSION;\\n bytes32 private immutable _TYPE_HASH;\\n\\n /* solhint-enable var-name-mixedcase */\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n constructor(string memory name, string memory version) {\\n bytes32 hashedName = keccak256(bytes(name));\\n bytes32 hashedVersion = keccak256(bytes(version));\\n bytes32 typeHash = keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n );\\n _HASHED_NAME = hashedName;\\n _HASHED_VERSION = hashedVersion;\\n _CACHED_CHAIN_ID = block.chainid;\\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n _CACHED_THIS = address(this);\\n _TYPE_HASH = typeHash;\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\\n return _CACHED_DOMAIN_SEPARATOR;\\n } else {\\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n }\\n }\\n\\n function _buildDomainSeparator(\\n bytes32 typeHash,\\n bytes32 nameHash,\\n bytes32 versionHash\\n ) private view returns (bytes32) {\\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\\n }\\n}\\n\",\"keccak256\":\"0x948d8b2d18f38141ec78c5229d770d950ebc781ed3f44cc9e3ccbb9fded5846a\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\\n\\nimport \\\"./EIP712.sol\\\";\\n\",\"keccak256\":\"0xea30c402170bc240354b74e6c6f6a8e5bdb1935d90d168cc58c0654461c6a72b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3546b156d97633f7f8cad536d5454c81d1d604687c02b2eb105fdc33cb962b41\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\\npragma solidity ^0.8.4;\\n\\nimport \\\"../math/SafeCast.sol\\\";\\n\\n/**\\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\\n * the existing queue contents are left in storage.\\n *\\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\\n * used in storage, and not in memory.\\n * ```\\n * DoubleEndedQueue.Bytes32Deque queue;\\n * ```\\n *\\n * _Available since v4.6._\\n */\\nlibrary DoubleEndedQueue {\\n /**\\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\\n */\\n error Empty();\\n\\n /**\\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\\n */\\n error OutOfBounds();\\n\\n /**\\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\\n *\\n * Struct members have an underscore prefix indicating that they are \\\"private\\\" and should not be read or written to\\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\\n * lead to unexpected behavior.\\n *\\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\\n * data[end - 1].\\n */\\n struct Bytes32Deque {\\n int128 _begin;\\n int128 _end;\\n mapping(int128 => bytes32) _data;\\n }\\n\\n /**\\n * @dev Inserts an item at the end of the queue.\\n */\\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 backIndex = deque._end;\\n deque._data[backIndex] = value;\\n unchecked {\\n deque._end = backIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Removes the item at the end of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n value = deque._data[backIndex];\\n delete deque._data[backIndex];\\n deque._end = backIndex;\\n }\\n\\n /**\\n * @dev Inserts an item at the beginning of the queue.\\n */\\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 frontIndex;\\n unchecked {\\n frontIndex = deque._begin - 1;\\n }\\n deque._data[frontIndex] = value;\\n deque._begin = frontIndex;\\n }\\n\\n /**\\n * @dev Removes the item at the beginning of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n value = deque._data[frontIndex];\\n delete deque._data[frontIndex];\\n unchecked {\\n deque._begin = frontIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Returns the item at the beginning of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n return deque._data[frontIndex];\\n }\\n\\n /**\\n * @dev Returns the item at the end of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n return deque._data[backIndex];\\n }\\n\\n /**\\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\\n * `length(deque) - 1`.\\n *\\n * Reverts with `OutOfBounds` if the index is out of bounds.\\n */\\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\\n // int256(deque._begin) is a safe upcast\\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\\n if (idx >= deque._end) revert OutOfBounds();\\n return deque._data[idx];\\n }\\n\\n /**\\n * @dev Resets the queue back to being empty.\\n *\\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\\n * out on potential gas refunds.\\n */\\n function clear(Bytes32Deque storage deque) internal {\\n deque._begin = 0;\\n deque._end = 0;\\n }\\n\\n /**\\n * @dev Returns the number of items in the queue.\\n */\\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\\n // We also assume there are at most int256.max items in the queue.\\n unchecked {\\n return uint256(int256(deque._end) - int256(deque._begin));\\n }\\n }\\n\\n /**\\n * @dev Returns true if the queue is empty.\\n */\\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\\n return deque._end <= deque._begin;\\n }\\n}\\n\",\"keccak256\":\"0x4859ffd6dd69382a1462930c00b6e394007da80e78e510f56930271034737bf2\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x61016060405260026007553480156200001757600080fd5b506040516200328f3803806200328f8339810160408190526200003a91620002e1565b600481604051806040016040528060128152602001712b32b637b23937b6b29023b7bb32b93737b960711b81525080620000796200015360201b60201c565b815160208084019190912082518383012060e08290526101008190524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81880181905281830187905260608201869052608082019490945230818401528151808203909301835260c00190528051940193909320919290916080523060c05261012052505082516200011f92506000915060208401906200023b565b50506001600160a01b03166101405262000139816200016e565b5050600680546001600160a01b031916331790556200034f565b6040805180820190915260018152603160f81b602082015290565b6064811115620001f65760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a40160405180910390fd5b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b828054620002499062000313565b90600052602060002090601f0160209004810192826200026d5760008555620002b8565b82601f106200028857805160ff1916838001178555620002b8565b82800160010185558215620002b8579182015b82811115620002b85782518255916020019190600101906200029b565b50620002c6929150620002ca565b5090565b5b80821115620002c65760008155600101620002cb565b600060208284031215620002f457600080fd5b81516001600160a01b03811681146200030c57600080fd5b9392505050565b600181811c908216806200032857607f821691505b6020821081036200034957634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e051610100516101205161014051612ed0620003bf600039600081816107df0152818161120f015281816113e40152611a0601526000611b2301526000611b7201526000611b4d01526000611aa601526000611ad001526000611afa0152612ed06000f3fe6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220119f957513c875b695417363f9b7062f502d1257a648dd454afcc82247be7f3f64736f6c634300080d0033", - "deployedBytecode": "0x6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220119f957513c875b695417363f9b7062f502d1257a648dd454afcc82247be7f3f64736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"_ve\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"Empty\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"proposer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"string[]\",\"name\":\"signatures\",\"type\":\"string[]\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"ProposalCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldQuorumNumerator\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"QuorumNumeratorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"VoteCast\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"VoteCastWithParams\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"COUNTING_MODE\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EXTENDED_BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_PROPOSAL_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROPOSAL_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"}],\"name\":\"castVote\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"castVoteWithReason\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"castVoteWithReasonAndParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteWithReasonAndParamsBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"execute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"getVotesWithParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasVoted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"hashProposal\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalDeadline\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalSnapshot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"againstVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"forVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"abstainVotes\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"propose\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"quorum\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumDenominator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"}],\"name\":\"setProposalNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTeam\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"state\",\"outputs\":[{\"internalType\":\"enum IGovernor.ProposalState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"updateQuorumNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"Empty()\":[{\"details\":\"An operation (e.g. {front}) couldn't be completed due to the queue being empty.\"}]},\"kind\":\"dev\",\"methods\":{\"COUNTING_MODE()\":{\"details\":\"See {IGovernor-COUNTING_MODE}.\"},\"castVote(uint256,uint8)\":{\"details\":\"See {IGovernor-castVote}.\"},\"castVoteBySig(uint256,uint8,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteBySig}.\"},\"castVoteWithReason(uint256,uint8,string)\":{\"details\":\"See {IGovernor-castVoteWithReason}.\"},\"castVoteWithReasonAndParams(uint256,uint8,string,bytes)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParams}.\"},\"castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParamsBySig}.\"},\"execute(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-execute}.\"},\"getVotes(address,uint256)\":{\"details\":\"See {IGovernor-getVotes}.\"},\"getVotesWithParams(address,uint256,bytes)\":{\"details\":\"See {IGovernor-getVotesWithParams}.\"},\"hasVoted(uint256,address)\":{\"details\":\"See {IGovernor-hasVoted}.\"},\"hashProposal(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-hashProposal}. The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in advance, before the proposal is submitted. Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the same proposal (with same operation and same description) will have the same id if submitted on multiple governors across multiple networks. This also means that in order to execute the same operation twice (on the same governor) the proposer will have to change the description in order to avoid proposal id conflicts.\"},\"name()\":{\"details\":\"See {IGovernor-name}.\"},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155BatchReceived}.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155Received}.\"},\"onERC721Received(address,address,uint256,bytes)\":{\"details\":\"See {IERC721Receiver-onERC721Received}.\"},\"proposalDeadline(uint256)\":{\"details\":\"See {IGovernor-proposalDeadline}.\"},\"proposalSnapshot(uint256)\":{\"details\":\"See {IGovernor-proposalSnapshot}.\"},\"proposalThreshold()\":{\"details\":\"Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\"},\"proposalVotes(uint256)\":{\"details\":\"Accessor to the internal vote counts.\"},\"propose(address[],uint256[],bytes[],string)\":{\"details\":\"See {IGovernor-propose}.\"},\"quorum(uint256)\":{\"details\":\"Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\"},\"quorumDenominator()\":{\"details\":\"Returns the quorum denominator. Defaults to 100, but may be overridden.\"},\"quorumNumerator()\":{\"details\":\"Returns the current quorum numerator. See {quorumDenominator}.\"},\"relay(address,uint256,bytes)\":{\"details\":\"Relays a transaction or function call to an arbitrary target. In cases where the governance executor is some contract other than the governor itself, like when using a timelock, this function can be invoked in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake. Note that if the executor is simply the governor itself, use of `relay` is redundant.\"},\"state(uint256)\":{\"details\":\"See {IGovernor-state}.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"updateQuorumNumerator(uint256)\":{\"details\":\"Changes the quorum numerator. Emits a {QuorumNumeratorUpdated} event. Requirements: - Must be called through a governance proposal. - New numerator must be smaller or equal to the denominator.\"},\"version()\":{\"details\":\"See {IGovernor-version}.\"},\"votingDelay()\":{\"details\":\"Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\"},\"votingPeriod()\":{\"details\":\"Delay, in number of blocks, between the vote start and vote ends. NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting duration compared to the voting delay.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"votingDelay()\":{\"notice\":\"module:user-config\"},\"votingPeriod()\":{\"notice\":\"module:user-config\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/FlowGovernor.sol\":\"VeloGovernor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/FlowGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IGovernor} from \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\nimport {L2GovernorCountingSimple} from \\\"contracts/governance/L2GovernorCountingSimple.sol\\\";\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\nimport {L2GovernorVotesQuorumFraction} from \\\"contracts/governance/L2GovernorVotesQuorumFraction.sol\\\";\\n\\ncontract VeloGovernor is\\n L2Governor,\\n L2GovernorCountingSimple,\\n L2GovernorVotes,\\n L2GovernorVotesQuorumFraction\\n{\\n address public team;\\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\\n uint256 public proposalNumerator = 2; // start at 0.02%\\n\\n constructor(IVotes _ve)\\n L2Governor(\\\"Velocimeter Governor\\\")\\n L2GovernorVotes(_ve)\\n L2GovernorVotesQuorumFraction(4) // 4%\\n {\\n team = msg.sender;\\n }\\n\\n function votingDelay() public pure override(IGovernor) returns (uint256) {\\n return 15 minutes; // 1 block\\n }\\n\\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\\n return 1 weeks;\\n }\\n\\n function setTeam(address newTeam) external {\\n require(msg.sender == team, \\\"not team\\\");\\n team = newTeam;\\n }\\n\\n function setProposalNumerator(uint256 numerator) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \\\"numerator too high\\\");\\n proposalNumerator = numerator;\\n }\\n\\n function proposalThreshold()\\n public\\n view\\n override(L2Governor)\\n returns (uint256)\\n {\\n return\\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\\n PROPOSAL_DENOMINATOR;\\n }\\n}\\n\",\"keccak256\":\"0x0386aabd5b5db4aee3d584995ec6e3546dbfdcd2c9006c125918bcfd2d496020\",\"license\":\"MIT\"},\"contracts/governance/L2Governor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Address.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Context.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\\n *\\n * @dev Core of the governance system, designed to be extended though various modules.\\n *\\n * This contract is abstract and requires several function to be implemented in various modules:\\n *\\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\\n * - A voting module must implement {_getVotes}\\n * - Additionanly, the {votingPeriod} must also be implemented\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\\n using SafeCast for uint256;\\n using Timers for Timers.Timestamp;\\n\\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\\\"Ballot(uint256 proposalId,uint8 support)\\\");\\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\\n keccak256(\\\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\\\");\\n\\n struct ProposalCore {\\n Timers.Timestamp voteStart;\\n Timers.Timestamp voteEnd;\\n bool executed;\\n bool canceled;\\n }\\n\\n string private _name;\\n\\n mapping(uint256 => ProposalCore) private _proposals;\\n\\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\\n\\n /**\\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\\n * parameter setters in {GovernorSettings} are protected using this modifier.\\n *\\n * The governance executing address may be different from the Governor's own address, for example it could be a\\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\\n * for example, additional timelock proposers are not able to change governance parameters without going through the\\n * governance protocol (since v4.6).\\n */\\n modifier onlyGovernance() {\\n require(_msgSender() == _executor(), \\\"Governor: onlyGovernance\\\");\\n if (_executor() != address(this)) {\\n bytes32 msgDataHash = keccak256(_msgData());\\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\\n while (_governanceCall.popFront() != msgDataHash) {}\\n }\\n _;\\n }\\n\\n /**\\n * @dev Sets the value for {name} and {version}\\n */\\n constructor(string memory name_) EIP712(name_, version()) {\\n _name = name_;\\n }\\n\\n /**\\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\\n */\\n receive() external payable virtual {\\n require(_executor() == address(this));\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\\n // include the castVoteWithReasonAndParams() function as standard\\n return\\n interfaceId ==\\n (type(IGovernor).interfaceId ^\\n this.castVoteWithReasonAndParams.selector ^\\n this.castVoteWithReasonAndParamsBySig.selector ^\\n this.getVotesWithParams.selector) ||\\n interfaceId == type(IGovernor).interfaceId ||\\n interfaceId == type(IERC1155Receiver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IGovernor-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IGovernor-version}.\\n */\\n function version() public view virtual override returns (string memory) {\\n return \\\"1\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hashProposal}.\\n *\\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\\n * advance, before the proposal is submitted.\\n *\\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual override returns (uint256) {\\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\\n }\\n\\n /**\\n * @dev See {IGovernor-state}.\\n */\\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n\\n if (proposal.executed) {\\n return ProposalState.Executed;\\n }\\n\\n if (proposal.canceled) {\\n return ProposalState.Canceled;\\n }\\n\\n uint256 start = proposalSnapshot(proposalId);\\n\\n if (start == 0) {\\n revert(\\\"Governor: unknown proposal id\\\");\\n }\\n\\n if (start >= block.timestamp) {\\n return ProposalState.Pending;\\n }\\n\\n uint256 deadline = proposalDeadline(proposalId);\\n\\n if (deadline >= block.timestamp) {\\n return ProposalState.Active;\\n }\\n\\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\\n return ProposalState.Succeeded;\\n } else {\\n return ProposalState.Defeated;\\n }\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalSnapshot}.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteStart.getDeadline();\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalDeadline}.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteEnd.getDeadline();\\n }\\n\\n /**\\n * @dev Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\\n */\\n function proposalThreshold() public view virtual returns (uint256) {\\n return 0;\\n }\\n\\n /**\\n * @dev Amount of votes already cast passes the threshold limit.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Is the proposal successful or not.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) internal view virtual returns (uint256);\\n\\n /**\\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\\n *\\n * Note: Support is generic and can represent various things depending on the voting system used.\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory params\\n ) internal virtual;\\n\\n /**\\n * @dev Default additional encoded parameters used by castVote methods that don't include them\\n *\\n * Note: Should be overridden by specific implementations to use an appropriate value, the\\n * meaning of the additional params, in the context of that implementation\\n */\\n function _defaultParams() internal view virtual returns (bytes memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-propose}.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual override returns (uint256) {\\n require(\\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\\n \\\"Governor: proposer votes below proposal threshold\\\"\\n );\\n\\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\\n\\n require(targets.length == values.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length == calldatas.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length > 0, \\\"Governor: empty proposal\\\");\\n\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(proposal.voteStart.isUnset(), \\\"Governor: proposal already exists\\\");\\n\\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\\n uint64 deadline = start + votingPeriod().toUint64();\\n\\n proposal.voteStart.setDeadline(start);\\n proposal.voteEnd.setDeadline(deadline);\\n\\n emit ProposalCreated(\\n proposalId,\\n _msgSender(),\\n targets,\\n values,\\n new string[](targets.length),\\n calldatas,\\n start,\\n deadline,\\n description\\n );\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-execute}.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual override returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n\\n ProposalState status = state(proposalId);\\n require(\\n status == ProposalState.Succeeded || status == ProposalState.Queued,\\n \\\"Governor: proposal not successful\\\"\\n );\\n _proposals[proposalId].executed = true;\\n\\n emit ProposalExecuted(proposalId);\\n\\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\\n _execute(proposalId, targets, values, calldatas, descriptionHash);\\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\\n */\\n function _execute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n string memory errorMessage = \\\"Governor: call reverted without message\\\";\\n for (uint256 i = 0; i < targets.length; ++i) {\\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\\n Address.verifyCallResult(success, returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Hook before execution is triggered.\\n */\\n function _beforeExecute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory, /* values */\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n for (uint256 i = 0; i < targets.length; ++i) {\\n if (targets[i] == address(this)) {\\n _governanceCall.pushBack(keccak256(calldatas[i]));\\n }\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook after execution is triggered.\\n */\\n function _afterExecute(\\n uint256, /* proposalId */\\n address[] memory, /* targets */\\n uint256[] memory, /* values */\\n bytes[] memory, /* calldatas */\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n if (!_governanceCall.empty()) {\\n _governanceCall.clear();\\n }\\n }\\n }\\n\\n /**\\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\\n * canceled to allow distinguishing it from executed proposals.\\n *\\n * Emits a {IGovernor-ProposalCanceled} event.\\n */\\n function _cancel(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) internal virtual returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n ProposalState status = state(proposalId);\\n\\n require(\\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\\n \\\"Governor: proposal not active\\\"\\n );\\n _proposals[proposalId].canceled = true;\\n\\n emit ProposalCanceled(proposalId);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotes}.\\n */\\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, _defaultParams());\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotesWithParams}.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVote}.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReason}.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteBySig}.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\\n v,\\n r,\\n s\\n );\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(\\n keccak256(\\n abi.encode(\\n EXTENDED_BALLOT_TYPEHASH,\\n proposalId,\\n support,\\n keccak256(bytes(reason)),\\n keccak256(params)\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason\\n ) internal virtual returns (uint256) {\\n return _castVote(proposalId, account, support, reason, _defaultParams());\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason,\\n bytes memory params\\n ) internal virtual returns (uint256) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(state(proposalId) == ProposalState.Active, \\\"Governor: vote not currently active\\\");\\n\\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\\n _countVote(proposalId, account, support, weight, params);\\n\\n if (params.length == 0) {\\n emit VoteCast(account, proposalId, support, weight, reason);\\n } else {\\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\\n }\\n\\n return weight;\\n }\\n\\n /**\\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\\n */\\n function relay(\\n address target,\\n uint256 value,\\n bytes calldata data\\n ) external virtual onlyGovernance {\\n Address.functionCallWithValue(target, data, value);\\n }\\n\\n /**\\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\\n * through another contract such as a timelock.\\n */\\n function _executor() internal view virtual returns (address) {\\n return address(this);\\n }\\n\\n /**\\n * @dev See {IERC721Receiver-onERC721Received}.\\n */\\n function onERC721Received(\\n address,\\n address,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155Received}.\\n */\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\\n */\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] memory,\\n uint256[] memory,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155BatchReceived.selector;\\n }\\n}\\n\",\"keccak256\":\"0xa2846313b89a871807cdebd0225b0bf8f23b17505ab8b3288549ec54a5a4a71b\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorCountingSimple.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\\n *\\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorCountingSimple is L2Governor {\\n /**\\n * @dev Supported vote types. Matches Governor Bravo ordering.\\n */\\n enum VoteType {\\n Against,\\n For,\\n Abstain\\n }\\n\\n struct ProposalVote {\\n uint256 againstVotes;\\n uint256 forVotes;\\n uint256 abstainVotes;\\n mapping(address => bool) hasVoted;\\n }\\n\\n mapping(uint256 => ProposalVote) private _proposalVotes;\\n\\n /**\\n * @dev See {IGovernor-COUNTING_MODE}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual override returns (string memory) {\\n return \\\"support=bravo&quorum=for,abstain\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hasVoted}.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\\n return _proposalVotes[proposalId].hasVoted[account];\\n }\\n\\n /**\\n * @dev Accessor to the internal vote counts.\\n */\\n function proposalVotes(uint256 proposalId)\\n public\\n view\\n virtual\\n returns (\\n uint256 againstVotes,\\n uint256 forVotes,\\n uint256 abstainVotes\\n )\\n {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\\n }\\n\\n /**\\n * @dev See {Governor-_quorumReached}.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return proposalvote.forVotes > proposalvote.againstVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory // params\\n ) internal virtual override {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n require(!proposalvote.hasVoted[account], \\\"GovernorVotingSimple: vote already cast\\\");\\n proposalvote.hasVoted[account] = true;\\n\\n if (support == uint8(VoteType.Against)) {\\n proposalvote.againstVotes += weight;\\n } else if (support == uint8(VoteType.For)) {\\n proposalvote.forVotes += weight;\\n } else if (support == uint8(VoteType.Abstain)) {\\n proposalvote.abstainVotes += weight;\\n } else {\\n revert(\\\"GovernorVotingSimple: invalid value for enum VoteType\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xdc37daa24118a6e6ba5208b4abefa1632af2ff340135ca6c6d7237f70102d5db\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotes is L2Governor {\\n IVotes public immutable token;\\n\\n constructor(IVotes tokenAddress) {\\n token = tokenAddress;\\n }\\n\\n /**\\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory /*params*/\\n ) internal view virtual override returns (uint256) {\\n return token.getPastVotes(account, blockTimestamp);\\n }\\n}\\n\",\"keccak256\":\"0x605a7de71228dda3cb8fd878cac313a86bc5841fd34d7344214346ba46e63af1\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotesQuorumFraction.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\\n * fraction of the total supply.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\\n uint256 private _quorumNumerator;\\n\\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\\n\\n /**\\n * @dev Initialize quorum as a fraction of the token's total supply.\\n *\\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\\n * customized by overriding {quorumDenominator}.\\n */\\n constructor(uint256 quorumNumeratorValue) {\\n _updateQuorumNumerator(quorumNumeratorValue);\\n }\\n\\n /**\\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\\n */\\n function quorumNumerator() public view virtual returns (uint256) {\\n return _quorumNumerator;\\n }\\n\\n /**\\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\\n */\\n function quorumDenominator() public view virtual returns (uint256) {\\n return 100;\\n }\\n\\n /**\\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\\n */\\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - Must be called through a governance proposal.\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\\n _updateQuorumNumerator(newQuorumNumerator);\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\\n require(\\n newQuorumNumerator <= quorumDenominator(),\\n \\\"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\\\"\\n );\\n\\n uint256 oldQuorumNumerator = _quorumNumerator;\\n _quorumNumerator = newQuorumNumerator;\\n\\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\\n }\\n}\\n\",\"keccak256\":\"0xe66d29c0ffd2274de933d80e11d68891f3acc3f078be4560a2b493b7d88dcb7f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Interface of the {Governor} core.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract IGovernor is IERC165 {\\n enum ProposalState {\\n Pending,\\n Active,\\n Canceled,\\n Defeated,\\n Succeeded,\\n Queued,\\n Expired,\\n Executed\\n }\\n\\n /**\\n * @dev Emitted when a proposal is created.\\n */\\n event ProposalCreated(\\n uint256 proposalId,\\n address proposer,\\n address[] targets,\\n uint256[] values,\\n string[] signatures,\\n bytes[] calldatas,\\n uint256 startBlock,\\n uint256 endBlock,\\n string description\\n );\\n\\n /**\\n * @dev Emitted when a proposal is canceled.\\n */\\n event ProposalCanceled(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a proposal is executed.\\n */\\n event ProposalExecuted(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a vote is cast without params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n */\\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\\n\\n /**\\n * @dev Emitted when a vote is cast with params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\\n */\\n event VoteCastWithParams(\\n address indexed voter,\\n uint256 proposalId,\\n uint8 support,\\n uint256 weight,\\n string reason,\\n bytes params\\n );\\n\\n /**\\n * @notice module:core\\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\\n */\\n function name() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \\\"1\\\"\\n */\\n function version() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:voting\\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\\n *\\n * There are 2 standard keys: `support` and `quorum`.\\n *\\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\\n * - `quorum=bravo` means that only For votes are counted towards quorum.\\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\\n *\\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\\n * name that describes the behavior. For example:\\n *\\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\\n *\\n * NOTE: The string can be decoded by the standard\\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\\n * JavaScript class.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Current state of a proposal, following Compound's convention\\n */\\n function state(uint256 proposalId) public view virtual returns (ProposalState);\\n\\n /**\\n * @notice module:core\\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\\n * beginning of the following block.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\\n * during this block.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\\n */\\n function votingDelay() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of blocks, between the vote start and vote ends.\\n *\\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\\n * duration compared to the voting delay.\\n */\\n function votingPeriod() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Minimum number of cast voted required for a proposal to be successful.\\n *\\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\\n */\\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber`.\\n *\\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\\n * multiple), {ERC20Votes} tokens.\\n */\\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockNumber,\\n bytes memory params\\n ) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:voting\\n * @dev Returns whether `account` has cast a vote on `proposalId`.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\\n\\n /**\\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\\n * {IGovernor-votingPeriod} blocks after the voting starts.\\n *\\n * Emits a {ProposalCreated} event.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\\n * deadline to be reached.\\n *\\n * Emits a {ProposalExecuted} event.\\n *\\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Cast a vote\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xa52d593ff06a2353f78fa149da31f2ca94f03d1eff99bde41977fa2fe985a92f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2e53602b96c1bf97c731ed3e2a981b4f85e23a9410a5ebd36e549a4cc93340dc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x2626d8ab3dfdad0fad630c212ad146d59473d0f48b771784c61a7c1dbbea1f3f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Tooling for timepoints, timers and delays\\n */\\nlibrary Timers {\\n struct Timestamp {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(Timestamp storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(Timestamp memory timer) internal view returns (bool) {\\n return timer._deadline > block.timestamp;\\n }\\n\\n function isExpired(Timestamp memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.timestamp;\\n }\\n\\n struct BlockNumber {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(BlockNumber storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(BlockNumber memory timer) internal view returns (bool) {\\n return timer._deadline > block.number;\\n }\\n\\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.number;\\n }\\n}\\n\",\"keccak256\":\"0x29791a62950a7983e02a673639c1a781d1e448691800456c2ce4b99715391b14\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS,\\n InvalidSignatureV // Deprecated in v4.8\\n }\\n\\n function _throwError(RecoverError error) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert(\\\"ECDSA: invalid signature\\\");\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert(\\\"ECDSA: invalid signature 's' value\\\");\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature` or error string. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\\n if (signature.length == 65) {\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n /// @solidity memory-safe-assembly\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n return tryRecover(hash, v, r, s);\\n } else {\\n return (address(0), RecoverError.InvalidSignatureLength);\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, signature);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n *\\n * _Available since v4.2._\\n */\\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature);\\n }\\n\\n return (signer, RecoverError.NoError);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from `s`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", Strings.toString(s.length), s));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Typed Data, created from a\\n * `domainSeparator` and a `structHash`. This produces hash corresponding\\n * to the one signed with the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\\n * JSON-RPC method as part of EIP-712.\\n *\\n * See {recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n }\\n}\\n\",\"keccak256\":\"0x54ee424bfc83ce63b2a918b9a1efb5090a0fb68dbd1de3b10bc667776885dd4f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ECDSA.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n /* solhint-disable var-name-mixedcase */\\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n // invalidate the cached domain separator if the chain id changes.\\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n uint256 private immutable _CACHED_CHAIN_ID;\\n address private immutable _CACHED_THIS;\\n\\n bytes32 private immutable _HASHED_NAME;\\n bytes32 private immutable _HASHED_VERSION;\\n bytes32 private immutable _TYPE_HASH;\\n\\n /* solhint-enable var-name-mixedcase */\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n constructor(string memory name, string memory version) {\\n bytes32 hashedName = keccak256(bytes(name));\\n bytes32 hashedVersion = keccak256(bytes(version));\\n bytes32 typeHash = keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n );\\n _HASHED_NAME = hashedName;\\n _HASHED_VERSION = hashedVersion;\\n _CACHED_CHAIN_ID = block.chainid;\\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n _CACHED_THIS = address(this);\\n _TYPE_HASH = typeHash;\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\\n return _CACHED_DOMAIN_SEPARATOR;\\n } else {\\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n }\\n }\\n\\n function _buildDomainSeparator(\\n bytes32 typeHash,\\n bytes32 nameHash,\\n bytes32 versionHash\\n ) private view returns (bytes32) {\\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\\n }\\n}\\n\",\"keccak256\":\"0x948d8b2d18f38141ec78c5229d770d950ebc781ed3f44cc9e3ccbb9fded5846a\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\\n\\nimport \\\"./EIP712.sol\\\";\\n\",\"keccak256\":\"0xea30c402170bc240354b74e6c6f6a8e5bdb1935d90d168cc58c0654461c6a72b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3546b156d97633f7f8cad536d5454c81d1d604687c02b2eb105fdc33cb962b41\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\\npragma solidity ^0.8.4;\\n\\nimport \\\"../math/SafeCast.sol\\\";\\n\\n/**\\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\\n * the existing queue contents are left in storage.\\n *\\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\\n * used in storage, and not in memory.\\n * ```\\n * DoubleEndedQueue.Bytes32Deque queue;\\n * ```\\n *\\n * _Available since v4.6._\\n */\\nlibrary DoubleEndedQueue {\\n /**\\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\\n */\\n error Empty();\\n\\n /**\\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\\n */\\n error OutOfBounds();\\n\\n /**\\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\\n *\\n * Struct members have an underscore prefix indicating that they are \\\"private\\\" and should not be read or written to\\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\\n * lead to unexpected behavior.\\n *\\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\\n * data[end - 1].\\n */\\n struct Bytes32Deque {\\n int128 _begin;\\n int128 _end;\\n mapping(int128 => bytes32) _data;\\n }\\n\\n /**\\n * @dev Inserts an item at the end of the queue.\\n */\\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 backIndex = deque._end;\\n deque._data[backIndex] = value;\\n unchecked {\\n deque._end = backIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Removes the item at the end of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n value = deque._data[backIndex];\\n delete deque._data[backIndex];\\n deque._end = backIndex;\\n }\\n\\n /**\\n * @dev Inserts an item at the beginning of the queue.\\n */\\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 frontIndex;\\n unchecked {\\n frontIndex = deque._begin - 1;\\n }\\n deque._data[frontIndex] = value;\\n deque._begin = frontIndex;\\n }\\n\\n /**\\n * @dev Removes the item at the beginning of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n value = deque._data[frontIndex];\\n delete deque._data[frontIndex];\\n unchecked {\\n deque._begin = frontIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Returns the item at the beginning of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n return deque._data[frontIndex];\\n }\\n\\n /**\\n * @dev Returns the item at the end of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n return deque._data[backIndex];\\n }\\n\\n /**\\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\\n * `length(deque) - 1`.\\n *\\n * Reverts with `OutOfBounds` if the index is out of bounds.\\n */\\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\\n // int256(deque._begin) is a safe upcast\\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\\n if (idx >= deque._end) revert OutOfBounds();\\n return deque._data[idx];\\n }\\n\\n /**\\n * @dev Resets the queue back to being empty.\\n *\\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\\n * out on potential gas refunds.\\n */\\n function clear(Bytes32Deque storage deque) internal {\\n deque._begin = 0;\\n deque._end = 0;\\n }\\n\\n /**\\n * @dev Returns the number of items in the queue.\\n */\\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\\n // We also assume there are at most int256.max items in the queue.\\n unchecked {\\n return uint256(int256(deque._end) - int256(deque._begin));\\n }\\n }\\n\\n /**\\n * @dev Returns true if the queue is empty.\\n */\\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\\n return deque._end <= deque._begin;\\n }\\n}\\n\",\"keccak256\":\"0x4859ffd6dd69382a1462930c00b6e394007da80e78e510f56930271034737bf2\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x61016060405260026007553480156200001757600080fd5b506040516200329a3803806200329a8339810160408190526200003a91620002ec565b6004816040518060400160405280601481526020017f56656c6f63696d6574657220476f7665726e6f7200000000000000000000000081525080620000846200015e60201b60201c565b815160208084019190912082518383012060e08290526101008190524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81880181905281830187905260608201869052608082019490945230818401528151808203909301835260c00190528051940193909320919290916080523060c05261012052505082516200012a925060009150602084019062000246565b50506001600160a01b031661014052620001448162000179565b5050600680546001600160a01b031916331790556200035a565b6040805180820190915260018152603160f81b602082015290565b6064811115620002015760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a40160405180910390fd5b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b82805462000254906200031e565b90600052602060002090601f016020900481019282620002785760008555620002c3565b82601f106200029357805160ff1916838001178555620002c3565b82800160010185558215620002c3579182015b82811115620002c3578251825591602001919060010190620002a6565b50620002d1929150620002d5565b5090565b5b80821115620002d15760008155600101620002d6565b600060208284031215620002ff57600080fd5b81516001600160a01b03811681146200031757600080fd5b9392505050565b600181811c908216806200033357607f821691505b6020821081036200035457634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e051610100516101205161014051612ed0620003ca600039600081816107df0152818161120f015281816113e40152611a0601526000611b2301526000611b7201526000611b4d01526000611aa601526000611ad001526000611afa0152612ed06000f3fe6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a264697066735822122077c95b1c95819f79104e702c1ed3b671348a3db770c4a3cdd65fea31281584db64736f6c634300080d0033", + "deployedBytecode": "0x6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a264697066735822122077c95b1c95819f79104e702c1ed3b671348a3db770c4a3cdd65fea31281584db64736f6c634300080d0033", "devdoc": { "errors": { "Empty()": [ @@ -1211,7 +1211,7 @@ "storage": [ { "astId": 21935, - "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "contract": "contracts/FlowGovernor.sol:VeloGovernor", "label": "_name", "offset": 0, "slot": "0", @@ -1219,7 +1219,7 @@ }, { "astId": 21940, - "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "contract": "contracts/FlowGovernor.sol:VeloGovernor", "label": "_proposals", "offset": 0, "slot": "1", @@ -1227,7 +1227,7 @@ }, { "astId": 21943, - "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "contract": "contracts/FlowGovernor.sol:VeloGovernor", "label": "_governanceCall", "offset": 0, "slot": "2", @@ -1235,7 +1235,7 @@ }, { "astId": 23199, - "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "contract": "contracts/FlowGovernor.sol:VeloGovernor", "label": "_proposalVotes", "offset": 0, "slot": "4", @@ -1243,23 +1243,23 @@ }, { "astId": 23452, - "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "contract": "contracts/FlowGovernor.sol:VeloGovernor", "label": "_quorumNumerator", "offset": 0, "slot": "5", "type": "t_uint256" }, { - "astId": 13423, - "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "astId": 1704, + "contract": "contracts/FlowGovernor.sol:VeloGovernor", "label": "team", "offset": 0, "slot": "6", "type": "t_address" }, { - "astId": 13432, - "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "astId": 1713, + "contract": "contracts/FlowGovernor.sol:VeloGovernor", "label": "proposalNumerator", "offset": 0, "slot": "7", @@ -1326,7 +1326,7 @@ "members": [ { "astId": 30240, - "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "contract": "contracts/FlowGovernor.sol:VeloGovernor", "label": "_begin", "offset": 0, "slot": "0", @@ -1334,7 +1334,7 @@ }, { "astId": 30242, - "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "contract": "contracts/FlowGovernor.sol:VeloGovernor", "label": "_end", "offset": 16, "slot": "0", @@ -1342,7 +1342,7 @@ }, { "astId": 30246, - "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "contract": "contracts/FlowGovernor.sol:VeloGovernor", "label": "_data", "offset": 0, "slot": "1", @@ -1357,7 +1357,7 @@ "members": [ { "astId": 21925, - "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "contract": "contracts/FlowGovernor.sol:VeloGovernor", "label": "voteStart", "offset": 0, "slot": "0", @@ -1365,7 +1365,7 @@ }, { "astId": 21928, - "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "contract": "contracts/FlowGovernor.sol:VeloGovernor", "label": "voteEnd", "offset": 0, "slot": "1", @@ -1373,7 +1373,7 @@ }, { "astId": 21930, - "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "contract": "contracts/FlowGovernor.sol:VeloGovernor", "label": "executed", "offset": 0, "slot": "2", @@ -1381,7 +1381,7 @@ }, { "astId": 21932, - "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "contract": "contracts/FlowGovernor.sol:VeloGovernor", "label": "canceled", "offset": 1, "slot": "2", @@ -1396,7 +1396,7 @@ "members": [ { "astId": 23185, - "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "contract": "contracts/FlowGovernor.sol:VeloGovernor", "label": "againstVotes", "offset": 0, "slot": "0", @@ -1404,7 +1404,7 @@ }, { "astId": 23187, - "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "contract": "contracts/FlowGovernor.sol:VeloGovernor", "label": "forVotes", "offset": 0, "slot": "1", @@ -1412,7 +1412,7 @@ }, { "astId": 23189, - "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "contract": "contracts/FlowGovernor.sol:VeloGovernor", "label": "abstainVotes", "offset": 0, "slot": "2", @@ -1420,7 +1420,7 @@ }, { "astId": 23193, - "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "contract": "contracts/FlowGovernor.sol:VeloGovernor", "label": "hasVoted", "offset": 0, "slot": "3", @@ -1435,7 +1435,7 @@ "members": [ { "astId": 26447, - "contract": "contracts/VeloGovernor.sol:VeloGovernor", + "contract": "contracts/FlowGovernor.sol:VeloGovernor", "label": "_deadline", "offset": 0, "slot": "0", diff --git a/deployments/arbitrumGoerli/VelocimeterLibrary.json b/deployments/arbitrumGoerli/VelocimeterLibrary.json new file mode 100644 index 00000000..b0350496 --- /dev/null +++ b/deployments/arbitrumGoerli/VelocimeterLibrary.json @@ -0,0 +1,229 @@ +{ + "address": "0x243fC1E928E4bce603669CAf4512B6Db9B965aB0", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_router", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getAmountOut", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getMinimumValue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getSample", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getTradeDiff", + "outputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "pair", + "type": "address" + } + ], + "name": "getTradeDiff", + "outputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x7e47a9bfe362a2dd18c5dad505da3b112c7b732ce5dc4df27cb81f227b153f22", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x243fC1E928E4bce603669CAf4512B6Db9B965aB0", + "transactionIndex": 1, + "gasUsed": "904016", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x0ae6a21fe96adf8c5886840e18cf11b782c5f3ae1426ab99af5bc79c3acda8ae", + "transactionHash": "0x7e47a9bfe362a2dd18c5dad505da3b112c7b732ce5dc4df27cb81f227b153f22", + "logs": [], + "blockNumber": 5716721, + "cumulativeGasUsed": "904016", + "status": 1, + "byzantium": true + }, + "args": [ + "0x49fb251F8Ff60bcd975D2018D0011D7a6065000B" + ], + "numDeployments": 2, + "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getMinimumValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getSample\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VelocimeterLibrary.sol\":\"VelocimeterLibrary\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VelocimeterLibrary.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\n\\ncontract VelocimeterLibrary {\\n IRouter internal immutable router;\\n\\n constructor(address _router) {\\n router = IRouter(_router);\\n }\\n\\n function _f(uint x0, uint y) internal pure returns (uint) {\\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\\n }\\n\\n function _d(uint x0, uint y) internal pure returns (uint) {\\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\\n }\\n\\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\\n for (uint i = 0; i < 255; i++) {\\n uint y_prev = y;\\n uint k = _f(x0, y);\\n if (k < xy) {\\n uint dy = (xy - k)*1e18/_d(x0, y);\\n y = y + dy;\\n } else {\\n uint dy = (k - xy)*1e18/_d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n }\\n\\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return (sample, r0, r1);\\n }\\n\\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\\n if (stable) {\\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\\n _reserve0 = _reserve0 * 1e18 / decimals0;\\n _reserve1 = _reserve1 * 1e18 / decimals1;\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\\n } else {\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n return amountIn * reserveB / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\\n if (stable) {\\n uint _x = x * 1e18 / decimals0;\\n uint _y = y * 1e18 / decimals1;\\n uint _a = (_x * _y) / 1e18;\\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return _a * _b / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n \\n}\\n\",\"keccak256\":\"0x8fa888fd7bda7d3d44a2cc0fd62aeb594c767907f24e7cd390a5fe998d60f388\",\"license\":\"MIT\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"}},\"version\":1}", + "bytecode": "0x60a060405234801561001057600080fd5b5060405161100238038061100283398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051610f626100a06000396000818161010c015281816102730152818161043701526105cb0152610f626000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea26469706673582212208b940b1f6efe2e8ce8c8f5a04b173ea4d5a3c085b7baf2282534cc04ab4a313764736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea26469706673582212208b940b1f6efe2e8ce8c8f5a04b173ea4d5a3c085b7baf2282534cc04ab4a313764736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/Voter.json b/deployments/arbitrumGoerli/Voter.json index f8e4b35c..2ece2c95 100644 --- a/deployments/arbitrumGoerli/Voter.json +++ b/deployments/arbitrumGoerli/Voter.json @@ -1,5 +1,5 @@ { - "address": "0x854086d39955d28317aE3856399312b8Edb1B473", + "address": "0x362502b7139761937067cf81a73Dc18D315f10A0", "abi": [ { "inputs": [ @@ -1141,33 +1141,33 @@ "type": "function" } ], - "transactionHash": "0x6ab790bf44fd3a54927607a33f2b5a57ea2fbafe2190b94ee74e56c31d08e70a", + "transactionHash": "0x79541f2305b40b18d21ee3506c24f656279ba2a3bb80a1b5e8e3234e977c216e", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x854086d39955d28317aE3856399312b8Edb1B473", + "contractAddress": "0x362502b7139761937067cf81a73Dc18D315f10A0", "transactionIndex": 1, - "gasUsed": "3116558", + "gasUsed": "3013820", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xd0e0eb7a2933832bbcb8e6990ff623f0fb228c4b67ebeedf90cf4bfcb44b99c7", - "transactionHash": "0x6ab790bf44fd3a54927607a33f2b5a57ea2fbafe2190b94ee74e56c31d08e70a", + "blockHash": "0x977e938152a0962481b4cd190adc69d2e590eb04a972595c42e0e6e54d0a3357", + "transactionHash": "0x79541f2305b40b18d21ee3506c24f656279ba2a3bb80a1b5e8e3234e977c216e", "logs": [], - "blockNumber": 4455890, - "cumulativeGasUsed": "3116558", + "blockNumber": 5716736, + "cumulativeGasUsed": "3013820", "status": 1, "byzantium": true }, "args": [ - "0xBf05364D6cf1586852c18c6b1CbEe218E3e09885", - "0x6389e934d35fC9e066FAb549C8DBc9FddaC10e0D", - "0xeAA8Ebb77A7e3b7AE2d8090E7A1c2F9B605dc919", - "0x560b401d9F28F80980451d8582DEe903dD5295c3" + "0xC43f6EbF97f9D99FF8a3aFe1413599e8DEc2aDB3", + "0xddadFF10D1C9eb062180a870150D11673FFf7ad6", + "0xA957E3958C7ed4590a28C5564438E89238b34EC1", + "0x5cD2336a80E72bf0480ae704df021e4531A09671" ], - "numDeployments": 1, - "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_gauges\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_bribes\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Abstained\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Attach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Detach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributeReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"internal_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"external_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"name\":\"GaugeCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeKilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeRevived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"reward\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NotifyReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Voted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"whitelister\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"Whitelisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"attachTokenToGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bribefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_bribes\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimBribes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_fees\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"}],\"name\":\"claimRewards\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"detachTokenFromGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"finish\",\"type\":\"uint256\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distributeFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distro\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"emergencyCouncil\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"external_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gaugefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"gauges\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_tokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"internal_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isAlive\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isGauge\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isWhitelisted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"killGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"lastVoted\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"length\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"notifyRewardAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"poke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolForGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"poolVote\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"reset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"reviveGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_council\",\"type\":\"address\"}],\"name\":\"setEmergencyCouncil\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"setGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalWeight\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"updateFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"name\":\"updateForRange\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"updateGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedWeights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"_poolVote\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_weights\",\"type\":\"uint256[]\"}],\"name\":\"vote\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"votes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"weights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"whitelist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Voter.sol\":\"Voter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Voter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/libraries/Math.sol';\\nimport 'contracts/interfaces/IBribe.sol';\\nimport 'contracts/interfaces/IBribeFactory.sol';\\nimport 'contracts/interfaces/IGauge.sol';\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/interfaces/IERC20.sol';\\nimport 'contracts/interfaces/IMinter.sol';\\nimport 'contracts/interfaces/IPair.sol';\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/interfaces/IVoter.sol';\\nimport 'contracts/interfaces/IVotingEscrow.sol';\\n\\ncontract Voter is IVoter {\\n\\n address public immutable _ve; // the ve token that governs these contracts\\n address public immutable factory; // the PairFactory\\n address internal immutable base;\\n address public immutable gaugefactory;\\n address public immutable bribefactory;\\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\\n address public minter;\\n address public governor; // should be set to an IGovernor\\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\\n\\n uint public totalWeight; // total voting weight\\n\\n address[] public pools; // all pools viable for incentives\\n mapping(address => address) public gauges; // pool => gauge\\n mapping(address => address) public poolForGauge; // gauge => pool\\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\\n mapping(address => uint256) public weights; // pool => weight\\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\\n mapping(uint => address[]) public poolVote; // nft => pools\\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\\n mapping(address => bool) public isGauge;\\n mapping(address => bool) public isWhitelisted;\\n mapping(address => bool) public isAlive;\\n\\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\\n event GaugeKilled(address indexed gauge);\\n event GaugeRevived(address indexed gauge);\\n event Voted(address indexed voter, uint tokenId, uint256 weight);\\n event Abstained(uint tokenId, uint256 weight);\\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\\n event Whitelisted(address indexed whitelister, address indexed token);\\n\\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\\n _ve = __ve;\\n factory = _factory;\\n base = IVotingEscrow(__ve).token();\\n gaugefactory = _gauges;\\n bribefactory = _bribes;\\n minter = msg.sender;\\n governor = msg.sender;\\n emergencyCouncil = msg.sender;\\n }\\n\\n // simple re-entrancy check\\n uint internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n modifier onlyNewEpoch(uint _tokenId) {\\n // ensure new epoch since last vote \\n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \\\"TOKEN_ALREADY_VOTED_THIS_EPOCH\\\");\\n _;\\n }\\n\\n function initialize(address[] memory _tokens, address _minter) external {\\n require(msg.sender == minter);\\n for (uint i = 0; i < _tokens.length; i++) {\\n _whitelist(_tokens[i]);\\n }\\n minter = _minter;\\n }\\n\\n function setGovernor(address _governor) public {\\n require(msg.sender == governor);\\n governor = _governor;\\n }\\n\\n function setEmergencyCouncil(address _council) public {\\n require(msg.sender == emergencyCouncil);\\n emergencyCouncil = _council;\\n }\\n\\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n lastVoted[_tokenId] = block.timestamp;\\n _reset(_tokenId);\\n IVotingEscrow(_ve).abstain(_tokenId);\\n }\\n\\n function _reset(uint _tokenId) internal {\\n address[] storage _poolVote = poolVote[_tokenId];\\n uint _poolVoteCnt = _poolVote.length;\\n uint256 _totalWeight = 0;\\n\\n for (uint i = 0; i < _poolVoteCnt; i ++) {\\n address _pool = _poolVote[i];\\n uint256 _votes = votes[_tokenId][_pool];\\n\\n if (_votes != 0) {\\n _updateFor(gauges[_pool]);\\n weights[_pool] -= _votes;\\n votes[_tokenId][_pool] -= _votes;\\n if (_votes > 0) {\\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n _totalWeight += _votes;\\n } else {\\n _totalWeight -= _votes;\\n }\\n emit Abstained(_tokenId, _votes);\\n }\\n }\\n totalWeight -= uint256(_totalWeight);\\n usedWeights[_tokenId] = 0;\\n delete poolVote[_tokenId];\\n }\\n\\n function poke(uint _tokenId) external {\\n address[] memory _poolVote = poolVote[_tokenId];\\n uint _poolCnt = _poolVote.length;\\n uint256[] memory _weights = new uint256[](_poolCnt);\\n\\n for (uint i = 0; i < _poolCnt; i ++) {\\n _weights[i] = votes[_tokenId][_poolVote[i]];\\n }\\n\\n _vote(_tokenId, _poolVote, _weights);\\n }\\n\\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\\n _reset(_tokenId);\\n uint _poolCnt = _poolVote.length;\\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\\n uint256 _totalVoteWeight = 0;\\n uint256 _totalWeight = 0;\\n uint256 _usedWeight = 0;\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n _totalVoteWeight += _weights[i];\\n }\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n address _pool = _poolVote[i];\\n address _gauge = gauges[_pool];\\n\\n if (isGauge[_gauge]) {\\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\\n require(votes[_tokenId][_pool] == 0);\\n require(_poolWeight != 0);\\n _updateFor(_gauge);\\n\\n poolVote[_tokenId].push(_pool);\\n\\n weights[_pool] += _poolWeight;\\n votes[_tokenId][_pool] += _poolWeight;\\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n _usedWeight += _poolWeight;\\n _totalWeight += _poolWeight;\\n emit Voted(msg.sender, _tokenId, _poolWeight);\\n }\\n }\\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\\n totalWeight += uint256(_totalWeight);\\n usedWeights[_tokenId] = uint256(_usedWeight);\\n }\\n\\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n require(_poolVote.length == _weights.length);\\n lastVoted[tokenId] = block.timestamp;\\n _vote(tokenId, _poolVote, _weights);\\n }\\n\\n function whitelist(address _token) public {\\n require(msg.sender == governor);\\n _whitelist(_token);\\n }\\n\\n function _whitelist(address _token) internal {\\n require(!isWhitelisted[_token]);\\n isWhitelisted[_token] = true;\\n emit Whitelisted(msg.sender, _token);\\n }\\n\\n function createGauge(address _pool) external returns (address) {\\n require(gauges[_pool] == address(0x0), \\\"exists\\\");\\n address[] memory allowedRewards = new address[](3);\\n address[] memory internalRewards = new address[](2);\\n bool isPair = IPairFactory(factory).isPair(_pool);\\n address tokenA;\\n address tokenB;\\n\\n if (isPair) {\\n (tokenA, tokenB) = IPair(_pool).tokens();\\n allowedRewards[0] = tokenA;\\n allowedRewards[1] = tokenB;\\n internalRewards[0] = tokenA;\\n internalRewards[1] = tokenB;\\n\\n if (base != tokenA && base != tokenB) {\\n allowedRewards[2] = base;\\n }\\n }\\n\\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\\n require(isPair, \\\"!_pool\\\");\\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \\\"!whitelisted\\\");\\n }\\n\\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\\n\\n IERC20(base).approve(_gauge, type(uint).max);\\n internal_bribes[_gauge] = _internal_bribe;\\n external_bribes[_gauge] = _external_bribe;\\n gauges[_pool] = _gauge;\\n poolForGauge[_gauge] = _pool;\\n isGauge[_gauge] = true;\\n isAlive[_gauge] = true;\\n _updateFor(_gauge);\\n pools.push(_pool);\\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\\n return _gauge;\\n }\\n\\n function killGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(isAlive[_gauge], \\\"gauge already dead\\\");\\n isAlive[_gauge] = false;\\n claimable[_gauge] = 0;\\n emit GaugeKilled(_gauge);\\n }\\n\\n function reviveGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(!isAlive[_gauge], \\\"gauge already alive\\\");\\n isAlive[_gauge] = true;\\n emit GaugeRevived(_gauge);\\n }\\n\\n function attachTokenToGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\\n emit Attach(account, msg.sender, tokenId);\\n }\\n\\n function emitDeposit(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]);\\n emit Deposit(account, msg.sender, tokenId, amount);\\n }\\n\\n function detachTokenFromGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\\n emit Detach(account, msg.sender, tokenId);\\n }\\n\\n function emitWithdraw(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n emit Withdraw(account, msg.sender, tokenId, amount);\\n }\\n\\n function length() external view returns (uint) {\\n return pools.length;\\n }\\n\\n uint internal index;\\n mapping(address => uint) internal supplyIndex;\\n mapping(address => uint) public claimable;\\n\\n function notifyRewardAmount(uint amount) external {\\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index += _ratio;\\n }\\n emit NotifyReward(msg.sender, base, amount);\\n }\\n\\n function updateFor(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n _updateFor(_gauges[i]);\\n }\\n }\\n\\n function updateForRange(uint start, uint end) public {\\n for (uint i = start; i < end; i++) {\\n _updateFor(gauges[pools[i]]);\\n }\\n }\\n\\n function updateAll() external {\\n updateForRange(0, pools.length);\\n }\\n\\n function updateGauge(address _gauge) external {\\n _updateFor(_gauge);\\n }\\n\\n function _updateFor(address _gauge) internal {\\n address _pool = poolForGauge[_gauge];\\n uint256 _supplied = weights[_pool];\\n if (_supplied > 0) {\\n uint _supplyIndex = supplyIndex[_gauge];\\n uint _index = index; // get global index0 for accumulated distro\\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\\n if (_delta > 0) {\\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\\n if (isAlive[_gauge]) {\\n claimable[_gauge] += _share;\\n }\\n }\\n } else {\\n supplyIndex[_gauge] = index; // new users are set to the default global state\\n }\\n }\\n\\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\\n }\\n }\\n\\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _bribes.length; i++) {\\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _fees.length; i++) {\\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function distributeFees(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n if (IGauge(_gauges[i]).isForPair()){\\n IGauge(_gauges[i]).claimFees();\\n }\\n }\\n }\\n\\n function distribute(address _gauge) public lock {\\n IMinter(minter).update_period();\\n _updateFor(_gauge); // should set claimable to 0 if killed\\n uint _claimable = claimable[_gauge];\\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\\n claimable[_gauge] = 0;\\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\\n emit DistributeReward(msg.sender, _gauge, _claimable);\\n }\\n }\\n\\n function distro() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute(uint start, uint finish) public {\\n for (uint x = start; x < finish; x++) {\\n distribute(gauges[pools[x]]);\\n }\\n }\\n\\n function distribute(address[] memory _gauges) external {\\n for (uint x = 0; x < _gauges.length; x++) {\\n distribute(_gauges[x]);\\n }\\n }\\n\\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2ff3fc2765dfa0c54870e428d3a2c625f413fb6e10ed7742e786ab4404aae6dc\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x61012060405260016011553480156200001757600080fd5b5060405162003656380380620036568339810160408190526200003a916200011c565b6001600160a01b03808516608081905290841660a05260408051637e062a3560e11b8152905163fc0c546a916004808201926020929091908290030181865afa1580156200008c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b2919062000179565b6001600160a01b0390811660c05291821660e0521661010052505060008054336001600160a01b03199182168117909255600180548216831790556002805490911690911790556200019e565b80516001600160a01b03811681146200011757600080fd5b919050565b600080600080608085870312156200013357600080fd5b6200013e85620000ff565b93506200014e60208601620000ff565b92506200015e60408601620000ff565b91506200016e60608601620000ff565b905092959194509250565b6000602082840312156200018c57600080fd5b6200019782620000ff565b9392505050565b60805160a05160c05160e051610100516133e062000276600039600081816103e701528181611c680152611ce60152600081816104d30152611d79015260008181610b9401528181610c0d01528181610edd01528181610f9901528181611acd01528181611b0601528181611b380152611e5a0152600081816106fc015261192401526000818161058c0152818161092b015281816109d701528181610c9a01528181611069015281816111ea0152818161131a015281816114d901528181611dab015281816125e501526129a801526133e06000f3fe608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea26469706673582212206417f3b87d56b8cad3ead79123e880da3688f5c8a600bd4d6bc932d9f942976264736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea26469706673582212206417f3b87d56b8cad3ead79123e880da3688f5c8a600bd4d6bc932d9f942976264736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_gauges\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_bribes\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Abstained\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Attach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Detach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributeReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"internal_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"external_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"name\":\"GaugeCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeKilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeRevived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"reward\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NotifyReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Voted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"whitelister\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"Whitelisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"attachTokenToGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bribefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_bribes\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimBribes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_fees\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"}],\"name\":\"claimRewards\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"detachTokenFromGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"finish\",\"type\":\"uint256\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distributeFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distro\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"emergencyCouncil\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"external_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gaugefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"gauges\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_tokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"internal_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isAlive\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isGauge\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isWhitelisted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"killGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"lastVoted\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"length\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"notifyRewardAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"poke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolForGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"poolVote\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"reset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"reviveGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_council\",\"type\":\"address\"}],\"name\":\"setEmergencyCouncil\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"setGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalWeight\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"updateFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"name\":\"updateForRange\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"updateGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedWeights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"_poolVote\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_weights\",\"type\":\"uint256[]\"}],\"name\":\"vote\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"votes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"weights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"whitelist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Voter.sol\":\"Voter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Voter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/libraries/Math.sol';\\nimport 'contracts/interfaces/IBribe.sol';\\nimport 'contracts/interfaces/IBribeFactory.sol';\\nimport 'contracts/interfaces/IGauge.sol';\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/interfaces/IERC20.sol';\\nimport 'contracts/interfaces/IMinter.sol';\\nimport 'contracts/interfaces/IPair.sol';\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/interfaces/IVoter.sol';\\nimport 'contracts/interfaces/IVotingEscrow.sol';\\n\\ncontract Voter is IVoter {\\n\\n address public immutable _ve; // the ve token that governs these contracts\\n address public immutable factory; // the PairFactory\\n address internal immutable base;\\n address public immutable gaugefactory;\\n address public immutable bribefactory;\\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\\n address public minter;\\n address public governor; // should be set to an IGovernor\\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\\n\\n uint public totalWeight; // total voting weight\\n\\n address[] public pools; // all pools viable for incentives\\n mapping(address => address) public gauges; // pool => gauge\\n mapping(address => address) public poolForGauge; // gauge => pool\\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\\n mapping(address => uint256) public weights; // pool => weight\\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\\n mapping(uint => address[]) public poolVote; // nft => pools\\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\\n mapping(address => bool) public isGauge;\\n mapping(address => bool) public isWhitelisted;\\n mapping(address => bool) public isAlive;\\n\\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\\n event GaugeKilled(address indexed gauge);\\n event GaugeRevived(address indexed gauge);\\n event Voted(address indexed voter, uint tokenId, uint256 weight);\\n event Abstained(uint tokenId, uint256 weight);\\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\\n event Whitelisted(address indexed whitelister, address indexed token);\\n\\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\\n _ve = __ve;\\n factory = _factory;\\n base = IVotingEscrow(__ve).token();\\n gaugefactory = _gauges;\\n bribefactory = _bribes;\\n minter = msg.sender;\\n governor = msg.sender;\\n emergencyCouncil = msg.sender;\\n }\\n\\n // simple re-entrancy check\\n uint internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n modifier onlyNewEpoch(uint _tokenId) {\\n // ensure new epoch since last vote \\n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \\\"TOKEN_ALREADY_VOTED_THIS_EPOCH\\\");\\n _;\\n }\\n\\n function initialize(address[] memory _tokens, address _minter) external {\\n require(msg.sender == minter);\\n for (uint i = 0; i < _tokens.length; i++) {\\n _whitelist(_tokens[i]);\\n }\\n minter = _minter;\\n }\\n\\n function setGovernor(address _governor) public {\\n require(msg.sender == governor);\\n governor = _governor;\\n }\\n\\n function setEmergencyCouncil(address _council) public {\\n require(msg.sender == emergencyCouncil);\\n emergencyCouncil = _council;\\n }\\n\\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n lastVoted[_tokenId] = block.timestamp;\\n _reset(_tokenId);\\n IVotingEscrow(_ve).abstain(_tokenId);\\n }\\n\\n function _reset(uint _tokenId) internal {\\n address[] storage _poolVote = poolVote[_tokenId];\\n uint _poolVoteCnt = _poolVote.length;\\n uint256 _totalWeight = 0;\\n\\n for (uint i = 0; i < _poolVoteCnt; i ++) {\\n address _pool = _poolVote[i];\\n uint256 _votes = votes[_tokenId][_pool];\\n\\n if (_votes != 0) {\\n _updateFor(gauges[_pool]);\\n weights[_pool] -= _votes;\\n votes[_tokenId][_pool] -= _votes;\\n if (_votes > 0) {\\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n _totalWeight += _votes;\\n } else {\\n _totalWeight -= _votes;\\n }\\n emit Abstained(_tokenId, _votes);\\n }\\n }\\n totalWeight -= uint256(_totalWeight);\\n usedWeights[_tokenId] = 0;\\n delete poolVote[_tokenId];\\n }\\n\\n function poke(uint _tokenId) external {\\n address[] memory _poolVote = poolVote[_tokenId];\\n uint _poolCnt = _poolVote.length;\\n uint256[] memory _weights = new uint256[](_poolCnt);\\n\\n for (uint i = 0; i < _poolCnt; i ++) {\\n _weights[i] = votes[_tokenId][_poolVote[i]];\\n }\\n\\n _vote(_tokenId, _poolVote, _weights);\\n }\\n\\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\\n _reset(_tokenId);\\n uint _poolCnt = _poolVote.length;\\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\\n uint256 _totalVoteWeight = 0;\\n uint256 _totalWeight = 0;\\n uint256 _usedWeight = 0;\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n _totalVoteWeight += _weights[i];\\n }\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n address _pool = _poolVote[i];\\n address _gauge = gauges[_pool];\\n\\n if (isGauge[_gauge]) {\\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\\n require(votes[_tokenId][_pool] == 0);\\n require(_poolWeight != 0);\\n _updateFor(_gauge);\\n\\n poolVote[_tokenId].push(_pool);\\n\\n weights[_pool] += _poolWeight;\\n votes[_tokenId][_pool] += _poolWeight;\\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n _usedWeight += _poolWeight;\\n _totalWeight += _poolWeight;\\n emit Voted(msg.sender, _tokenId, _poolWeight);\\n }\\n }\\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\\n totalWeight += uint256(_totalWeight);\\n usedWeights[_tokenId] = uint256(_usedWeight);\\n }\\n\\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n require(_poolVote.length == _weights.length);\\n lastVoted[tokenId] = block.timestamp;\\n _vote(tokenId, _poolVote, _weights);\\n }\\n\\n function whitelist(address _token) public {\\n require(msg.sender == governor);\\n _whitelist(_token);\\n }\\n\\n function _whitelist(address _token) internal {\\n require(!isWhitelisted[_token]);\\n isWhitelisted[_token] = true;\\n emit Whitelisted(msg.sender, _token);\\n }\\n\\n function createGauge(address _pool) external returns (address) {\\n require(gauges[_pool] == address(0x0), \\\"exists\\\");\\n address[] memory allowedRewards = new address[](3);\\n address[] memory internalRewards = new address[](2);\\n bool isPair = IPairFactory(factory).isPair(_pool);\\n address tokenA;\\n address tokenB;\\n\\n if (isPair) {\\n (tokenA, tokenB) = IPair(_pool).tokens();\\n allowedRewards[0] = tokenA;\\n allowedRewards[1] = tokenB;\\n internalRewards[0] = tokenA;\\n internalRewards[1] = tokenB;\\n\\n if (base != tokenA && base != tokenB) {\\n allowedRewards[2] = base;\\n }\\n }\\n\\n if (msg.sender != governor) { // gov can create for any pool, even non-Velocimeter pairs\\n require(isPair, \\\"!_pool\\\");\\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \\\"!whitelisted\\\");\\n }\\n\\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\\n\\n IERC20(base).approve(_gauge, type(uint).max);\\n internal_bribes[_gauge] = _internal_bribe;\\n external_bribes[_gauge] = _external_bribe;\\n gauges[_pool] = _gauge;\\n poolForGauge[_gauge] = _pool;\\n isGauge[_gauge] = true;\\n isAlive[_gauge] = true;\\n _updateFor(_gauge);\\n pools.push(_pool);\\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\\n return _gauge;\\n }\\n\\n function killGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(isAlive[_gauge], \\\"gauge already dead\\\");\\n isAlive[_gauge] = false;\\n claimable[_gauge] = 0;\\n emit GaugeKilled(_gauge);\\n }\\n\\n function reviveGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(!isAlive[_gauge], \\\"gauge already alive\\\");\\n isAlive[_gauge] = true;\\n emit GaugeRevived(_gauge);\\n }\\n\\n function attachTokenToGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\\n emit Attach(account, msg.sender, tokenId);\\n }\\n\\n function emitDeposit(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]);\\n emit Deposit(account, msg.sender, tokenId, amount);\\n }\\n\\n function detachTokenFromGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\\n emit Detach(account, msg.sender, tokenId);\\n }\\n\\n function emitWithdraw(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n emit Withdraw(account, msg.sender, tokenId, amount);\\n }\\n\\n function length() external view returns (uint) {\\n return pools.length;\\n }\\n\\n uint internal index;\\n mapping(address => uint) internal supplyIndex;\\n mapping(address => uint) public claimable;\\n\\n function notifyRewardAmount(uint amount) external {\\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index += _ratio;\\n }\\n emit NotifyReward(msg.sender, base, amount);\\n }\\n\\n function updateFor(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n _updateFor(_gauges[i]);\\n }\\n }\\n\\n function updateForRange(uint start, uint end) public {\\n for (uint i = start; i < end; i++) {\\n _updateFor(gauges[pools[i]]);\\n }\\n }\\n\\n function updateAll() external {\\n updateForRange(0, pools.length);\\n }\\n\\n function updateGauge(address _gauge) external {\\n _updateFor(_gauge);\\n }\\n\\n function _updateFor(address _gauge) internal {\\n address _pool = poolForGauge[_gauge];\\n uint256 _supplied = weights[_pool];\\n if (_supplied > 0) {\\n uint _supplyIndex = supplyIndex[_gauge];\\n uint _index = index; // get global index0 for accumulated distro\\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\\n if (_delta > 0) {\\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\\n if (isAlive[_gauge]) {\\n claimable[_gauge] += _share;\\n }\\n }\\n } else {\\n supplyIndex[_gauge] = index; // new users are set to the default global state\\n }\\n }\\n\\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\\n }\\n }\\n\\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _bribes.length; i++) {\\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _fees.length; i++) {\\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function distributeFees(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n if (IGauge(_gauges[i]).isForPair()){\\n IGauge(_gauges[i]).claimFees();\\n }\\n }\\n }\\n\\n function distribute(address _gauge) public lock {\\n IMinter(minter).update_period();\\n _updateFor(_gauge); // should set claimable to 0 if killed\\n uint _claimable = claimable[_gauge];\\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\\n claimable[_gauge] = 0;\\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\\n emit DistributeReward(msg.sender, _gauge, _claimable);\\n }\\n }\\n\\n function distro() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute(uint start, uint finish) public {\\n for (uint x = start; x < finish; x++) {\\n distribute(gauges[pools[x]]);\\n }\\n }\\n\\n function distribute(address[] memory _gauges) external {\\n for (uint x = 0; x < _gauges.length; x++) {\\n distribute(_gauges[x]);\\n }\\n }\\n\\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x16f98751f0144d1758ecb2bec2062be56c718e18d65f0b948fd2a1404b37e6f8\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x61012060405260016011553480156200001757600080fd5b5060405162003656380380620036568339810160408190526200003a916200011c565b6001600160a01b03808516608081905290841660a05260408051637e062a3560e11b8152905163fc0c546a916004808201926020929091908290030181865afa1580156200008c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b2919062000179565b6001600160a01b0390811660c05291821660e0521661010052505060008054336001600160a01b03199182168117909255600180548216831790556002805490911690911790556200019e565b80516001600160a01b03811681146200011757600080fd5b919050565b600080600080608085870312156200013357600080fd5b6200013e85620000ff565b93506200014e60208601620000ff565b92506200015e60408601620000ff565b91506200016e60608601620000ff565b905092959194509250565b6000602082840312156200018c57600080fd5b6200019782620000ff565b9392505050565b60805160a05160c05160e051610100516133e062000276600039600081816103e701528181611c680152611ce60152600081816104d30152611d79015260008181610b9401528181610c0d01528181610edd01528181610f9901528181611acd01528181611b0601528181611b380152611e5a0152600081816106fc015261192401526000818161058c0152818161092b015281816109d701528181610c9a01528181611069015281816111ea0152818161131a015281816114d901528181611dab015281816125e501526129a801526133e06000f3fe608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea264697066735822122037b1584fd5e73726f301a3b06836497dcb851acadb4f734682e2b0825bddc10264736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea264697066735822122037b1584fd5e73726f301a3b06836497dcb851acadb4f734682e2b0825bddc10264736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/VotingEscrow.json b/deployments/arbitrumGoerli/VotingEscrow.json index 695b796f..7e639417 100644 --- a/deployments/arbitrumGoerli/VotingEscrow.json +++ b/deployments/arbitrumGoerli/VotingEscrow.json @@ -1,5 +1,5 @@ { - "address": "0xBf05364D6cf1586852c18c6b1CbEe218E3e09885", + "address": "0xC43f6EbF97f9D99FF8a3aFe1413599e8DEc2aDB3", "abi": [ { "inputs": [ @@ -1521,62 +1521,62 @@ "type": "function" } ], - "transactionHash": "0x2a4f550ce7f771e6c1174ee30ef320f5f4c5ff7e16cdcf1b8e96862fc0bf6b44", + "transactionHash": "0x27f78542ce64b4f54e5d963978165833f7d926c7239dd264b9109d541b2ada45", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xBf05364D6cf1586852c18c6b1CbEe218E3e09885", + "contractAddress": "0xC43f6EbF97f9D99FF8a3aFe1413599e8DEc2aDB3", "transactionIndex": 1, - "gasUsed": "4394475", - "logsBloom": "0x00000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000020000000000000000000800000401000000000000000010000000000000000000000000000000000000000000000000000000000000000004000000000001000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000400000000000000000", - "blockHash": "0x8900ffab23000b0b19a48cbfe5540b30cc7088ef54c85315850b24e4b6ff5ce9", - "transactionHash": "0x2a4f550ce7f771e6c1174ee30ef320f5f4c5ff7e16cdcf1b8e96862fc0bf6b44", + "gasUsed": "4240754", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000008000400000000000000000000000000000000000000000000020000000000000000000800000000000000000000000010004000000000000000000000000000000000000000000000000000000000000000000000000000400000000080000000000000000000000000000000000000000000000000000002000000000000000000000000040000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x6da0f879c4d4a6a88011182380eaead5f8835b7a19b3e7cc322b791c7d9503bb", + "transactionHash": "0x27f78542ce64b4f54e5d963978165833f7d926c7239dd264b9109d541b2ada45", "logs": [ { "transactionIndex": 1, - "blockNumber": 4455885, - "transactionHash": "0x2a4f550ce7f771e6c1174ee30ef320f5f4c5ff7e16cdcf1b8e96862fc0bf6b44", - "address": "0xBf05364D6cf1586852c18c6b1CbEe218E3e09885", + "blockNumber": 5716730, + "transactionHash": "0x27f78542ce64b4f54e5d963978165833f7d926c7239dd264b9109d541b2ada45", + "address": "0xC43f6EbF97f9D99FF8a3aFe1413599e8DEc2aDB3", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000bf05364d6cf1586852c18c6b1cbee218e3e09885", + "0x000000000000000000000000c43f6ebf97f9d99ff8a3afe1413599e8dec2adb3", "0x0000000000000000000000000000000000000000000000000000000000000000" ], "data": "0x", "logIndex": 0, - "blockHash": "0x8900ffab23000b0b19a48cbfe5540b30cc7088ef54c85315850b24e4b6ff5ce9" + "blockHash": "0x6da0f879c4d4a6a88011182380eaead5f8835b7a19b3e7cc322b791c7d9503bb" }, { "transactionIndex": 1, - "blockNumber": 4455885, - "transactionHash": "0x2a4f550ce7f771e6c1174ee30ef320f5f4c5ff7e16cdcf1b8e96862fc0bf6b44", - "address": "0xBf05364D6cf1586852c18c6b1CbEe218E3e09885", + "blockNumber": 5716730, + "transactionHash": "0x27f78542ce64b4f54e5d963978165833f7d926c7239dd264b9109d541b2ada45", + "address": "0xC43f6EbF97f9D99FF8a3aFe1413599e8DEc2aDB3", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x000000000000000000000000bf05364d6cf1586852c18c6b1cbee218e3e09885", + "0x000000000000000000000000c43f6ebf97f9d99ff8a3afe1413599e8dec2adb3", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000" ], "data": "0x", "logIndex": 1, - "blockHash": "0x8900ffab23000b0b19a48cbfe5540b30cc7088ef54c85315850b24e4b6ff5ce9" + "blockHash": "0x6da0f879c4d4a6a88011182380eaead5f8835b7a19b3e7cc322b791c7d9503bb" } ], - "blockNumber": 4455885, - "cumulativeGasUsed": "4394475", + "blockNumber": 5716730, + "cumulativeGasUsed": "4240754", "status": 1, "byzantium": true }, "args": [ - "0x84Ca387E7ede764A3284c67Ff8c68a305a9030a0", - "0x821B98D42D3AB509AF4F54205f0c52B019b9E2D5" + "0xf5A53c1b4072425DF6eC082f0A48B4652bc4188C", + "0xDe032908A79276B257d1ae80f0C0A2c070eDa1F4" ], - "numDeployments": 1, - "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token_addr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"art_proxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromDelegate\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toDelegate\",\"type\":\"address\"}],\"name\":\"DelegateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"DelegateVotesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"locktime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum VotingEscrow.DepositType\",\"name\":\"deposit_type\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"prevSupply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"supply\",\"type\":\"uint256\"}],\"name\":\"Supply\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DELEGATION_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_DELEGATES\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"abstain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_approved\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"artProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"attach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"attachments\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"balanceOfAtNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_t\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFTAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"block_number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"checkpoints\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"create_lock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"create_lock_for\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"}],\"name\":\"delegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"delegateBySig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"}],\"name\":\"delegates\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"deposit_for\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"detach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastTotalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotesIndex\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"get_last_user_slope\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"increase_amount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"increase_unlock_time\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"isApprovedOrOwner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"locked\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"amount\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"locked__end\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_from\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_to\",\"type\":\"uint256\"}],\"name\":\"merge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"numCheckpoints\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ownership_change\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_proxy\",\"type\":\"address\"}],\"name\":\"setArtProxy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voter\",\"type\":\"address\"}],\"name\":\"setVoter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"slope_changes\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenIndex\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"t\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAtT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_idx\",\"type\":\"uint256\"}],\"name\":\"user_point_history__ts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"voted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"voting\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\",\"details\":\"Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\",\"kind\":\"dev\",\"methods\":{\"approve(address,uint256)\":{\"details\":\"Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address. Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner. Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP) Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"Address to be approved for the given NFT ID.\",\"_tokenId\":\"ID of the token to be approved.\"}},\"balanceOf(address)\":{\"details\":\"Returns the number of NFTs owned by `_owner`. Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\",\"params\":{\"_owner\":\"Address for whom to query the balance.\"}},\"constructor\":{\"params\":{\"token_addr\":\"`VELO` token address\"}},\"create_lock(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_value\":\"Amount to deposit\"}},\"create_lock_for(uint256,uint256,address)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_to\":\"Address to deposit\",\"_value\":\"Amount to deposit\"}},\"delegate(address)\":{\"params\":{\"delegatee\":\"The address to delegate votes to\"}},\"delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Delegates votes from signer to `delegatee`.\"},\"deposit_for(uint256,uint256)\":{\"details\":\"Anyone (even a smart contract) can deposit for someone else, but cannot extend their locktime and deposit for a brand new user\",\"params\":{\"_tokenId\":\"lock NFT\",\"_value\":\"Amount to add to user's lock\"}},\"getApproved(uint256)\":{\"details\":\"Get the approved address for a single NFT.\",\"params\":{\"_tokenId\":\"ID of the NFT to query the approval of.\"}},\"getVotes(address)\":{\"params\":{\"account\":\"The address to get votes balance\"},\"returns\":{\"_0\":\"The number of current votes for `account`\"}},\"get_last_user_slope(uint256)\":{\"params\":{\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Value of the slope\"}},\"increase_amount(uint256,uint256)\":{\"params\":{\"_value\":\"Amount of tokens to deposit and add to the lock\"}},\"increase_unlock_time(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"New number of seconds until tokens unlock\"}},\"isApprovedForAll(address,address)\":{\"details\":\"Checks if `_operator` is an approved operator for `_owner`.\",\"params\":{\"_operator\":\"The address that acts on behalf of the owner.\",\"_owner\":\"The address that owns the NFTs.\"}},\"locked__end(uint256)\":{\"params\":{\"_tokenId\":\"User NFT\"},\"returns\":{\"_0\":\"Epoch time of the lock end\"}},\"ownerOf(uint256)\":{\"details\":\"Returns the address of the owner of the NFT.\",\"params\":{\"_tokenId\":\"The identifier for an NFT.\"}},\"safeTransferFrom(address,address,uint256)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"safeTransferFrom(address,address,uint256,bytes)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_data\":\"Additional data with no specified format, sent in call to `_to`.\",\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"details\":\"Enables or disables approval for a third party (\\\"operator\\\") to manage all of `msg.sender`'s assets. It also emits the ApprovalForAll event. Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"True if the operators is approved, false to revoke approval.\",\"_operator\":\"Address to add to the set of authorized operators.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Interface identification is specified in ERC-165.\",\"params\":{\"_interfaceID\":\"Id of the interface\"}},\"tokenOfOwnerByIndex(address,uint256)\":{\"details\":\"Get token by index\"},\"tokenURI(uint256)\":{\"details\":\"Returns current token URI metadata\",\"params\":{\"_tokenId\":\"Token ID to fetch URI for.\"}},\"totalSupplyAt(uint256)\":{\"params\":{\"_block\":\"Block to calculate the total voting power at\"},\"returns\":{\"_0\":\"Total voting power at `_block`\"}},\"totalSupplyAtT(uint256)\":{\"details\":\"Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\",\"returns\":{\"_0\":\"Total voting power\"}},\"transferFrom(address,address,uint256)\":{\"details\":\"Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"user_point_history__ts(uint256,uint256)\":{\"params\":{\"_idx\":\"User epoch number\",\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Epoch time of the checkpoint\"}},\"withdraw(uint256)\":{\"details\":\"Only possible if the lock has expired\"}},\"stateVariables\":{\"ERC165_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC165\"},\"ERC721_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721\"},\"ERC721_METADATA_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721Metadata\"},\"_not_entered\":{\"details\":\"reentrancy guard\"},\"idToApprovals\":{\"details\":\"Mapping from NFT ID to approved address.\"},\"idToOwner\":{\"details\":\"Mapping from NFT ID to the address that owns it.\"},\"name\":{\"details\":\"Returns the token collection name.\"},\"ownerToNFTokenCount\":{\"details\":\"Mapping from owner address to count of his tokens.\"},\"ownerToNFTokenIdList\":{\"details\":\"Mapping from owner address to mapping of index to tokenIds\"},\"ownerToOperators\":{\"details\":\"Mapping from owner address to mapping of operator addresses.\"},\"supportedInterfaces\":{\"details\":\"Mapping of interface id to bool about whether or not it's supported\"},\"symbol\":{\"details\":\"Returns the token collection symbol.\"},\"tokenId\":{\"details\":\"Current count of token\"},\"tokenToOwnerIndex\":{\"details\":\"Mapping from NFT ID to index of owner\"}},\"title\":\"Voting Escrow\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DELEGATION_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the delegation struct used by the contract\"},\"DOMAIN_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the contract's domain\"},\"checkpoint()\":{\"notice\":\"Record global data to checkpoint\"},\"checkpoints(address,uint32)\":{\"notice\":\"A record of delegated token checkpoints for each account, by index\"},\"constructor\":{\"notice\":\"Contract constructor\"},\"create_lock(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\"},\"create_lock_for(uint256,uint256,address)\":{\"notice\":\"Deposit `_value` tokens for `_to` and lock for `_lock_duration`\"},\"delegate(address)\":{\"notice\":\"Delegate votes from `msg.sender` to `delegatee`\"},\"delegates(address)\":{\"notice\":\"Overrides the standard `Comp.sol` delegates mapping to return the delegator's own address if they haven't delegated. This avoids having to delegate to oneself.\"},\"deposit_for(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `_tokenId` and add to the lock\"},\"getVotes(address)\":{\"notice\":\"Gets the current votes balance for `account`\"},\"get_last_user_slope(uint256)\":{\"notice\":\"Get the most recently recorded rate of voting power decrease for `_tokenId`\"},\"increase_amount(uint256,uint256)\":{\"notice\":\"Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\"},\"increase_unlock_time(uint256,uint256)\":{\"notice\":\"Extend the unlock time for `_tokenId`\"},\"locked__end(uint256)\":{\"notice\":\"Get timestamp when `_tokenId`'s lock finishes\"},\"nonces(address)\":{\"notice\":\"A record of states for signing / validating signatures\"},\"numCheckpoints(address)\":{\"notice\":\"The number of checkpoints for each account\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"This works even if sender doesn't own any tokens at the time.\"},\"totalSupplyAt(uint256)\":{\"notice\":\"Calculate total voting power at some point in the past\"},\"totalSupplyAtT(uint256)\":{\"notice\":\"Calculate total voting power\"},\"transferFrom(address,address,uint256)\":{\"notice\":\"The caller is responsible to confirm that `_to` is capable of receiving NFTs or else they maybe be permanently lost.\"},\"user_point_history__ts(uint256,uint256)\":{\"notice\":\"Get the timestamp for checkpoint `_idx` for `_tokenId`\"},\"withdraw(uint256)\":{\"notice\":\"Withdraw all tokens for `_tokenId`\"}},\"notice\":\"veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFTVotes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VotingEscrow.sol\":\"VotingEscrow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VotingEscrow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IERC721, IERC721Metadata} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {IERC721Receiver} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {IERC20} from \\\"contracts/interfaces/IERC20.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\nimport {IVotingEscrow} from \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/// @title Voting Escrow\\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\\n enum DepositType {\\n DEPOSIT_FOR_TYPE,\\n CREATE_LOCK_TYPE,\\n INCREASE_LOCK_AMOUNT,\\n INCREASE_UNLOCK_TIME,\\n MERGE_TYPE\\n }\\n\\n struct LockedBalance {\\n int128 amount;\\n uint end;\\n }\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint ts;\\n uint blk; // block\\n }\\n /* We cannot really do block numbers per se b/c slope is per time, not per block\\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\\n * What we can do is to extrapolate ***At functions */\\n\\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\\n struct Checkpoint {\\n uint timestamp;\\n uint[] tokenIds;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Deposit(\\n address indexed provider,\\n uint tokenId,\\n uint value,\\n uint indexed locktime,\\n DepositType deposit_type,\\n uint ts\\n );\\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\\n event Supply(uint prevSupply, uint supply);\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n address public immutable token;\\n address public voter;\\n address public team;\\n address public artProxy;\\n\\n mapping(uint => Point) public point_history; // epoch -> unsigned point\\n\\n /// @dev Mapping of interface id to bool about whether or not it's supported\\n mapping(bytes4 => bool) internal supportedInterfaces;\\n\\n /// @dev ERC165 interface ID of ERC165\\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\\n\\n /// @dev ERC165 interface ID of ERC721\\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\\n\\n /// @dev ERC165 interface ID of ERC721Metadata\\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\\n\\n /// @dev Current count of token\\n uint internal tokenId;\\n\\n /// @notice Contract constructor\\n /// @param token_addr `VELO` token address\\n constructor(address token_addr, address art_proxy) {\\n token = token_addr;\\n voter = msg.sender;\\n team = msg.sender;\\n artProxy = art_proxy;\\n\\n point_history[0].blk = block.number;\\n point_history[0].ts = block.timestamp;\\n\\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\\n\\n // mint-ish\\n emit Transfer(address(0), address(this), tokenId);\\n // burn-ish\\n emit Transfer(address(this), address(0), tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n MODIFIERS\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev reentrancy guard\\n uint8 internal constant _not_entered = 1;\\n uint8 internal constant _entered = 2;\\n uint8 internal _entered_state = 1;\\n modifier nonreentrant() {\\n require(_entered_state == _not_entered);\\n _entered_state = _entered;\\n _;\\n _entered_state = _not_entered;\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string constant public name = \\\"veNFT\\\";\\n string constant public symbol = \\\"veNFT\\\";\\n string constant public version = \\\"1.0.0\\\";\\n uint8 constant public decimals = 18;\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team);\\n team = _team;\\n }\\n\\n function setArtProxy(address _proxy) external {\\n require(msg.sender == team);\\n artProxy = _proxy;\\n }\\n\\n /// @dev Returns current token URI metadata\\n /// @param _tokenId Token ID to fetch URI for.\\n function tokenURI(uint _tokenId) external view returns (string memory) {\\n require(idToOwner[_tokenId] != address(0), \\\"Query for nonexistent token\\\");\\n LockedBalance memory _locked = locked[_tokenId];\\n return IVeArtProxy(artProxy)._tokenURI(\\n _tokenId,\\n _balanceOfNFT(_tokenId, block.timestamp),\\n _locked.end,\\n uint(int256(_locked.amount))\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 BALANCE/OWNER STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to the address that owns it.\\n mapping(uint => address) internal idToOwner;\\n\\n /// @dev Mapping from owner address to count of his tokens.\\n mapping(address => uint) internal ownerToNFTokenCount;\\n\\n /// @dev Returns the address of the owner of the NFT.\\n /// @param _tokenId The identifier for an NFT.\\n function ownerOf(uint _tokenId) public view returns (address) {\\n return idToOwner[_tokenId];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function _balance(address _owner) internal view returns (uint) {\\n return ownerToNFTokenCount[_owner];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function balanceOf(address _owner) external view returns (uint) {\\n return _balance(_owner);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 APPROVAL STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to approved address.\\n mapping(uint => address) internal idToApprovals;\\n\\n /// @dev Mapping from owner address to mapping of operator addresses.\\n mapping(address => mapping(address => bool)) internal ownerToOperators;\\n\\n mapping(uint => uint) public ownership_change;\\n\\n /// @dev Get the approved address for a single NFT.\\n /// @param _tokenId ID of the NFT to query the approval of.\\n function getApproved(uint _tokenId) external view returns (address) {\\n return idToApprovals[_tokenId];\\n }\\n\\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\\n /// @param _owner The address that owns the NFTs.\\n /// @param _operator The address that acts on behalf of the owner.\\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\\n return (ownerToOperators[_owner])[_operator];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\\n /// @param _approved Address to be approved for the given NFT ID.\\n /// @param _tokenId ID of the token to be approved.\\n function approve(address _approved, uint _tokenId) public {\\n address owner = idToOwner[_tokenId];\\n // Throws if `_tokenId` is not a valid NFT\\n require(owner != address(0));\\n // Throws if `_approved` is the current owner\\n require(_approved != owner);\\n // Check requirements\\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\\n require(senderIsOwner || senderIsApprovedForAll);\\n // Set the approval\\n idToApprovals[_tokenId] = _approved;\\n emit Approval(owner, _approved, _tokenId);\\n }\\n\\n /// @dev Enables or disables approval for a third party (\\\"operator\\\") to manage all of\\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\\n /// @notice This works even if sender doesn't own any tokens at the time.\\n /// @param _operator Address to add to the set of authorized operators.\\n /// @param _approved True if the operators is approved, false to revoke approval.\\n function setApprovalForAll(address _operator, bool _approved) external {\\n // Throws if `_operator` is the `msg.sender`\\n assert(_operator != msg.sender);\\n ownerToOperators[msg.sender][_operator] = _approved;\\n emit ApprovalForAll(msg.sender, _operator, _approved);\\n }\\n\\n /* TRANSFER FUNCTIONS */\\n /// @dev Clear an approval of a given address\\n /// Throws if `_owner` is not the current owner.\\n function _clearApproval(address _owner, uint _tokenId) internal {\\n // Throws if `_owner` is not the current owner\\n assert(idToOwner[_tokenId] == _owner);\\n if (idToApprovals[_tokenId] != address(0)) {\\n // Reset approvals\\n idToApprovals[_tokenId] = address(0);\\n }\\n }\\n\\n /// @dev Returns whether the given spender can transfer a given token ID\\n /// @param _spender address of the spender to query\\n /// @param _tokenId uint ID of the token to be transferred\\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\\n address owner = idToOwner[_tokenId];\\n bool spenderIsOwner = owner == _spender;\\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\\n }\\n\\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\\n return _isApprovedOrOwner(_spender, _tokenId);\\n }\\n\\n /// @dev Exeute transfer of a NFT.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_tokenId` is not a valid NFT.\\n function _transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n address _sender\\n ) internal {\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n // Check requirements\\n require(_isApprovedOrOwner(_sender, _tokenId));\\n // Clear approval. Throws if `_from` is not the current owner\\n _clearApproval(_from, _tokenId);\\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\\n _removeTokenFrom(_from, _tokenId);\\n // auto re-delegate\\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\\n // Add NFT\\n _addTokenTo(_to, _tokenId);\\n // Set the block of ownership transfer (for Flash NFT protection)\\n ownership_change[_tokenId] = block.number;\\n // Log the transfer\\n emit Transfer(_from, _to, _tokenId);\\n }\\n\\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\\n /// they maybe be permanently lost.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n safeTransferFrom(_from, _to, _tokenId, \\\"\\\");\\n }\\n\\n function _isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n uint size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n /// @param _data Additional data with no specified format, sent in call to `_to`.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n bytes memory _data\\n ) public {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n\\n if (_isContract(_to)) {\\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\\n revert(\\\"ERC721: ERC721Receiver rejected tokens\\\");\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert('ERC721: transfer to non ERC721Receiver implementer');\\n } else {\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC165 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Interface identification is specified in ERC-165.\\n /// @param _interfaceID Id of the interface\\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\\n return supportedInterfaces[_interfaceID];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from owner address to mapping of index to tokenIds\\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\\n\\n /// @dev Mapping from NFT ID to index of owner\\n mapping(uint => uint) internal tokenToOwnerIndex;\\n\\n /// @dev Get token by index\\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\\n return ownerToNFTokenIdList[_owner][_tokenIndex];\\n }\\n\\n /// @dev Add a NFT to an index mapping to a given address\\n /// @param _to address of the receiver\\n /// @param _tokenId uint ID Of the token to be added\\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\\n uint current_count = _balance(_to);\\n\\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\\n tokenToOwnerIndex[_tokenId] = current_count;\\n }\\n\\n /// @dev Add a NFT to a given address\\n /// Throws if `_tokenId` is owned by someone.\\n function _addTokenTo(address _to, uint _tokenId) internal {\\n // Throws if `_tokenId` is owned by someone\\n assert(idToOwner[_tokenId] == address(0));\\n // Change the owner\\n idToOwner[_tokenId] = _to;\\n // Update owner token index tracking\\n _addTokenToOwnerList(_to, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_to] += 1;\\n }\\n\\n /// @dev Function to mint tokens\\n /// Throws if `_to` is zero address.\\n /// Throws if `_tokenId` is owned by someone.\\n /// @param _to The address that will receive the minted tokens.\\n /// @param _tokenId The token id to mint.\\n /// @return A boolean that indicates if the operation was successful.\\n function _mint(address _to, uint _tokenId) internal returns (bool) {\\n // Throws if `_to` is zero address\\n assert(_to != address(0));\\n // checkpoint for gov\\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\\n // Add NFT. Throws if `_tokenId` is owned by someone\\n _addTokenTo(_to, _tokenId);\\n emit Transfer(address(0), _to, _tokenId);\\n return true;\\n }\\n\\n /// @dev Remove a NFT from an index mapping to a given address\\n /// @param _from address of the sender\\n /// @param _tokenId uint ID Of the token to be removed\\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\\n // Delete\\n uint current_count = _balance(_from) - 1;\\n uint current_index = tokenToOwnerIndex[_tokenId];\\n\\n if (current_count == current_index) {\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n } else {\\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\\n\\n // Add\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[lastTokenId] = current_index;\\n\\n // Delete\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n }\\n }\\n\\n /// @dev Remove a NFT from a given address\\n /// Throws if `_from` is not the current owner.\\n function _removeTokenFrom(address _from, uint _tokenId) internal {\\n // Throws if `_from` is not the current owner\\n assert(idToOwner[_tokenId] == _from);\\n // Change the owner\\n idToOwner[_tokenId] = address(0);\\n // Update owner token index tracking\\n _removeTokenFromOwnerList(_from, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_from] -= 1;\\n }\\n\\n function _burn(uint _tokenId) internal {\\n require(_isApprovedOrOwner(msg.sender, _tokenId), \\\"caller is not owner nor approved\\\");\\n\\n address owner = ownerOf(_tokenId);\\n\\n // Clear approval\\n approve(address(0), _tokenId);\\n // checkpoint for gov\\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\\n // Remove token\\n _removeTokenFrom(msg.sender, _tokenId);\\n emit Transfer(owner, address(0), _tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public user_point_epoch;\\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\\n mapping(uint => LockedBalance) public locked;\\n uint public epoch;\\n mapping(uint => int128) public slope_changes; // time -> signed slope change\\n uint public supply;\\n\\n uint internal constant WEEK = 1 weeks;\\n uint internal constant MAXTIME = 4 * 365 * 86400;\\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\\n uint internal constant MULTIPLIER = 1 ether;\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @return Value of the slope\\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\\n uint uepoch = user_point_epoch[_tokenId];\\n return user_point_history[_tokenId][uepoch].slope;\\n }\\n\\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @param _idx User epoch number\\n /// @return Epoch time of the checkpoint\\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\\n return user_point_history[_tokenId][_idx].ts;\\n }\\n\\n /// @notice Get timestamp when `_tokenId`'s lock finishes\\n /// @param _tokenId User NFT\\n /// @return Epoch time of the lock end\\n function locked__end(uint _tokenId) external view returns (uint) {\\n return locked[_tokenId].end;\\n }\\n\\n /// @notice Record global and per-user data to checkpoint\\n /// @param _tokenId NFT token ID. No user checkpoint if 0\\n /// @param old_locked Pevious locked amount / end lock time for the user\\n /// @param new_locked New locked amount / end lock time for the user\\n function _checkpoint(\\n uint _tokenId,\\n LockedBalance memory old_locked,\\n LockedBalance memory new_locked\\n ) internal {\\n Point memory u_old;\\n Point memory u_new;\\n int128 old_dslope = 0;\\n int128 new_dslope = 0;\\n uint _epoch = epoch;\\n\\n if (_tokenId != 0) {\\n // Calculate slopes and biases\\n // Kept at zero when they have to\\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\\n u_old.slope = old_locked.amount / iMAXTIME;\\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\\n }\\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\\n u_new.slope = new_locked.amount / iMAXTIME;\\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\\n }\\n\\n // Read values of scheduled changes in the slope\\n // old_locked.end can be in the past and in the future\\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\\n old_dslope = slope_changes[old_locked.end];\\n if (new_locked.end != 0) {\\n if (new_locked.end == old_locked.end) {\\n new_dslope = old_dslope;\\n } else {\\n new_dslope = slope_changes[new_locked.end];\\n }\\n }\\n }\\n\\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\\n if (_epoch > 0) {\\n last_point = point_history[_epoch];\\n }\\n uint last_checkpoint = last_point.ts;\\n // initial_last_point is used for extrapolation to calculate block number\\n // (approximately, for *At methods) and save them\\n // as we cannot figure that out exactly from inside the contract\\n Point memory initial_last_point = last_point;\\n uint block_slope = 0; // dblock/dt\\n if (block.timestamp > last_point.ts) {\\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\\n }\\n // If last point is already recorded in this block, slope=0\\n // But that's ok b/c we know the block in such case\\n\\n // Go over weeks to fill history and calculate what the current point is\\n {\\n uint t_i = (last_checkpoint / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n // Hopefully it won't happen that this won't get used in 5 years!\\n // If it does, users will be able to withdraw but vote weight will be broken\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > block.timestamp) {\\n t_i = block.timestamp;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\\n last_point.slope += d_slope;\\n if (last_point.bias < 0) {\\n // This can happen\\n last_point.bias = 0;\\n }\\n if (last_point.slope < 0) {\\n // This cannot happen - just in case\\n last_point.slope = 0;\\n }\\n last_checkpoint = t_i;\\n last_point.ts = t_i;\\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\\n _epoch += 1;\\n if (t_i == block.timestamp) {\\n last_point.blk = block.number;\\n break;\\n } else {\\n point_history[_epoch] = last_point;\\n }\\n }\\n }\\n\\n epoch = _epoch;\\n // Now point_history is filled until t=now\\n\\n if (_tokenId != 0) {\\n // If last point was in this block, the slope change has been applied already\\n // But in such case we have 0 slope(s)\\n last_point.slope += (u_new.slope - u_old.slope);\\n last_point.bias += (u_new.bias - u_old.bias);\\n if (last_point.slope < 0) {\\n last_point.slope = 0;\\n }\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n }\\n\\n // Record the changed point into history\\n point_history[_epoch] = last_point;\\n\\n if (_tokenId != 0) {\\n // Schedule the slope changes (slope is going down)\\n // We subtract new_user_slope from [new_locked.end]\\n // and add old_user_slope to [old_locked.end]\\n if (old_locked.end > block.timestamp) {\\n // old_dslope was - u_old.slope, so we cancel that\\n old_dslope += u_old.slope;\\n if (new_locked.end == old_locked.end) {\\n old_dslope -= u_new.slope; // It was a new deposit, not extension\\n }\\n slope_changes[old_locked.end] = old_dslope;\\n }\\n\\n if (new_locked.end > block.timestamp) {\\n if (new_locked.end > old_locked.end) {\\n new_dslope -= u_new.slope; // old slope disappeared at this point\\n slope_changes[new_locked.end] = new_dslope;\\n }\\n // else: we recorded it already in old_dslope\\n }\\n // Now handle user history\\n uint user_epoch = user_point_epoch[_tokenId] + 1;\\n\\n user_point_epoch[_tokenId] = user_epoch;\\n u_new.ts = block.timestamp;\\n u_new.blk = block.number;\\n user_point_history[_tokenId][user_epoch] = u_new;\\n }\\n }\\n\\n /// @notice Deposit and lock tokens for a user\\n /// @param _tokenId NFT that holds lock\\n /// @param _value Amount to deposit\\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\\n /// @param locked_balance Previous locked amount / timestamp\\n /// @param deposit_type The type of deposit\\n function _deposit_for(\\n uint _tokenId,\\n uint _value,\\n uint unlock_time,\\n LockedBalance memory locked_balance,\\n DepositType deposit_type\\n ) internal {\\n LockedBalance memory _locked = locked_balance;\\n uint supply_before = supply;\\n\\n supply = supply_before + _value;\\n LockedBalance memory old_locked;\\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\\n // Adding to existing lock, or if a lock is expired - creating a new one\\n _locked.amount += int128(int256(_value));\\n if (unlock_time != 0) {\\n _locked.end = unlock_time;\\n }\\n locked[_tokenId] = _locked;\\n\\n // Possibilities:\\n // Both old_locked.end could be current or expired (>/< block.timestamp)\\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\\n // _locked.end > block.timestamp (always)\\n _checkpoint(_tokenId, old_locked, _locked);\\n\\n address from = msg.sender;\\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\\n assert(IERC20(token).transferFrom(from, address(this), _value));\\n }\\n\\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\\n emit Supply(supply_before, supply_before + _value);\\n }\\n\\n function block_number() external view returns (uint) {\\n return block.number;\\n }\\n\\n /// @notice Record global data to checkpoint\\n function checkpoint() external {\\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\\n }\\n\\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\\n /// cannot extend their locktime and deposit for a brand new user\\n /// @param _tokenId lock NFT\\n /// @param _value Amount to add to user's lock\\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n require(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_value > 0); // dev: need non-zero value\\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n ++tokenId;\\n uint _tokenId = tokenId;\\n _mint(_to, _tokenId);\\n\\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\\n return _tokenId;\\n }\\n\\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, msg.sender);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, _to);\\n }\\n\\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\\n /// @param _value Amount of tokens to deposit and add to the lock\\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n assert(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\\n }\\n\\n /// @notice Extend the unlock time for `_tokenId`\\n /// @param _lock_duration New number of seconds until tokens unlock\\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_locked.end > block.timestamp, 'Lock expired');\\n require(_locked.amount > 0, 'Nothing is locked');\\n require(unlock_time > _locked.end, 'Can only increase lock duration');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\\n }\\n\\n /// @notice Withdraw all tokens for `_tokenId`\\n /// @dev Only possible if the lock has expired\\n function withdraw(uint _tokenId) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n require(block.timestamp >= _locked.end, \\\"The lock didn't expire\\\");\\n uint value = uint(int256(_locked.amount));\\n\\n locked[_tokenId] = LockedBalance(0,0);\\n uint supply_before = supply;\\n supply = supply_before - value;\\n\\n // old_locked can have either expired <= timestamp or zero end\\n // _locked has only 0 end\\n // Both can have >= 0 amount\\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\\n\\n assert(IERC20(token).transfer(msg.sender, value));\\n\\n // Burn the NFT\\n _burn(_tokenId);\\n\\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\\n emit Supply(supply_before, supply_before - value);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\\n // They measure the weights for the purpose of voting, so they don't represent\\n // real coins.\\n\\n /// @notice Binary search to estimate timestamp for block number\\n /// @param _block Block to find\\n /// @param max_epoch Don't go beyond this epoch\\n /// @return Approximate timestamp for block\\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\\n // Binary search\\n uint _min = 0;\\n uint _max = max_epoch;\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (point_history[_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n /// @notice Get the current voting power for `_tokenId`\\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\\n /// @param _tokenId NFT for lock\\n /// @param _t Epoch time to return voting power at\\n /// @return User voting power\\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\\n uint _epoch = user_point_epoch[_tokenId];\\n if (_epoch == 0) {\\n return 0;\\n } else {\\n Point memory last_point = user_point_history[_tokenId][_epoch];\\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(int256(last_point.bias));\\n }\\n }\\n\\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\\n if (ownership_change[_tokenId] == block.number) return 0;\\n return _balanceOfNFT(_tokenId, block.timestamp);\\n }\\n\\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\\n return _balanceOfNFT(_tokenId, _t);\\n }\\n\\n /// @notice Measure voting power of `_tokenId` at block height `_block`\\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\\n /// @param _tokenId User's wallet NFT\\n /// @param _block Block to calculate the voting power at\\n /// @return Voting power\\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\\n // Copying and pasting totalSupply code because Vyper cannot pass by\\n // reference yet\\n assert(_block <= block.number);\\n\\n // Binary search\\n uint _min = 0;\\n uint _max = user_point_epoch[_tokenId];\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (user_point_history[_tokenId][_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n\\n Point memory upoint = user_point_history[_tokenId][_min];\\n\\n uint max_epoch = epoch;\\n uint _epoch = _find_block_epoch(_block, max_epoch);\\n Point memory point_0 = point_history[_epoch];\\n uint d_block = 0;\\n uint d_t = 0;\\n if (_epoch < max_epoch) {\\n Point memory point_1 = point_history[_epoch + 1];\\n d_block = point_1.blk - point_0.blk;\\n d_t = point_1.ts - point_0.ts;\\n } else {\\n d_block = block.number - point_0.blk;\\n d_t = block.timestamp - point_0.ts;\\n }\\n uint block_time = point_0.ts;\\n if (d_block != 0) {\\n block_time += (d_t * (_block - point_0.blk)) / d_block;\\n }\\n\\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\\n if (upoint.bias >= 0) {\\n return uint(uint128(upoint.bias));\\n } else {\\n return 0;\\n }\\n }\\n\\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\\n return _balanceOfAtNFT(_tokenId, _block);\\n }\\n\\n /// @notice Calculate total voting power at some point in the past\\n /// @param _block Block to calculate the total voting power at\\n /// @return Total voting power at `_block`\\n function totalSupplyAt(uint _block) external view returns (uint) {\\n assert(_block <= block.number);\\n uint _epoch = epoch;\\n uint target_epoch = _find_block_epoch(_block, _epoch);\\n\\n Point memory point = point_history[target_epoch];\\n uint dt = 0;\\n if (target_epoch < _epoch) {\\n Point memory point_next = point_history[target_epoch + 1];\\n if (point.blk != point_next.blk) {\\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\\n }\\n } else {\\n if (point.blk != block.number) {\\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\\n }\\n }\\n // Now dt contains info on how far are we beyond point\\n return _supply_at(point, point.ts + dt);\\n }\\n /// @notice Calculate total voting power at some point in the past\\n /// @param point The point (bias/slope) to start search from\\n /// @param t Time to calculate the total voting power at\\n /// @return Total voting power at that time\\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\\n Point memory last_point = point;\\n uint t_i = (last_point.ts / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > t) {\\n t_i = t;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\\n if (t_i == t) {\\n break;\\n }\\n last_point.slope += d_slope;\\n last_point.ts = t_i;\\n }\\n\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(uint128(last_point.bias));\\n }\\n\\n function totalSupply() external view returns (uint) {\\n return totalSupplyAtT(block.timestamp);\\n }\\n\\n /// @notice Calculate total voting power\\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\\n /// @return Total voting power\\n function totalSupplyAtT(uint t) public view returns (uint) {\\n uint _epoch = epoch;\\n Point memory last_point = point_history[_epoch];\\n return _supply_at(last_point, t);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public attachments;\\n mapping(uint => bool) public voted;\\n\\n function setVoter(address _voter) external {\\n require(msg.sender == voter);\\n voter = _voter;\\n }\\n\\n function voting(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = true;\\n }\\n\\n function abstain(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = false;\\n }\\n\\n function attach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] + 1;\\n }\\n\\n function detach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] - 1;\\n }\\n\\n function merge(uint _from, uint _to) external {\\n require(attachments[_from] == 0 && !voted[_from], \\\"attached\\\");\\n require(_from != _to);\\n require(_isApprovedOrOwner(msg.sender, _from));\\n require(_isApprovedOrOwner(msg.sender, _to));\\n\\n LockedBalance memory _locked0 = locked[_from];\\n LockedBalance memory _locked1 = locked[_to];\\n uint value0 = uint(int256(_locked0.amount));\\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\\n\\n locked[_from] = LockedBalance(0, 0);\\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\\n _burn(_from);\\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of each accounts delegate\\n mapping(address => address) private _delegates;\\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\\n\\n /// @notice A record of delegated token checkpoints for each account, by index\\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint32) public numCheckpoints;\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping(address => uint) public nonces;\\n\\n /**\\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\\n * the delegator's own address if they haven't delegated.\\n * This avoids having to delegate to oneself.\\n */\\n function delegates(address delegator) public view returns (address) {\\n address current = _delegates[delegator];\\n return current == address(0) ? delegator : current;\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getVotes(address account) external view returns (uint) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n votes = votes + _balanceOfNFT(tId, block.timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint storage cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPastVotes(address account, uint timestamp)\\n public\\n view\\n returns (uint)\\n {\\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\\n // Sum votes\\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n // Use the provided input timestamp here to get the right decay\\n votes = votes + _balanceOfNFT(tId, timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\\n return totalSupplyAtT(timestamp);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _moveTokenDelegates(\\n address srcRep,\\n address dstRep,\\n uint _tokenId\\n ) internal {\\n if (srcRep != dstRep && _tokenId > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except _tokenId\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (tId != _tokenId) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n // All the same plus _tokenId\\n require(\\n dstRepOld.length + 1 <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n dstRepNew.push(_tokenId);\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _findWhatCheckpointToWrite(address account)\\n internal\\n view\\n returns (uint32)\\n {\\n uint _timestamp = block.timestamp;\\n uint32 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n return _nCheckPoints - 1;\\n } else {\\n return _nCheckPoints;\\n }\\n }\\n\\n function _moveAllDelegates(\\n address owner,\\n address srcRep,\\n address dstRep\\n ) internal {\\n // You can only redelegate what you own\\n if (srcRep != dstRep) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except what owner owns\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (idToOwner[tId] != owner) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n uint ownerTokenCount = ownerToNFTokenCount[owner];\\n require(\\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n // All the same\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n // Plus all that's owned\\n for (uint i = 0; i < ownerTokenCount; i++) {\\n uint tId = ownerToNFTokenIdList[owner][i];\\n dstRepNew.push(tId);\\n }\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\\n address currentDelegate = delegates(delegator);\\n\\n _delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n _moveAllDelegates(delegator, currentDelegate, delegatee);\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n if (delegatee == address(0)) delegatee = msg.sender;\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n function delegateBySig(\\n address delegatee,\\n uint nonce,\\n uint expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public {\\n bytes32 domainSeparator = keccak256(\\n abi.encode(\\n DOMAIN_TYPEHASH,\\n keccak256(bytes(name)),\\n keccak256(bytes(version)),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 structHash = keccak256(\\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash)\\n );\\n address signatory = ecrecover(digest, v, r, s);\\n require(\\n signatory != address(0),\\n \\\"VotingEscrow::delegateBySig: invalid signature\\\"\\n );\\n require(\\n nonce == nonces[signatory]++,\\n \\\"VotingEscrow::delegateBySig: invalid nonce\\\"\\n );\\n require(\\n block.timestamp <= expiry,\\n \\\"VotingEscrow::delegateBySig: signature expired\\\"\\n );\\n return _delegate(signatory, delegatee);\\n }\\n}\\n\",\"keccak256\":\"0x37e5ee306472a946a665be22bc1d370d566a575a1fac84f72f97b0575571d40d\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x41bbb2c41036ca64b2f6c9e973e8cfaa113ebc42af86702cd0d267f915a7e886\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60a06040526006805460ff191660011790553480156200001e57600080fd5b5060405162004a1c38038062004a1c8339810160408190526200004191620001b8565b6001600160a01b0382811660805260008054336001600160a01b031991821681178355600180548316909117815560028054909216938516939093179055437f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f0155427f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f005560046020527f9fe05126d2d9ecf60592e254dead906a4b2e492f36cca727682c38e9008c6ac1805460ff1990811684179091557f4267c0a6fd96b7a87f183ee8744f24d011423cd0e0142b3f563f183d8d9a456b8054821684179055635b5e139f60e01b82527e24030bcf4927897dffe721c2d8dda4bfd8910861687c42b03a463b43b04147805490911690921790915560055460405190913091600080516020620049fc833981519152908290a46005546040516000903090600080516020620049fc833981519152908390a45050620001f0565b80516001600160a01b0381168114620001b357600080fd5b919050565b60008060408385031215620001cc57600080fd5b620001d7836200019b565b9150620001e7602084016200019b565b90509250929050565b6080516147e26200021a60003960008181610b220152818161101801526133b501526147e26000f3fe608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea26469706673582212200d861f6646b49aa0a1731ef5e7e97f6ca91f05890c57fa056a41a43c6168d99f64736f6c634300080d0033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea26469706673582212200d861f6646b49aa0a1731ef5e7e97f6ca91f05890c57fa056a41a43c6168d99f64736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token_addr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"art_proxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromDelegate\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toDelegate\",\"type\":\"address\"}],\"name\":\"DelegateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"DelegateVotesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"locktime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum VotingEscrow.DepositType\",\"name\":\"deposit_type\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"prevSupply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"supply\",\"type\":\"uint256\"}],\"name\":\"Supply\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DELEGATION_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_DELEGATES\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"abstain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_approved\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"artProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"attach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"attachments\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"balanceOfAtNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_t\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFTAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"block_number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"checkpoints\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"create_lock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"create_lock_for\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"}],\"name\":\"delegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"delegateBySig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"}],\"name\":\"delegates\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"deposit_for\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"detach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastTotalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotesIndex\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"get_last_user_slope\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"increase_amount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"increase_unlock_time\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"isApprovedOrOwner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"locked\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"amount\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"locked__end\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_from\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_to\",\"type\":\"uint256\"}],\"name\":\"merge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"numCheckpoints\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ownership_change\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_proxy\",\"type\":\"address\"}],\"name\":\"setArtProxy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voter\",\"type\":\"address\"}],\"name\":\"setVoter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"slope_changes\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenIndex\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"t\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAtT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_idx\",\"type\":\"uint256\"}],\"name\":\"user_point_history__ts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"voted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"voting\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\",\"details\":\"Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\",\"kind\":\"dev\",\"methods\":{\"approve(address,uint256)\":{\"details\":\"Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address. Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner. Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP) Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"Address to be approved for the given NFT ID.\",\"_tokenId\":\"ID of the token to be approved.\"}},\"balanceOf(address)\":{\"details\":\"Returns the number of NFTs owned by `_owner`. Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\",\"params\":{\"_owner\":\"Address for whom to query the balance.\"}},\"constructor\":{\"params\":{\"token_addr\":\"`FLOW` token address\"}},\"create_lock(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_value\":\"Amount to deposit\"}},\"create_lock_for(uint256,uint256,address)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_to\":\"Address to deposit\",\"_value\":\"Amount to deposit\"}},\"delegate(address)\":{\"params\":{\"delegatee\":\"The address to delegate votes to\"}},\"delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Delegates votes from signer to `delegatee`.\"},\"deposit_for(uint256,uint256)\":{\"details\":\"Anyone (even a smart contract) can deposit for someone else, but cannot extend their locktime and deposit for a brand new user\",\"params\":{\"_tokenId\":\"lock NFT\",\"_value\":\"Amount to add to user's lock\"}},\"getApproved(uint256)\":{\"details\":\"Get the approved address for a single NFT.\",\"params\":{\"_tokenId\":\"ID of the NFT to query the approval of.\"}},\"getVotes(address)\":{\"params\":{\"account\":\"The address to get votes balance\"},\"returns\":{\"_0\":\"The number of current votes for `account`\"}},\"get_last_user_slope(uint256)\":{\"params\":{\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Value of the slope\"}},\"increase_amount(uint256,uint256)\":{\"params\":{\"_value\":\"Amount of tokens to deposit and add to the lock\"}},\"increase_unlock_time(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"New number of seconds until tokens unlock\"}},\"isApprovedForAll(address,address)\":{\"details\":\"Checks if `_operator` is an approved operator for `_owner`.\",\"params\":{\"_operator\":\"The address that acts on behalf of the owner.\",\"_owner\":\"The address that owns the NFTs.\"}},\"locked__end(uint256)\":{\"params\":{\"_tokenId\":\"User NFT\"},\"returns\":{\"_0\":\"Epoch time of the lock end\"}},\"ownerOf(uint256)\":{\"details\":\"Returns the address of the owner of the NFT.\",\"params\":{\"_tokenId\":\"The identifier for an NFT.\"}},\"safeTransferFrom(address,address,uint256)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"safeTransferFrom(address,address,uint256,bytes)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_data\":\"Additional data with no specified format, sent in call to `_to`.\",\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"details\":\"Enables or disables approval for a third party (\\\"operator\\\") to manage all of `msg.sender`'s assets. It also emits the ApprovalForAll event. Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"True if the operators is approved, false to revoke approval.\",\"_operator\":\"Address to add to the set of authorized operators.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Interface identification is specified in ERC-165.\",\"params\":{\"_interfaceID\":\"Id of the interface\"}},\"tokenOfOwnerByIndex(address,uint256)\":{\"details\":\"Get token by index\"},\"tokenURI(uint256)\":{\"details\":\"Returns current token URI metadata\",\"params\":{\"_tokenId\":\"Token ID to fetch URI for.\"}},\"totalSupplyAt(uint256)\":{\"params\":{\"_block\":\"Block to calculate the total voting power at\"},\"returns\":{\"_0\":\"Total voting power at `_block`\"}},\"totalSupplyAtT(uint256)\":{\"details\":\"Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\",\"returns\":{\"_0\":\"Total voting power\"}},\"transferFrom(address,address,uint256)\":{\"details\":\"Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"user_point_history__ts(uint256,uint256)\":{\"params\":{\"_idx\":\"User epoch number\",\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Epoch time of the checkpoint\"}},\"withdraw(uint256)\":{\"details\":\"Only possible if the lock has expired\"}},\"stateVariables\":{\"ERC165_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC165\"},\"ERC721_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721\"},\"ERC721_METADATA_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721Metadata\"},\"_not_entered\":{\"details\":\"reentrancy guard\"},\"idToApprovals\":{\"details\":\"Mapping from NFT ID to approved address.\"},\"idToOwner\":{\"details\":\"Mapping from NFT ID to the address that owns it.\"},\"name\":{\"details\":\"Returns the token collection name.\"},\"ownerToNFTokenCount\":{\"details\":\"Mapping from owner address to count of his tokens.\"},\"ownerToNFTokenIdList\":{\"details\":\"Mapping from owner address to mapping of index to tokenIds\"},\"ownerToOperators\":{\"details\":\"Mapping from owner address to mapping of operator addresses.\"},\"supportedInterfaces\":{\"details\":\"Mapping of interface id to bool about whether or not it's supported\"},\"symbol\":{\"details\":\"Returns the token collection symbol.\"},\"tokenId\":{\"details\":\"Current count of token\"},\"tokenToOwnerIndex\":{\"details\":\"Mapping from NFT ID to index of owner\"}},\"title\":\"Voting Escrow\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DELEGATION_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the delegation struct used by the contract\"},\"DOMAIN_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the contract's domain\"},\"checkpoint()\":{\"notice\":\"Record global data to checkpoint\"},\"checkpoints(address,uint32)\":{\"notice\":\"A record of delegated token checkpoints for each account, by index\"},\"constructor\":{\"notice\":\"Contract constructor\"},\"create_lock(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\"},\"create_lock_for(uint256,uint256,address)\":{\"notice\":\"Deposit `_value` tokens for `_to` and lock for `_lock_duration`\"},\"delegate(address)\":{\"notice\":\"Delegate votes from `msg.sender` to `delegatee`\"},\"delegates(address)\":{\"notice\":\"Overrides the standard `Comp.sol` delegates mapping to return the delegator's own address if they haven't delegated. This avoids having to delegate to oneself.\"},\"deposit_for(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `_tokenId` and add to the lock\"},\"getVotes(address)\":{\"notice\":\"Gets the current votes balance for `account`\"},\"get_last_user_slope(uint256)\":{\"notice\":\"Get the most recently recorded rate of voting power decrease for `_tokenId`\"},\"increase_amount(uint256,uint256)\":{\"notice\":\"Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\"},\"increase_unlock_time(uint256,uint256)\":{\"notice\":\"Extend the unlock time for `_tokenId`\"},\"locked__end(uint256)\":{\"notice\":\"Get timestamp when `_tokenId`'s lock finishes\"},\"nonces(address)\":{\"notice\":\"A record of states for signing / validating signatures\"},\"numCheckpoints(address)\":{\"notice\":\"The number of checkpoints for each account\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"This works even if sender doesn't own any tokens at the time.\"},\"totalSupplyAt(uint256)\":{\"notice\":\"Calculate total voting power at some point in the past\"},\"totalSupplyAtT(uint256)\":{\"notice\":\"Calculate total voting power\"},\"transferFrom(address,address,uint256)\":{\"notice\":\"The caller is responsible to confirm that `_to` is capable of receiving NFTs or else they maybe be permanently lost.\"},\"user_point_history__ts(uint256,uint256)\":{\"notice\":\"Get the timestamp for checkpoint `_idx` for `_tokenId`\"},\"withdraw(uint256)\":{\"notice\":\"Withdraw all tokens for `_tokenId`\"}},\"notice\":\"veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFTVotes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VotingEscrow.sol\":\"VotingEscrow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VotingEscrow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IERC721, IERC721Metadata} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {IERC721Receiver} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {IERC20} from \\\"contracts/interfaces/IERC20.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\nimport {IVotingEscrow} from \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/// @title Voting Escrow\\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\\n enum DepositType {\\n DEPOSIT_FOR_TYPE,\\n CREATE_LOCK_TYPE,\\n INCREASE_LOCK_AMOUNT,\\n INCREASE_UNLOCK_TIME,\\n MERGE_TYPE\\n }\\n\\n struct LockedBalance {\\n int128 amount;\\n uint end;\\n }\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint ts;\\n uint blk; // block\\n }\\n /* We cannot really do block numbers per se b/c slope is per time, not per block\\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\\n * What we can do is to extrapolate ***At functions */\\n\\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\\n struct Checkpoint {\\n uint timestamp;\\n uint[] tokenIds;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Deposit(\\n address indexed provider,\\n uint tokenId,\\n uint value,\\n uint indexed locktime,\\n DepositType deposit_type,\\n uint ts\\n );\\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\\n event Supply(uint prevSupply, uint supply);\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n address public immutable token;\\n address public voter;\\n address public team;\\n address public artProxy;\\n\\n mapping(uint => Point) public point_history; // epoch -> unsigned point\\n\\n /// @dev Mapping of interface id to bool about whether or not it's supported\\n mapping(bytes4 => bool) internal supportedInterfaces;\\n\\n /// @dev ERC165 interface ID of ERC165\\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\\n\\n /// @dev ERC165 interface ID of ERC721\\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\\n\\n /// @dev ERC165 interface ID of ERC721Metadata\\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\\n\\n /// @dev Current count of token\\n uint internal tokenId;\\n\\n /// @notice Contract constructor\\n /// @param token_addr `FLOW` token address\\n constructor(address token_addr, address art_proxy) {\\n token = token_addr;\\n voter = msg.sender;\\n team = msg.sender;\\n artProxy = art_proxy;\\n\\n point_history[0].blk = block.number;\\n point_history[0].ts = block.timestamp;\\n\\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\\n\\n // mint-ish\\n emit Transfer(address(0), address(this), tokenId);\\n // burn-ish\\n emit Transfer(address(this), address(0), tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n MODIFIERS\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev reentrancy guard\\n uint8 internal constant _not_entered = 1;\\n uint8 internal constant _entered = 2;\\n uint8 internal _entered_state = 1;\\n modifier nonreentrant() {\\n require(_entered_state == _not_entered);\\n _entered_state = _entered;\\n _;\\n _entered_state = _not_entered;\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string constant public name = \\\"veNFT\\\";\\n string constant public symbol = \\\"veNFT\\\";\\n string constant public version = \\\"1.0.0\\\";\\n uint8 constant public decimals = 18;\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team);\\n team = _team;\\n }\\n\\n function setArtProxy(address _proxy) external {\\n require(msg.sender == team);\\n artProxy = _proxy;\\n }\\n\\n /// @dev Returns current token URI metadata\\n /// @param _tokenId Token ID to fetch URI for.\\n function tokenURI(uint _tokenId) external view returns (string memory) {\\n require(idToOwner[_tokenId] != address(0), \\\"Query for nonexistent token\\\");\\n LockedBalance memory _locked = locked[_tokenId];\\n return IVeArtProxy(artProxy)._tokenURI(\\n _tokenId,\\n _balanceOfNFT(_tokenId, block.timestamp),\\n _locked.end,\\n uint(int256(_locked.amount))\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 BALANCE/OWNER STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to the address that owns it.\\n mapping(uint => address) internal idToOwner;\\n\\n /// @dev Mapping from owner address to count of his tokens.\\n mapping(address => uint) internal ownerToNFTokenCount;\\n\\n /// @dev Returns the address of the owner of the NFT.\\n /// @param _tokenId The identifier for an NFT.\\n function ownerOf(uint _tokenId) public view returns (address) {\\n return idToOwner[_tokenId];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function _balance(address _owner) internal view returns (uint) {\\n return ownerToNFTokenCount[_owner];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function balanceOf(address _owner) external view returns (uint) {\\n return _balance(_owner);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 APPROVAL STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to approved address.\\n mapping(uint => address) internal idToApprovals;\\n\\n /// @dev Mapping from owner address to mapping of operator addresses.\\n mapping(address => mapping(address => bool)) internal ownerToOperators;\\n\\n mapping(uint => uint) public ownership_change;\\n\\n /// @dev Get the approved address for a single NFT.\\n /// @param _tokenId ID of the NFT to query the approval of.\\n function getApproved(uint _tokenId) external view returns (address) {\\n return idToApprovals[_tokenId];\\n }\\n\\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\\n /// @param _owner The address that owns the NFTs.\\n /// @param _operator The address that acts on behalf of the owner.\\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\\n return (ownerToOperators[_owner])[_operator];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\\n /// @param _approved Address to be approved for the given NFT ID.\\n /// @param _tokenId ID of the token to be approved.\\n function approve(address _approved, uint _tokenId) public {\\n address owner = idToOwner[_tokenId];\\n // Throws if `_tokenId` is not a valid NFT\\n require(owner != address(0));\\n // Throws if `_approved` is the current owner\\n require(_approved != owner);\\n // Check requirements\\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\\n require(senderIsOwner || senderIsApprovedForAll);\\n // Set the approval\\n idToApprovals[_tokenId] = _approved;\\n emit Approval(owner, _approved, _tokenId);\\n }\\n\\n /// @dev Enables or disables approval for a third party (\\\"operator\\\") to manage all of\\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\\n /// @notice This works even if sender doesn't own any tokens at the time.\\n /// @param _operator Address to add to the set of authorized operators.\\n /// @param _approved True if the operators is approved, false to revoke approval.\\n function setApprovalForAll(address _operator, bool _approved) external {\\n // Throws if `_operator` is the `msg.sender`\\n assert(_operator != msg.sender);\\n ownerToOperators[msg.sender][_operator] = _approved;\\n emit ApprovalForAll(msg.sender, _operator, _approved);\\n }\\n\\n /* TRANSFER FUNCTIONS */\\n /// @dev Clear an approval of a given address\\n /// Throws if `_owner` is not the current owner.\\n function _clearApproval(address _owner, uint _tokenId) internal {\\n // Throws if `_owner` is not the current owner\\n assert(idToOwner[_tokenId] == _owner);\\n if (idToApprovals[_tokenId] != address(0)) {\\n // Reset approvals\\n idToApprovals[_tokenId] = address(0);\\n }\\n }\\n\\n /// @dev Returns whether the given spender can transfer a given token ID\\n /// @param _spender address of the spender to query\\n /// @param _tokenId uint ID of the token to be transferred\\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\\n address owner = idToOwner[_tokenId];\\n bool spenderIsOwner = owner == _spender;\\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\\n }\\n\\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\\n return _isApprovedOrOwner(_spender, _tokenId);\\n }\\n\\n /// @dev Exeute transfer of a NFT.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_tokenId` is not a valid NFT.\\n function _transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n address _sender\\n ) internal {\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n // Check requirements\\n require(_isApprovedOrOwner(_sender, _tokenId));\\n // Clear approval. Throws if `_from` is not the current owner\\n _clearApproval(_from, _tokenId);\\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\\n _removeTokenFrom(_from, _tokenId);\\n // auto re-delegate\\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\\n // Add NFT\\n _addTokenTo(_to, _tokenId);\\n // Set the block of ownership transfer (for Flash NFT protection)\\n ownership_change[_tokenId] = block.number;\\n // Log the transfer\\n emit Transfer(_from, _to, _tokenId);\\n }\\n\\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\\n /// they maybe be permanently lost.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n safeTransferFrom(_from, _to, _tokenId, \\\"\\\");\\n }\\n\\n function _isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n uint size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n /// @param _data Additional data with no specified format, sent in call to `_to`.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n bytes memory _data\\n ) public {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n\\n if (_isContract(_to)) {\\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\\n revert(\\\"ERC721: ERC721Receiver rejected tokens\\\");\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert('ERC721: transfer to non ERC721Receiver implementer');\\n } else {\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC165 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Interface identification is specified in ERC-165.\\n /// @param _interfaceID Id of the interface\\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\\n return supportedInterfaces[_interfaceID];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from owner address to mapping of index to tokenIds\\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\\n\\n /// @dev Mapping from NFT ID to index of owner\\n mapping(uint => uint) internal tokenToOwnerIndex;\\n\\n /// @dev Get token by index\\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\\n return ownerToNFTokenIdList[_owner][_tokenIndex];\\n }\\n\\n /// @dev Add a NFT to an index mapping to a given address\\n /// @param _to address of the receiver\\n /// @param _tokenId uint ID Of the token to be added\\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\\n uint current_count = _balance(_to);\\n\\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\\n tokenToOwnerIndex[_tokenId] = current_count;\\n }\\n\\n /// @dev Add a NFT to a given address\\n /// Throws if `_tokenId` is owned by someone.\\n function _addTokenTo(address _to, uint _tokenId) internal {\\n // Throws if `_tokenId` is owned by someone\\n assert(idToOwner[_tokenId] == address(0));\\n // Change the owner\\n idToOwner[_tokenId] = _to;\\n // Update owner token index tracking\\n _addTokenToOwnerList(_to, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_to] += 1;\\n }\\n\\n /// @dev Function to mint tokens\\n /// Throws if `_to` is zero address.\\n /// Throws if `_tokenId` is owned by someone.\\n /// @param _to The address that will receive the minted tokens.\\n /// @param _tokenId The token id to mint.\\n /// @return A boolean that indicates if the operation was successful.\\n function _mint(address _to, uint _tokenId) internal returns (bool) {\\n // Throws if `_to` is zero address\\n assert(_to != address(0));\\n // checkpoint for gov\\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\\n // Add NFT. Throws if `_tokenId` is owned by someone\\n _addTokenTo(_to, _tokenId);\\n emit Transfer(address(0), _to, _tokenId);\\n return true;\\n }\\n\\n /// @dev Remove a NFT from an index mapping to a given address\\n /// @param _from address of the sender\\n /// @param _tokenId uint ID Of the token to be removed\\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\\n // Delete\\n uint current_count = _balance(_from) - 1;\\n uint current_index = tokenToOwnerIndex[_tokenId];\\n\\n if (current_count == current_index) {\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n } else {\\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\\n\\n // Add\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[lastTokenId] = current_index;\\n\\n // Delete\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n }\\n }\\n\\n /// @dev Remove a NFT from a given address\\n /// Throws if `_from` is not the current owner.\\n function _removeTokenFrom(address _from, uint _tokenId) internal {\\n // Throws if `_from` is not the current owner\\n assert(idToOwner[_tokenId] == _from);\\n // Change the owner\\n idToOwner[_tokenId] = address(0);\\n // Update owner token index tracking\\n _removeTokenFromOwnerList(_from, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_from] -= 1;\\n }\\n\\n function _burn(uint _tokenId) internal {\\n require(_isApprovedOrOwner(msg.sender, _tokenId), \\\"caller is not owner nor approved\\\");\\n\\n address owner = ownerOf(_tokenId);\\n\\n // Clear approval\\n approve(address(0), _tokenId);\\n // checkpoint for gov\\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\\n // Remove token\\n _removeTokenFrom(msg.sender, _tokenId);\\n emit Transfer(owner, address(0), _tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public user_point_epoch;\\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\\n mapping(uint => LockedBalance) public locked;\\n uint public epoch;\\n mapping(uint => int128) public slope_changes; // time -> signed slope change\\n uint public supply;\\n\\n uint internal constant WEEK = 1 weeks;\\n uint internal constant MAXTIME = 4 * 365 * 86400;\\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\\n uint internal constant MULTIPLIER = 1 ether;\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @return Value of the slope\\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\\n uint uepoch = user_point_epoch[_tokenId];\\n return user_point_history[_tokenId][uepoch].slope;\\n }\\n\\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @param _idx User epoch number\\n /// @return Epoch time of the checkpoint\\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\\n return user_point_history[_tokenId][_idx].ts;\\n }\\n\\n /// @notice Get timestamp when `_tokenId`'s lock finishes\\n /// @param _tokenId User NFT\\n /// @return Epoch time of the lock end\\n function locked__end(uint _tokenId) external view returns (uint) {\\n return locked[_tokenId].end;\\n }\\n\\n /// @notice Record global and per-user data to checkpoint\\n /// @param _tokenId NFT token ID. No user checkpoint if 0\\n /// @param old_locked Pevious locked amount / end lock time for the user\\n /// @param new_locked New locked amount / end lock time for the user\\n function _checkpoint(\\n uint _tokenId,\\n LockedBalance memory old_locked,\\n LockedBalance memory new_locked\\n ) internal {\\n Point memory u_old;\\n Point memory u_new;\\n int128 old_dslope = 0;\\n int128 new_dslope = 0;\\n uint _epoch = epoch;\\n\\n if (_tokenId != 0) {\\n // Calculate slopes and biases\\n // Kept at zero when they have to\\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\\n u_old.slope = old_locked.amount / iMAXTIME;\\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\\n }\\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\\n u_new.slope = new_locked.amount / iMAXTIME;\\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\\n }\\n\\n // Read values of scheduled changes in the slope\\n // old_locked.end can be in the past and in the future\\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\\n old_dslope = slope_changes[old_locked.end];\\n if (new_locked.end != 0) {\\n if (new_locked.end == old_locked.end) {\\n new_dslope = old_dslope;\\n } else {\\n new_dslope = slope_changes[new_locked.end];\\n }\\n }\\n }\\n\\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\\n if (_epoch > 0) {\\n last_point = point_history[_epoch];\\n }\\n uint last_checkpoint = last_point.ts;\\n // initial_last_point is used for extrapolation to calculate block number\\n // (approximately, for *At methods) and save them\\n // as we cannot figure that out exactly from inside the contract\\n Point memory initial_last_point = last_point;\\n uint block_slope = 0; // dblock/dt\\n if (block.timestamp > last_point.ts) {\\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\\n }\\n // If last point is already recorded in this block, slope=0\\n // But that's ok b/c we know the block in such case\\n\\n // Go over weeks to fill history and calculate what the current point is\\n {\\n uint t_i = (last_checkpoint / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n // Hopefully it won't happen that this won't get used in 5 years!\\n // If it does, users will be able to withdraw but vote weight will be broken\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > block.timestamp) {\\n t_i = block.timestamp;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\\n last_point.slope += d_slope;\\n if (last_point.bias < 0) {\\n // This can happen\\n last_point.bias = 0;\\n }\\n if (last_point.slope < 0) {\\n // This cannot happen - just in case\\n last_point.slope = 0;\\n }\\n last_checkpoint = t_i;\\n last_point.ts = t_i;\\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\\n _epoch += 1;\\n if (t_i == block.timestamp) {\\n last_point.blk = block.number;\\n break;\\n } else {\\n point_history[_epoch] = last_point;\\n }\\n }\\n }\\n\\n epoch = _epoch;\\n // Now point_history is filled until t=now\\n\\n if (_tokenId != 0) {\\n // If last point was in this block, the slope change has been applied already\\n // But in such case we have 0 slope(s)\\n last_point.slope += (u_new.slope - u_old.slope);\\n last_point.bias += (u_new.bias - u_old.bias);\\n if (last_point.slope < 0) {\\n last_point.slope = 0;\\n }\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n }\\n\\n // Record the changed point into history\\n point_history[_epoch] = last_point;\\n\\n if (_tokenId != 0) {\\n // Schedule the slope changes (slope is going down)\\n // We subtract new_user_slope from [new_locked.end]\\n // and add old_user_slope to [old_locked.end]\\n if (old_locked.end > block.timestamp) {\\n // old_dslope was - u_old.slope, so we cancel that\\n old_dslope += u_old.slope;\\n if (new_locked.end == old_locked.end) {\\n old_dslope -= u_new.slope; // It was a new deposit, not extension\\n }\\n slope_changes[old_locked.end] = old_dslope;\\n }\\n\\n if (new_locked.end > block.timestamp) {\\n if (new_locked.end > old_locked.end) {\\n new_dslope -= u_new.slope; // old slope disappeared at this point\\n slope_changes[new_locked.end] = new_dslope;\\n }\\n // else: we recorded it already in old_dslope\\n }\\n // Now handle user history\\n uint user_epoch = user_point_epoch[_tokenId] + 1;\\n\\n user_point_epoch[_tokenId] = user_epoch;\\n u_new.ts = block.timestamp;\\n u_new.blk = block.number;\\n user_point_history[_tokenId][user_epoch] = u_new;\\n }\\n }\\n\\n /// @notice Deposit and lock tokens for a user\\n /// @param _tokenId NFT that holds lock\\n /// @param _value Amount to deposit\\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\\n /// @param locked_balance Previous locked amount / timestamp\\n /// @param deposit_type The type of deposit\\n function _deposit_for(\\n uint _tokenId,\\n uint _value,\\n uint unlock_time,\\n LockedBalance memory locked_balance,\\n DepositType deposit_type\\n ) internal {\\n LockedBalance memory _locked = locked_balance;\\n uint supply_before = supply;\\n\\n supply = supply_before + _value;\\n LockedBalance memory old_locked;\\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\\n // Adding to existing lock, or if a lock is expired - creating a new one\\n _locked.amount += int128(int256(_value));\\n if (unlock_time != 0) {\\n _locked.end = unlock_time;\\n }\\n locked[_tokenId] = _locked;\\n\\n // Possibilities:\\n // Both old_locked.end could be current or expired (>/< block.timestamp)\\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\\n // _locked.end > block.timestamp (always)\\n _checkpoint(_tokenId, old_locked, _locked);\\n\\n address from = msg.sender;\\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\\n assert(IERC20(token).transferFrom(from, address(this), _value));\\n }\\n\\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\\n emit Supply(supply_before, supply_before + _value);\\n }\\n\\n function block_number() external view returns (uint) {\\n return block.number;\\n }\\n\\n /// @notice Record global data to checkpoint\\n function checkpoint() external {\\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\\n }\\n\\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\\n /// cannot extend their locktime and deposit for a brand new user\\n /// @param _tokenId lock NFT\\n /// @param _value Amount to add to user's lock\\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n require(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_value > 0); // dev: need non-zero value\\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n ++tokenId;\\n uint _tokenId = tokenId;\\n _mint(_to, _tokenId);\\n\\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\\n return _tokenId;\\n }\\n\\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, msg.sender);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, _to);\\n }\\n\\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\\n /// @param _value Amount of tokens to deposit and add to the lock\\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n assert(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\\n }\\n\\n /// @notice Extend the unlock time for `_tokenId`\\n /// @param _lock_duration New number of seconds until tokens unlock\\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_locked.end > block.timestamp, 'Lock expired');\\n require(_locked.amount > 0, 'Nothing is locked');\\n require(unlock_time > _locked.end, 'Can only increase lock duration');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\\n }\\n\\n /// @notice Withdraw all tokens for `_tokenId`\\n /// @dev Only possible if the lock has expired\\n function withdraw(uint _tokenId) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n require(block.timestamp >= _locked.end, \\\"The lock didn't expire\\\");\\n uint value = uint(int256(_locked.amount));\\n\\n locked[_tokenId] = LockedBalance(0,0);\\n uint supply_before = supply;\\n supply = supply_before - value;\\n\\n // old_locked can have either expired <= timestamp or zero end\\n // _locked has only 0 end\\n // Both can have >= 0 amount\\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\\n\\n assert(IERC20(token).transfer(msg.sender, value));\\n\\n // Burn the NFT\\n _burn(_tokenId);\\n\\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\\n emit Supply(supply_before, supply_before - value);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\\n // They measure the weights for the purpose of voting, so they don't represent\\n // real coins.\\n\\n /// @notice Binary search to estimate timestamp for block number\\n /// @param _block Block to find\\n /// @param max_epoch Don't go beyond this epoch\\n /// @return Approximate timestamp for block\\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\\n // Binary search\\n uint _min = 0;\\n uint _max = max_epoch;\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (point_history[_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n /// @notice Get the current voting power for `_tokenId`\\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\\n /// @param _tokenId NFT for lock\\n /// @param _t Epoch time to return voting power at\\n /// @return User voting power\\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\\n uint _epoch = user_point_epoch[_tokenId];\\n if (_epoch == 0) {\\n return 0;\\n } else {\\n Point memory last_point = user_point_history[_tokenId][_epoch];\\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(int256(last_point.bias));\\n }\\n }\\n\\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\\n if (ownership_change[_tokenId] == block.number) return 0;\\n return _balanceOfNFT(_tokenId, block.timestamp);\\n }\\n\\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\\n return _balanceOfNFT(_tokenId, _t);\\n }\\n\\n /// @notice Measure voting power of `_tokenId` at block height `_block`\\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\\n /// @param _tokenId User's wallet NFT\\n /// @param _block Block to calculate the voting power at\\n /// @return Voting power\\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\\n // Copying and pasting totalSupply code because Vyper cannot pass by\\n // reference yet\\n assert(_block <= block.number);\\n\\n // Binary search\\n uint _min = 0;\\n uint _max = user_point_epoch[_tokenId];\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (user_point_history[_tokenId][_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n\\n Point memory upoint = user_point_history[_tokenId][_min];\\n\\n uint max_epoch = epoch;\\n uint _epoch = _find_block_epoch(_block, max_epoch);\\n Point memory point_0 = point_history[_epoch];\\n uint d_block = 0;\\n uint d_t = 0;\\n if (_epoch < max_epoch) {\\n Point memory point_1 = point_history[_epoch + 1];\\n d_block = point_1.blk - point_0.blk;\\n d_t = point_1.ts - point_0.ts;\\n } else {\\n d_block = block.number - point_0.blk;\\n d_t = block.timestamp - point_0.ts;\\n }\\n uint block_time = point_0.ts;\\n if (d_block != 0) {\\n block_time += (d_t * (_block - point_0.blk)) / d_block;\\n }\\n\\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\\n if (upoint.bias >= 0) {\\n return uint(uint128(upoint.bias));\\n } else {\\n return 0;\\n }\\n }\\n\\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\\n return _balanceOfAtNFT(_tokenId, _block);\\n }\\n\\n /// @notice Calculate total voting power at some point in the past\\n /// @param _block Block to calculate the total voting power at\\n /// @return Total voting power at `_block`\\n function totalSupplyAt(uint _block) external view returns (uint) {\\n assert(_block <= block.number);\\n uint _epoch = epoch;\\n uint target_epoch = _find_block_epoch(_block, _epoch);\\n\\n Point memory point = point_history[target_epoch];\\n uint dt = 0;\\n if (target_epoch < _epoch) {\\n Point memory point_next = point_history[target_epoch + 1];\\n if (point.blk != point_next.blk) {\\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\\n }\\n } else {\\n if (point.blk != block.number) {\\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\\n }\\n }\\n // Now dt contains info on how far are we beyond point\\n return _supply_at(point, point.ts + dt);\\n }\\n /// @notice Calculate total voting power at some point in the past\\n /// @param point The point (bias/slope) to start search from\\n /// @param t Time to calculate the total voting power at\\n /// @return Total voting power at that time\\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\\n Point memory last_point = point;\\n uint t_i = (last_point.ts / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > t) {\\n t_i = t;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\\n if (t_i == t) {\\n break;\\n }\\n last_point.slope += d_slope;\\n last_point.ts = t_i;\\n }\\n\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(uint128(last_point.bias));\\n }\\n\\n function totalSupply() external view returns (uint) {\\n return totalSupplyAtT(block.timestamp);\\n }\\n\\n /// @notice Calculate total voting power\\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\\n /// @return Total voting power\\n function totalSupplyAtT(uint t) public view returns (uint) {\\n uint _epoch = epoch;\\n Point memory last_point = point_history[_epoch];\\n return _supply_at(last_point, t);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public attachments;\\n mapping(uint => bool) public voted;\\n\\n function setVoter(address _voter) external {\\n require(msg.sender == voter);\\n voter = _voter;\\n }\\n\\n function voting(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = true;\\n }\\n\\n function abstain(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = false;\\n }\\n\\n function attach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] + 1;\\n }\\n\\n function detach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] - 1;\\n }\\n\\n function merge(uint _from, uint _to) external {\\n require(attachments[_from] == 0 && !voted[_from], \\\"attached\\\");\\n require(_from != _to);\\n require(_isApprovedOrOwner(msg.sender, _from));\\n require(_isApprovedOrOwner(msg.sender, _to));\\n\\n LockedBalance memory _locked0 = locked[_from];\\n LockedBalance memory _locked1 = locked[_to];\\n uint value0 = uint(int256(_locked0.amount));\\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\\n\\n locked[_from] = LockedBalance(0, 0);\\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\\n _burn(_from);\\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of each accounts delegate\\n mapping(address => address) private _delegates;\\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\\n\\n /// @notice A record of delegated token checkpoints for each account, by index\\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint32) public numCheckpoints;\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping(address => uint) public nonces;\\n\\n /**\\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\\n * the delegator's own address if they haven't delegated.\\n * This avoids having to delegate to oneself.\\n */\\n function delegates(address delegator) public view returns (address) {\\n address current = _delegates[delegator];\\n return current == address(0) ? delegator : current;\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getVotes(address account) external view returns (uint) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n votes = votes + _balanceOfNFT(tId, block.timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint storage cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPastVotes(address account, uint timestamp)\\n public\\n view\\n returns (uint)\\n {\\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\\n // Sum votes\\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n // Use the provided input timestamp here to get the right decay\\n votes = votes + _balanceOfNFT(tId, timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\\n return totalSupplyAtT(timestamp);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _moveTokenDelegates(\\n address srcRep,\\n address dstRep,\\n uint _tokenId\\n ) internal {\\n if (srcRep != dstRep && _tokenId > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except _tokenId\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (tId != _tokenId) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n // All the same plus _tokenId\\n require(\\n dstRepOld.length + 1 <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n dstRepNew.push(_tokenId);\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _findWhatCheckpointToWrite(address account)\\n internal\\n view\\n returns (uint32)\\n {\\n uint _timestamp = block.timestamp;\\n uint32 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n return _nCheckPoints - 1;\\n } else {\\n return _nCheckPoints;\\n }\\n }\\n\\n function _moveAllDelegates(\\n address owner,\\n address srcRep,\\n address dstRep\\n ) internal {\\n // You can only redelegate what you own\\n if (srcRep != dstRep) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except what owner owns\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (idToOwner[tId] != owner) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n uint ownerTokenCount = ownerToNFTokenCount[owner];\\n require(\\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n // All the same\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n // Plus all that's owned\\n for (uint i = 0; i < ownerTokenCount; i++) {\\n uint tId = ownerToNFTokenIdList[owner][i];\\n dstRepNew.push(tId);\\n }\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\\n address currentDelegate = delegates(delegator);\\n\\n _delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n _moveAllDelegates(delegator, currentDelegate, delegatee);\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n if (delegatee == address(0)) delegatee = msg.sender;\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n function delegateBySig(\\n address delegatee,\\n uint nonce,\\n uint expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public {\\n bytes32 domainSeparator = keccak256(\\n abi.encode(\\n DOMAIN_TYPEHASH,\\n keccak256(bytes(name)),\\n keccak256(bytes(version)),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 structHash = keccak256(\\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash)\\n );\\n address signatory = ecrecover(digest, v, r, s);\\n require(\\n signatory != address(0),\\n \\\"VotingEscrow::delegateBySig: invalid signature\\\"\\n );\\n require(\\n nonce == nonces[signatory]++,\\n \\\"VotingEscrow::delegateBySig: invalid nonce\\\"\\n );\\n require(\\n block.timestamp <= expiry,\\n \\\"VotingEscrow::delegateBySig: signature expired\\\"\\n );\\n return _delegate(signatory, delegatee);\\n }\\n}\\n\",\"keccak256\":\"0x7109ed9d84b5504fe5d4c73d5a10997a0b73f2f4d45813ce5e161997d405fd73\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x41bbb2c41036ca64b2f6c9e973e8cfaa113ebc42af86702cd0d267f915a7e886\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a06040526006805460ff191660011790553480156200001e57600080fd5b5060405162004a1c38038062004a1c8339810160408190526200004191620001b8565b6001600160a01b0382811660805260008054336001600160a01b031991821681178355600180548316909117815560028054909216938516939093179055437f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f0155427f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f005560046020527f9fe05126d2d9ecf60592e254dead906a4b2e492f36cca727682c38e9008c6ac1805460ff1990811684179091557f4267c0a6fd96b7a87f183ee8744f24d011423cd0e0142b3f563f183d8d9a456b8054821684179055635b5e139f60e01b82527e24030bcf4927897dffe721c2d8dda4bfd8910861687c42b03a463b43b04147805490911690921790915560055460405190913091600080516020620049fc833981519152908290a46005546040516000903090600080516020620049fc833981519152908390a45050620001f0565b80516001600160a01b0381168114620001b357600080fd5b919050565b60008060408385031215620001cc57600080fd5b620001d7836200019b565b9150620001e7602084016200019b565b90509250929050565b6080516147e26200021a60003960008181610b220152818161101801526133b501526147e26000f3fe608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea26469706673582212206e4938af8652c6d7c3a2e86f49c422f443b67b5bce3c2f44cf77757a7f5057ea64736f6c634300080d0033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea26469706673582212206e4938af8652c6d7c3a2e86f49c422f443b67b5bce3c2f44cf77757a7f5057ea64736f6c634300080d0033", "devdoc": { "author": "Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)", "details": "Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).", @@ -1597,7 +1597,7 @@ }, "constructor": { "params": { - "token_addr": "`VELO` token address" + "token_addr": "`FLOW` token address" } }, "create_lock(uint256,uint256)": { diff --git a/deployments/arbitrumGoerli/solcInputs/4fb7d8e79af343f7b73620261b95024e.json b/deployments/arbitrumGoerli/solcInputs/4fb7d8e79af343f7b73620261b95024e.json new file mode 100644 index 00000000..83a20d4b --- /dev/null +++ b/deployments/arbitrumGoerli/solcInputs/4fb7d8e79af343f7b73620261b95024e.json @@ -0,0 +1,238 @@ +{ + "language": "Solidity", + "sources": { + "contracts/ExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/factories/BribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n\n// if this imports int and ext bribe why is the the gauge factory asking for those address as if they are deployed to an address.\n" + }, + "contracts/factories/GaugeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" + }, + "contracts/factories/PairFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" + }, + "contracts/factories/WrappedExternalBribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" + }, + "contracts/Flow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IFlow.sol\";\n\ncontract Flow is IFlow {\n\n string public constant name = \"Velocimeter\";\n string public constant symbol = \"FLOW\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" + }, + "contracts/FlowGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velocimeter Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" + }, + "contracts/Gauge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/governance/L2Governor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" + }, + "contracts/governance/L2GovernorCountingSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" + }, + "contracts/governance/L2GovernorVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" + }, + "contracts/governance/L2GovernorVotesQuorumFraction.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" + }, + "contracts/interfaces/IBribe.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IBribeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IERC20.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" + }, + "contracts/interfaces/IFlow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IFlow {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" + }, + "contracts/interfaces/IGauge.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" + }, + "contracts/interfaces/IGaugeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IMinter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" + }, + "contracts/interfaces/IPair.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IPairCallee.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" + }, + "contracts/interfaces/IPairFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" + }, + "contracts/interfaces/IRewardsDistributor.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" + }, + "contracts/interfaces/IRouter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" + }, + "contracts/interfaces/IVeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" + }, + "contracts/interfaces/IVoter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" + }, + "contracts/interfaces/IVotingEscrow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" + }, + "contracts/interfaces/IWETH.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" + }, + "contracts/InternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/libraries/Base64.sol": { + "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" + }, + "contracts/libraries/Math.sol": { + "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" + }, + "contracts/Minter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IFlow.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IFlow public immutable _flow;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M FLOW (FLOW has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _flow = IFlow(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _flow.mint(address(this), max);\n _flow.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _flow.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _flowTotal = _flow.totalSupply();\n return\n (((((_minted * _veTotal) / _flowTotal) * _veTotal) / _flowTotal) *\n _veTotal) /\n _flowTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _flow.balanceOf(address(this));\n if (_balanceOf < _required) {\n _flow.mint(address(this), _required - _balanceOf);\n }\n\n require(_flow.transfer(team, _teamEmissions));\n require(_flow.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _flow.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" + }, + "contracts/Pair.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/PairFees.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" + }, + "contracts/redeem/MerkleClaim.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IFlow} from \"contracts/interfaces/IFlow.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims FLOW for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice FLOW token to claim\n IFlow public immutable FLOW;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _flow address\n /// @param _merkleRoot of claimees\n constructor(address _flow, bytes32 _merkleRoot) {\n FLOW = IFlow(_flow);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(FLOW.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" + }, + "contracts/redeem/RedemptionReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IFlow.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + FLOW\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IFlow public immutable FLOW;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableFLOW;\n uint256 public leftoverFLOW;\n\n constructor(\n address _usdc,\n address _flow,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n FLOW = IFlow(_flow);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableFLOW);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableFLOW\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableFLOW = _redeemableFLOW;\n leftoverFLOW = _redeemableFLOW;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableFLOW);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfFLOW)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata FLOW\n shareOfFLOW = (amountWEVE * redeemableFLOW) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfFLOW) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverFLOW -= shareOfFLOW; // this will revert if underflows\n require(\n FLOW.claim(redemptionAddress, shareOfFLOW),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" + }, + "contracts/redeem/RedemptionSender.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" + }, + "contracts/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" + }, + "contracts/Router.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velocimeter locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" + }, + "contracts/VelocimeterLibrary.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelocimeterLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" + }, + "contracts/Voter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velocimeter pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VotingEscrow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `FLOW` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" + }, + "contracts/WrappedExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + }, + "libraries": { + "": { + "__CACHE_BREAKER__": "0x0000000000000031363734373930343136383836" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/d1b0dfe2e40ce60c1a0cf04472752ec9.json b/deployments/arbitrumGoerli/solcInputs/d1b0dfe2e40ce60c1a0cf04472752ec9.json new file mode 100644 index 00000000..906e7671 --- /dev/null +++ b/deployments/arbitrumGoerli/solcInputs/d1b0dfe2e40ce60c1a0cf04472752ec9.json @@ -0,0 +1,238 @@ +{ + "language": "Solidity", + "sources": { + "contracts/ExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/factories/BribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n\n// if this imports int and ext bribe why is the the gauge factory asking for those address as if they are deployed to an address.\n" + }, + "contracts/factories/GaugeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" + }, + "contracts/factories/PairFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" + }, + "contracts/factories/WrappedExternalBribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" + }, + "contracts/Flow.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IFlow.sol\";\n\ncontract Flow is IFlow {\n\n string public constant name = \"Velocimeter\";\n string public constant symbol = \"FLOW\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" + }, + "contracts/FlowGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velocimeter Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" + }, + "contracts/Gauge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/governance/L2Governor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" + }, + "contracts/governance/L2GovernorCountingSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" + }, + "contracts/governance/L2GovernorVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" + }, + "contracts/governance/L2GovernorVotesQuorumFraction.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" + }, + "contracts/interfaces/IBribe.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IBribeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IERC20.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" + }, + "contracts/interfaces/IFlow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IFlow {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" + }, + "contracts/interfaces/IGauge.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" + }, + "contracts/interfaces/IGaugeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IMinter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" + }, + "contracts/interfaces/IPair.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IPairCallee.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" + }, + "contracts/interfaces/IPairFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" + }, + "contracts/interfaces/IRewardsDistributor.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" + }, + "contracts/interfaces/IRouter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" + }, + "contracts/interfaces/IVeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" + }, + "contracts/interfaces/IVoter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" + }, + "contracts/interfaces/IVotingEscrow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" + }, + "contracts/interfaces/IWETH.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" + }, + "contracts/InternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/libraries/Base64.sol": { + "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" + }, + "contracts/libraries/Math.sol": { + "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" + }, + "contracts/Minter.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IFlow.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IFlow public immutable _flow;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M FLOW (FLOW has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _flow = IFlow(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _flow.mint(address(this), max);\n _flow.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _flow.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _flowTotal = _flow.totalSupply();\n return\n (((((_minted * _veTotal) / _flowTotal) * _veTotal) / _flowTotal) *\n _veTotal) /\n _flowTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _flow.balanceOf(address(this));\n if (_balanceOf < _required) {\n _flow.mint(address(this), _required - _balanceOf);\n }\n\n require(_flow.transfer(team, _teamEmissions));\n require(_flow.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _flow.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" + }, + "contracts/Pair.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/PairFees.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" + }, + "contracts/redeem/MerkleClaim.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IFlow} from \"contracts/interfaces/IFlow.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims FLOW for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice FLOW token to claim\n IFlow public immutable FLOW;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _flow address\n /// @param _merkleRoot of claimees\n constructor(address _flow, bytes32 _merkleRoot) {\n FLOW = IFlow(_flow);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(FLOW.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" + }, + "contracts/redeem/RedemptionReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IFlow.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + FLOW\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IFlow public immutable FLOW;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableFLOW;\n uint256 public leftoverFLOW;\n\n constructor(\n address _usdc,\n address _flow,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n FLOW = IFlow(_flow);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableFLOW);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableFLOW\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableFLOW = _redeemableFLOW;\n leftoverFLOW = _redeemableFLOW;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableFLOW);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfFLOW)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata FLOW\n shareOfFLOW = (amountWEVE * redeemableFLOW) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfFLOW) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverFLOW -= shareOfFLOW; // this will revert if underflows\n require(\n FLOW.claim(redemptionAddress, shareOfFLOW),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" + }, + "contracts/redeem/RedemptionSender.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" + }, + "contracts/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" + }, + "contracts/Router.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velocimeter locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" + }, + "contracts/VelocimeterLibrary.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelocimeterLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" + }, + "contracts/Voter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velocimeter pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VotingEscrow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `FLOW` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" + }, + "contracts/WrappedExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + }, + "libraries": { + "": { + "__CACHE_BREAKER__": "0x0000000000000031363734373930313535343434" + } + } + } +} \ No newline at end of file diff --git a/hardhat.config.ts b/hardhat.config.ts index 60675af1..6d36c6c4 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -56,7 +56,7 @@ const config: HardhatUserConfig = { verify: { etherscan: { apiUrl: 'https://api-goerli.arbiscan.io', - apiKey: 'Dyp61CtoHxyYVSrAY7oD6IzSVzOgkJuf' + apiKey: process.env.ARB_SCAN_API_KEY! } } } diff --git a/package.json b/package.json index d8252e6b..cde00b8d 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "exportMainnet": "npx hardhat --network arbitrum export --export ./mainnet-exported.json", "deploy": "npx hardhat deploy --network arbitrumGoerli", "deployHardhat": "npx hardhat deploy --network hardhat", - "verifyMainnet": "npx hardhat --network arbitrum etherscan-verify --solc-input --sleep" + "verifyMainnet": "npx hardhat --network arbitrum etherscan-verify --solc-input --sleep", + "verifyGoerli": "npx hardhat --network arbitrumGoerli etherscan-verify --solc-input --sleep" }, "devDependencies": { "@nomiclabs/hardhat-ethers": "yarn:hardhat-deploy-ethers", diff --git a/test/utils/TestToken.sol b/test/utils/TestToken.sol index 17246b5b..b5105794 100644 --- a/test/utils/TestToken.sol +++ b/test/utils/TestToken.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-License-Identifier: MIT pragma solidity 0.8.13; contract TestToken { diff --git a/test/utils/TestVoter.sol b/test/utils/TestVoter.sol index 14819702..66b4abe1 100644 --- a/test/utils/TestVoter.sol +++ b/test/utils/TestVoter.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-License-Identifier: MIT pragma solidity 0.8.13; contract TestVoter { diff --git a/test/utils/TestVotingEscrow.sol b/test/utils/TestVotingEscrow.sol index bab48c79..ed232769 100644 --- a/test/utils/TestVotingEscrow.sol +++ b/test/utils/TestVotingEscrow.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-License-Identifier: MIT pragma solidity 0.8.13; contract TestVotingEscrow { From 9990ffacf5bf7bd37e799b0fc03c53af81396be1 Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Fri, 27 Jan 2023 14:50:21 +1100 Subject: [PATCH 19/43] yarn export --- exported.json | 639 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 607 insertions(+), 32 deletions(-) diff --git a/exported.json b/exported.json index f40f0efb..9c1181d1 100644 --- a/exported.json +++ b/exported.json @@ -3,7 +3,7 @@ "chainId": "421613", "contracts": { "BribeFactory": { - "address": "0x560b401d9F28F80980451d8582DEe903dD5295c3", + "address": "0x5cD2336a80E72bf0480ae704df021e4531A09671", "abi": [ { "inputs": [ @@ -71,8 +71,392 @@ } ] }, + "Flow": { + "address": "0xf5A53c1b4072425DF6eC082f0A48B4652bc4188C", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "claim", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_recipient", + "type": "address" + } + ], + "name": "initialMint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initialMinted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "merkleClaim", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "minter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "redemptionReceiver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_merkleClaim", + "type": "address" + } + ], + "name": "setMerkleClaim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_minter", + "type": "address" + } + ], + "name": "setMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_receiver", + "type": "address" + } + ], + "name": "setRedemptionReceiver", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, "GaugeFactory": { - "address": "0xeAA8Ebb77A7e3b7AE2d8090E7A1c2F9B605dc919", + "address": "0xA957E3958C7ed4590a28C5564438E89238b34EC1", "abi": [ { "inputs": [ @@ -134,13 +518,13 @@ ] }, "MerkleClaim": { - "address": "0x92eB499DBC33446Ace4f84Fba84E3A230370858D", + "address": "0x7F86f722a510CACb2cCD880a41dfE64773bfb371", "abi": [ { "inputs": [ { "internalType": "address", - "name": "_velo", + "name": "_flow", "type": "address" }, { @@ -173,10 +557,10 @@ }, { "inputs": [], - "name": "VELO", + "name": "FLOW", "outputs": [ { - "internalType": "contract IVelo", + "internalType": "contract IFlow", "name": "", "type": "address" } @@ -242,7 +626,7 @@ ] }, "Minter": { - "address": "0x402f3c314149F252144EE4Ca8646b4a215ACD6aC", + "address": "0x388c6C5e6D27E3b6fa40eb98e0ef573D9E8e037E", "abi": [ { "inputs": [ @@ -311,10 +695,10 @@ }, { "inputs": [], - "name": "_rewards_distributor", + "name": "_flow", "outputs": [ { - "internalType": "contract IRewardsDistributor", + "internalType": "contract IFlow", "name": "", "type": "address" } @@ -324,10 +708,10 @@ }, { "inputs": [], - "name": "_ve", + "name": "_rewards_distributor", "outputs": [ { - "internalType": "contract IVotingEscrow", + "internalType": "contract IRewardsDistributor", "name": "", "type": "address" } @@ -337,10 +721,10 @@ }, { "inputs": [], - "name": "_velo", + "name": "_ve", "outputs": [ { - "internalType": "contract IVelo", + "internalType": "contract IVotingEscrow", "name": "", "type": "address" } @@ -569,7 +953,7 @@ ] }, "PairFactory": { - "address": "0x6389e934d35fC9e066FAb549C8DBc9FddaC10e0D", + "address": "0xddadFF10D1C9eb062180a870150D11673FFf7ad6", "abi": [ { "inputs": [], @@ -955,7 +1339,7 @@ ] }, "RedemptionReceiver": { - "address": "0x52018E83E84ebe30ac6923F3747c7aE503923aaB", + "address": "0x552dD2458Ac8Fb7bC83a2BFF16e57e44Aa30cd4F", "abi": [ { "inputs": [ @@ -966,7 +1350,7 @@ }, { "internalType": "address", - "name": "_velo", + "name": "_flow", "type": "address" }, { @@ -1001,7 +1385,7 @@ { "indexed": false, "internalType": "uint256", - "name": "redeemableVELO", + "name": "redeemableFLOW", "type": "uint256" } ], @@ -1023,10 +1407,10 @@ }, { "inputs": [], - "name": "USDC", + "name": "FLOW", "outputs": [ { - "internalType": "contract IERC20", + "internalType": "contract IFlow", "name": "", "type": "address" } @@ -1036,10 +1420,10 @@ }, { "inputs": [], - "name": "VELO", + "name": "USDC", "outputs": [ { - "internalType": "contract IVelo", + "internalType": "contract IERC20", "name": "", "type": "address" } @@ -1139,7 +1523,7 @@ }, { "internalType": "uint256", - "name": "_redeemableVELO", + "name": "_redeemableFLOW", "type": "uint256" } ], @@ -1150,7 +1534,7 @@ }, { "inputs": [], - "name": "leftoverVELO", + "name": "leftoverFLOW", "outputs": [ { "internalType": "uint256", @@ -1206,7 +1590,7 @@ }, { "internalType": "uint256", - "name": "shareOfVELO", + "name": "shareOfFLOW", "type": "uint256" } ], @@ -1215,7 +1599,7 @@ }, { "inputs": [], - "name": "redeemableUSDC", + "name": "redeemableFLOW", "outputs": [ { "internalType": "uint256", @@ -1228,7 +1612,7 @@ }, { "inputs": [], - "name": "redeemableVELO", + "name": "redeemableUSDC", "outputs": [ { "internalType": "uint256", @@ -1281,7 +1665,7 @@ ] }, "RewardsDistributor": { - "address": "0xc4b9295487B4C43C1929299076820D8f55BBf957", + "address": "0xEED0deFB831F96fC45B5e0ACb477F517F186496F", "abi": [ { "inputs": [ @@ -1635,7 +2019,7 @@ ] }, "Router": { - "address": "0x1B0aC6bf6f35E638f6cce8D69C6074561273dc52", + "address": "0x49fb251F8Ff60bcd975D2018D0011D7a6065000B", "abi": [ { "inputs": [ @@ -2617,7 +3001,7 @@ ] }, "VeArtProxy": { - "address": "0x821B98D42D3AB509AF4F54205f0c52B019b9E2D5", + "address": "0xDe032908A79276B257d1ae80f0C0A2c070eDa1F4", "abi": [ { "inputs": [ @@ -3040,7 +3424,7 @@ ] }, "VeloGovernor": { - "address": "0x1a79b9daa3E741774bf67732F8a8B5820De8A53a", + "address": "0xB843444d08bee4f79f571Bd34D13Ec71D4194b40", "abi": [ { "inputs": [ @@ -4097,6 +4481,197 @@ } ] }, + "VelocimeterLibrary": { + "address": "0x243fC1E928E4bce603669CAf4512B6Db9B965aB0", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_router", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getAmountOut", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getMinimumValue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getSample", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getTradeDiff", + "outputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "pair", + "type": "address" + } + ], + "name": "getTradeDiff", + "outputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, "VelodromeLibrary": { "address": "0xcbE4714A95f866EB9C2eB50856F431f9E7353Ab6", "abi": [ @@ -4289,7 +4864,7 @@ ] }, "Voter": { - "address": "0x854086d39955d28317aE3856399312b8Edb1B473", + "address": "0x362502b7139761937067cf81a73Dc18D315f10A0", "abi": [ { "inputs": [ @@ -5433,7 +6008,7 @@ ] }, "VotingEscrow": { - "address": "0xBf05364D6cf1586852c18c6b1CbEe218E3e09885", + "address": "0xC43f6EbF97f9D99FF8a3aFe1413599e8DEc2aDB3", "abi": [ { "inputs": [ From 0ced1b11c005e392fa50c173f91a2e3d8cc1615f Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Fri, 27 Jan 2023 21:23:48 +1100 Subject: [PATCH 20/43] config with ceazor --- dist/tasks/deploy/constants/arbConfig.js | 256 ++++++++++++++++------- 1 file changed, 176 insertions(+), 80 deletions(-) diff --git a/dist/tasks/deploy/constants/arbConfig.js b/dist/tasks/deploy/constants/arbConfig.js index 9c2d36e9..c7f9f484 100644 --- a/dist/tasks/deploy/constants/arbConfig.js +++ b/dist/tasks/deploy/constants/arbConfig.js @@ -1,82 +1,178 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const ethers_1 = require("ethers"); -const TOKEN_DECIMALS = ethers_1.ethers.BigNumber.from('10').pow(ethers_1.ethers.BigNumber.from('18')); -const MILLION = ethers_1.ethers.BigNumber.from('10').pow(ethers_1.ethers.BigNumber.from('6')); -const FOUR_MILLION = ethers_1.ethers.BigNumber.from('4').mul(MILLION).mul(TOKEN_DECIMALS); -const TEN_MILLION = ethers_1.ethers.BigNumber.from('10').mul(MILLION).mul(TOKEN_DECIMALS); +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) +const ethers_1 = require('ethers') +const TOKEN_DECIMALS = ethers_1.ethers.BigNumber.from('10').pow( + ethers_1.ethers.BigNumber.from('18') +) +const MILLION = ethers_1.ethers.BigNumber.from('10').pow( + ethers_1.ethers.BigNumber.from('6') +) +const FOUR_MILLION = ethers_1.ethers.BigNumber.from('4') + .mul(MILLION) + .mul(TOKEN_DECIMALS) +const TWO_MILLION = ethers_1.ethers.BigNumber.from('2') + .mul(MILLION) + .mul(TOKEN_DECIMALS) +const TEN_MILLION = ethers_1.ethers.BigNumber.from('10') + .mul(MILLION) + .mul(TOKEN_DECIMALS) +const TWELVE_MILLION = ethers_1.ethers.BigNumber.from('12') + .mul(MILLION) + .mul(TOKEN_DECIMALS) const TWENTY_MILLION = ethers_1.ethers.BigNumber.from('20') - .mul(MILLION) - .mul(TOKEN_DECIMALS); -const PARTNER_MAX = ethers_1.ethers.BigNumber.from('78').mul(MILLION).mul(TOKEN_DECIMALS); -const TEAM_MULTISIG = '0x069e85D4F1010DD961897dC8C095FBB5FF297434'; -const TEAM_EOA = '0x069e85D4F1010DD961897dC8C095FBB5FF297434'; + .mul(MILLION) + .mul(TOKEN_DECIMALS) +const PARTNER_MAX = ethers_1.ethers.BigNumber.from('78') + .mul(MILLION) + .mul(TOKEN_DECIMALS) +const TEAM_MULTISIG = '0x16ec7CD5E35682B751d0c77c41A4e6a1A3E2DE01' +const TEAM_EOA = '0x16ec7CD5E35682B751d0c77c41A4e6a1A3E2DE01' const arbConfig = { - // Chain const - lzChainId: 110, - lzEndpoint: '0x3c2269811836af69497E5F486A85D7316753cf62', - // Tokens - WETH: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', - USDC: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', - // Addresses - teamEOA: TEAM_EOA, - teamMultisig: TEAM_MULTISIG, - emergencyCouncil: '0xcC2D01030eC2cd187346F70bFc483F24488C32E8', - merkleRoot: '0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f', - tokenWhitelist: [ - '0x4200000000000000000000000000000000000042', - '0x4200000000000000000000000000000000000006', - '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', - '0x2E3D870790dC77A83DD1d18184Acc7439A53f475', - '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', - '0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9', - '0x217D47011b23BB961eB6D93cA9945B7501a5BB11', - '0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb', - '0x67CCEA5bb16181E7b4109c9c2143c24a1c2205Be', - '0x9e1028F5F1D5eDE59748FFceE5532509976840E0', - '0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4', - '0xCB8FA9a76b8e203D8C3797bF438d8FB81Ea3326A', - '0x3E29D3A9316dAB217754d13b28646B76607c5f04', - '0x8aE125E8653821E851F12A49F7765db9a9ce7384', - '0x10010078a54396F62c96dF8532dc2B4847d47ED3', - // "", // BTRFLY -- N/A - // "", // pxVELO -- N/A - '0xc40F949F8a4e094D1b49a23ea9241D289B7b2819' // LUSD - // "", // wstETH -- N/A - // "", // HOP -- N/A - ], - partnerAddrs: [ - TEAM_EOA, - '0x4a84675512949f81EBFEAAcC6C00D03eDd329de5', - TEAM_EOA, - '0xa283139017a2f5BAdE8d8e25412C600055D318F8', - '0xDcf664d0f76E99eaA2DBD569474d0E75dC899FCD', - '0x489863b61C625a15C74FB4C21486baCb4A3937AB', - '0x641f26c67A5D0829Ae61019131093B6a7c7d18a3', - '0xC224bf25Dcc99236F00843c7D8C4194abE8AA94a', - '0xB6DACAE4eF97b4817d54df8e005269f509f803f9', - TEAM_EOA, - TEAM_EOA, - '0x0dF840dCbf1229262A4125C1fc559bd338eC9491', - '0x2E33A660742e813aD948fB9f7d682FE461E5fbf3', - '0xd2D4e9024D8C90aB52032a9F1e0d92D4cE20191B' // LUSD - ], - partnerAmts: [ - TEN_MILLION, - TWENTY_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION - ], - partnerMax: PARTNER_MAX -}; -exports.default = arbConfig; + // Chain const + lzChainId: 110, + lzEndpoint: '0x3c2269811836af69497E5F486A85D7316753cf62', + // Tokens + WETH: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', + USDC: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', + + // Addresses + teamEOA: TEAM_EOA, + teamMultisig: TEAM_MULTISIG, + coolie: TEAM_EOA, + dunks: '0x069e85D4F1010DD961897dC8C095FBB5FF297434', + ceazor: '0x3c5Aac016EF2F178e8699D6208796A2D67557fe2', + faeflow: TEAM_EOA, //update + wtck: TEAM_EOA, + torbik: TEAM_EOA, + velodromeMultisig: TEAM_EOA, + + emergencyCouncil: '0xcC2D01030eC2cd187346F70bFc483F24488C32E8', + merkleRoot: + '0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f', + tokenWhitelist: [ + // tokens whitelisted for gauges + '0x4200000000000000000000000000000000000042', + '0x4200000000000000000000000000000000000006', + '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', + '0x2E3D870790dC77A83DD1d18184Acc7439A53f475', + '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', + '0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9', + '0x217D47011b23BB961eB6D93cA9945B7501a5BB11', + '0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb', + '0x67CCEA5bb16181E7b4109c9c2143c24a1c2205Be', + '0x9e1028F5F1D5eDE59748FFceE5532509976840E0', + '0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4', + '0xCB8FA9a76b8e203D8C3797bF438d8FB81Ea3326A', + '0x3E29D3A9316dAB217754d13b28646B76607c5f04', + '0x8aE125E8653821E851F12A49F7765db9a9ce7384', + '0x10010078a54396F62c96dF8532dc2B4847d47ED3', + // "", // BTRFLY -- N/A + // "", // pxFLOW -- N/A + '0xc40F949F8a4e094D1b49a23ea9241D289B7b2819' // LUSD + // "", // wstETH -- N/A + // "", // HOP -- N/A + ], + partnerAddrs: [ + TEAM_MULTISIG, // Protocol owned NFT 64m + '0x069e85D4F1010DD961897dC8C095FBB5FF297434', // dunks + '0x3c5Aac016EF2F178e8699D6208796A2D67557fe2', // ceazor + coolie, + dunks, + ceazor, + faeflow, + wtck, + torbik, + velodromeMultisig, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG, + TEAM_MULTISIG // 38 x protcol / partner NFTs + ], + partnerAmts: [ + TEN_MILLION * 6.4, // 64 million + TWO_MILLION, // dunks presale + TWO_MILLION, // ceazor presale + TWELVE_MILLION, // team veFLOW 1% + TWELVE_MILLION, // team veFLOW 1% + TWELVE_MILLION, // team veFLOW 1% + TWELVE_MILLION, // team veFLOW 1% + TWELVE_MILLION, // team veFLOW 1% + TWELVE_MILLION, // team veFLOW 1% + FOUR_MILLION, // tribute to velodrome (need to get their arb address DO NOT USE MULTISIG FROM OP) + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION // 1% to each partner x 38 partners + ], + partnerMax: PARTNER_MAX +} +exports.default = arbConfig From 5c7b7b76bcb93a9892820651ff8e9b8359c74ee5 Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Sat, 28 Jan 2023 10:55:53 +1100 Subject: [PATCH 21/43] count for partner and team and tribute NFTs --- dist/tasks/deploy/constants/arbConfig.js | 31 ++++++++++++------------ 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/dist/tasks/deploy/constants/arbConfig.js b/dist/tasks/deploy/constants/arbConfig.js index c7f9f484..d70c0474 100644 --- a/dist/tasks/deploy/constants/arbConfig.js +++ b/dist/tasks/deploy/constants/arbConfig.js @@ -4,7 +4,8 @@ const ethers_1 = require('ethers') const TOKEN_DECIMALS = ethers_1.ethers.BigNumber.from('10').pow( ethers_1.ethers.BigNumber.from('18') ) -const MILLION = ethers_1.ethers.BigNumber.from('10').pow( + +const MILLION = ethers_1.ethers.BigNumber.from('1').pow( ethers_1.ethers.BigNumber.from('6') ) const FOUR_MILLION = ethers_1.ethers.BigNumber.from('4') @@ -19,7 +20,7 @@ const TEN_MILLION = ethers_1.ethers.BigNumber.from('10') const TWELVE_MILLION = ethers_1.ethers.BigNumber.from('12') .mul(MILLION) .mul(TOKEN_DECIMALS) -const TWENTY_MILLION = ethers_1.ethers.BigNumber.from('20') +const SIXTY_MILLION = ethers_1.ethers.BigNumber.from('60') .mul(MILLION) .mul(TOKEN_DECIMALS) const PARTNER_MAX = ethers_1.ethers.BigNumber.from('78') @@ -76,12 +77,12 @@ const arbConfig = { TEAM_MULTISIG, // Protocol owned NFT 64m '0x069e85D4F1010DD961897dC8C095FBB5FF297434', // dunks '0x3c5Aac016EF2F178e8699D6208796A2D67557fe2', // ceazor - coolie, - dunks, - ceazor, - faeflow, - wtck, - torbik, + '0x03B88DacB7c21B54cEfEcC297D981E5b721A9dF1', //coolie + + + ''//faeflow, + '0x78e801136F77805239A7F533521A7a5570F572C8', //wtck, + '0x0b776552c1Aef1Dc33005DD25AcDA22493b6615d',//torbik, velodromeMultisig, TEAM_MULTISIG, TEAM_MULTISIG, @@ -123,15 +124,15 @@ const arbConfig = { TEAM_MULTISIG // 38 x protcol / partner NFTs ], partnerAmts: [ - TEN_MILLION * 6.4, // 64 million + SIXTY_MILLION, // 60 million for protcol owned NFT 15% TWO_MILLION, // dunks presale TWO_MILLION, // ceazor presale - TWELVE_MILLION, // team veFLOW 1% - TWELVE_MILLION, // team veFLOW 1% - TWELVE_MILLION, // team veFLOW 1% - TWELVE_MILLION, // team veFLOW 1% - TWELVE_MILLION, // team veFLOW 1% - TWELVE_MILLION, // team veFLOW 1% + FOUR_MILLION, // team veFLOW 1% + FOUR_MILLION, // team veFLOW 1% + FOUR_MILLION, // team veFLOW 1% + FOUR_MILLION, // team veFLOW 1% + FOUR_MILLION, // team veFLOW 1% + FOUR_MILLION, // team veFLOW 1% FOUR_MILLION, // tribute to velodrome (need to get their arb address DO NOT USE MULTISIG FROM OP) FOUR_MILLION, FOUR_MILLION, From f733c0683ba017a30b05897a2e627e88dea331f2 Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Sat, 28 Jan 2023 14:45:00 +1100 Subject: [PATCH 22/43] switch from arbHardhat config to arbConfig in prep for mainnet deploy --- contracts/FlowGovernor.sol | 2 +- deploy/12_veloGovernor.ts | 6 +- deploy/15_init.ts | 6 +- deployments/arbitrumGoerli/BribeFactory.json | 22 +- deployments/arbitrumGoerli/Flow.json | 32 +- deployments/arbitrumGoerli/FlowGovernor.json | 1459 +++++++++++++++++ deployments/arbitrumGoerli/GaugeFactory.json | 22 +- deployments/arbitrumGoerli/MerkleClaim.json | 30 +- deployments/arbitrumGoerli/Minter.json | 28 +- deployments/arbitrumGoerli/PairFactory.json | 26 +- .../arbitrumGoerli/RedemptionReceiver.json | 24 +- .../arbitrumGoerli/RewardsDistributor.json | 38 +- deployments/arbitrumGoerli/Router.json | 24 +- deployments/arbitrumGoerli/VeArtProxy.json | 26 +- deployments/arbitrumGoerli/VeloGovernor.json | 34 +- .../arbitrumGoerli/VelocimeterLibrary.json | 28 +- deployments/arbitrumGoerli/Voter.json | 30 +- deployments/arbitrumGoerli/VotingEscrow.json | 48 +- .../1dbda4b04c9e26660611556bc8d2a346.json | 238 +++ .../87c2a0284a68497703d818e47e6d0a63.json | 238 +++ dist/deploy/12_veloGovernor.js | 6 +- dist/deploy/15_init.js | 4 +- dist/tasks/deploy/arb.js | 8 +- dist/tasks/deploy/arbHardhat.js | 8 +- dist/tasks/deploy/arbTest.js | 8 +- dist/tasks/deploy/constants/arbConfig.js | 200 +-- dist/tasks/deploy/op.js | 8 +- readme.md | 4 +- tasks/deploy/arb.ts | 8 +- tasks/deploy/arbHardhat.ts | 8 +- tasks/deploy/arbTest.ts | 8 +- tasks/deploy/op.ts | 8 +- test/VeloGovernor.t.sol | 8 +- 33 files changed, 2294 insertions(+), 353 deletions(-) create mode 100644 deployments/arbitrumGoerli/FlowGovernor.json create mode 100644 deployments/arbitrumGoerli/solcInputs/1dbda4b04c9e26660611556bc8d2a346.json create mode 100644 deployments/arbitrumGoerli/solcInputs/87c2a0284a68497703d818e47e6d0a63.json diff --git a/contracts/FlowGovernor.sol b/contracts/FlowGovernor.sol index df67969d..05d2bdaa 100644 --- a/contracts/FlowGovernor.sol +++ b/contracts/FlowGovernor.sol @@ -9,7 +9,7 @@ import {L2GovernorCountingSimple} from "contracts/governance/L2GovernorCountingS import {L2GovernorVotes} from "contracts/governance/L2GovernorVotes.sol"; import {L2GovernorVotesQuorumFraction} from "contracts/governance/L2GovernorVotesQuorumFraction.sol"; -contract VeloGovernor is +contract FlowGovernor is L2Governor, L2GovernorCountingSimple, L2GovernorVotes, diff --git a/deploy/12_veloGovernor.ts b/deploy/12_veloGovernor.ts index 5462f7d6..55ef6d0a 100644 --- a/deploy/12_veloGovernor.ts +++ b/deploy/12_veloGovernor.ts @@ -9,7 +9,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const escrow = await deployments.get('VotingEscrow') - await deploy('VeloGovernor', { + await deploy('FlowGovernor', { from: deployer, args: [escrow.address], log: true, @@ -17,5 +17,5 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { }) } export default func -func.tags = ['VeloGovernor'] -func.id = 'veloGovernor' +func.tags = ['FlowGovernor'] +func.id = 'FlowGovernor' diff --git a/deploy/15_init.ts b/deploy/15_init.ts index 919a06df..2ef1ae36 100644 --- a/deploy/15_init.ts +++ b/deploy/15_init.ts @@ -1,9 +1,9 @@ import { HardhatRuntimeEnvironment } from 'hardhat/types' import { DeployFunction } from 'hardhat-deploy/types' -import arbHardhatConfig from '../tasks/deploy/constants/arbHardhatConfig' +import arbConfig from '../tasks/deploy/constants/arbConfig' -const ARB_TEST_CONFIG = arbHardhatConfig +const ARB_TEST_CONFIG = arbConfig const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, ethers } = hre @@ -13,7 +13,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const escrow = await ethers.getContract('VotingEscrow') const voter = await ethers.getContract('Voter') const distributor = await ethers.getContract('RewardsDistributor') - const governor = await ethers.getContract('VeloGovernor') + const governor = await ethers.getContract('FlowGovernor') const minter = await ethers.getContract('Minter') const receiver = await ethers.getContract('RedemptionReceiver') diff --git a/deployments/arbitrumGoerli/BribeFactory.json b/deployments/arbitrumGoerli/BribeFactory.json index 1a613f49..324b3fee 100644 --- a/deployments/arbitrumGoerli/BribeFactory.json +++ b/deployments/arbitrumGoerli/BribeFactory.json @@ -1,5 +1,5 @@ { - "address": "0x5cD2336a80E72bf0480ae704df021e4531A09671", + "address": "0xb6270b92939c7b3676dcecA9a32D50Be27Db1291", "abi": [ { "inputs": [ @@ -66,28 +66,28 @@ "type": "function" } ], - "transactionHash": "0x77a94f275b395e421f082a3cfabcf1927db848226adbfc12e4f39282af163148", + "transactionHash": "0x5bfd3edf05b7fe48dd4be98c83fc8c210c97b29ea50f41fd052a9e6cf2ca1059", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x5cD2336a80E72bf0480ae704df021e4531A09671", + "contractAddress": "0xb6270b92939c7b3676dcecA9a32D50Be27Db1291", "transactionIndex": 1, "gasUsed": "4288891", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xaccbf40c13ccf9a9f1c88e673ba78a7a891d8c74f1db7dc2fc95b6306b3938d3", - "transactionHash": "0x77a94f275b395e421f082a3cfabcf1927db848226adbfc12e4f39282af163148", + "blockHash": "0xd6379e3f2c35fc33daa6ea3033b9ec75c8819a84755580d9ce9b41fac1444914", + "transactionHash": "0x5bfd3edf05b7fe48dd4be98c83fc8c210c97b29ea50f41fd052a9e6cf2ca1059", "logs": [], - "blockNumber": 5716710, + "blockNumber": 5814401, "cumulativeGasUsed": "4288891", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 3, - "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createExternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createInternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_external_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_internal_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/BribeFactory.sol\":\"BribeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/ExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract ExternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve; // \\u5929\\u4f7f\\u306e\\u305f\\u307e\\u3054\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balanceOf;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n _prevSupply = supplyCheckpoints[\\n getPriorSupplyIndex(_nextEpochStart + DURATION)\\n ].supply;\\n prevRewards.balanceOf =\\n (cp0.balanceOf *\\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (block.timestamp > _lastEpochEnd) {\\n reward +=\\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\\n }\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0xfe1e53dea8a63ce448c5856a740ed73038ad29a9dcd0f2a2752049b146bb4eb0\",\"license\":\"MIT\"},\"contracts/InternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract InternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve;\\n\\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 public constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n mapping(address => mapping(uint256 => uint256))\\n public userRewardPerTokenStored;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (totalSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / totalSupply);\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\\n _startTimestamp = endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][tokenId],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][tokenId]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n require(isReward[token]);\\n\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2dc302de5dfd95018d1fba7a3a1916d2c1fcf32859d19d38648767f13422a694\",\"license\":\"MIT\"},\"contracts/factories/BribeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IBribeFactory.sol\\\";\\nimport 'contracts/InternalBribe.sol';\\nimport 'contracts/ExternalBribe.sol';\\n\\ncontract BribeFactory is IBribeFactory {\\n address public last_internal_bribe;\\n address public last_external_bribe;\\n\\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\\n return last_internal_bribe;\\n }\\n\\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\\n return last_external_bribe;\\n }\\n}\\n\\n// if this imports int and ext bribe why is the the gauge factory asking for those address as if they are deployed to an address.\\n\",\"keccak256\":\"0xd107fb5a520bae9b655bec4ad2eb11d598e74d0eeda0db547e2526a907dea7ec\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50614cca806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea26469706673582212208f809014e1be8a684b75e7a6caaac3aae9d2d6082521efe651fdef5245aa62c364736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea26469706673582212200ac3824bebc233077a386d729739b930145f110bb778ad11e43e1b6a5453856364736f6c634300080d0033a2646970667358221220822b550e682635bdd856a9670b0ae5f85deb16da9b775f7411a7b2b69c291e5164736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea26469706673582212208f809014e1be8a684b75e7a6caaac3aae9d2d6082521efe651fdef5245aa62c364736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea26469706673582212200ac3824bebc233077a386d729739b930145f110bb778ad11e43e1b6a5453856364736f6c634300080d0033a2646970667358221220822b550e682635bdd856a9670b0ae5f85deb16da9b775f7411a7b2b69c291e5164736f6c634300080d0033", + "numDeployments": 5, + "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createExternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createInternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_external_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_internal_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/BribeFactory.sol\":\"BribeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/ExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract ExternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve; // \\u5929\\u4f7f\\u306e\\u305f\\u307e\\u3054\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balanceOf;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n _prevSupply = supplyCheckpoints[\\n getPriorSupplyIndex(_nextEpochStart + DURATION)\\n ].supply;\\n prevRewards.balanceOf =\\n (cp0.balanceOf *\\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (block.timestamp > _lastEpochEnd) {\\n reward +=\\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\\n }\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0xfe1e53dea8a63ce448c5856a740ed73038ad29a9dcd0f2a2752049b146bb4eb0\",\"license\":\"MIT\"},\"contracts/InternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract InternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve;\\n\\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 public constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n mapping(address => mapping(uint256 => uint256))\\n public userRewardPerTokenStored;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (totalSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / totalSupply);\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\\n _startTimestamp = endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][tokenId],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][tokenId]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n require(isReward[token]);\\n\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2dc302de5dfd95018d1fba7a3a1916d2c1fcf32859d19d38648767f13422a694\",\"license\":\"MIT\"},\"contracts/factories/BribeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IBribeFactory.sol\\\";\\nimport 'contracts/InternalBribe.sol';\\nimport 'contracts/ExternalBribe.sol';\\n\\ncontract BribeFactory is IBribeFactory {\\n address public last_internal_bribe;\\n address public last_external_bribe;\\n\\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\\n return last_internal_bribe;\\n }\\n\\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\\n return last_external_bribe;\\n }\\n}\\n\\n// if this imports int and ext bribe why is the the gauge factory asking for those address as if they are deployed to an address.\\n\",\"keccak256\":\"0xd107fb5a520bae9b655bec4ad2eb11d598e74d0eeda0db547e2526a907dea7ec\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50614cca806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea264697066735822122099fa841b90b874d1d8e3877992e98699cca22eb466c2095187adf17c4142358164736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea2646970667358221220108cbdd951d42091601d20569bfe784ae172226099bd78015371ae45d69bad1b64736f6c634300080d0033a264697066735822122075eeee7578461764c8547abe69c1b3d9c2cbce0bf0444eac1122b06c51a763bf64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea264697066735822122099fa841b90b874d1d8e3877992e98699cca22eb466c2095187adf17c4142358164736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea2646970667358221220108cbdd951d42091601d20569bfe784ae172226099bd78015371ae45d69bad1b64736f6c634300080d0033a264697066735822122075eeee7578461764c8547abe69c1b3d9c2cbce0bf0444eac1122b06c51a763bf64736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/Flow.json b/deployments/arbitrumGoerli/Flow.json index cf30e482..4f8a060e 100644 --- a/deployments/arbitrumGoerli/Flow.json +++ b/deployments/arbitrumGoerli/Flow.json @@ -1,5 +1,5 @@ { - "address": "0xf5A53c1b4072425DF6eC082f0A48B4652bc4188C", + "address": "0x8c35578054126d4DD063CFaBA40B7F9B63A13981", "abi": [ { "inputs": [], @@ -381,22 +381,22 @@ "type": "function" } ], - "transactionHash": "0x31ab3451d3d9dce5b823a7fb929a52936a64aa3cb1c2c0f3970404573aa38605", + "transactionHash": "0x791ea54fe41f0c5d4cc08281af6429e5313c9ca4ca5cc513ce7a67502bce5d19", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xf5A53c1b4072425DF6eC082f0A48B4652bc4188C", + "contractAddress": "0x8c35578054126d4DD063CFaBA40B7F9B63A13981", "transactionIndex": 1, "gasUsed": "537302", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000010000000000000000000040000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000400000000004000000000000002000000000000000000000800000000000000000000000000000020000000000000000000000000080000000000000000000000000000000000000000", - "blockHash": "0xc1c1d58e5d1ad27f96d332fe52913cefdeb32e6f1bc25ff56b4919739d03031b", - "transactionHash": "0x31ab3451d3d9dce5b823a7fb929a52936a64aa3cb1c2c0f3970404573aa38605", + "logsBloom": "0x00000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000008000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000010000000000000000000000000000000000000000000100000000000000800000000000000000000000000000000000000000000000000000000000000000000004000000000000002000000000000000000000000000000000000000000000000000020000000000000000000000000080000000000000000000000000000000000000000", + "blockHash": "0x96cef44b85f7609794f6a375423cbc39f740b41d7fb33010efa7fc9d0c3cb840", + "transactionHash": "0x791ea54fe41f0c5d4cc08281af6429e5313c9ca4ca5cc513ce7a67502bce5d19", "logs": [ { "transactionIndex": 1, - "blockNumber": 5716700, - "transactionHash": "0x31ab3451d3d9dce5b823a7fb929a52936a64aa3cb1c2c0f3970404573aa38605", - "address": "0xf5A53c1b4072425DF6eC082f0A48B4652bc4188C", + "blockNumber": 5814391, + "transactionHash": "0x791ea54fe41f0c5d4cc08281af6429e5313c9ca4ca5cc513ce7a67502bce5d19", + "address": "0x8c35578054126d4DD063CFaBA40B7F9B63A13981", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x0000000000000000000000000000000000000000000000000000000000000000", @@ -404,20 +404,20 @@ ], "data": "0x0000000000000000000000000000000000000000000000000000000000000000", "logIndex": 0, - "blockHash": "0xc1c1d58e5d1ad27f96d332fe52913cefdeb32e6f1bc25ff56b4919739d03031b" + "blockHash": "0x96cef44b85f7609794f6a375423cbc39f740b41d7fb33010efa7fc9d0c3cb840" } ], - "blockNumber": 5716700, + "blockNumber": 5814391, "cumulativeGasUsed": "537302", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 3, - "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"initialMint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialMinted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleClaim\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redemptionReceiver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_merkleClaim\",\"type\":\"address\"}],\"name\":\"setMerkleClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"setMinter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_receiver\",\"type\":\"address\"}],\"name\":\"setRedemptionReceiver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Flow.sol\":\"Flow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Flow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\n\\ncontract Flow is IFlow {\\n\\n string public constant name = \\\"Velocimeter\\\";\\n string public constant symbol = \\\"FLOW\\\";\\n uint8 public constant decimals = 18;\\n uint public totalSupply = 0;\\n\\n mapping(address => uint) public balanceOf;\\n mapping(address => mapping(address => uint)) public allowance;\\n\\n bool public initialMinted;\\n address public minter;\\n address public redemptionReceiver;\\n address public merkleClaim;\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n\\n constructor() {\\n minter = msg.sender;\\n _mint(msg.sender, 0);\\n }\\n\\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\\n function setMinter(address _minter) external {\\n require(msg.sender == minter);\\n minter = _minter;\\n }\\n\\n function setRedemptionReceiver(address _receiver) external {\\n require(msg.sender == minter);\\n redemptionReceiver = _receiver;\\n }\\n\\n function setMerkleClaim(address _merkleClaim) external {\\n require(msg.sender == minter);\\n merkleClaim = _merkleClaim;\\n }\\n\\n // Initial mint: total 82M\\n // 4M for \\\"Genesis\\\" pools\\n // 30M for liquid team allocation (40M excl init veNFT)\\n // 48M for future partners\\n function initialMint(address _recipient) external {\\n require(msg.sender == minter && !initialMinted);\\n initialMinted = true;\\n _mint(_recipient, 82 * 1e6 * 1e18);\\n }\\n\\n function approve(address _spender, uint _value) external returns (bool) {\\n allowance[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n function _mint(address _to, uint _amount) internal returns (bool) {\\n totalSupply += _amount;\\n unchecked {\\n balanceOf[_to] += _amount;\\n }\\n emit Transfer(address(0x0), _to, _amount);\\n return true;\\n }\\n\\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\\n balanceOf[_from] -= _value;\\n unchecked {\\n balanceOf[_to] += _value;\\n }\\n emit Transfer(_from, _to, _value);\\n return true;\\n }\\n\\n function transfer(address _to, uint _value) external returns (bool) {\\n return _transfer(msg.sender, _to, _value);\\n }\\n\\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\\n uint allowed_from = allowance[_from][msg.sender];\\n if (allowed_from != type(uint).max) {\\n allowance[_from][msg.sender] -= _value;\\n }\\n return _transfer(_from, _to, _value);\\n }\\n\\n function mint(address account, uint amount) external returns (bool) {\\n require(msg.sender == minter);\\n _mint(account, amount);\\n return true;\\n }\\n\\n function claim(address account, uint amount) external returns (bool) {\\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\\n _mint(account, amount);\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xe98c291786f74c8f02edb3673870ba99d6b9adac299bbe42f1df42c740d737ac\",\"license\":\"MIT\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"}},\"version\":1}", - "bytecode": "0x60806040526000805534801561001457600080fd5b5060038054610100600160a81b0319163361010081029190911790915561003c906000610042565b506100d9565b60008160008082825461005591906100b3565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a350600192915050565b600082198211156100d457634e487b7160e01b600052601160045260246000fd5b500190565b61082e806100e86000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ae578063dd62ed3e146102c1578063e752c44a146102ec578063ec676a25146102ff578063fca3b5aa1461031257600080fd5b806395d89b4114610243578063a9059cbb14610266578063aad3ec9614610279578063c268f9ba1461028c578063ca1c4de9146102a157600080fd5b806323b872dd116100f457806323b872dd146101d0578063313ce567146101e357806340c10f19146101fd5780635e05fe501461021057806370a082311461022357600080fd5b806306fdde03146101265780630754617214610166578063095ea7b31461019657806318160ddd146101b9575b600080fd5b6101506040518060400160405280600b81526020016a2b32b637b1b4b6b2ba32b960a91b81525081565b60405161015d919061068e565b60405180910390f35b60035461017e9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015d565b6101a96101a43660046106ff565b610325565b604051901515815260200161015d565b6101c260005481565b60405190815260200161015d565b6101a96101de366004610729565b610391565b6101eb601281565b60405160ff909116815260200161015d565b6101a961020b3660046106ff565b61040b565b60045461017e906001600160a01b031681565b6101c2610231366004610765565b60016020526000908152604090205481565b61015060405180604001604052806004815260200163464c4f5760e01b81525081565b6101a96102743660046106ff565b61043e565b6101a96102873660046106ff565b610452565b61029f61029a366004610765565b610481565b005b6003546101a99060ff1681565b61029f6102bc366004610765565b6104d2565b6101c26102cf366004610780565b600260209081526000928352604080842090915290825290205481565b60055461017e906001600160a01b031681565b61029f61030d366004610765565b610510565b61029f610320366004610765565b61054e565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103809086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f7576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103f19084906107c9565b90915550505b610402858585610592565b95945050505050565b60035460009061010090046001600160a01b0316331461042a57600080fd5b6104348383610629565b5060019392505050565b600061044b338484610592565b9392505050565b6004546000906001600160a01b031633148061047857506005546001600160a01b031633145b61042a57600080fd5b60035461010090046001600160a01b0316331480156104a3575060035460ff16155b6104ac57600080fd5b6003805460ff191660011790556104ce816a43d42ce83da41d92000000610629565b5050565b60035461010090046001600160a01b031633146104ee57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052c57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056a57600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105bc9084906107c9565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106179086815260200190565b60405180910390a35060019392505050565b60008160008082825461063c91906107e0565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610380565b600060208083528351808285015260005b818110156106bb5785810183015185820160400152820161069f565b818111156106cd576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106fa57600080fd5b919050565b6000806040838503121561071257600080fd5b61071b836106e3565b946020939093013593505050565b60008060006060848603121561073e57600080fd5b610747846106e3565b9250610755602085016106e3565b9150604084013590509250925092565b60006020828403121561077757600080fd5b61044b826106e3565b6000806040838503121561079357600080fd5b61079c836106e3565b91506107aa602084016106e3565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107db576107db6107b3565b500390565b600082198211156107f3576107f36107b3565b50019056fea26469706673582212202aa872e848c1e34938f3ed63a66bc6d089c78d27e13a03d66d1a7c12ab495dbd64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ae578063dd62ed3e146102c1578063e752c44a146102ec578063ec676a25146102ff578063fca3b5aa1461031257600080fd5b806395d89b4114610243578063a9059cbb14610266578063aad3ec9614610279578063c268f9ba1461028c578063ca1c4de9146102a157600080fd5b806323b872dd116100f457806323b872dd146101d0578063313ce567146101e357806340c10f19146101fd5780635e05fe501461021057806370a082311461022357600080fd5b806306fdde03146101265780630754617214610166578063095ea7b31461019657806318160ddd146101b9575b600080fd5b6101506040518060400160405280600b81526020016a2b32b637b1b4b6b2ba32b960a91b81525081565b60405161015d919061068e565b60405180910390f35b60035461017e9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015d565b6101a96101a43660046106ff565b610325565b604051901515815260200161015d565b6101c260005481565b60405190815260200161015d565b6101a96101de366004610729565b610391565b6101eb601281565b60405160ff909116815260200161015d565b6101a961020b3660046106ff565b61040b565b60045461017e906001600160a01b031681565b6101c2610231366004610765565b60016020526000908152604090205481565b61015060405180604001604052806004815260200163464c4f5760e01b81525081565b6101a96102743660046106ff565b61043e565b6101a96102873660046106ff565b610452565b61029f61029a366004610765565b610481565b005b6003546101a99060ff1681565b61029f6102bc366004610765565b6104d2565b6101c26102cf366004610780565b600260209081526000928352604080842090915290825290205481565b60055461017e906001600160a01b031681565b61029f61030d366004610765565b610510565b61029f610320366004610765565b61054e565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103809086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f7576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103f19084906107c9565b90915550505b610402858585610592565b95945050505050565b60035460009061010090046001600160a01b0316331461042a57600080fd5b6104348383610629565b5060019392505050565b600061044b338484610592565b9392505050565b6004546000906001600160a01b031633148061047857506005546001600160a01b031633145b61042a57600080fd5b60035461010090046001600160a01b0316331480156104a3575060035460ff16155b6104ac57600080fd5b6003805460ff191660011790556104ce816a43d42ce83da41d92000000610629565b5050565b60035461010090046001600160a01b031633146104ee57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052c57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056a57600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105bc9084906107c9565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106179086815260200190565b60405180910390a35060019392505050565b60008160008082825461063c91906107e0565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610380565b600060208083528351808285015260005b818110156106bb5785810183015185820160400152820161069f565b818111156106cd576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106fa57600080fd5b919050565b6000806040838503121561071257600080fd5b61071b836106e3565b946020939093013593505050565b60008060006060848603121561073e57600080fd5b610747846106e3565b9250610755602085016106e3565b9150604084013590509250925092565b60006020828403121561077757600080fd5b61044b826106e3565b6000806040838503121561079357600080fd5b61079c836106e3565b91506107aa602084016106e3565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107db576107db6107b3565b500390565b600082198211156107f3576107f36107b3565b50019056fea26469706673582212202aa872e848c1e34938f3ed63a66bc6d089c78d27e13a03d66d1a7c12ab495dbd64736f6c634300080d0033", + "numDeployments": 5, + "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"initialMint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialMinted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleClaim\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redemptionReceiver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_merkleClaim\",\"type\":\"address\"}],\"name\":\"setMerkleClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"setMinter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_receiver\",\"type\":\"address\"}],\"name\":\"setRedemptionReceiver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Flow.sol\":\"Flow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Flow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\n\\ncontract Flow is IFlow {\\n\\n string public constant name = \\\"Velocimeter\\\";\\n string public constant symbol = \\\"FLOW\\\";\\n uint8 public constant decimals = 18;\\n uint public totalSupply = 0;\\n\\n mapping(address => uint) public balanceOf;\\n mapping(address => mapping(address => uint)) public allowance;\\n\\n bool public initialMinted;\\n address public minter;\\n address public redemptionReceiver;\\n address public merkleClaim;\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n\\n constructor() {\\n minter = msg.sender;\\n _mint(msg.sender, 0);\\n }\\n\\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\\n function setMinter(address _minter) external {\\n require(msg.sender == minter);\\n minter = _minter;\\n }\\n\\n function setRedemptionReceiver(address _receiver) external {\\n require(msg.sender == minter);\\n redemptionReceiver = _receiver;\\n }\\n\\n function setMerkleClaim(address _merkleClaim) external {\\n require(msg.sender == minter);\\n merkleClaim = _merkleClaim;\\n }\\n\\n // Initial mint: total 82M\\n // 4M for \\\"Genesis\\\" pools\\n // 30M for liquid team allocation (40M excl init veNFT)\\n // 48M for future partners\\n function initialMint(address _recipient) external {\\n require(msg.sender == minter && !initialMinted);\\n initialMinted = true;\\n _mint(_recipient, 82 * 1e6 * 1e18);\\n }\\n\\n function approve(address _spender, uint _value) external returns (bool) {\\n allowance[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n function _mint(address _to, uint _amount) internal returns (bool) {\\n totalSupply += _amount;\\n unchecked {\\n balanceOf[_to] += _amount;\\n }\\n emit Transfer(address(0x0), _to, _amount);\\n return true;\\n }\\n\\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\\n balanceOf[_from] -= _value;\\n unchecked {\\n balanceOf[_to] += _value;\\n }\\n emit Transfer(_from, _to, _value);\\n return true;\\n }\\n\\n function transfer(address _to, uint _value) external returns (bool) {\\n return _transfer(msg.sender, _to, _value);\\n }\\n\\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\\n uint allowed_from = allowance[_from][msg.sender];\\n if (allowed_from != type(uint).max) {\\n allowance[_from][msg.sender] -= _value;\\n }\\n return _transfer(_from, _to, _value);\\n }\\n\\n function mint(address account, uint amount) external returns (bool) {\\n require(msg.sender == minter);\\n _mint(account, amount);\\n return true;\\n }\\n\\n function claim(address account, uint amount) external returns (bool) {\\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\\n _mint(account, amount);\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xe98c291786f74c8f02edb3673870ba99d6b9adac299bbe42f1df42c740d737ac\",\"license\":\"MIT\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"}},\"version\":1}", + "bytecode": "0x60806040526000805534801561001457600080fd5b5060038054610100600160a81b0319163361010081029190911790915561003c906000610042565b506100d9565b60008160008082825461005591906100b3565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a350600192915050565b600082198211156100d457634e487b7160e01b600052601160045260246000fd5b500190565b61082e806100e86000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ae578063dd62ed3e146102c1578063e752c44a146102ec578063ec676a25146102ff578063fca3b5aa1461031257600080fd5b806395d89b4114610243578063a9059cbb14610266578063aad3ec9614610279578063c268f9ba1461028c578063ca1c4de9146102a157600080fd5b806323b872dd116100f457806323b872dd146101d0578063313ce567146101e357806340c10f19146101fd5780635e05fe501461021057806370a082311461022357600080fd5b806306fdde03146101265780630754617214610166578063095ea7b31461019657806318160ddd146101b9575b600080fd5b6101506040518060400160405280600b81526020016a2b32b637b1b4b6b2ba32b960a91b81525081565b60405161015d919061068e565b60405180910390f35b60035461017e9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015d565b6101a96101a43660046106ff565b610325565b604051901515815260200161015d565b6101c260005481565b60405190815260200161015d565b6101a96101de366004610729565b610391565b6101eb601281565b60405160ff909116815260200161015d565b6101a961020b3660046106ff565b61040b565b60045461017e906001600160a01b031681565b6101c2610231366004610765565b60016020526000908152604090205481565b61015060405180604001604052806004815260200163464c4f5760e01b81525081565b6101a96102743660046106ff565b61043e565b6101a96102873660046106ff565b610452565b61029f61029a366004610765565b610481565b005b6003546101a99060ff1681565b61029f6102bc366004610765565b6104d2565b6101c26102cf366004610780565b600260209081526000928352604080842090915290825290205481565b60055461017e906001600160a01b031681565b61029f61030d366004610765565b610510565b61029f610320366004610765565b61054e565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103809086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f7576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103f19084906107c9565b90915550505b610402858585610592565b95945050505050565b60035460009061010090046001600160a01b0316331461042a57600080fd5b6104348383610629565b5060019392505050565b600061044b338484610592565b9392505050565b6004546000906001600160a01b031633148061047857506005546001600160a01b031633145b61042a57600080fd5b60035461010090046001600160a01b0316331480156104a3575060035460ff16155b6104ac57600080fd5b6003805460ff191660011790556104ce816a43d42ce83da41d92000000610629565b5050565b60035461010090046001600160a01b031633146104ee57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052c57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056a57600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105bc9084906107c9565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106179086815260200190565b60405180910390a35060019392505050565b60008160008082825461063c91906107e0565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610380565b600060208083528351808285015260005b818110156106bb5785810183015185820160400152820161069f565b818111156106cd576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106fa57600080fd5b919050565b6000806040838503121561071257600080fd5b61071b836106e3565b946020939093013593505050565b60008060006060848603121561073e57600080fd5b610747846106e3565b9250610755602085016106e3565b9150604084013590509250925092565b60006020828403121561077757600080fd5b61044b826106e3565b6000806040838503121561079357600080fd5b61079c836106e3565b91506107aa602084016106e3565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107db576107db6107b3565b500390565b600082198211156107f3576107f36107b3565b50019056fea26469706673582212204d79ba21f3f516cb55fa2c0931b0d4e06d3f09a2681f5ab33064f7374590d31e64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ae578063dd62ed3e146102c1578063e752c44a146102ec578063ec676a25146102ff578063fca3b5aa1461031257600080fd5b806395d89b4114610243578063a9059cbb14610266578063aad3ec9614610279578063c268f9ba1461028c578063ca1c4de9146102a157600080fd5b806323b872dd116100f457806323b872dd146101d0578063313ce567146101e357806340c10f19146101fd5780635e05fe501461021057806370a082311461022357600080fd5b806306fdde03146101265780630754617214610166578063095ea7b31461019657806318160ddd146101b9575b600080fd5b6101506040518060400160405280600b81526020016a2b32b637b1b4b6b2ba32b960a91b81525081565b60405161015d919061068e565b60405180910390f35b60035461017e9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015d565b6101a96101a43660046106ff565b610325565b604051901515815260200161015d565b6101c260005481565b60405190815260200161015d565b6101a96101de366004610729565b610391565b6101eb601281565b60405160ff909116815260200161015d565b6101a961020b3660046106ff565b61040b565b60045461017e906001600160a01b031681565b6101c2610231366004610765565b60016020526000908152604090205481565b61015060405180604001604052806004815260200163464c4f5760e01b81525081565b6101a96102743660046106ff565b61043e565b6101a96102873660046106ff565b610452565b61029f61029a366004610765565b610481565b005b6003546101a99060ff1681565b61029f6102bc366004610765565b6104d2565b6101c26102cf366004610780565b600260209081526000928352604080842090915290825290205481565b60055461017e906001600160a01b031681565b61029f61030d366004610765565b610510565b61029f610320366004610765565b61054e565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103809086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f7576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103f19084906107c9565b90915550505b610402858585610592565b95945050505050565b60035460009061010090046001600160a01b0316331461042a57600080fd5b6104348383610629565b5060019392505050565b600061044b338484610592565b9392505050565b6004546000906001600160a01b031633148061047857506005546001600160a01b031633145b61042a57600080fd5b60035461010090046001600160a01b0316331480156104a3575060035460ff16155b6104ac57600080fd5b6003805460ff191660011790556104ce816a43d42ce83da41d92000000610629565b5050565b60035461010090046001600160a01b031633146104ee57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052c57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056a57600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105bc9084906107c9565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106179086815260200190565b60405180910390a35060019392505050565b60008160008082825461063c91906107e0565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610380565b600060208083528351808285015260005b818110156106bb5785810183015185820160400152820161069f565b818111156106cd576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106fa57600080fd5b919050565b6000806040838503121561071257600080fd5b61071b836106e3565b946020939093013593505050565b60008060006060848603121561073e57600080fd5b610747846106e3565b9250610755602085016106e3565b9150604084013590509250925092565b60006020828403121561077757600080fd5b61044b826106e3565b6000806040838503121561079357600080fd5b61079c836106e3565b91506107aa602084016106e3565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107db576107db6107b3565b500390565b600082198211156107f3576107f36107b3565b50019056fea26469706673582212204d79ba21f3f516cb55fa2c0931b0d4e06d3f09a2681f5ab33064f7374590d31e64736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/FlowGovernor.json b/deployments/arbitrumGoerli/FlowGovernor.json new file mode 100644 index 00000000..cf1abe5c --- /dev/null +++ b/deployments/arbitrumGoerli/FlowGovernor.json @@ -0,0 +1,1459 @@ +{ + "address": "0x82659caE4Dd0C19F7FBf47A5492E31Ad9501CA73", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IVotes", + "name": "_ve", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "Empty", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "ProposalCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "ProposalExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldQuorumNumerator", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newQuorumNumerator", + "type": "uint256" + } + ], + "name": "QuorumNumeratorUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "VoteCast", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "VoteCastWithParams", + "type": "event" + }, + { + "inputs": [], + "name": "BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COUNTING_MODE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "EXTENDED_BALLOT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_PROPOSAL_NUMERATOR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PROPOSAL_DENOMINATOR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + } + ], + "name": "castVote", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "castVoteBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "castVoteWithReason", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "castVoteWithReasonAndParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "castVoteWithReasonAndParamsBySig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "execute", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockTimestamp", + "type": "uint256" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockTimestamp", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "getVotesWithParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasVoted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "descriptionHash", + "type": "bytes32" + } + ], + "name": "hashProposal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalDeadline", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalNumerator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposalThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "againstVotes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "forVotes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "abstainVotes", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "propose", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "blockTimestamp", + "type": "uint256" + } + ], + "name": "quorum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "quorumDenominator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "quorumNumerator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "relay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "numerator", + "type": "uint256" + } + ], + "name": "setProposalNumerator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newTeam", + "type": "address" + } + ], + "name": "setTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "state", + "outputs": [ + { + "internalType": "enum IGovernor.ProposalState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "team", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IVotes", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newQuorumNumerator", + "type": "uint256" + } + ], + "name": "updateQuorumNumerator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "votingDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "votingPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xf8b26b26f3fabd0df348a04581c229369d345799b41ca81d52273d35f68fa56c", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x82659caE4Dd0C19F7FBf47A5492E31Ad9501CA73", + "transactionIndex": 1, + "gasUsed": "2742878", + "logsBloom": "0x00000000000000000100000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x50fd06f452de54148b6f2afaa4711612696cb06d46db28f2d5a06a90140e9cb2", + "transactionHash": "0xf8b26b26f3fabd0df348a04581c229369d345799b41ca81d52273d35f68fa56c", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 5814442, + "transactionHash": "0xf8b26b26f3fabd0df348a04581c229369d345799b41ca81d52273d35f68fa56c", + "address": "0x82659caE4Dd0C19F7FBf47A5492E31Ad9501CA73", + "topics": [ + "0x0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004", + "logIndex": 0, + "blockHash": "0x50fd06f452de54148b6f2afaa4711612696cb06d46db28f2d5a06a90140e9cb2" + } + ], + "blockNumber": 5814442, + "cumulativeGasUsed": "2742878", + "status": 1, + "byzantium": true + }, + "args": [ + "0xad0F425b3edB0FC3a06096092B5736A280C90C40" + ], + "numDeployments": 1, + "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"_ve\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"Empty\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"proposer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"string[]\",\"name\":\"signatures\",\"type\":\"string[]\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"ProposalCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldQuorumNumerator\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"QuorumNumeratorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"VoteCast\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"VoteCastWithParams\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"COUNTING_MODE\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EXTENDED_BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_PROPOSAL_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROPOSAL_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"}],\"name\":\"castVote\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"castVoteWithReason\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"castVoteWithReasonAndParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteWithReasonAndParamsBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"execute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"getVotesWithParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasVoted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"hashProposal\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalDeadline\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalSnapshot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"againstVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"forVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"abstainVotes\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"propose\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"quorum\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumDenominator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"}],\"name\":\"setProposalNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTeam\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"state\",\"outputs\":[{\"internalType\":\"enum IGovernor.ProposalState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"updateQuorumNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"Empty()\":[{\"details\":\"An operation (e.g. {front}) couldn't be completed due to the queue being empty.\"}]},\"kind\":\"dev\",\"methods\":{\"COUNTING_MODE()\":{\"details\":\"See {IGovernor-COUNTING_MODE}.\"},\"castVote(uint256,uint8)\":{\"details\":\"See {IGovernor-castVote}.\"},\"castVoteBySig(uint256,uint8,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteBySig}.\"},\"castVoteWithReason(uint256,uint8,string)\":{\"details\":\"See {IGovernor-castVoteWithReason}.\"},\"castVoteWithReasonAndParams(uint256,uint8,string,bytes)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParams}.\"},\"castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParamsBySig}.\"},\"execute(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-execute}.\"},\"getVotes(address,uint256)\":{\"details\":\"See {IGovernor-getVotes}.\"},\"getVotesWithParams(address,uint256,bytes)\":{\"details\":\"See {IGovernor-getVotesWithParams}.\"},\"hasVoted(uint256,address)\":{\"details\":\"See {IGovernor-hasVoted}.\"},\"hashProposal(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-hashProposal}. The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in advance, before the proposal is submitted. Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the same proposal (with same operation and same description) will have the same id if submitted on multiple governors across multiple networks. This also means that in order to execute the same operation twice (on the same governor) the proposer will have to change the description in order to avoid proposal id conflicts.\"},\"name()\":{\"details\":\"See {IGovernor-name}.\"},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155BatchReceived}.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155Received}.\"},\"onERC721Received(address,address,uint256,bytes)\":{\"details\":\"See {IERC721Receiver-onERC721Received}.\"},\"proposalDeadline(uint256)\":{\"details\":\"See {IGovernor-proposalDeadline}.\"},\"proposalSnapshot(uint256)\":{\"details\":\"See {IGovernor-proposalSnapshot}.\"},\"proposalThreshold()\":{\"details\":\"Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\"},\"proposalVotes(uint256)\":{\"details\":\"Accessor to the internal vote counts.\"},\"propose(address[],uint256[],bytes[],string)\":{\"details\":\"See {IGovernor-propose}.\"},\"quorum(uint256)\":{\"details\":\"Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\"},\"quorumDenominator()\":{\"details\":\"Returns the quorum denominator. Defaults to 100, but may be overridden.\"},\"quorumNumerator()\":{\"details\":\"Returns the current quorum numerator. See {quorumDenominator}.\"},\"relay(address,uint256,bytes)\":{\"details\":\"Relays a transaction or function call to an arbitrary target. In cases where the governance executor is some contract other than the governor itself, like when using a timelock, this function can be invoked in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake. Note that if the executor is simply the governor itself, use of `relay` is redundant.\"},\"state(uint256)\":{\"details\":\"See {IGovernor-state}.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"updateQuorumNumerator(uint256)\":{\"details\":\"Changes the quorum numerator. Emits a {QuorumNumeratorUpdated} event. Requirements: - Must be called through a governance proposal. - New numerator must be smaller or equal to the denominator.\"},\"version()\":{\"details\":\"See {IGovernor-version}.\"},\"votingDelay()\":{\"details\":\"Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\"},\"votingPeriod()\":{\"details\":\"Delay, in number of blocks, between the vote start and vote ends. NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting duration compared to the voting delay.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"votingDelay()\":{\"notice\":\"module:user-config\"},\"votingPeriod()\":{\"notice\":\"module:user-config\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/FlowGovernor.sol\":\"FlowGovernor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/FlowGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IGovernor} from \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\nimport {L2GovernorCountingSimple} from \\\"contracts/governance/L2GovernorCountingSimple.sol\\\";\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\nimport {L2GovernorVotesQuorumFraction} from \\\"contracts/governance/L2GovernorVotesQuorumFraction.sol\\\";\\n\\ncontract FlowGovernor is\\n L2Governor,\\n L2GovernorCountingSimple,\\n L2GovernorVotes,\\n L2GovernorVotesQuorumFraction\\n{\\n address public team;\\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\\n uint256 public proposalNumerator = 2; // start at 0.02%\\n\\n constructor(IVotes _ve)\\n L2Governor(\\\"Velocimeter Governor\\\")\\n L2GovernorVotes(_ve)\\n L2GovernorVotesQuorumFraction(4) // 4%\\n {\\n team = msg.sender;\\n }\\n\\n function votingDelay() public pure override(IGovernor) returns (uint256) {\\n return 15 minutes; // 1 block\\n }\\n\\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\\n return 1 weeks;\\n }\\n\\n function setTeam(address newTeam) external {\\n require(msg.sender == team, \\\"not team\\\");\\n team = newTeam;\\n }\\n\\n function setProposalNumerator(uint256 numerator) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \\\"numerator too high\\\");\\n proposalNumerator = numerator;\\n }\\n\\n function proposalThreshold()\\n public\\n view\\n override(L2Governor)\\n returns (uint256)\\n {\\n return\\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\\n PROPOSAL_DENOMINATOR;\\n }\\n}\\n\",\"keccak256\":\"0xbf02f2fa1b0179b06bba2274ce6720c31ba3783f899502567cc25a093b27edb6\",\"license\":\"MIT\"},\"contracts/governance/L2Governor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Address.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Context.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\\n *\\n * @dev Core of the governance system, designed to be extended though various modules.\\n *\\n * This contract is abstract and requires several function to be implemented in various modules:\\n *\\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\\n * - A voting module must implement {_getVotes}\\n * - Additionanly, the {votingPeriod} must also be implemented\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\\n using SafeCast for uint256;\\n using Timers for Timers.Timestamp;\\n\\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\\\"Ballot(uint256 proposalId,uint8 support)\\\");\\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\\n keccak256(\\\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\\\");\\n\\n struct ProposalCore {\\n Timers.Timestamp voteStart;\\n Timers.Timestamp voteEnd;\\n bool executed;\\n bool canceled;\\n }\\n\\n string private _name;\\n\\n mapping(uint256 => ProposalCore) private _proposals;\\n\\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\\n\\n /**\\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\\n * parameter setters in {GovernorSettings} are protected using this modifier.\\n *\\n * The governance executing address may be different from the Governor's own address, for example it could be a\\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\\n * for example, additional timelock proposers are not able to change governance parameters without going through the\\n * governance protocol (since v4.6).\\n */\\n modifier onlyGovernance() {\\n require(_msgSender() == _executor(), \\\"Governor: onlyGovernance\\\");\\n if (_executor() != address(this)) {\\n bytes32 msgDataHash = keccak256(_msgData());\\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\\n while (_governanceCall.popFront() != msgDataHash) {}\\n }\\n _;\\n }\\n\\n /**\\n * @dev Sets the value for {name} and {version}\\n */\\n constructor(string memory name_) EIP712(name_, version()) {\\n _name = name_;\\n }\\n\\n /**\\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\\n */\\n receive() external payable virtual {\\n require(_executor() == address(this));\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\\n // include the castVoteWithReasonAndParams() function as standard\\n return\\n interfaceId ==\\n (type(IGovernor).interfaceId ^\\n this.castVoteWithReasonAndParams.selector ^\\n this.castVoteWithReasonAndParamsBySig.selector ^\\n this.getVotesWithParams.selector) ||\\n interfaceId == type(IGovernor).interfaceId ||\\n interfaceId == type(IERC1155Receiver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IGovernor-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IGovernor-version}.\\n */\\n function version() public view virtual override returns (string memory) {\\n return \\\"1\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hashProposal}.\\n *\\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\\n * advance, before the proposal is submitted.\\n *\\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual override returns (uint256) {\\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\\n }\\n\\n /**\\n * @dev See {IGovernor-state}.\\n */\\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n\\n if (proposal.executed) {\\n return ProposalState.Executed;\\n }\\n\\n if (proposal.canceled) {\\n return ProposalState.Canceled;\\n }\\n\\n uint256 start = proposalSnapshot(proposalId);\\n\\n if (start == 0) {\\n revert(\\\"Governor: unknown proposal id\\\");\\n }\\n\\n if (start >= block.timestamp) {\\n return ProposalState.Pending;\\n }\\n\\n uint256 deadline = proposalDeadline(proposalId);\\n\\n if (deadline >= block.timestamp) {\\n return ProposalState.Active;\\n }\\n\\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\\n return ProposalState.Succeeded;\\n } else {\\n return ProposalState.Defeated;\\n }\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalSnapshot}.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteStart.getDeadline();\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalDeadline}.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteEnd.getDeadline();\\n }\\n\\n /**\\n * @dev Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\\n */\\n function proposalThreshold() public view virtual returns (uint256) {\\n return 0;\\n }\\n\\n /**\\n * @dev Amount of votes already cast passes the threshold limit.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Is the proposal successful or not.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) internal view virtual returns (uint256);\\n\\n /**\\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\\n *\\n * Note: Support is generic and can represent various things depending on the voting system used.\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory params\\n ) internal virtual;\\n\\n /**\\n * @dev Default additional encoded parameters used by castVote methods that don't include them\\n *\\n * Note: Should be overridden by specific implementations to use an appropriate value, the\\n * meaning of the additional params, in the context of that implementation\\n */\\n function _defaultParams() internal view virtual returns (bytes memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-propose}.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual override returns (uint256) {\\n require(\\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\\n \\\"Governor: proposer votes below proposal threshold\\\"\\n );\\n\\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\\n\\n require(targets.length == values.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length == calldatas.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length > 0, \\\"Governor: empty proposal\\\");\\n\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(proposal.voteStart.isUnset(), \\\"Governor: proposal already exists\\\");\\n\\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\\n uint64 deadline = start + votingPeriod().toUint64();\\n\\n proposal.voteStart.setDeadline(start);\\n proposal.voteEnd.setDeadline(deadline);\\n\\n emit ProposalCreated(\\n proposalId,\\n _msgSender(),\\n targets,\\n values,\\n new string[](targets.length),\\n calldatas,\\n start,\\n deadline,\\n description\\n );\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-execute}.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual override returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n\\n ProposalState status = state(proposalId);\\n require(\\n status == ProposalState.Succeeded || status == ProposalState.Queued,\\n \\\"Governor: proposal not successful\\\"\\n );\\n _proposals[proposalId].executed = true;\\n\\n emit ProposalExecuted(proposalId);\\n\\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\\n _execute(proposalId, targets, values, calldatas, descriptionHash);\\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\\n */\\n function _execute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n string memory errorMessage = \\\"Governor: call reverted without message\\\";\\n for (uint256 i = 0; i < targets.length; ++i) {\\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\\n Address.verifyCallResult(success, returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Hook before execution is triggered.\\n */\\n function _beforeExecute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory, /* values */\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n for (uint256 i = 0; i < targets.length; ++i) {\\n if (targets[i] == address(this)) {\\n _governanceCall.pushBack(keccak256(calldatas[i]));\\n }\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook after execution is triggered.\\n */\\n function _afterExecute(\\n uint256, /* proposalId */\\n address[] memory, /* targets */\\n uint256[] memory, /* values */\\n bytes[] memory, /* calldatas */\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n if (!_governanceCall.empty()) {\\n _governanceCall.clear();\\n }\\n }\\n }\\n\\n /**\\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\\n * canceled to allow distinguishing it from executed proposals.\\n *\\n * Emits a {IGovernor-ProposalCanceled} event.\\n */\\n function _cancel(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) internal virtual returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n ProposalState status = state(proposalId);\\n\\n require(\\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\\n \\\"Governor: proposal not active\\\"\\n );\\n _proposals[proposalId].canceled = true;\\n\\n emit ProposalCanceled(proposalId);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotes}.\\n */\\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, _defaultParams());\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotesWithParams}.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVote}.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReason}.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteBySig}.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\\n v,\\n r,\\n s\\n );\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(\\n keccak256(\\n abi.encode(\\n EXTENDED_BALLOT_TYPEHASH,\\n proposalId,\\n support,\\n keccak256(bytes(reason)),\\n keccak256(params)\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason\\n ) internal virtual returns (uint256) {\\n return _castVote(proposalId, account, support, reason, _defaultParams());\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason,\\n bytes memory params\\n ) internal virtual returns (uint256) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(state(proposalId) == ProposalState.Active, \\\"Governor: vote not currently active\\\");\\n\\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\\n _countVote(proposalId, account, support, weight, params);\\n\\n if (params.length == 0) {\\n emit VoteCast(account, proposalId, support, weight, reason);\\n } else {\\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\\n }\\n\\n return weight;\\n }\\n\\n /**\\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\\n */\\n function relay(\\n address target,\\n uint256 value,\\n bytes calldata data\\n ) external virtual onlyGovernance {\\n Address.functionCallWithValue(target, data, value);\\n }\\n\\n /**\\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\\n * through another contract such as a timelock.\\n */\\n function _executor() internal view virtual returns (address) {\\n return address(this);\\n }\\n\\n /**\\n * @dev See {IERC721Receiver-onERC721Received}.\\n */\\n function onERC721Received(\\n address,\\n address,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155Received}.\\n */\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\\n */\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] memory,\\n uint256[] memory,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155BatchReceived.selector;\\n }\\n}\\n\",\"keccak256\":\"0xa2846313b89a871807cdebd0225b0bf8f23b17505ab8b3288549ec54a5a4a71b\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorCountingSimple.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\\n *\\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorCountingSimple is L2Governor {\\n /**\\n * @dev Supported vote types. Matches Governor Bravo ordering.\\n */\\n enum VoteType {\\n Against,\\n For,\\n Abstain\\n }\\n\\n struct ProposalVote {\\n uint256 againstVotes;\\n uint256 forVotes;\\n uint256 abstainVotes;\\n mapping(address => bool) hasVoted;\\n }\\n\\n mapping(uint256 => ProposalVote) private _proposalVotes;\\n\\n /**\\n * @dev See {IGovernor-COUNTING_MODE}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual override returns (string memory) {\\n return \\\"support=bravo&quorum=for,abstain\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hasVoted}.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\\n return _proposalVotes[proposalId].hasVoted[account];\\n }\\n\\n /**\\n * @dev Accessor to the internal vote counts.\\n */\\n function proposalVotes(uint256 proposalId)\\n public\\n view\\n virtual\\n returns (\\n uint256 againstVotes,\\n uint256 forVotes,\\n uint256 abstainVotes\\n )\\n {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\\n }\\n\\n /**\\n * @dev See {Governor-_quorumReached}.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return proposalvote.forVotes > proposalvote.againstVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory // params\\n ) internal virtual override {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n require(!proposalvote.hasVoted[account], \\\"GovernorVotingSimple: vote already cast\\\");\\n proposalvote.hasVoted[account] = true;\\n\\n if (support == uint8(VoteType.Against)) {\\n proposalvote.againstVotes += weight;\\n } else if (support == uint8(VoteType.For)) {\\n proposalvote.forVotes += weight;\\n } else if (support == uint8(VoteType.Abstain)) {\\n proposalvote.abstainVotes += weight;\\n } else {\\n revert(\\\"GovernorVotingSimple: invalid value for enum VoteType\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xdc37daa24118a6e6ba5208b4abefa1632af2ff340135ca6c6d7237f70102d5db\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotes is L2Governor {\\n IVotes public immutable token;\\n\\n constructor(IVotes tokenAddress) {\\n token = tokenAddress;\\n }\\n\\n /**\\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory /*params*/\\n ) internal view virtual override returns (uint256) {\\n return token.getPastVotes(account, blockTimestamp);\\n }\\n}\\n\",\"keccak256\":\"0x605a7de71228dda3cb8fd878cac313a86bc5841fd34d7344214346ba46e63af1\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotesQuorumFraction.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\\n * fraction of the total supply.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\\n uint256 private _quorumNumerator;\\n\\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\\n\\n /**\\n * @dev Initialize quorum as a fraction of the token's total supply.\\n *\\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\\n * customized by overriding {quorumDenominator}.\\n */\\n constructor(uint256 quorumNumeratorValue) {\\n _updateQuorumNumerator(quorumNumeratorValue);\\n }\\n\\n /**\\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\\n */\\n function quorumNumerator() public view virtual returns (uint256) {\\n return _quorumNumerator;\\n }\\n\\n /**\\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\\n */\\n function quorumDenominator() public view virtual returns (uint256) {\\n return 100;\\n }\\n\\n /**\\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\\n */\\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - Must be called through a governance proposal.\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\\n _updateQuorumNumerator(newQuorumNumerator);\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\\n require(\\n newQuorumNumerator <= quorumDenominator(),\\n \\\"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\\\"\\n );\\n\\n uint256 oldQuorumNumerator = _quorumNumerator;\\n _quorumNumerator = newQuorumNumerator;\\n\\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\\n }\\n}\\n\",\"keccak256\":\"0xe66d29c0ffd2274de933d80e11d68891f3acc3f078be4560a2b493b7d88dcb7f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Interface of the {Governor} core.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract IGovernor is IERC165 {\\n enum ProposalState {\\n Pending,\\n Active,\\n Canceled,\\n Defeated,\\n Succeeded,\\n Queued,\\n Expired,\\n Executed\\n }\\n\\n /**\\n * @dev Emitted when a proposal is created.\\n */\\n event ProposalCreated(\\n uint256 proposalId,\\n address proposer,\\n address[] targets,\\n uint256[] values,\\n string[] signatures,\\n bytes[] calldatas,\\n uint256 startBlock,\\n uint256 endBlock,\\n string description\\n );\\n\\n /**\\n * @dev Emitted when a proposal is canceled.\\n */\\n event ProposalCanceled(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a proposal is executed.\\n */\\n event ProposalExecuted(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a vote is cast without params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n */\\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\\n\\n /**\\n * @dev Emitted when a vote is cast with params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\\n */\\n event VoteCastWithParams(\\n address indexed voter,\\n uint256 proposalId,\\n uint8 support,\\n uint256 weight,\\n string reason,\\n bytes params\\n );\\n\\n /**\\n * @notice module:core\\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\\n */\\n function name() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \\\"1\\\"\\n */\\n function version() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:voting\\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\\n *\\n * There are 2 standard keys: `support` and `quorum`.\\n *\\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\\n * - `quorum=bravo` means that only For votes are counted towards quorum.\\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\\n *\\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\\n * name that describes the behavior. For example:\\n *\\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\\n *\\n * NOTE: The string can be decoded by the standard\\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\\n * JavaScript class.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Current state of a proposal, following Compound's convention\\n */\\n function state(uint256 proposalId) public view virtual returns (ProposalState);\\n\\n /**\\n * @notice module:core\\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\\n * beginning of the following block.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\\n * during this block.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\\n */\\n function votingDelay() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of blocks, between the vote start and vote ends.\\n *\\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\\n * duration compared to the voting delay.\\n */\\n function votingPeriod() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Minimum number of cast voted required for a proposal to be successful.\\n *\\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\\n */\\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber`.\\n *\\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\\n * multiple), {ERC20Votes} tokens.\\n */\\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockNumber,\\n bytes memory params\\n ) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:voting\\n * @dev Returns whether `account` has cast a vote on `proposalId`.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\\n\\n /**\\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\\n * {IGovernor-votingPeriod} blocks after the voting starts.\\n *\\n * Emits a {ProposalCreated} event.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\\n * deadline to be reached.\\n *\\n * Emits a {ProposalExecuted} event.\\n *\\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Cast a vote\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xa52d593ff06a2353f78fa149da31f2ca94f03d1eff99bde41977fa2fe985a92f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2e53602b96c1bf97c731ed3e2a981b4f85e23a9410a5ebd36e549a4cc93340dc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x2626d8ab3dfdad0fad630c212ad146d59473d0f48b771784c61a7c1dbbea1f3f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Tooling for timepoints, timers and delays\\n */\\nlibrary Timers {\\n struct Timestamp {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(Timestamp storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(Timestamp memory timer) internal view returns (bool) {\\n return timer._deadline > block.timestamp;\\n }\\n\\n function isExpired(Timestamp memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.timestamp;\\n }\\n\\n struct BlockNumber {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(BlockNumber storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(BlockNumber memory timer) internal view returns (bool) {\\n return timer._deadline > block.number;\\n }\\n\\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.number;\\n }\\n}\\n\",\"keccak256\":\"0x29791a62950a7983e02a673639c1a781d1e448691800456c2ce4b99715391b14\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS,\\n InvalidSignatureV // Deprecated in v4.8\\n }\\n\\n function _throwError(RecoverError error) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert(\\\"ECDSA: invalid signature\\\");\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert(\\\"ECDSA: invalid signature 's' value\\\");\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature` or error string. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\\n if (signature.length == 65) {\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n /// @solidity memory-safe-assembly\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n return tryRecover(hash, v, r, s);\\n } else {\\n return (address(0), RecoverError.InvalidSignatureLength);\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, signature);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n *\\n * _Available since v4.2._\\n */\\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature);\\n }\\n\\n return (signer, RecoverError.NoError);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from `s`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", Strings.toString(s.length), s));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Typed Data, created from a\\n * `domainSeparator` and a `structHash`. This produces hash corresponding\\n * to the one signed with the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\\n * JSON-RPC method as part of EIP-712.\\n *\\n * See {recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n }\\n}\\n\",\"keccak256\":\"0x54ee424bfc83ce63b2a918b9a1efb5090a0fb68dbd1de3b10bc667776885dd4f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ECDSA.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n /* solhint-disable var-name-mixedcase */\\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n // invalidate the cached domain separator if the chain id changes.\\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n uint256 private immutable _CACHED_CHAIN_ID;\\n address private immutable _CACHED_THIS;\\n\\n bytes32 private immutable _HASHED_NAME;\\n bytes32 private immutable _HASHED_VERSION;\\n bytes32 private immutable _TYPE_HASH;\\n\\n /* solhint-enable var-name-mixedcase */\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n constructor(string memory name, string memory version) {\\n bytes32 hashedName = keccak256(bytes(name));\\n bytes32 hashedVersion = keccak256(bytes(version));\\n bytes32 typeHash = keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n );\\n _HASHED_NAME = hashedName;\\n _HASHED_VERSION = hashedVersion;\\n _CACHED_CHAIN_ID = block.chainid;\\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n _CACHED_THIS = address(this);\\n _TYPE_HASH = typeHash;\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\\n return _CACHED_DOMAIN_SEPARATOR;\\n } else {\\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n }\\n }\\n\\n function _buildDomainSeparator(\\n bytes32 typeHash,\\n bytes32 nameHash,\\n bytes32 versionHash\\n ) private view returns (bytes32) {\\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\\n }\\n}\\n\",\"keccak256\":\"0x948d8b2d18f38141ec78c5229d770d950ebc781ed3f44cc9e3ccbb9fded5846a\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\\n\\nimport \\\"./EIP712.sol\\\";\\n\",\"keccak256\":\"0xea30c402170bc240354b74e6c6f6a8e5bdb1935d90d168cc58c0654461c6a72b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3546b156d97633f7f8cad536d5454c81d1d604687c02b2eb105fdc33cb962b41\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\\npragma solidity ^0.8.4;\\n\\nimport \\\"../math/SafeCast.sol\\\";\\n\\n/**\\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\\n * the existing queue contents are left in storage.\\n *\\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\\n * used in storage, and not in memory.\\n * ```\\n * DoubleEndedQueue.Bytes32Deque queue;\\n * ```\\n *\\n * _Available since v4.6._\\n */\\nlibrary DoubleEndedQueue {\\n /**\\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\\n */\\n error Empty();\\n\\n /**\\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\\n */\\n error OutOfBounds();\\n\\n /**\\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\\n *\\n * Struct members have an underscore prefix indicating that they are \\\"private\\\" and should not be read or written to\\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\\n * lead to unexpected behavior.\\n *\\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\\n * data[end - 1].\\n */\\n struct Bytes32Deque {\\n int128 _begin;\\n int128 _end;\\n mapping(int128 => bytes32) _data;\\n }\\n\\n /**\\n * @dev Inserts an item at the end of the queue.\\n */\\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 backIndex = deque._end;\\n deque._data[backIndex] = value;\\n unchecked {\\n deque._end = backIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Removes the item at the end of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n value = deque._data[backIndex];\\n delete deque._data[backIndex];\\n deque._end = backIndex;\\n }\\n\\n /**\\n * @dev Inserts an item at the beginning of the queue.\\n */\\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 frontIndex;\\n unchecked {\\n frontIndex = deque._begin - 1;\\n }\\n deque._data[frontIndex] = value;\\n deque._begin = frontIndex;\\n }\\n\\n /**\\n * @dev Removes the item at the beginning of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n value = deque._data[frontIndex];\\n delete deque._data[frontIndex];\\n unchecked {\\n deque._begin = frontIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Returns the item at the beginning of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n return deque._data[frontIndex];\\n }\\n\\n /**\\n * @dev Returns the item at the end of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n return deque._data[backIndex];\\n }\\n\\n /**\\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\\n * `length(deque) - 1`.\\n *\\n * Reverts with `OutOfBounds` if the index is out of bounds.\\n */\\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\\n // int256(deque._begin) is a safe upcast\\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\\n if (idx >= deque._end) revert OutOfBounds();\\n return deque._data[idx];\\n }\\n\\n /**\\n * @dev Resets the queue back to being empty.\\n *\\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\\n * out on potential gas refunds.\\n */\\n function clear(Bytes32Deque storage deque) internal {\\n deque._begin = 0;\\n deque._end = 0;\\n }\\n\\n /**\\n * @dev Returns the number of items in the queue.\\n */\\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\\n // We also assume there are at most int256.max items in the queue.\\n unchecked {\\n return uint256(int256(deque._end) - int256(deque._begin));\\n }\\n }\\n\\n /**\\n * @dev Returns true if the queue is empty.\\n */\\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\\n return deque._end <= deque._begin;\\n }\\n}\\n\",\"keccak256\":\"0x4859ffd6dd69382a1462930c00b6e394007da80e78e510f56930271034737bf2\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x61016060405260026007553480156200001757600080fd5b506040516200329a3803806200329a8339810160408190526200003a91620002ec565b6004816040518060400160405280601481526020017f56656c6f63696d6574657220476f7665726e6f7200000000000000000000000081525080620000846200015e60201b60201c565b815160208084019190912082518383012060e08290526101008190524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81880181905281830187905260608201869052608082019490945230818401528151808203909301835260c00190528051940193909320919290916080523060c05261012052505082516200012a925060009150602084019062000246565b50506001600160a01b031661014052620001448162000179565b5050600680546001600160a01b031916331790556200035a565b6040805180820190915260018152603160f81b602082015290565b6064811115620002015760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a40160405180910390fd5b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b82805462000254906200031e565b90600052602060002090601f016020900481019282620002785760008555620002c3565b82601f106200029357805160ff1916838001178555620002c3565b82800160010185558215620002c3579182015b82811115620002c3578251825591602001919060010190620002a6565b50620002d1929150620002d5565b5090565b5b80821115620002d15760008155600101620002d6565b600060208284031215620002ff57600080fd5b81516001600160a01b03811681146200031757600080fd5b9392505050565b600181811c908216806200033357607f821691505b6020821081036200035457634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e051610100516101205161014051612ed0620003ca600039600081816107df0152818161120f015281816113e40152611a0601526000611b2301526000611b7201526000611b4d01526000611aa601526000611ad001526000611afa0152612ed06000f3fe6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a26469706673582212203270a9fc50cfa0f139ef918071f19d9b00812268f9d1e713077fc9299cb1081d64736f6c634300080d0033", + "deployedBytecode": "0x6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a26469706673582212203270a9fc50cfa0f139ef918071f19d9b00812268f9d1e713077fc9299cb1081d64736f6c634300080d0033", + "devdoc": { + "errors": { + "Empty()": [ + { + "details": "An operation (e.g. {front}) couldn't be completed due to the queue being empty." + } + ] + }, + "kind": "dev", + "methods": { + "COUNTING_MODE()": { + "details": "See {IGovernor-COUNTING_MODE}." + }, + "castVote(uint256,uint8)": { + "details": "See {IGovernor-castVote}." + }, + "castVoteBySig(uint256,uint8,uint8,bytes32,bytes32)": { + "details": "See {IGovernor-castVoteBySig}." + }, + "castVoteWithReason(uint256,uint8,string)": { + "details": "See {IGovernor-castVoteWithReason}." + }, + "castVoteWithReasonAndParams(uint256,uint8,string,bytes)": { + "details": "See {IGovernor-castVoteWithReasonAndParams}." + }, + "castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32)": { + "details": "See {IGovernor-castVoteWithReasonAndParamsBySig}." + }, + "execute(address[],uint256[],bytes[],bytes32)": { + "details": "See {IGovernor-execute}." + }, + "getVotes(address,uint256)": { + "details": "See {IGovernor-getVotes}." + }, + "getVotesWithParams(address,uint256,bytes)": { + "details": "See {IGovernor-getVotesWithParams}." + }, + "hasVoted(uint256,address)": { + "details": "See {IGovernor-hasVoted}." + }, + "hashProposal(address[],uint256[],bytes[],bytes32)": { + "details": "See {IGovernor-hashProposal}. The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in advance, before the proposal is submitted. Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the same proposal (with same operation and same description) will have the same id if submitted on multiple governors across multiple networks. This also means that in order to execute the same operation twice (on the same governor) the proposer will have to change the description in order to avoid proposal id conflicts." + }, + "name()": { + "details": "See {IGovernor-name}." + }, + "onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)": { + "details": "See {IERC1155Receiver-onERC1155BatchReceived}." + }, + "onERC1155Received(address,address,uint256,uint256,bytes)": { + "details": "See {IERC1155Receiver-onERC1155Received}." + }, + "onERC721Received(address,address,uint256,bytes)": { + "details": "See {IERC721Receiver-onERC721Received}." + }, + "proposalDeadline(uint256)": { + "details": "See {IGovernor-proposalDeadline}." + }, + "proposalSnapshot(uint256)": { + "details": "See {IGovernor-proposalSnapshot}." + }, + "proposalThreshold()": { + "details": "Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_." + }, + "proposalVotes(uint256)": { + "details": "Accessor to the internal vote counts." + }, + "propose(address[],uint256[],bytes[],string)": { + "details": "See {IGovernor-propose}." + }, + "quorum(uint256)": { + "details": "Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`." + }, + "quorumDenominator()": { + "details": "Returns the quorum denominator. Defaults to 100, but may be overridden." + }, + "quorumNumerator()": { + "details": "Returns the current quorum numerator. See {quorumDenominator}." + }, + "relay(address,uint256,bytes)": { + "details": "Relays a transaction or function call to an arbitrary target. In cases where the governance executor is some contract other than the governor itself, like when using a timelock, this function can be invoked in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake. Note that if the executor is simply the governor itself, use of `relay` is redundant." + }, + "state(uint256)": { + "details": "See {IGovernor-state}." + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + }, + "updateQuorumNumerator(uint256)": { + "details": "Changes the quorum numerator. Emits a {QuorumNumeratorUpdated} event. Requirements: - Must be called through a governance proposal. - New numerator must be smaller or equal to the denominator." + }, + "version()": { + "details": "See {IGovernor-version}." + }, + "votingDelay()": { + "details": "Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to leave time for users to buy voting power, or delegate it, before the voting of a proposal starts." + }, + "votingPeriod()": { + "details": "Delay, in number of blocks, between the vote start and vote ends. NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting duration compared to the voting delay." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "votingDelay()": { + "notice": "module:user-config" + }, + "votingPeriod()": { + "notice": "module:user-config" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 21935, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "_name", + "offset": 0, + "slot": "0", + "type": "t_string_storage" + }, + { + "astId": 21940, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "_proposals", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_uint256,t_struct(ProposalCore)21933_storage)" + }, + { + "astId": 21943, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "_governanceCall", + "offset": 0, + "slot": "2", + "type": "t_struct(Bytes32Deque)30247_storage" + }, + { + "astId": 23199, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "_proposalVotes", + "offset": 0, + "slot": "4", + "type": "t_mapping(t_uint256,t_struct(ProposalVote)23194_storage)" + }, + { + "astId": 23452, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "_quorumNumerator", + "offset": 0, + "slot": "5", + "type": "t_uint256" + }, + { + "astId": 1704, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "team", + "offset": 0, + "slot": "6", + "type": "t_address" + }, + { + "astId": 1713, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "proposalNumerator", + "offset": 0, + "slot": "7", + "type": "t_uint256" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_int128": { + "encoding": "inplace", + "label": "int128", + "numberOfBytes": "16" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_int128,t_bytes32)": { + "encoding": "mapping", + "key": "t_int128", + "label": "mapping(int128 => bytes32)", + "numberOfBytes": "32", + "value": "t_bytes32" + }, + "t_mapping(t_uint256,t_struct(ProposalCore)21933_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct L2Governor.ProposalCore)", + "numberOfBytes": "32", + "value": "t_struct(ProposalCore)21933_storage" + }, + "t_mapping(t_uint256,t_struct(ProposalVote)23194_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct L2GovernorCountingSimple.ProposalVote)", + "numberOfBytes": "32", + "value": "t_struct(ProposalVote)23194_storage" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Bytes32Deque)30247_storage": { + "encoding": "inplace", + "label": "struct DoubleEndedQueue.Bytes32Deque", + "members": [ + { + "astId": 30240, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "_begin", + "offset": 0, + "slot": "0", + "type": "t_int128" + }, + { + "astId": 30242, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "_end", + "offset": 16, + "slot": "0", + "type": "t_int128" + }, + { + "astId": 30246, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "_data", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_int128,t_bytes32)" + } + ], + "numberOfBytes": "64" + }, + "t_struct(ProposalCore)21933_storage": { + "encoding": "inplace", + "label": "struct L2Governor.ProposalCore", + "members": [ + { + "astId": 21925, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "voteStart", + "offset": 0, + "slot": "0", + "type": "t_struct(Timestamp)26448_storage" + }, + { + "astId": 21928, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "voteEnd", + "offset": 0, + "slot": "1", + "type": "t_struct(Timestamp)26448_storage" + }, + { + "astId": 21930, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "executed", + "offset": 0, + "slot": "2", + "type": "t_bool" + }, + { + "astId": 21932, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "canceled", + "offset": 1, + "slot": "2", + "type": "t_bool" + } + ], + "numberOfBytes": "96" + }, + "t_struct(ProposalVote)23194_storage": { + "encoding": "inplace", + "label": "struct L2GovernorCountingSimple.ProposalVote", + "members": [ + { + "astId": 23185, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "againstVotes", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 23187, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "forVotes", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 23189, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "abstainVotes", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 23193, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "hasVoted", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_address,t_bool)" + } + ], + "numberOfBytes": "128" + }, + "t_struct(Timestamp)26448_storage": { + "encoding": "inplace", + "label": "struct Timers.Timestamp", + "members": [ + { + "astId": 26447, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "_deadline", + "offset": 0, + "slot": "0", + "type": "t_uint64" + } + ], + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint64": { + "encoding": "inplace", + "label": "uint64", + "numberOfBytes": "8" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/GaugeFactory.json b/deployments/arbitrumGoerli/GaugeFactory.json index 2dcc2896..9fbf8194 100644 --- a/deployments/arbitrumGoerli/GaugeFactory.json +++ b/deployments/arbitrumGoerli/GaugeFactory.json @@ -1,5 +1,5 @@ { - "address": "0xA957E3958C7ed4590a28C5564438E89238b34EC1", + "address": "0x18B8e4fEf12a17BFe35f0A1a4ca3cA7208F30123", "abi": [ { "inputs": [ @@ -59,28 +59,28 @@ "type": "function" } ], - "transactionHash": "0x85efc32d1e1f57ec2317ea7f06e5066c523fb0ce28325e1755e390d2d7046ca8", + "transactionHash": "0xb6453d5b0001f1377c6a90bdeb63e578a2637846a3bdf6fb5a1f5bfb4629abd7", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xA957E3958C7ed4590a28C5564438E89238b34EC1", + "contractAddress": "0x18B8e4fEf12a17BFe35f0A1a4ca3cA7208F30123", "transactionIndex": 1, "gasUsed": "3308285", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x0c70caef0b5b20139b77a153f56d8b52ac092b78130d749353ec2eb408f34b17", - "transactionHash": "0x85efc32d1e1f57ec2317ea7f06e5066c523fb0ce28325e1755e390d2d7046ca8", + "blockHash": "0xeb412148cd5f01ceae88fae38c726bba49346e9b772e4301c2b15300a8a1e105", + "transactionHash": "0xb6453d5b0001f1377c6a90bdeb63e578a2637846a3bdf6fb5a1f5bfb4629abd7", "logs": [], - "blockNumber": 5716706, + "blockNumber": 5814394, "cumulativeGasUsed": "3308285", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 3, - "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_internal_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_external_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_ve\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isPair\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_gauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/GaugeFactory.sol\":\"GaugeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Gauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\\ncontract Gauge is IGauge {\\n address public immutable stake; // the LP token that needs to be staked for rewards\\n address public immutable _ve; // the ve token used for gauges\\n address public immutable internal_bribe;\\n address public immutable external_bribe;\\n address public immutable voter;\\n\\n uint256 public derivedSupply;\\n mapping(address => uint256) public derivedBalances;\\n\\n bool public isForPair;\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 internal constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(address => uint256)) public lastEarn;\\n mapping(address => mapping(address => uint256))\\n public userRewardPerTokenStored;\\n\\n mapping(address => uint256) public tokenIds;\\n\\n uint256 public totalSupply;\\n mapping(address => uint256) public balanceOf;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n uint256 public fees0;\\n uint256 public fees1;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(\\n address _stake,\\n address _internal_bribe,\\n address _external_bribe,\\n address __ve,\\n address _voter,\\n bool _forPair,\\n address[] memory _allowedRewardTokens\\n ) {\\n stake = _stake;\\n internal_bribe = _internal_bribe;\\n external_bribe = _external_bribe;\\n _ve = __ve;\\n voter = _voter;\\n isForPair = _forPair;\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function claimFees()\\n external\\n lock\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n return _claimFees();\\n }\\n\\n function _claimFees()\\n internal\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n if (!isForPair) {\\n return (0, 0);\\n }\\n (claimed0, claimed1) = IPair(stake).claimFees();\\n if (claimed0 > 0 || claimed1 > 0) {\\n uint256 _fees0 = fees0 + claimed0;\\n uint256 _fees1 = fees1 + claimed1;\\n (address _token0, address _token1) = IPair(stake).tokens();\\n if (\\n _fees0 > IBribe(internal_bribe).left(_token0) &&\\n _fees0 / DURATION > 0\\n ) {\\n fees0 = 0;\\n _safeApprove(_token0, internal_bribe, _fees0);\\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\\n } else {\\n fees0 = _fees0;\\n }\\n if (\\n _fees1 > IBribe(internal_bribe).left(_token1) &&\\n _fees1 / DURATION > 0\\n ) {\\n fees1 = 0;\\n _safeApprove(_token1, internal_bribe, _fees1);\\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\\n } else {\\n fees1 = _fees1;\\n }\\n\\n emit ClaimFees(msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(address account, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(address account, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[account][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[account] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n derivedSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n function getReward(address account, address[] memory tokens) external lock {\\n require(msg.sender == account || msg.sender == voter);\\n _unlocked = 1;\\n IVoter(voter).distribute(address(this));\\n _unlocked = 2;\\n\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], account);\\n lastEarn[tokens[i]][account] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n\\n uint256 _derivedBalance = derivedBalances[account];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(account);\\n derivedBalances[account] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(account, derivedBalances[account]);\\n _writeSupplyCheckpoint();\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (derivedSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / derivedSupply);\\n }\\n\\n function derivedBalance(address account) public view returns (uint256) {\\n return balanceOf[account];\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\\n function earned(address token, address account)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][account],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[account] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[account] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[account][i];\\n Checkpoint memory cp1 = checkpoints[account][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[account][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][account]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n function depositAll(uint256 tokenId) external {\\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\\n }\\n\\n function deposit(uint256 amount, uint256 tokenId) public lock {\\n require(amount > 0);\\n _updateRewardForAllTokens();\\n\\n _safeTransferFrom(stake, msg.sender, address(this), amount);\\n totalSupply += amount;\\n balanceOf[msg.sender] += amount;\\n\\n if (tokenId > 0) {\\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\\n if (tokenIds[msg.sender] == 0) {\\n tokenIds[msg.sender] = tokenId;\\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\\n }\\n require(tokenIds[msg.sender] == tokenId);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, _derivedBalance);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function withdrawAll() external {\\n withdraw(balanceOf[msg.sender]);\\n }\\n\\n function withdraw(uint256 amount) public {\\n uint256 tokenId = 0;\\n if (amount == balanceOf[msg.sender]) {\\n tokenId = tokenIds[msg.sender];\\n }\\n withdrawToken(amount, tokenId);\\n }\\n\\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[msg.sender] -= amount;\\n _safeTransfer(stake, msg.sender, amount);\\n\\n if (tokenId > 0) {\\n require(tokenId == tokenIds[msg.sender]);\\n tokenIds[msg.sender] = 0;\\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(token != stake);\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"rewards tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n _claimFees();\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeApprove(\\n address token,\\n address spender,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x38cc0284dd60d8a1418d9c34e6be84911ca4a1b479dc129f19b9027e4c670e1f\",\"license\":\"MIT\"},\"contracts/factories/GaugeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/Gauge.sol';\\n\\ncontract GaugeFactory is IGaugeFactory {\\n address public last_gauge;\\n\\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\\n return last_gauge;\\n }\\n}\\n\",\"keccak256\":\"0x34f6ac4bdace9ef01d8cffda9b45842efae88b519230c67759b9936aee6acc9b\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50613b19806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea26469706673582212208a503e90ec86652bffaad1a8a72d166d5f800a64e217b3ae0e9e2239815ddf4a64736f6c634300080d0033a264697066735822122090d33148904466ef33139c1a9443e5d4726004bb8187f8f4e03966c135b5f79664736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea26469706673582212208a503e90ec86652bffaad1a8a72d166d5f800a64e217b3ae0e9e2239815ddf4a64736f6c634300080d0033a264697066735822122090d33148904466ef33139c1a9443e5d4726004bb8187f8f4e03966c135b5f79664736f6c634300080d0033", + "numDeployments": 5, + "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_internal_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_external_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_ve\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isPair\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_gauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/GaugeFactory.sol\":\"GaugeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Gauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\\ncontract Gauge is IGauge {\\n address public immutable stake; // the LP token that needs to be staked for rewards\\n address public immutable _ve; // the ve token used for gauges\\n address public immutable internal_bribe;\\n address public immutable external_bribe;\\n address public immutable voter;\\n\\n uint256 public derivedSupply;\\n mapping(address => uint256) public derivedBalances;\\n\\n bool public isForPair;\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 internal constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(address => uint256)) public lastEarn;\\n mapping(address => mapping(address => uint256))\\n public userRewardPerTokenStored;\\n\\n mapping(address => uint256) public tokenIds;\\n\\n uint256 public totalSupply;\\n mapping(address => uint256) public balanceOf;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n uint256 public fees0;\\n uint256 public fees1;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(\\n address _stake,\\n address _internal_bribe,\\n address _external_bribe,\\n address __ve,\\n address _voter,\\n bool _forPair,\\n address[] memory _allowedRewardTokens\\n ) {\\n stake = _stake;\\n internal_bribe = _internal_bribe;\\n external_bribe = _external_bribe;\\n _ve = __ve;\\n voter = _voter;\\n isForPair = _forPair;\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function claimFees()\\n external\\n lock\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n return _claimFees();\\n }\\n\\n function _claimFees()\\n internal\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n if (!isForPair) {\\n return (0, 0);\\n }\\n (claimed0, claimed1) = IPair(stake).claimFees();\\n if (claimed0 > 0 || claimed1 > 0) {\\n uint256 _fees0 = fees0 + claimed0;\\n uint256 _fees1 = fees1 + claimed1;\\n (address _token0, address _token1) = IPair(stake).tokens();\\n if (\\n _fees0 > IBribe(internal_bribe).left(_token0) &&\\n _fees0 / DURATION > 0\\n ) {\\n fees0 = 0;\\n _safeApprove(_token0, internal_bribe, _fees0);\\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\\n } else {\\n fees0 = _fees0;\\n }\\n if (\\n _fees1 > IBribe(internal_bribe).left(_token1) &&\\n _fees1 / DURATION > 0\\n ) {\\n fees1 = 0;\\n _safeApprove(_token1, internal_bribe, _fees1);\\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\\n } else {\\n fees1 = _fees1;\\n }\\n\\n emit ClaimFees(msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(address account, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(address account, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[account][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[account] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n derivedSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n function getReward(address account, address[] memory tokens) external lock {\\n require(msg.sender == account || msg.sender == voter);\\n _unlocked = 1;\\n IVoter(voter).distribute(address(this));\\n _unlocked = 2;\\n\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], account);\\n lastEarn[tokens[i]][account] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n\\n uint256 _derivedBalance = derivedBalances[account];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(account);\\n derivedBalances[account] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(account, derivedBalances[account]);\\n _writeSupplyCheckpoint();\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (derivedSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / derivedSupply);\\n }\\n\\n function derivedBalance(address account) public view returns (uint256) {\\n return balanceOf[account];\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\\n function earned(address token, address account)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][account],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[account] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[account] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[account][i];\\n Checkpoint memory cp1 = checkpoints[account][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[account][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][account]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n function depositAll(uint256 tokenId) external {\\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\\n }\\n\\n function deposit(uint256 amount, uint256 tokenId) public lock {\\n require(amount > 0);\\n _updateRewardForAllTokens();\\n\\n _safeTransferFrom(stake, msg.sender, address(this), amount);\\n totalSupply += amount;\\n balanceOf[msg.sender] += amount;\\n\\n if (tokenId > 0) {\\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\\n if (tokenIds[msg.sender] == 0) {\\n tokenIds[msg.sender] = tokenId;\\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\\n }\\n require(tokenIds[msg.sender] == tokenId);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, _derivedBalance);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function withdrawAll() external {\\n withdraw(balanceOf[msg.sender]);\\n }\\n\\n function withdraw(uint256 amount) public {\\n uint256 tokenId = 0;\\n if (amount == balanceOf[msg.sender]) {\\n tokenId = tokenIds[msg.sender];\\n }\\n withdrawToken(amount, tokenId);\\n }\\n\\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[msg.sender] -= amount;\\n _safeTransfer(stake, msg.sender, amount);\\n\\n if (tokenId > 0) {\\n require(tokenId == tokenIds[msg.sender]);\\n tokenIds[msg.sender] = 0;\\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(token != stake);\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"rewards tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n _claimFees();\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeApprove(\\n address token,\\n address spender,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x38cc0284dd60d8a1418d9c34e6be84911ca4a1b479dc129f19b9027e4c670e1f\",\"license\":\"MIT\"},\"contracts/factories/GaugeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/Gauge.sol';\\n\\ncontract GaugeFactory is IGaugeFactory {\\n address public last_gauge;\\n\\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\\n return last_gauge;\\n }\\n}\\n\",\"keccak256\":\"0x34f6ac4bdace9ef01d8cffda9b45842efae88b519230c67759b9936aee6acc9b\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50613b19806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea2646970667358221220c9c7170e6533f9335bb092247861296b17f43f3dd5553246381036dde06e43f364736f6c634300080d0033a2646970667358221220036a8a62293c9b1a5f9ccfeaf493ee8d2c511917db3b1f888e333523d7fb117264736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea2646970667358221220c9c7170e6533f9335bb092247861296b17f43f3dd5553246381036dde06e43f364736f6c634300080d0033a2646970667358221220036a8a62293c9b1a5f9ccfeaf493ee8d2c511917db3b1f888e333523d7fb117264736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/MerkleClaim.json b/deployments/arbitrumGoerli/MerkleClaim.json index a73c3a19..0b2d815b 100644 --- a/deployments/arbitrumGoerli/MerkleClaim.json +++ b/deployments/arbitrumGoerli/MerkleClaim.json @@ -1,5 +1,5 @@ { - "address": "0x7F86f722a510CACb2cCD880a41dfE64773bfb371", + "address": "0x0BDAc938ec4f1af0f6C204e02C0BbdFC9ebd0f7c", "abi": [ { "inputs": [ @@ -105,31 +105,31 @@ "type": "function" } ], - "transactionHash": "0x9eee7514b364ed8b59f8f853c7122f3ed4b8a7e443e8239db2ab7c64b9166f33", + "transactionHash": "0xcc8c8ccc2638458967c3317621c92db366e7c03f40fa24a0643454c4f0f75d0a", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x7F86f722a510CACb2cCD880a41dfE64773bfb371", - "transactionIndex": 1, - "gasUsed": "356954", + "contractAddress": "0x0BDAc938ec4f1af0f6C204e02C0BbdFC9ebd0f7c", + "transactionIndex": 2, + "gasUsed": "356966", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x4c9918bfc3679e56c838bebb22d8cf7149af2bda2952f5d05a87188926c6b1a4", - "transactionHash": "0x9eee7514b364ed8b59f8f853c7122f3ed4b8a7e443e8239db2ab7c64b9166f33", + "blockHash": "0xc6812df80d99d1860e7e02f59b24352e93cee25bc38196eba4c1b4a9c36ae3ee", + "transactionHash": "0xcc8c8ccc2638458967c3317621c92db366e7c03f40fa24a0643454c4f0f75d0a", "logs": [], - "blockNumber": 5716760, - "cumulativeGasUsed": "356954", + "blockNumber": 5814457, + "cumulativeGasUsed": "841938", "status": 1, "byzantium": true }, "args": [ - "0xf5A53c1b4072425DF6eC082f0A48B4652bc4188C", + "0x8c35578054126d4DD063CFaBA40B7F9B63A13981", "0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f" ], - "numDeployments": 3, - "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_flow\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"_merkleRoot\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Claim\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FLOW\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"hasClaimed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\",\"events\":{\"Claim(address,uint256)\":{\"params\":{\"amount\":\"of tokens claimed\",\"to\":\"recipient of claim\"}}},\"kind\":\"dev\",\"methods\":{\"claim(address,uint256,bytes32[])\":{\"params\":{\"amount\":\"of tokens owed to claimee\",\"proof\":\"merkle proof to prove address and amount are in tree\",\"to\":\"address of claimee\"}},\"constructor\":{\"params\":{\"_flow\":\"address\",\"_merkleRoot\":\"of claimees\"}}},\"title\":\"MerkleClaim\",\"version\":1},\"userdoc\":{\"events\":{\"Claim(address,uint256)\":{\"notice\":\"Emitted after a successful token claim\"}},\"kind\":\"user\",\"methods\":{\"FLOW()\":{\"notice\":\"FLOW token to claim\"},\"claim(address,uint256,bytes32[])\":{\"notice\":\"Allows claiming tokens if address is part of merkle tree\"},\"constructor\":{\"notice\":\"Creates a new MerkleClaim contract\"},\"hasClaimed(address)\":{\"notice\":\"Mapping of addresses who have claimed tokens\"},\"merkleRoot()\":{\"notice\":\"ERC20-claimee inclusion root\"}},\"notice\":\"Claims FLOW for members of a merkle tree\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/MerkleClaim.sol\":\"MerkleClaim\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/redeem/MerkleClaim.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity 0.8.13;\\n\\n/// ============ Imports ============\\n\\nimport {IFlow} from \\\"contracts/interfaces/IFlow.sol\\\";\\nimport {MerkleProof} from \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\\\"; // OZ: MerkleProof\\n\\n/// @title MerkleClaim\\n/// @notice Claims FLOW for members of a merkle tree\\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\\ncontract MerkleClaim {\\n /// ============ Immutable storage ============\\n\\n /// @notice FLOW token to claim\\n IFlow public immutable FLOW;\\n /// @notice ERC20-claimee inclusion root\\n bytes32 public immutable merkleRoot;\\n\\n /// ============ Mutable storage ============\\n\\n /// @notice Mapping of addresses who have claimed tokens\\n mapping(address => bool) public hasClaimed;\\n\\n /// ============ Constructor ============\\n\\n /// @notice Creates a new MerkleClaim contract\\n /// @param _flow address\\n /// @param _merkleRoot of claimees\\n constructor(address _flow, bytes32 _merkleRoot) {\\n FLOW = IFlow(_flow);\\n merkleRoot = _merkleRoot;\\n }\\n\\n /// ============ Events ============\\n\\n /// @notice Emitted after a successful token claim\\n /// @param to recipient of claim\\n /// @param amount of tokens claimed\\n event Claim(address indexed to, uint256 amount);\\n\\n /// ============ Functions ============\\n\\n /// @notice Allows claiming tokens if address is part of merkle tree\\n /// @param to address of claimee\\n /// @param amount of tokens owed to claimee\\n /// @param proof merkle proof to prove address and amount are in tree\\n function claim(\\n address to,\\n uint256 amount,\\n bytes32[] calldata proof\\n ) external {\\n // Throw if address has already claimed tokens\\n require(!hasClaimed[to], \\\"ALREADY_CLAIMED\\\");\\n\\n // Verify merkle proof, or revert if not in tree\\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\\n require(isValidLeaf, \\\"NOT_IN_MERKLE\\\");\\n\\n // Set address to claimed\\n hasClaimed[to] = true;\\n\\n // Claim tokens for address\\n require(FLOW.claim(to, amount), \\\"CLAIM_FAILED\\\");\\n\\n // Emit claim event\\n emit Claim(to, amount);\\n }\\n}\\n\",\"keccak256\":\"0xf169ba9559c5c39dc79b2281410b09fd92f200a3b0489b32e28ce08a00a98826\",\"license\":\"AGPL-3.0-only\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev These functions deal with verification of Merkle Tree proofs.\\n *\\n * The tree and the proofs can be generated using our\\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\\n * You will find a quickstart guide in the readme.\\n *\\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\\n * hashing, or use a hash function other than keccak256 for hashing leaves.\\n * This is because the concatenation of a sorted pair of internal nodes in\\n * the merkle tree could be reinterpreted as a leaf value.\\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\\n * against this attack out of the box.\\n */\\nlibrary MerkleProof {\\n /**\\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\\n * defined by `root`. For this, a `proof` must be provided, containing\\n * sibling hashes on the branch from the leaf to the root of the tree. Each\\n * pair of leaves and each pair of pre-images are assumed to be sorted.\\n */\\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProof(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {verify}\\n *\\n * _Available since v4.7._\\n */\\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProofCalldata(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\\n * hash matches the root of the tree. When processing the proof, the pairs\\n * of leafs & pre-images are assumed to be sorted.\\n *\\n * _Available since v4.4._\\n */\\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Calldata version of {processProof}\\n *\\n * _Available since v4.7._\\n */\\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerify(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProof(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {multiProofVerify}\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerifyCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\\n * respectively.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProof(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n /**\\n * @dev Calldata version of {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProofCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\\n }\\n\\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x00, a)\\n mstore(0x20, b)\\n value := keccak256(0x00, 0x40)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcc76dbe53154a5bbd12fdd1613a73f73f3dc7c63d813be36f7ee606f52d6a7b3\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60c060405234801561001057600080fd5b5060405161062638038061062683398101604081905261002f91610045565b6001600160a01b0390911660805260a05261007f565b6000806040838503121561005857600080fd5b82516001600160a01b038116811461006f57600080fd5b6020939093015192949293505050565b60805160a0516105766100b060003960008181605601526101ea0152600081816090015261029601526105766000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633189097b1461008b5780633d13f874146100ca57806373b2e80e146100df575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6100b27f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6100dd6100d836600461043c565b610112565b005b6101026100ed3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea26469706673582212209c52c6d8a33927001b183ce0a24bb8ee0b37d362594a46e4cb302c90ea5c7f7564736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633189097b1461008b5780633d13f874146100ca57806373b2e80e146100df575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6100b27f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6100dd6100d836600461043c565b610112565b005b6101026100ed3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea26469706673582212209c52c6d8a33927001b183ce0a24bb8ee0b37d362594a46e4cb302c90ea5c7f7564736f6c634300080d0033", + "numDeployments": 5, + "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_flow\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"_merkleRoot\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Claim\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FLOW\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"hasClaimed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\",\"events\":{\"Claim(address,uint256)\":{\"params\":{\"amount\":\"of tokens claimed\",\"to\":\"recipient of claim\"}}},\"kind\":\"dev\",\"methods\":{\"claim(address,uint256,bytes32[])\":{\"params\":{\"amount\":\"of tokens owed to claimee\",\"proof\":\"merkle proof to prove address and amount are in tree\",\"to\":\"address of claimee\"}},\"constructor\":{\"params\":{\"_flow\":\"address\",\"_merkleRoot\":\"of claimees\"}}},\"title\":\"MerkleClaim\",\"version\":1},\"userdoc\":{\"events\":{\"Claim(address,uint256)\":{\"notice\":\"Emitted after a successful token claim\"}},\"kind\":\"user\",\"methods\":{\"FLOW()\":{\"notice\":\"FLOW token to claim\"},\"claim(address,uint256,bytes32[])\":{\"notice\":\"Allows claiming tokens if address is part of merkle tree\"},\"constructor\":{\"notice\":\"Creates a new MerkleClaim contract\"},\"hasClaimed(address)\":{\"notice\":\"Mapping of addresses who have claimed tokens\"},\"merkleRoot()\":{\"notice\":\"ERC20-claimee inclusion root\"}},\"notice\":\"Claims FLOW for members of a merkle tree\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/MerkleClaim.sol\":\"MerkleClaim\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/redeem/MerkleClaim.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity 0.8.13;\\n\\n/// ============ Imports ============\\n\\nimport {IFlow} from \\\"contracts/interfaces/IFlow.sol\\\";\\nimport {MerkleProof} from \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\\\"; // OZ: MerkleProof\\n\\n/// @title MerkleClaim\\n/// @notice Claims FLOW for members of a merkle tree\\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\\ncontract MerkleClaim {\\n /// ============ Immutable storage ============\\n\\n /// @notice FLOW token to claim\\n IFlow public immutable FLOW;\\n /// @notice ERC20-claimee inclusion root\\n bytes32 public immutable merkleRoot;\\n\\n /// ============ Mutable storage ============\\n\\n /// @notice Mapping of addresses who have claimed tokens\\n mapping(address => bool) public hasClaimed;\\n\\n /// ============ Constructor ============\\n\\n /// @notice Creates a new MerkleClaim contract\\n /// @param _flow address\\n /// @param _merkleRoot of claimees\\n constructor(address _flow, bytes32 _merkleRoot) {\\n FLOW = IFlow(_flow);\\n merkleRoot = _merkleRoot;\\n }\\n\\n /// ============ Events ============\\n\\n /// @notice Emitted after a successful token claim\\n /// @param to recipient of claim\\n /// @param amount of tokens claimed\\n event Claim(address indexed to, uint256 amount);\\n\\n /// ============ Functions ============\\n\\n /// @notice Allows claiming tokens if address is part of merkle tree\\n /// @param to address of claimee\\n /// @param amount of tokens owed to claimee\\n /// @param proof merkle proof to prove address and amount are in tree\\n function claim(\\n address to,\\n uint256 amount,\\n bytes32[] calldata proof\\n ) external {\\n // Throw if address has already claimed tokens\\n require(!hasClaimed[to], \\\"ALREADY_CLAIMED\\\");\\n\\n // Verify merkle proof, or revert if not in tree\\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\\n require(isValidLeaf, \\\"NOT_IN_MERKLE\\\");\\n\\n // Set address to claimed\\n hasClaimed[to] = true;\\n\\n // Claim tokens for address\\n require(FLOW.claim(to, amount), \\\"CLAIM_FAILED\\\");\\n\\n // Emit claim event\\n emit Claim(to, amount);\\n }\\n}\\n\",\"keccak256\":\"0xf169ba9559c5c39dc79b2281410b09fd92f200a3b0489b32e28ce08a00a98826\",\"license\":\"AGPL-3.0-only\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev These functions deal with verification of Merkle Tree proofs.\\n *\\n * The tree and the proofs can be generated using our\\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\\n * You will find a quickstart guide in the readme.\\n *\\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\\n * hashing, or use a hash function other than keccak256 for hashing leaves.\\n * This is because the concatenation of a sorted pair of internal nodes in\\n * the merkle tree could be reinterpreted as a leaf value.\\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\\n * against this attack out of the box.\\n */\\nlibrary MerkleProof {\\n /**\\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\\n * defined by `root`. For this, a `proof` must be provided, containing\\n * sibling hashes on the branch from the leaf to the root of the tree. Each\\n * pair of leaves and each pair of pre-images are assumed to be sorted.\\n */\\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProof(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {verify}\\n *\\n * _Available since v4.7._\\n */\\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProofCalldata(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\\n * hash matches the root of the tree. When processing the proof, the pairs\\n * of leafs & pre-images are assumed to be sorted.\\n *\\n * _Available since v4.4._\\n */\\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Calldata version of {processProof}\\n *\\n * _Available since v4.7._\\n */\\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerify(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProof(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {multiProofVerify}\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerifyCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\\n * respectively.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProof(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n /**\\n * @dev Calldata version of {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProofCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\\n }\\n\\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x00, a)\\n mstore(0x20, b)\\n value := keccak256(0x00, 0x40)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcc76dbe53154a5bbd12fdd1613a73f73f3dc7c63d813be36f7ee606f52d6a7b3\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c060405234801561001057600080fd5b5060405161062638038061062683398101604081905261002f91610045565b6001600160a01b0390911660805260a05261007f565b6000806040838503121561005857600080fd5b82516001600160a01b038116811461006f57600080fd5b6020939093015192949293505050565b60805160a0516105766100b060003960008181605601526101ea0152600081816090015261029601526105766000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633189097b1461008b5780633d13f874146100ca57806373b2e80e146100df575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6100b27f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6100dd6100d836600461043c565b610112565b005b6101026100ed3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220a1b07a4e977287c43c42e0b0a2edb40fce264268ea2158cb90b7041e8a3aa19464736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633189097b1461008b5780633d13f874146100ca57806373b2e80e146100df575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6100b27f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6100dd6100d836600461043c565b610112565b005b6101026100ed3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220a1b07a4e977287c43c42e0b0a2edb40fce264268ea2158cb90b7041e8a3aa19464736f6c634300080d0033", "devdoc": { "author": "Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)", "events": { diff --git a/deployments/arbitrumGoerli/Minter.json b/deployments/arbitrumGoerli/Minter.json index cfeb83bb..c3faba2e 100644 --- a/deployments/arbitrumGoerli/Minter.json +++ b/deployments/arbitrumGoerli/Minter.json @@ -1,5 +1,5 @@ { - "address": "0x388c6C5e6D27E3b6fa40eb98e0ef573D9E8e037E", + "address": "0x07430f617D301343db890E42f3Fd7d61AA435a1A", "abi": [ { "inputs": [ @@ -324,32 +324,32 @@ "type": "function" } ], - "transactionHash": "0x356a312c4d8f1b2798a49b56e2fd152d6e032bc3d634fed3f3476aa062cd8e57", + "transactionHash": "0xb0588b210ecf7e3a0b144eac270b11bd57813f69fba45512ad7c2caf577ccb86", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x388c6C5e6D27E3b6fa40eb98e0ef573D9E8e037E", + "contractAddress": "0x07430f617D301343db890E42f3Fd7d61AA435a1A", "transactionIndex": 1, "gasUsed": "1199219", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xd0490e4f90eee1e815840ca4c6032d9c26121484c5251a3cd90102f8dfaaac32", - "transactionHash": "0x356a312c4d8f1b2798a49b56e2fd152d6e032bc3d634fed3f3476aa062cd8e57", + "blockHash": "0xe7a558c4aa52fae6851c8e72d692d25e80572c4e412851e9343330d846f5d5f6", + "transactionHash": "0xb0588b210ecf7e3a0b144eac270b11bd57813f69fba45512ad7c2caf577ccb86", "logs": [], - "blockNumber": 5716740, + "blockNumber": 5814441, "cumulativeGasUsed": "1199219", "status": 1, "byzantium": true }, "args": [ - "0x362502b7139761937067cf81a73Dc18D315f10A0", - "0xC43f6EbF97f9D99FF8a3aFe1413599e8DEc2aDB3", - "0xEED0deFB831F96fC45B5e0ACb477F517F186496F" + "0xfD6108E8FDD2e6D125f71E68C7B8eD48f997c2Ad", + "0xad0F425b3edB0FC3a06096092B5736A280C90C40", + "0x85e7505be0F725AED67379Eb7F78d8561101caAE" ], - "numDeployments": 3, - "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__voter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__rewards_distributor\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weekly\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_supply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_emission\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_TEAM_RATE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_flow\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_rewards_distributor\",\"outputs\":[{\"internalType\":\"contract IRewardsDistributor\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"contract IVotingEscrow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_voter\",\"outputs\":[{\"internalType\":\"contract IVoter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"active_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"calculate_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minted\",\"type\":\"uint256\"}],\"name\":\"calculate_growth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"claimants\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingTeam\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_teamRate\",\"type\":\"uint256\"}],\"name\":\"setTeamRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"teamRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"update_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Minter.sol\":\"Minter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Minter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IMinter.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\\n\\ncontract Minter is IMinter {\\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\\n uint256 internal constant EMISSION = 990;\\n uint256 internal constant TAIL_EMISSION = 2;\\n uint256 internal constant PRECISION = 1000;\\n IFlow public immutable _flow;\\n IVoter public immutable _voter;\\n IVotingEscrow public immutable _ve;\\n IRewardsDistributor public immutable _rewards_distributor;\\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M FLOW (FLOW has 18 decimals)\\n uint256 public active_period;\\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\\n\\n address internal initializer;\\n address public team;\\n address public pendingTeam;\\n uint256 public teamRate;\\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\\n\\n event Mint(\\n address indexed sender,\\n uint256 weekly,\\n uint256 circulating_supply,\\n uint256 circulating_emission\\n );\\n\\n constructor(\\n address __voter, // the voting & distribution system\\n address __ve, // the ve(3,3) system that will be locked into\\n address __rewards_distributor // the distribution system that ensures users aren't diluted\\n ) {\\n initializer = msg.sender;\\n team = msg.sender;\\n teamRate = 30; // 30 bps = 0.03%\\n _flow = IFlow(IVotingEscrow(__ve).token());\\n _voter = IVoter(__voter);\\n _ve = IVotingEscrow(__ve);\\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\\n }\\n\\n function initialize(\\n address[] memory claimants,\\n uint256[] memory amounts,\\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\\n ) external {\\n require(initializer == msg.sender);\\n _flow.mint(address(this), max);\\n _flow.approve(address(_ve), type(uint256).max);\\n for (uint256 i = 0; i < claimants.length; i++) {\\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\\n }\\n initializer = address(0);\\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\\n }\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team, \\\"not team\\\");\\n pendingTeam = _team;\\n }\\n\\n function acceptTeam() external {\\n require(msg.sender == pendingTeam, \\\"not pending team\\\");\\n team = pendingTeam;\\n }\\n\\n function setTeamRate(uint256 _teamRate) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(_teamRate <= MAX_TEAM_RATE, \\\"rate too high\\\");\\n teamRate = _teamRate;\\n }\\n\\n // calculate circulating supply as total token supply - locked supply\\n function circulating_supply() public view returns (uint256) {\\n return _flow.totalSupply() - _ve.totalSupply();\\n }\\n\\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\\n function calculate_emission() public view returns (uint256) {\\n return (weekly * EMISSION) / PRECISION;\\n }\\n\\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\\n function weekly_emission() public view returns (uint256) {\\n return MathDunks.max(calculate_emission(), circulating_emission());\\n }\\n\\n // calculates tail end (infinity) emissions as 0.2% of total supply\\n function circulating_emission() public view returns (uint256) {\\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\\n }\\n\\n // calculate inflation and adjust ve balances accordingly\\n function calculate_growth(uint256 _minted) public view returns (uint256) {\\n uint256 _veTotal = _ve.totalSupply();\\n uint256 _flowTotal = _flow.totalSupply();\\n return\\n (((((_minted * _veTotal) / _flowTotal) * _veTotal) / _flowTotal) *\\n _veTotal) /\\n _flowTotal /\\n 2;\\n }\\n\\n // update period can only be called once per cycle (1 week)\\n function update_period() external returns (uint256) {\\n uint256 _period = active_period;\\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\\n // only trigger if new week\\n _period = (block.timestamp / WEEK) * WEEK;\\n active_period = _period;\\n weekly = weekly_emission();\\n\\n uint256 _growth = calculate_growth(weekly);\\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\\n (PRECISION - teamRate);\\n uint256 _required = _growth + weekly + _teamEmissions;\\n uint256 _balanceOf = _flow.balanceOf(address(this));\\n if (_balanceOf < _required) {\\n _flow.mint(address(this), _required - _balanceOf);\\n }\\n\\n require(_flow.transfer(team, _teamEmissions));\\n require(_flow.transfer(address(_rewards_distributor), _growth));\\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\\n\\n _flow.approve(address(_voter), weekly);\\n _voter.notifyRewardAmount(weekly);\\n\\n emit Mint(\\n msg.sender,\\n weekly,\\n circulating_supply(),\\n circulating_emission()\\n );\\n }\\n return _period;\\n }\\n}\\n\",\"keccak256\":\"0xc661046dd2b90d93e4f057d2497b137703b4f0c3caccfe846f1a81906a2e1961\",\"license\":\"MIT\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x6101006040526a0c685fa11e01ec6f0000006000553480156200002157600080fd5b506040516200158938038062001589833981016040819052620000449162000156565b60028054336001600160a01b03199182168117909255600380549091169091179055601e60055560408051637e062a3560e11b815290516001600160a01b0384169163fc0c546a9160048083019260209291908290030181865afa158015620000b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d79190620001a0565b6001600160a01b0390811660805283811660a05282811660c052811660e05262093a808062000108816002620001db565b620001149042620001fd565b62000120919062000218565b6200012c9190620001db565b600155506200023b915050565b80516001600160a01b03811681146200015157600080fd5b919050565b6000806000606084860312156200016c57600080fd5b620001778462000139565b9250620001876020850162000139565b9150620001976040850162000139565b90509250925092565b600060208284031215620001b357600080fd5b620001be8262000139565b9392505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620001f857620001f8620001c5565b500290565b60008219821115620002135762000213620001c5565b500190565b6000826200023657634e487b7160e01b600052601260045260246000fd5b500490565b60805160a05160c05160e051611296620002f3600039600081816101d101528181610c3701528181610cde0152610d5101526000818161023a015281816104b30152818161055f01528181610689015261087501526000818161019201528181610e090152610ea301526000818161029d01528181610426015281816104e30152818161070f015281816108f701528181610a5f01528181610ade01528181610ba801528181610c660152610dda01526112966000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c806385170813116100ad578063cfc6c8ff11610071578063cfc6c8ff14610277578063d13996081461027f578063e038c75a14610288578063ed29fc1114610290578063fe75cac51461029857600080fd5b8063851708131461020f57806385f2aef2146102225780638dd598fb146102355780638e01fbfa1461025c578063b5cc143a1461026f57600080fd5b806336d96faf116100f457806336d96faf146101855780633db9b42a1461018d5780634b1cd5da146101cc57806359d46ffc146101f357806378ef7f021461020657600080fd5b806301c8e6fd14610131578063095cf5c61461014c5780631eebae801461016157806326cfc17b146101695780632e8f7b1f14610172575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b61015f61015a366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61015f610180366004610fb8565b610353565b6101396103de565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6004546101b4906001600160a01b031681565b61013960055481565b61015f61021d3660046110a7565b6103f3565b6003546101b4906001600160a01b031681565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b61013961026a366004610fb8565b610684565b61015f6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea2646970667358221220fd177bce5ff2a20e0ff464c75ae7fa0fb1787a1d805a0ee0ff24890d9985a70164736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c806385170813116100ad578063cfc6c8ff11610071578063cfc6c8ff14610277578063d13996081461027f578063e038c75a14610288578063ed29fc1114610290578063fe75cac51461029857600080fd5b8063851708131461020f57806385f2aef2146102225780638dd598fb146102355780638e01fbfa1461025c578063b5cc143a1461026f57600080fd5b806336d96faf116100f457806336d96faf146101855780633db9b42a1461018d5780634b1cd5da146101cc57806359d46ffc146101f357806378ef7f021461020657600080fd5b806301c8e6fd14610131578063095cf5c61461014c5780631eebae801461016157806326cfc17b146101695780632e8f7b1f14610172575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b61015f61015a366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61015f610180366004610fb8565b610353565b6101396103de565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6004546101b4906001600160a01b031681565b61013960055481565b61015f61021d3660046110a7565b6103f3565b6003546101b4906001600160a01b031681565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b61013961026a366004610fb8565b610684565b61015f6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea2646970667358221220fd177bce5ff2a20e0ff464c75ae7fa0fb1787a1d805a0ee0ff24890d9985a70164736f6c634300080d0033", + "numDeployments": 5, + "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__voter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__rewards_distributor\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weekly\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_supply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_emission\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_TEAM_RATE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_flow\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_rewards_distributor\",\"outputs\":[{\"internalType\":\"contract IRewardsDistributor\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"contract IVotingEscrow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_voter\",\"outputs\":[{\"internalType\":\"contract IVoter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"active_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"calculate_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minted\",\"type\":\"uint256\"}],\"name\":\"calculate_growth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"claimants\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingTeam\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_teamRate\",\"type\":\"uint256\"}],\"name\":\"setTeamRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"teamRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"update_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Minter.sol\":\"Minter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Minter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IMinter.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\\n\\ncontract Minter is IMinter {\\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\\n uint256 internal constant EMISSION = 990;\\n uint256 internal constant TAIL_EMISSION = 2;\\n uint256 internal constant PRECISION = 1000;\\n IFlow public immutable _flow;\\n IVoter public immutable _voter;\\n IVotingEscrow public immutable _ve;\\n IRewardsDistributor public immutable _rewards_distributor;\\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M FLOW (FLOW has 18 decimals)\\n uint256 public active_period;\\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\\n\\n address internal initializer;\\n address public team;\\n address public pendingTeam;\\n uint256 public teamRate;\\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\\n\\n event Mint(\\n address indexed sender,\\n uint256 weekly,\\n uint256 circulating_supply,\\n uint256 circulating_emission\\n );\\n\\n constructor(\\n address __voter, // the voting & distribution system\\n address __ve, // the ve(3,3) system that will be locked into\\n address __rewards_distributor // the distribution system that ensures users aren't diluted\\n ) {\\n initializer = msg.sender;\\n team = msg.sender;\\n teamRate = 30; // 30 bps = 0.03%\\n _flow = IFlow(IVotingEscrow(__ve).token());\\n _voter = IVoter(__voter);\\n _ve = IVotingEscrow(__ve);\\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\\n }\\n\\n function initialize(\\n address[] memory claimants,\\n uint256[] memory amounts,\\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\\n ) external {\\n require(initializer == msg.sender);\\n _flow.mint(address(this), max);\\n _flow.approve(address(_ve), type(uint256).max);\\n for (uint256 i = 0; i < claimants.length; i++) {\\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\\n }\\n initializer = address(0);\\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\\n }\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team, \\\"not team\\\");\\n pendingTeam = _team;\\n }\\n\\n function acceptTeam() external {\\n require(msg.sender == pendingTeam, \\\"not pending team\\\");\\n team = pendingTeam;\\n }\\n\\n function setTeamRate(uint256 _teamRate) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(_teamRate <= MAX_TEAM_RATE, \\\"rate too high\\\");\\n teamRate = _teamRate;\\n }\\n\\n // calculate circulating supply as total token supply - locked supply\\n function circulating_supply() public view returns (uint256) {\\n return _flow.totalSupply() - _ve.totalSupply();\\n }\\n\\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\\n function calculate_emission() public view returns (uint256) {\\n return (weekly * EMISSION) / PRECISION;\\n }\\n\\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\\n function weekly_emission() public view returns (uint256) {\\n return MathDunks.max(calculate_emission(), circulating_emission());\\n }\\n\\n // calculates tail end (infinity) emissions as 0.2% of total supply\\n function circulating_emission() public view returns (uint256) {\\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\\n }\\n\\n // calculate inflation and adjust ve balances accordingly\\n function calculate_growth(uint256 _minted) public view returns (uint256) {\\n uint256 _veTotal = _ve.totalSupply();\\n uint256 _flowTotal = _flow.totalSupply();\\n return\\n (((((_minted * _veTotal) / _flowTotal) * _veTotal) / _flowTotal) *\\n _veTotal) /\\n _flowTotal /\\n 2;\\n }\\n\\n // update period can only be called once per cycle (1 week)\\n function update_period() external returns (uint256) {\\n uint256 _period = active_period;\\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\\n // only trigger if new week\\n _period = (block.timestamp / WEEK) * WEEK;\\n active_period = _period;\\n weekly = weekly_emission();\\n\\n uint256 _growth = calculate_growth(weekly);\\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\\n (PRECISION - teamRate);\\n uint256 _required = _growth + weekly + _teamEmissions;\\n uint256 _balanceOf = _flow.balanceOf(address(this));\\n if (_balanceOf < _required) {\\n _flow.mint(address(this), _required - _balanceOf);\\n }\\n\\n require(_flow.transfer(team, _teamEmissions));\\n require(_flow.transfer(address(_rewards_distributor), _growth));\\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\\n\\n _flow.approve(address(_voter), weekly);\\n _voter.notifyRewardAmount(weekly);\\n\\n emit Mint(\\n msg.sender,\\n weekly,\\n circulating_supply(),\\n circulating_emission()\\n );\\n }\\n return _period;\\n }\\n}\\n\",\"keccak256\":\"0xc661046dd2b90d93e4f057d2497b137703b4f0c3caccfe846f1a81906a2e1961\",\"license\":\"MIT\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x6101006040526a0c685fa11e01ec6f0000006000553480156200002157600080fd5b506040516200158938038062001589833981016040819052620000449162000156565b60028054336001600160a01b03199182168117909255600380549091169091179055601e60055560408051637e062a3560e11b815290516001600160a01b0384169163fc0c546a9160048083019260209291908290030181865afa158015620000b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d79190620001a0565b6001600160a01b0390811660805283811660a05282811660c052811660e05262093a808062000108816002620001db565b620001149042620001fd565b62000120919062000218565b6200012c9190620001db565b600155506200023b915050565b80516001600160a01b03811681146200015157600080fd5b919050565b6000806000606084860312156200016c57600080fd5b620001778462000139565b9250620001876020850162000139565b9150620001976040850162000139565b90509250925092565b600060208284031215620001b357600080fd5b620001be8262000139565b9392505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620001f857620001f8620001c5565b500290565b60008219821115620002135762000213620001c5565b500190565b6000826200023657634e487b7160e01b600052601260045260246000fd5b500490565b60805160a05160c05160e051611296620002f3600039600081816101d101528181610c3701528181610cde0152610d5101526000818161023a015281816104b30152818161055f01528181610689015261087501526000818161019201528181610e090152610ea301526000818161029d01528181610426015281816104e30152818161070f015281816108f701528181610a5f01528181610ade01528181610ba801528181610c660152610dda01526112966000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c806385170813116100ad578063cfc6c8ff11610071578063cfc6c8ff14610277578063d13996081461027f578063e038c75a14610288578063ed29fc1114610290578063fe75cac51461029857600080fd5b8063851708131461020f57806385f2aef2146102225780638dd598fb146102355780638e01fbfa1461025c578063b5cc143a1461026f57600080fd5b806336d96faf116100f457806336d96faf146101855780633db9b42a1461018d5780634b1cd5da146101cc57806359d46ffc146101f357806378ef7f021461020657600080fd5b806301c8e6fd14610131578063095cf5c61461014c5780631eebae801461016157806326cfc17b146101695780632e8f7b1f14610172575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b61015f61015a366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61015f610180366004610fb8565b610353565b6101396103de565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6004546101b4906001600160a01b031681565b61013960055481565b61015f61021d3660046110a7565b6103f3565b6003546101b4906001600160a01b031681565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b61013961026a366004610fb8565b610684565b61015f6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea2646970667358221220611c27f9ec43450f21c5035bcf854d588812e7b814d381a4e6f1f4d748cde01c64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c806385170813116100ad578063cfc6c8ff11610071578063cfc6c8ff14610277578063d13996081461027f578063e038c75a14610288578063ed29fc1114610290578063fe75cac51461029857600080fd5b8063851708131461020f57806385f2aef2146102225780638dd598fb146102355780638e01fbfa1461025c578063b5cc143a1461026f57600080fd5b806336d96faf116100f457806336d96faf146101855780633db9b42a1461018d5780634b1cd5da146101cc57806359d46ffc146101f357806378ef7f021461020657600080fd5b806301c8e6fd14610131578063095cf5c61461014c5780631eebae801461016157806326cfc17b146101695780632e8f7b1f14610172575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b61015f61015a366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61015f610180366004610fb8565b610353565b6101396103de565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6004546101b4906001600160a01b031681565b61013960055481565b61015f61021d3660046110a7565b6103f3565b6003546101b4906001600160a01b031681565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b61013961026a366004610fb8565b610684565b61015f6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea2646970667358221220611c27f9ec43450f21c5035bcf854d588812e7b814d381a4e6f1f4d748cde01c64736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/PairFactory.json b/deployments/arbitrumGoerli/PairFactory.json index 5d5c0292..4ff7bc2e 100644 --- a/deployments/arbitrumGoerli/PairFactory.json +++ b/deployments/arbitrumGoerli/PairFactory.json @@ -1,5 +1,5 @@ { - "address": "0xddadFF10D1C9eb062180a870150D11673FFf7ad6", + "address": "0xE4a96d05579a4306e19E1C36F8e6A1567c982750", "abi": [ { "inputs": [], @@ -383,28 +383,28 @@ "type": "function" } ], - "transactionHash": "0x8dc1c3a31146015f6268ba5bd7c44d4a6119d330d0160a5281b3f24d551df73b", + "transactionHash": "0x7d6ecce94e4b0fdfbb6517e5f12b8144a2c462bae3c930bb89b27a2c3d76743a", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xddadFF10D1C9eb062180a870150D11673FFf7ad6", + "contractAddress": "0xE4a96d05579a4306e19E1C36F8e6A1567c982750", "transactionIndex": 1, - "gasUsed": "4628154", + "gasUsed": "4628142", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x4838e8d0987d654b382fa3c6380dd10c976bd9abf020f9e33ed688f05cbcdb1c", - "transactionHash": "0x8dc1c3a31146015f6268ba5bd7c44d4a6119d330d0160a5281b3f24d551df73b", + "blockHash": "0x5d2cb85b06cb5c4425a24994bfb67c1dc2da92fab91ba21f76c9ad32b3c19e97", + "transactionHash": "0x7d6ecce94e4b0fdfbb6517e5f12b8144a2c462bae3c930bb89b27a2c3d76743a", "logs": [], - "blockNumber": 5716716, - "cumulativeGasUsed": "4628154", + "blockNumber": 5814405, + "cumulativeGasUsed": "4628142", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 3, - "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"PairCreated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_FEE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allPairs\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"allPairsLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"createPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getInitializable\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"name\":\"getPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pairCodeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingFeeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingPauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_feeManager\",\"type\":\"address\"}],\"name\":\"setFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_state\",\"type\":\"bool\"}],\"name\":\"setPause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pauser\",\"type\":\"address\"}],\"name\":\"setPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stableFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"volatileFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/PairFactory.sol\":\"PairFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Pair.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairCallee.sol\\\";\\nimport \\\"contracts/factories/PairFactory.sol\\\";\\nimport \\\"contracts/PairFees.sol\\\";\\n\\n// The base pair of pools, either stable or volatile\\ncontract Pair is IPair {\\n string public name;\\n string public symbol;\\n uint8 public constant decimals = 18;\\n\\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\\n bool public immutable stable;\\n\\n uint256 public totalSupply = 0;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n mapping(address => uint256) public balanceOf;\\n\\n bytes32 internal DOMAIN_SEPARATOR;\\n // keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 internal constant PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n mapping(address => uint256) public nonces;\\n\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n\\n address public immutable token0;\\n address public immutable token1;\\n address public immutable fees;\\n address immutable factory;\\n\\n // Structure to capture time period obervations every 30 minutes, used for local oracles\\n struct Observation {\\n uint256 timestamp;\\n uint256 reserve0Cumulative;\\n uint256 reserve1Cumulative;\\n }\\n\\n // Capture oracle reading every 30 minutes\\n uint256 constant periodSize = 1800;\\n\\n Observation[] public observations;\\n\\n uint256 internal immutable decimals0;\\n uint256 internal immutable decimals1;\\n\\n uint256 public reserve0;\\n uint256 public reserve1;\\n uint256 public blockTimestampLast;\\n\\n uint256 public reserve0CumulativeLast;\\n uint256 public reserve1CumulativeLast;\\n\\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \\\"clean\\\"\\n // this further allows LP holders to easily claim fees for tokens they have/staked\\n uint256 public index0 = 0;\\n uint256 public index1 = 0;\\n\\n // position assigned to each LP to track their current index0 & index1 vs the global position\\n mapping(address => uint256) public supplyIndex0;\\n mapping(address => uint256) public supplyIndex1;\\n\\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\\n mapping(address => uint256) public claimable0;\\n mapping(address => uint256) public claimable1;\\n\\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\\n event Burn(\\n address indexed sender,\\n uint256 amount0,\\n uint256 amount1,\\n address indexed to\\n );\\n event Swap(\\n address indexed sender,\\n uint256 amount0In,\\n uint256 amount1In,\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address indexed to\\n );\\n event Sync(uint256 reserve0, uint256 reserve1);\\n event Claim(\\n address indexed sender,\\n address indexed recipient,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 amount\\n );\\n\\n constructor() {\\n factory = msg.sender;\\n (address _token0, address _token1, bool _stable) = PairFactory(\\n msg.sender\\n ).getInitializable();\\n (token0, token1, stable) = (_token0, _token1, _stable);\\n fees = address(new PairFees(_token0, _token1));\\n if (_stable) {\\n name = string(\\n abi.encodePacked(\\n \\\"StableV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"sAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n } else {\\n name = string(\\n abi.encodePacked(\\n \\\"VolatileV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"vAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n }\\n\\n decimals0 = 10**IERC20(_token0).decimals();\\n decimals1 = 10**IERC20(_token1).decimals();\\n\\n observations.push(Observation(block.timestamp, 0, 0));\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function observationLength() external view returns (uint256) {\\n return observations.length;\\n }\\n\\n function lastObservation() public view returns (Observation memory) {\\n return observations[observations.length - 1];\\n }\\n\\n function metadata()\\n external\\n view\\n returns (\\n uint256 dec0,\\n uint256 dec1,\\n uint256 r0,\\n uint256 r1,\\n bool st,\\n address t0,\\n address t1\\n )\\n {\\n return (\\n decimals0,\\n decimals1,\\n reserve0,\\n reserve1,\\n stable,\\n token0,\\n token1\\n );\\n }\\n\\n function tokens() external view returns (address, address) {\\n return (token0, token1);\\n }\\n\\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\\n _updateFor(msg.sender);\\n\\n claimed0 = claimable0[msg.sender];\\n claimed1 = claimable1[msg.sender];\\n\\n if (claimed0 > 0 || claimed1 > 0) {\\n claimable0[msg.sender] = 0;\\n claimable1[msg.sender] = 0;\\n\\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\\n\\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n // Accrue fees on token0\\n function _update0(uint256 amount) internal {\\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index0 += _ratio;\\n }\\n emit Fees(msg.sender, amount, 0);\\n }\\n\\n // Accrue fees on token1\\n function _update1(uint256 amount) internal {\\n _safeTransfer(token1, fees, amount);\\n uint256 _ratio = (amount * 1e18) / totalSupply;\\n if (_ratio > 0) {\\n index1 += _ratio;\\n }\\n emit Fees(msg.sender, 0, amount);\\n }\\n\\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\\n // Fees are segregated from core funds, so fees can never put liquidity at risk\\n function _updateFor(address recipient) internal {\\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\\n if (_supplied > 0) {\\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\\n uint256 _supplyIndex1 = supplyIndex1[recipient];\\n uint256 _index0 = index0; // get global index0 for accumulated fees\\n uint256 _index1 = index1;\\n supplyIndex0[recipient] = _index0; // update user current position to global position\\n supplyIndex1[recipient] = _index1;\\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\\n uint256 _delta1 = _index1 - _supplyIndex1;\\n if (_delta0 > 0) {\\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\\n claimable0[recipient] += _share;\\n }\\n if (_delta1 > 0) {\\n uint256 _share = (_supplied * _delta1) / 1e18;\\n claimable1[recipient] += _share;\\n }\\n } else {\\n supplyIndex0[recipient] = index0; // new users are set to the default global state\\n supplyIndex1[recipient] = index1;\\n }\\n }\\n\\n function getReserves()\\n public\\n view\\n returns (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n )\\n {\\n _reserve0 = reserve0;\\n _reserve1 = reserve1;\\n _blockTimestampLast = blockTimestampLast;\\n }\\n\\n // update reserves and, on the first call per block, price accumulators\\n function _update(\\n uint256 balance0,\\n uint256 balance1,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal {\\n uint256 blockTimestamp = block.timestamp;\\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\\n reserve0CumulativeLast += _reserve0 * timeElapsed;\\n reserve1CumulativeLast += _reserve1 * timeElapsed;\\n }\\n\\n Observation memory _point = lastObservation();\\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\\n if (timeElapsed > periodSize) {\\n observations.push(\\n Observation(\\n blockTimestamp,\\n reserve0CumulativeLast,\\n reserve1CumulativeLast\\n )\\n );\\n }\\n reserve0 = balance0;\\n reserve1 = balance1;\\n blockTimestampLast = blockTimestamp;\\n emit Sync(reserve0, reserve1);\\n }\\n\\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\\n function currentCumulativePrices()\\n public\\n view\\n returns (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n uint256 blockTimestamp\\n )\\n {\\n blockTimestamp = block.timestamp;\\n reserve0Cumulative = reserve0CumulativeLast;\\n reserve1Cumulative = reserve1CumulativeLast;\\n\\n // if time has elapsed since the last update on the pair, mock the accumulated price values\\n (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n ) = getReserves();\\n if (_blockTimestampLast != blockTimestamp) {\\n // subtraction overflow is desired\\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\\n reserve0Cumulative += _reserve0 * timeElapsed;\\n reserve1Cumulative += _reserve1 * timeElapsed;\\n }\\n }\\n\\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\\n function current(address tokenIn, uint256 amountIn)\\n external\\n view\\n returns (uint256 amountOut)\\n {\\n Observation memory _observation = lastObservation();\\n (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n\\n ) = currentCumulativePrices();\\n if (block.timestamp == _observation.timestamp) {\\n _observation = observations[observations.length - 2];\\n }\\n\\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\\n uint256 _reserve0 = (reserve0Cumulative -\\n _observation.reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (reserve1Cumulative -\\n _observation.reserve1Cumulative) / timeElapsed;\\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n // as per `current`, however allows user configured granularity, up to the full window size\\n function quote(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 granularity\\n ) external view returns (uint256 amountOut) {\\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\\n uint256 priceAverageCumulative;\\n for (uint256 i = 0; i < _prices.length; i++) {\\n priceAverageCumulative += _prices[i];\\n }\\n return priceAverageCumulative / granularity;\\n }\\n\\n // returns a memory set of twap prices\\n function prices(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points\\n ) external view returns (uint256[] memory) {\\n return sample(tokenIn, amountIn, points, 1);\\n }\\n\\n function sample(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points,\\n uint256 window\\n ) public view returns (uint256[] memory) {\\n uint256[] memory _prices = new uint256[](points);\\n\\n uint256 length = observations.length - 1;\\n uint256 i = length - (points * window);\\n uint256 nextIndex = 0;\\n uint256 index = 0;\\n\\n for (; i < length; i += window) {\\n nextIndex = i + window;\\n uint256 timeElapsed = observations[nextIndex].timestamp -\\n observations[i].timestamp;\\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\\n observations[i].reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\\n observations[i].reserve1Cumulative) / timeElapsed;\\n _prices[index] = _getAmountOut(\\n amountIn,\\n tokenIn,\\n _reserve0,\\n _reserve1\\n );\\n // index < length; length cannot overflow\\n unchecked {\\n index = index + 1;\\n }\\n }\\n return _prices;\\n }\\n\\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\\n // standard uniswap v2 implementation\\n function mint(address to) external lock returns (uint256 liquidity) {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\\n uint256 _amount0 = _balance0 - _reserve0;\\n uint256 _amount1 = _balance1 - _reserve1;\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n if (_totalSupply == 0) {\\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\\n } else {\\n liquidity = MathDunks.min(\\n (_amount0 * _totalSupply) / _reserve0,\\n (_amount1 * _totalSupply) / _reserve1\\n );\\n }\\n require(liquidity > 0, \\\"ILM\\\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\\n _mint(to, liquidity);\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Mint(msg.sender, _amount0, _amount1);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n // standard uniswap v2 implementation\\n function burn(address to)\\n external\\n lock\\n returns (uint256 amount0, uint256 amount1)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n (address _token0, address _token1) = (token0, token1);\\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\\n uint256 _liquidity = balanceOf[address(this)];\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\\n require(amount0 > 0 && amount1 > 0, \\\"ILB\\\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\\n _burn(address(this), _liquidity);\\n _safeTransfer(_token0, to, amount0);\\n _safeTransfer(_token1, to, amount1);\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Burn(msg.sender, amount0, amount1, to);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n function swap(\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address to,\\n bytes calldata data\\n ) external lock {\\n require(!PairFactory(factory).isPaused());\\n require(amount0Out > 0 || amount1Out > 0, \\\"IOA\\\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \\\"IL\\\"); // Pair: INSUFFICIENT_LIQUIDITY\\n\\n uint256 _balance0;\\n uint256 _balance1;\\n {\\n // scope for _token{0,1}, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n require(to != _token0 && to != _token1, \\\"IT\\\"); // Pair: INVALID_TO\\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\\n if (data.length > 0)\\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n }\\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\\n ? _balance0 - (_reserve0 - amount0Out)\\n : 0;\\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\\n ? _balance1 - (_reserve1 - amount1Out)\\n : 0;\\n require(amount0In > 0 || amount1In > 0, \\\"IIA\\\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\\n {\\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n if (amount0In > 0)\\n _update0(\\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token0 and move them out of pool\\n if (amount1In > 0)\\n _update1(\\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token1 and move them out of pool\\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \\\"K\\\"); // Pair: K\\n }\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\\n }\\n\\n // force balances to match reserves\\n function skim(address to) external lock {\\n (address _token0, address _token1) = (token0, token1);\\n _safeTransfer(\\n _token0,\\n to,\\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\\n );\\n _safeTransfer(\\n _token1,\\n to,\\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\\n );\\n }\\n\\n // force reserves to match balances\\n function sync() external lock {\\n _update(\\n IERC20(token0).balanceOf(address(this)),\\n IERC20(token1).balanceOf(address(this)),\\n reserve0,\\n reserve1\\n );\\n }\\n\\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\\n 1e18 +\\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\\n 1e18;\\n }\\n\\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (3 * x0 * ((y * y) / 1e18)) /\\n 1e18 +\\n ((((x0 * x0) / 1e18) * x0) / 1e18);\\n }\\n\\n function _get_y(\\n uint256 x0,\\n uint256 xy,\\n uint256 y\\n ) internal pure returns (uint256) {\\n for (uint256 i = 0; i < 255; i++) {\\n uint256 y_prev = y;\\n uint256 k = _f(x0, y);\\n if (k < xy) {\\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\\n y = y + dy;\\n } else {\\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getAmountOut(uint256 amountIn, address tokenIn)\\n external\\n view\\n returns (uint256)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n function _getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal view returns (uint256) {\\n if (stable) {\\n uint256 xy = _k(_reserve0, _reserve1);\\n _reserve0 = (_reserve0 * 1e18) / decimals0;\\n _reserve1 = (_reserve1 * 1e18) / decimals1;\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0\\n ? (amountIn * 1e18) / decimals0\\n : (amountIn * 1e18) / decimals1;\\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\\n } else {\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n return (amountIn * reserveB) / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\\n if (stable) {\\n uint256 _x = (x * 1e18) / decimals0;\\n uint256 _y = (y * 1e18) / decimals1;\\n uint256 _a = (_x * _y) / 1e18;\\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return (_a * _b) / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n\\n function _mint(address dst, uint256 amount) internal {\\n _updateFor(dst); // balances must be updated on mint/burn/transfer\\n totalSupply += amount;\\n balanceOf[dst] += amount;\\n emit Transfer(address(0), dst, amount);\\n }\\n\\n function _burn(address dst, uint256 amount) internal {\\n _updateFor(dst);\\n totalSupply -= amount;\\n balanceOf[dst] -= amount;\\n emit Transfer(dst, address(0), amount);\\n }\\n\\n function approve(address spender, uint256 amount) external returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external {\\n require(deadline >= block.timestamp, \\\"Pair: EXPIRED\\\");\\n DOMAIN_SEPARATOR = keccak256(\\n abi.encode(\\n keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n ),\\n keccak256(bytes(name)),\\n keccak256(bytes(\\\"1\\\")),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR,\\n keccak256(\\n abi.encode(\\n PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n );\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n require(\\n recoveredAddress != address(0) && recoveredAddress == owner,\\n \\\"Pair: INVALID_SIGNATURE\\\"\\n );\\n allowance[owner][spender] = value;\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function transfer(address dst, uint256 amount) external returns (bool) {\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 amount\\n ) external returns (bool) {\\n address spender = msg.sender;\\n uint256 spenderAllowance = allowance[src][spender];\\n\\n if (spender != src && spenderAllowance != type(uint256).max) {\\n uint256 newAllowance = spenderAllowance - amount;\\n allowance[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n function _transferTokens(\\n address src,\\n address dst,\\n uint256 amount\\n ) internal {\\n _updateFor(src); // update fee position for src\\n _updateFor(dst); // update fee position for dst\\n\\n balanceOf[src] -= amount;\\n balanceOf[dst] += amount;\\n\\n emit Transfer(src, dst, amount);\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x4f508747645f4480e0b0f23d952fa9b82af1d9bc60b15b8cd1f542ee136043d1\",\"license\":\"MIT\"},\"contracts/PairFees.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IERC20.sol';\\n\\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\\ncontract PairFees {\\n\\n address internal immutable pair; // The pair it is bonded to\\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\\n\\n constructor(address _token0, address _token1) {\\n pair = msg.sender;\\n token0 = _token0;\\n token1 = _token1;\\n }\\n\\n function _safeTransfer(address token,address to,uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n // Allow the pair to transfer fees to users\\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\\n require(msg.sender == pair);\\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\\n }\\n\\n}\\n\",\"keccak256\":\"0xb772e192bab353f8642e89a95ef4ef0255d1caef08444101d7fe34469c1000ca\",\"license\":\"MIT\"},\"contracts/factories/PairFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/Pair.sol';\\n\\ncontract PairFactory is IPairFactory {\\n\\n bool public isPaused;\\n address public pauser;\\n address public pendingPauser;\\n\\n uint256 public stableFee;\\n uint256 public volatileFee;\\n uint256 public constant MAX_FEE = 5; // 0.05%\\n address public feeManager;\\n address public pendingFeeManager;\\n\\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\\n address[] public allPairs;\\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\\n\\n address internal _temp0;\\n address internal _temp1;\\n bool internal _temp;\\n\\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\\n\\n constructor() {\\n pauser = msg.sender;\\n isPaused = false;\\n feeManager = msg.sender;\\n stableFee = 2; // 0.02%\\n volatileFee = 2;\\n }\\n\\n function allPairsLength() external view returns (uint) {\\n return allPairs.length;\\n }\\n\\n function setPauser(address _pauser) external {\\n require(msg.sender == pauser);\\n pendingPauser = _pauser;\\n }\\n\\n function acceptPauser() external {\\n require(msg.sender == pendingPauser);\\n pauser = pendingPauser;\\n }\\n\\n function setPause(bool _state) external {\\n require(msg.sender == pauser);\\n isPaused = _state;\\n }\\n\\n function setFeeManager(address _feeManager) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n pendingFeeManager = _feeManager;\\n }\\n\\n function acceptFeeManager() external {\\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\\n feeManager = pendingFeeManager;\\n }\\n\\n function setFee(bool _stable, uint256 _fee) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n require(_fee <= MAX_FEE, 'fee too high');\\n require(_fee != 0, 'fee must be nonzero');\\n if (_stable) {\\n stableFee = _fee;\\n } else {\\n volatileFee = _fee;\\n }\\n }\\n\\n function getFee(bool _stable) public view returns(uint256) {\\n return _stable ? stableFee : volatileFee;\\n }\\n\\n function pairCodeHash() external pure returns (bytes32) {\\n return keccak256(type(Pair).creationCode);\\n }\\n\\n function getInitializable() external view returns (address, address, bool) {\\n return (_temp0, _temp1, _temp);\\n }\\n\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\\n (_temp0, _temp1, _temp) = (token0, token1, stable);\\n pair = address(new Pair{salt:salt}());\\n getPair[token0][token1][stable] = pair;\\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\\n allPairs.push(pair);\\n isPair[pair] = true;\\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\\n }\\n}\\n\",\"keccak256\":\"0x9b7984117a5a32188aa9ddf42b6cff024240579ab30f3776f7a201285d813e4f\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairCallee.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairCallee {\\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x3ac2de2c7a08bf59fd1006e4d108b247916369de15fbd048b72ca2b7814023ca\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50600080546001600160a81b03191633610100810260ff1916919091178255600480546001600160a01b0319169091179055600280805560035561519190819061005a90396000f3fe60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea2646970667358221220c096b5b8eff492cfa56eca7766bf438a7772873d9d55ac3fb8495fc6e91048df64736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea26469706673582212203b862e6743be8a92d1eec9a88fc2f68597ac055d6ad2133ccb634ef6a70ed04764736f6c634300080d0033a2646970667358221220cba5a1771a35b11c991d6154f51a9021074ad34c96b2d242ead8321a39d961cb64736f6c634300080d0033", - "deployedBytecode": "0x60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea2646970667358221220c096b5b8eff492cfa56eca7766bf438a7772873d9d55ac3fb8495fc6e91048df64736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea26469706673582212203b862e6743be8a92d1eec9a88fc2f68597ac055d6ad2133ccb634ef6a70ed04764736f6c634300080d0033a2646970667358221220cba5a1771a35b11c991d6154f51a9021074ad34c96b2d242ead8321a39d961cb64736f6c634300080d0033", + "numDeployments": 5, + "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"PairCreated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_FEE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allPairs\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"allPairsLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"createPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getInitializable\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"name\":\"getPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pairCodeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingFeeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingPauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_feeManager\",\"type\":\"address\"}],\"name\":\"setFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_state\",\"type\":\"bool\"}],\"name\":\"setPause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pauser\",\"type\":\"address\"}],\"name\":\"setPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stableFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"volatileFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/PairFactory.sol\":\"PairFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Pair.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairCallee.sol\\\";\\nimport \\\"contracts/factories/PairFactory.sol\\\";\\nimport \\\"contracts/PairFees.sol\\\";\\n\\n// The base pair of pools, either stable or volatile\\ncontract Pair is IPair {\\n string public name;\\n string public symbol;\\n uint8 public constant decimals = 18;\\n\\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\\n bool public immutable stable;\\n\\n uint256 public totalSupply = 0;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n mapping(address => uint256) public balanceOf;\\n\\n bytes32 internal DOMAIN_SEPARATOR;\\n // keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 internal constant PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n mapping(address => uint256) public nonces;\\n\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n\\n address public immutable token0;\\n address public immutable token1;\\n address public immutable fees;\\n address immutable factory;\\n\\n // Structure to capture time period obervations every 30 minutes, used for local oracles\\n struct Observation {\\n uint256 timestamp;\\n uint256 reserve0Cumulative;\\n uint256 reserve1Cumulative;\\n }\\n\\n // Capture oracle reading every 30 minutes\\n uint256 constant periodSize = 1800;\\n\\n Observation[] public observations;\\n\\n uint256 internal immutable decimals0;\\n uint256 internal immutable decimals1;\\n\\n uint256 public reserve0;\\n uint256 public reserve1;\\n uint256 public blockTimestampLast;\\n\\n uint256 public reserve0CumulativeLast;\\n uint256 public reserve1CumulativeLast;\\n\\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \\\"clean\\\"\\n // this further allows LP holders to easily claim fees for tokens they have/staked\\n uint256 public index0 = 0;\\n uint256 public index1 = 0;\\n\\n // position assigned to each LP to track their current index0 & index1 vs the global position\\n mapping(address => uint256) public supplyIndex0;\\n mapping(address => uint256) public supplyIndex1;\\n\\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\\n mapping(address => uint256) public claimable0;\\n mapping(address => uint256) public claimable1;\\n\\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\\n event Burn(\\n address indexed sender,\\n uint256 amount0,\\n uint256 amount1,\\n address indexed to\\n );\\n event Swap(\\n address indexed sender,\\n uint256 amount0In,\\n uint256 amount1In,\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address indexed to\\n );\\n event Sync(uint256 reserve0, uint256 reserve1);\\n event Claim(\\n address indexed sender,\\n address indexed recipient,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 amount\\n );\\n\\n constructor() {\\n factory = msg.sender;\\n (address _token0, address _token1, bool _stable) = PairFactory(\\n msg.sender\\n ).getInitializable();\\n (token0, token1, stable) = (_token0, _token1, _stable);\\n fees = address(new PairFees(_token0, _token1));\\n if (_stable) {\\n name = string(\\n abi.encodePacked(\\n \\\"StableV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"sAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n } else {\\n name = string(\\n abi.encodePacked(\\n \\\"VolatileV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"vAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n }\\n\\n decimals0 = 10**IERC20(_token0).decimals();\\n decimals1 = 10**IERC20(_token1).decimals();\\n\\n observations.push(Observation(block.timestamp, 0, 0));\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function observationLength() external view returns (uint256) {\\n return observations.length;\\n }\\n\\n function lastObservation() public view returns (Observation memory) {\\n return observations[observations.length - 1];\\n }\\n\\n function metadata()\\n external\\n view\\n returns (\\n uint256 dec0,\\n uint256 dec1,\\n uint256 r0,\\n uint256 r1,\\n bool st,\\n address t0,\\n address t1\\n )\\n {\\n return (\\n decimals0,\\n decimals1,\\n reserve0,\\n reserve1,\\n stable,\\n token0,\\n token1\\n );\\n }\\n\\n function tokens() external view returns (address, address) {\\n return (token0, token1);\\n }\\n\\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\\n _updateFor(msg.sender);\\n\\n claimed0 = claimable0[msg.sender];\\n claimed1 = claimable1[msg.sender];\\n\\n if (claimed0 > 0 || claimed1 > 0) {\\n claimable0[msg.sender] = 0;\\n claimable1[msg.sender] = 0;\\n\\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\\n\\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n // Accrue fees on token0\\n function _update0(uint256 amount) internal {\\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index0 += _ratio;\\n }\\n emit Fees(msg.sender, amount, 0);\\n }\\n\\n // Accrue fees on token1\\n function _update1(uint256 amount) internal {\\n _safeTransfer(token1, fees, amount);\\n uint256 _ratio = (amount * 1e18) / totalSupply;\\n if (_ratio > 0) {\\n index1 += _ratio;\\n }\\n emit Fees(msg.sender, 0, amount);\\n }\\n\\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\\n // Fees are segregated from core funds, so fees can never put liquidity at risk\\n function _updateFor(address recipient) internal {\\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\\n if (_supplied > 0) {\\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\\n uint256 _supplyIndex1 = supplyIndex1[recipient];\\n uint256 _index0 = index0; // get global index0 for accumulated fees\\n uint256 _index1 = index1;\\n supplyIndex0[recipient] = _index0; // update user current position to global position\\n supplyIndex1[recipient] = _index1;\\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\\n uint256 _delta1 = _index1 - _supplyIndex1;\\n if (_delta0 > 0) {\\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\\n claimable0[recipient] += _share;\\n }\\n if (_delta1 > 0) {\\n uint256 _share = (_supplied * _delta1) / 1e18;\\n claimable1[recipient] += _share;\\n }\\n } else {\\n supplyIndex0[recipient] = index0; // new users are set to the default global state\\n supplyIndex1[recipient] = index1;\\n }\\n }\\n\\n function getReserves()\\n public\\n view\\n returns (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n )\\n {\\n _reserve0 = reserve0;\\n _reserve1 = reserve1;\\n _blockTimestampLast = blockTimestampLast;\\n }\\n\\n // update reserves and, on the first call per block, price accumulators\\n function _update(\\n uint256 balance0,\\n uint256 balance1,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal {\\n uint256 blockTimestamp = block.timestamp;\\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\\n reserve0CumulativeLast += _reserve0 * timeElapsed;\\n reserve1CumulativeLast += _reserve1 * timeElapsed;\\n }\\n\\n Observation memory _point = lastObservation();\\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\\n if (timeElapsed > periodSize) {\\n observations.push(\\n Observation(\\n blockTimestamp,\\n reserve0CumulativeLast,\\n reserve1CumulativeLast\\n )\\n );\\n }\\n reserve0 = balance0;\\n reserve1 = balance1;\\n blockTimestampLast = blockTimestamp;\\n emit Sync(reserve0, reserve1);\\n }\\n\\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\\n function currentCumulativePrices()\\n public\\n view\\n returns (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n uint256 blockTimestamp\\n )\\n {\\n blockTimestamp = block.timestamp;\\n reserve0Cumulative = reserve0CumulativeLast;\\n reserve1Cumulative = reserve1CumulativeLast;\\n\\n // if time has elapsed since the last update on the pair, mock the accumulated price values\\n (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n ) = getReserves();\\n if (_blockTimestampLast != blockTimestamp) {\\n // subtraction overflow is desired\\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\\n reserve0Cumulative += _reserve0 * timeElapsed;\\n reserve1Cumulative += _reserve1 * timeElapsed;\\n }\\n }\\n\\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\\n function current(address tokenIn, uint256 amountIn)\\n external\\n view\\n returns (uint256 amountOut)\\n {\\n Observation memory _observation = lastObservation();\\n (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n\\n ) = currentCumulativePrices();\\n if (block.timestamp == _observation.timestamp) {\\n _observation = observations[observations.length - 2];\\n }\\n\\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\\n uint256 _reserve0 = (reserve0Cumulative -\\n _observation.reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (reserve1Cumulative -\\n _observation.reserve1Cumulative) / timeElapsed;\\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n // as per `current`, however allows user configured granularity, up to the full window size\\n function quote(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 granularity\\n ) external view returns (uint256 amountOut) {\\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\\n uint256 priceAverageCumulative;\\n for (uint256 i = 0; i < _prices.length; i++) {\\n priceAverageCumulative += _prices[i];\\n }\\n return priceAverageCumulative / granularity;\\n }\\n\\n // returns a memory set of twap prices\\n function prices(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points\\n ) external view returns (uint256[] memory) {\\n return sample(tokenIn, amountIn, points, 1);\\n }\\n\\n function sample(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points,\\n uint256 window\\n ) public view returns (uint256[] memory) {\\n uint256[] memory _prices = new uint256[](points);\\n\\n uint256 length = observations.length - 1;\\n uint256 i = length - (points * window);\\n uint256 nextIndex = 0;\\n uint256 index = 0;\\n\\n for (; i < length; i += window) {\\n nextIndex = i + window;\\n uint256 timeElapsed = observations[nextIndex].timestamp -\\n observations[i].timestamp;\\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\\n observations[i].reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\\n observations[i].reserve1Cumulative) / timeElapsed;\\n _prices[index] = _getAmountOut(\\n amountIn,\\n tokenIn,\\n _reserve0,\\n _reserve1\\n );\\n // index < length; length cannot overflow\\n unchecked {\\n index = index + 1;\\n }\\n }\\n return _prices;\\n }\\n\\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\\n // standard uniswap v2 implementation\\n function mint(address to) external lock returns (uint256 liquidity) {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\\n uint256 _amount0 = _balance0 - _reserve0;\\n uint256 _amount1 = _balance1 - _reserve1;\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n if (_totalSupply == 0) {\\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\\n } else {\\n liquidity = MathDunks.min(\\n (_amount0 * _totalSupply) / _reserve0,\\n (_amount1 * _totalSupply) / _reserve1\\n );\\n }\\n require(liquidity > 0, \\\"ILM\\\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\\n _mint(to, liquidity);\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Mint(msg.sender, _amount0, _amount1);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n // standard uniswap v2 implementation\\n function burn(address to)\\n external\\n lock\\n returns (uint256 amount0, uint256 amount1)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n (address _token0, address _token1) = (token0, token1);\\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\\n uint256 _liquidity = balanceOf[address(this)];\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\\n require(amount0 > 0 && amount1 > 0, \\\"ILB\\\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\\n _burn(address(this), _liquidity);\\n _safeTransfer(_token0, to, amount0);\\n _safeTransfer(_token1, to, amount1);\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Burn(msg.sender, amount0, amount1, to);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n function swap(\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address to,\\n bytes calldata data\\n ) external lock {\\n require(!PairFactory(factory).isPaused());\\n require(amount0Out > 0 || amount1Out > 0, \\\"IOA\\\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \\\"IL\\\"); // Pair: INSUFFICIENT_LIQUIDITY\\n\\n uint256 _balance0;\\n uint256 _balance1;\\n {\\n // scope for _token{0,1}, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n require(to != _token0 && to != _token1, \\\"IT\\\"); // Pair: INVALID_TO\\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\\n if (data.length > 0)\\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n }\\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\\n ? _balance0 - (_reserve0 - amount0Out)\\n : 0;\\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\\n ? _balance1 - (_reserve1 - amount1Out)\\n : 0;\\n require(amount0In > 0 || amount1In > 0, \\\"IIA\\\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\\n {\\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n if (amount0In > 0)\\n _update0(\\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token0 and move them out of pool\\n if (amount1In > 0)\\n _update1(\\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token1 and move them out of pool\\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \\\"K\\\"); // Pair: K\\n }\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\\n }\\n\\n // force balances to match reserves\\n function skim(address to) external lock {\\n (address _token0, address _token1) = (token0, token1);\\n _safeTransfer(\\n _token0,\\n to,\\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\\n );\\n _safeTransfer(\\n _token1,\\n to,\\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\\n );\\n }\\n\\n // force reserves to match balances\\n function sync() external lock {\\n _update(\\n IERC20(token0).balanceOf(address(this)),\\n IERC20(token1).balanceOf(address(this)),\\n reserve0,\\n reserve1\\n );\\n }\\n\\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\\n 1e18 +\\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\\n 1e18;\\n }\\n\\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (3 * x0 * ((y * y) / 1e18)) /\\n 1e18 +\\n ((((x0 * x0) / 1e18) * x0) / 1e18);\\n }\\n\\n function _get_y(\\n uint256 x0,\\n uint256 xy,\\n uint256 y\\n ) internal pure returns (uint256) {\\n for (uint256 i = 0; i < 255; i++) {\\n uint256 y_prev = y;\\n uint256 k = _f(x0, y);\\n if (k < xy) {\\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\\n y = y + dy;\\n } else {\\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getAmountOut(uint256 amountIn, address tokenIn)\\n external\\n view\\n returns (uint256)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n function _getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal view returns (uint256) {\\n if (stable) {\\n uint256 xy = _k(_reserve0, _reserve1);\\n _reserve0 = (_reserve0 * 1e18) / decimals0;\\n _reserve1 = (_reserve1 * 1e18) / decimals1;\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0\\n ? (amountIn * 1e18) / decimals0\\n : (amountIn * 1e18) / decimals1;\\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\\n } else {\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n return (amountIn * reserveB) / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\\n if (stable) {\\n uint256 _x = (x * 1e18) / decimals0;\\n uint256 _y = (y * 1e18) / decimals1;\\n uint256 _a = (_x * _y) / 1e18;\\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return (_a * _b) / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n\\n function _mint(address dst, uint256 amount) internal {\\n _updateFor(dst); // balances must be updated on mint/burn/transfer\\n totalSupply += amount;\\n balanceOf[dst] += amount;\\n emit Transfer(address(0), dst, amount);\\n }\\n\\n function _burn(address dst, uint256 amount) internal {\\n _updateFor(dst);\\n totalSupply -= amount;\\n balanceOf[dst] -= amount;\\n emit Transfer(dst, address(0), amount);\\n }\\n\\n function approve(address spender, uint256 amount) external returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external {\\n require(deadline >= block.timestamp, \\\"Pair: EXPIRED\\\");\\n DOMAIN_SEPARATOR = keccak256(\\n abi.encode(\\n keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n ),\\n keccak256(bytes(name)),\\n keccak256(bytes(\\\"1\\\")),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR,\\n keccak256(\\n abi.encode(\\n PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n );\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n require(\\n recoveredAddress != address(0) && recoveredAddress == owner,\\n \\\"Pair: INVALID_SIGNATURE\\\"\\n );\\n allowance[owner][spender] = value;\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function transfer(address dst, uint256 amount) external returns (bool) {\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 amount\\n ) external returns (bool) {\\n address spender = msg.sender;\\n uint256 spenderAllowance = allowance[src][spender];\\n\\n if (spender != src && spenderAllowance != type(uint256).max) {\\n uint256 newAllowance = spenderAllowance - amount;\\n allowance[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n function _transferTokens(\\n address src,\\n address dst,\\n uint256 amount\\n ) internal {\\n _updateFor(src); // update fee position for src\\n _updateFor(dst); // update fee position for dst\\n\\n balanceOf[src] -= amount;\\n balanceOf[dst] += amount;\\n\\n emit Transfer(src, dst, amount);\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x4f508747645f4480e0b0f23d952fa9b82af1d9bc60b15b8cd1f542ee136043d1\",\"license\":\"MIT\"},\"contracts/PairFees.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IERC20.sol';\\n\\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\\ncontract PairFees {\\n\\n address internal immutable pair; // The pair it is bonded to\\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\\n\\n constructor(address _token0, address _token1) {\\n pair = msg.sender;\\n token0 = _token0;\\n token1 = _token1;\\n }\\n\\n function _safeTransfer(address token,address to,uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n // Allow the pair to transfer fees to users\\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\\n require(msg.sender == pair);\\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\\n }\\n\\n}\\n\",\"keccak256\":\"0xb772e192bab353f8642e89a95ef4ef0255d1caef08444101d7fe34469c1000ca\",\"license\":\"MIT\"},\"contracts/factories/PairFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/Pair.sol';\\n\\ncontract PairFactory is IPairFactory {\\n\\n bool public isPaused;\\n address public pauser;\\n address public pendingPauser;\\n\\n uint256 public stableFee;\\n uint256 public volatileFee;\\n uint256 public constant MAX_FEE = 5; // 0.05%\\n address public feeManager;\\n address public pendingFeeManager;\\n\\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\\n address[] public allPairs;\\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\\n\\n address internal _temp0;\\n address internal _temp1;\\n bool internal _temp;\\n\\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\\n\\n constructor() {\\n pauser = msg.sender;\\n isPaused = false;\\n feeManager = msg.sender;\\n stableFee = 2; // 0.02%\\n volatileFee = 2;\\n }\\n\\n function allPairsLength() external view returns (uint) {\\n return allPairs.length;\\n }\\n\\n function setPauser(address _pauser) external {\\n require(msg.sender == pauser);\\n pendingPauser = _pauser;\\n }\\n\\n function acceptPauser() external {\\n require(msg.sender == pendingPauser);\\n pauser = pendingPauser;\\n }\\n\\n function setPause(bool _state) external {\\n require(msg.sender == pauser);\\n isPaused = _state;\\n }\\n\\n function setFeeManager(address _feeManager) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n pendingFeeManager = _feeManager;\\n }\\n\\n function acceptFeeManager() external {\\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\\n feeManager = pendingFeeManager;\\n }\\n\\n function setFee(bool _stable, uint256 _fee) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n require(_fee <= MAX_FEE, 'fee too high');\\n require(_fee != 0, 'fee must be nonzero');\\n if (_stable) {\\n stableFee = _fee;\\n } else {\\n volatileFee = _fee;\\n }\\n }\\n\\n function getFee(bool _stable) public view returns(uint256) {\\n return _stable ? stableFee : volatileFee;\\n }\\n\\n function pairCodeHash() external pure returns (bytes32) {\\n return keccak256(type(Pair).creationCode);\\n }\\n\\n function getInitializable() external view returns (address, address, bool) {\\n return (_temp0, _temp1, _temp);\\n }\\n\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\\n (_temp0, _temp1, _temp) = (token0, token1, stable);\\n pair = address(new Pair{salt:salt}());\\n getPair[token0][token1][stable] = pair;\\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\\n allPairs.push(pair);\\n isPair[pair] = true;\\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\\n }\\n}\\n\",\"keccak256\":\"0x9b7984117a5a32188aa9ddf42b6cff024240579ab30f3776f7a201285d813e4f\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairCallee.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairCallee {\\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x3ac2de2c7a08bf59fd1006e4d108b247916369de15fbd048b72ca2b7814023ca\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50600080546001600160a81b03191633610100810260ff1916919091178255600480546001600160a01b0319169091179055600280805560035561519190819061005a90396000f3fe60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea2646970667358221220ff1d4003304bd460d210311318fdfcf0424b931f7affbe2b2f368518adf993e564736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea2646970667358221220897f96d22d617a86c8245dcbfac365296ab66900e6de019e62f6b31bc214be2c64736f6c634300080d0033a26469706673582212204645a8cdd9943867307d2264d375485cfdbe388ee5ca8c7335f9e2fc9f900ec764736f6c634300080d0033", + "deployedBytecode": "0x60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea2646970667358221220ff1d4003304bd460d210311318fdfcf0424b931f7affbe2b2f368518adf993e564736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea2646970667358221220897f96d22d617a86c8245dcbfac365296ab66900e6de019e62f6b31bc214be2c64736f6c634300080d0033a26469706673582212204645a8cdd9943867307d2264d375485cfdbe388ee5ca8c7335f9e2fc9f900ec764736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/RedemptionReceiver.json b/deployments/arbitrumGoerli/RedemptionReceiver.json index d3f792e7..0cfe5f33 100644 --- a/deployments/arbitrumGoerli/RedemptionReceiver.json +++ b/deployments/arbitrumGoerli/RedemptionReceiver.json @@ -1,5 +1,5 @@ { - "address": "0x552dD2458Ac8Fb7bC83a2BFF16e57e44Aa30cd4F", + "address": "0xCe4d8bccE6d2D9B48565d660c45a397D3Fb4a497", "abi": [ { "inputs": [ @@ -323,33 +323,33 @@ "type": "function" } ], - "transactionHash": "0x16c49dd70b141dc4df3888393a02418744bd2a6dbb0b864af1a7ba82a1847f6b", + "transactionHash": "0x299e902c0e7a5f362b791877aa19a16d7869bc3149bec56ce64be85f8957c904", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x552dD2458Ac8Fb7bC83a2BFF16e57e44Aa30cd4F", + "contractAddress": "0xCe4d8bccE6d2D9B48565d660c45a397D3Fb4a497", "transactionIndex": 1, "gasUsed": "841985", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xd1753b9b7f09a0dd4dea81afdf1f617e8f0224c4dd3ca1436e14cc1c85b6c03d", - "transactionHash": "0x16c49dd70b141dc4df3888393a02418744bd2a6dbb0b864af1a7ba82a1847f6b", + "blockHash": "0xc8fcd776d23ee2cb7efd3795d529b15a6769f03ae3e23c810a625ff04d9aeb5b", + "transactionHash": "0x299e902c0e7a5f362b791877aa19a16d7869bc3149bec56ce64be85f8957c904", "logs": [], - "blockNumber": 5716750, + "blockNumber": 5814450, "cumulativeGasUsed": "841985", "status": 1, "byzantium": true }, "args": [ "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8", - "0xf5A53c1b4072425DF6eC082f0A48B4652bc4188C", + "0x8c35578054126d4DD063CFaBA40B7F9B63A13981", 10012, "0x3c2269811836af69497E5F486A85D7316753cf62" ], - "numDeployments": 3, - "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_usdc\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_flow\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"_fantomChainId\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"_endpoint\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fantomSender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableUSDC\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableFLOW\",\"type\":\"uint256\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ELIGIBLE_WEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FLOW\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"USDC\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"toAddressBytes\",\"type\":\"bytes\"}],\"name\":\"addressFromPackedBytes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimLeftovers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endpoint\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomChainId\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_fantomSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableFLOW\",\"type\":\"uint256\"}],\"name\":\"initializeReceiverWith\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"leftoverFLOW\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"srcChainId\",\"type\":\"uint16\"},{\"internalType\":\"bytes\",\"name\":\"srcAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"lzReceive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountWEVE\",\"type\":\"uint256\"}],\"name\":\"previewRedeem\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"shareOfUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shareOfFLOW\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableFLOW\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableUSDC\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemedWEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process This contract is responsible for receiving the LZ message and distributing USDC + FLOW\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/RedemptionReceiver.sol\":\"RedemptionReceiver\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/redeem/RedemptionReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\\\";\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\n\\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\\n/// This contract is responsible for receiving the LZ message and distributing USDC + FLOW\\ncontract RedemptionReceiver is ILayerZeroReceiver {\\n IERC20 public immutable USDC;\\n IFlow public immutable FLOW;\\n\\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\\n address public immutable endpoint;\\n\\n address public team;\\n uint256 public immutable deployed;\\n\\n address public fantomSender;\\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\\n uint256 public redeemedWEVE;\\n uint256 public redeemableUSDC;\\n uint256 public redeemableFLOW;\\n uint256 public leftoverFLOW;\\n\\n constructor(\\n address _usdc,\\n address _flow,\\n uint16 _fantomChainId,\\n address _endpoint\\n ) {\\n require(_fantomChainId == 12 || _fantomChainId == 10012, \\\"CHAIN_ID_NOT_FTM\\\");\\n\\n USDC = IERC20(_usdc);\\n FLOW = IFlow(_flow);\\n\\n fantomChainId = _fantomChainId;\\n endpoint = _endpoint;\\n\\n team = msg.sender;\\n deployed = block.timestamp;\\n }\\n\\n modifier onlyTeam() {\\n require(msg.sender == team, \\\"ONLY_TEAM\\\");\\n _;\\n }\\n\\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableFLOW);\\n\\n function initializeReceiverWith(\\n address _fantomSender,\\n uint256 _redeemableUSDC,\\n uint256 _redeemableFLOW\\n ) external onlyTeam {\\n require(fantomSender == address(0), \\\"ALREADY_INITIALIZED\\\");\\n require(\\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n fantomSender = _fantomSender;\\n redeemableUSDC = _redeemableUSDC;\\n redeemableFLOW = _redeemableFLOW;\\n leftoverFLOW = _redeemableFLOW;\\n\\n emit Initialized(fantomSender, redeemableUSDC, redeemableFLOW);\\n }\\n\\n function setTeam(address _team) external onlyTeam {\\n team = _team;\\n }\\n\\n function previewRedeem(uint256 amountWEVE)\\n public\\n view\\n returns (uint256 shareOfUSDC, uint256 shareOfFLOW)\\n {\\n // pro rata USDC\\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\\n // pro rata FLOW\\n shareOfFLOW = (amountWEVE * redeemableFLOW) / ELIGIBLE_WEVE;\\n }\\n\\n function lzReceive(\\n uint16 srcChainId,\\n bytes memory srcAddress,\\n uint64,\\n bytes memory payload\\n ) external override {\\n require(fantomSender != address(0), \\\"NOT_INITIALIZED\\\");\\n require(\\n msg.sender == endpoint &&\\n srcChainId == fantomChainId &&\\n addressFromPackedBytes(srcAddress) == fantomSender,\\n \\\"UNAUTHORIZED_CALLER\\\"\\n );\\n\\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\\n payload,\\n (address, uint256)\\n );\\n\\n require(\\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\\n \\\"cannot redeem more than eligible\\\"\\n );\\n (uint256 shareOfUSDC, uint256 shareOfFLOW) = previewRedeem(amountWEVE);\\n\\n require(\\n USDC.transfer(redemptionAddress, shareOfUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n leftoverFLOW -= shareOfFLOW; // this will revert if underflows\\n require(\\n FLOW.claim(redemptionAddress, shareOfFLOW),\\n \\\"CLAIM_FAILED\\\"\\n );\\n }\\n\\n function addressFromPackedBytes(bytes memory toAddressBytes)\\n public\\n pure\\n returns (address toAddress)\\n {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n toAddress := mload(add(toAddressBytes, 20))\\n }\\n }\\n\\n function claimLeftovers() external onlyTeam {\\n require(block.timestamp >= deployed + 30 days, \\\"LEFTOVERS_NOT_CLAIMABLE\\\");\\n require(\\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n }\\n}\\n\",\"keccak256\":\"0x582d45a8db937fe4a965056bcbe7d1427f71be66e8071bb1cae76d5f36c6c314\",\"license\":\"MIT\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\nimport \\\"./ILayerZeroUserApplicationConfig.sol\\\";\\n\\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\\n // @param _dstChainId - the destination chain identifier\\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\\n // @param _payload - a custom bytes payload to send to the destination contract\\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\\n\\n // @notice used by the messaging library to publish verified payload\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source contract (as bytes) at the source chain\\n // @param _dstAddress - the address on destination chain\\n // @param _nonce - the unbound message ordering nonce\\n // @param _gasLimit - the gas limit for external contract execution\\n // @param _payload - verified payload to send to the destination contract\\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\\n\\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\\n\\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\\n // @param _srcAddress - the source chain contract address\\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\\n\\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\\n // @param _dstChainId - the destination chain identifier\\n // @param _userApplication - the user app address on this EVM chain\\n // @param _payload - the custom message to send over LayerZero\\n // @param _payInZRO - if false, user app pays the protocol fee in native token\\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\\n\\n // @notice get this Endpoint's immutable source identifier\\n function getChainId() external view returns (uint16);\\n\\n // @notice the interface to retry failed message on this Endpoint destination\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n // @param _payload - the payload to be retried\\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\\n\\n // @notice query if any STORED payload (message blocking) at the endpoint.\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\\n\\n // @notice query if the _libraryAddress is valid for sending msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getSendLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the _libraryAddress is valid for receiving msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the non-reentrancy guard for send() is on\\n // @return true if the guard is on. false otherwise\\n function isSendingPayload() external view returns (bool);\\n\\n // @notice query if the non-reentrancy guard for receive() is on\\n // @return true if the guard is on. false otherwise\\n function isReceivingPayload() external view returns (bool);\\n\\n // @notice get the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _userApplication - the contract address of the user application\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\\n\\n // @notice get the send() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getSendVersion(address _userApplication) external view returns (uint16);\\n\\n // @notice get the lzReceive() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getReceiveVersion(address _userApplication) external view returns (uint16);\\n}\\n\",\"keccak256\":\"0xbc2e0022d4d53d136830aa90037be2ed7a0966f5fd1b409bf5986185984c495f\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroReceiver {\\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\\n // @param _srcChainId - the source endpoint identifier\\n // @param _srcAddress - the source sending contract address from the source chain\\n // @param _nonce - the ordered message nonce\\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\\n}\\n\",\"keccak256\":\"0xd1617e455d90d41556bba636bc440627d301ec481de16ff04fbd520333c3c6f3\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroUserApplicationConfig {\\n // @notice set the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n // @param _config - configuration in the bytes. can encode arbitrary content.\\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\\n\\n // @notice set the send() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setSendVersion(uint16 _version) external;\\n\\n // @notice set the lzReceive() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setReceiveVersion(uint16 _version) external;\\n\\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\\n // @param _srcChainId - the chainId of the source chain\\n // @param _srcAddress - the contract address of the source contract at the source chain\\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\\n}\\n\",\"keccak256\":\"0xdc7e072cf3064081a8edf4a286ca43ddecc24330f2923d96f416f9d3f6538447\",\"license\":\"BUSL-1.1\"}},\"version\":1}", - "bytecode": "0x61012060405234801561001157600080fd5b50604051610f81380380610f81833981016040819052610030916100e2565b8161ffff16600c148061004857508161ffff1661271c145b61008b5760405162461bcd60e51b815260206004820152601060248201526f434841494e5f49445f4e4f545f46544d60801b604482015260640160405180910390fd5b6001600160a01b0393841660805291831660a05261ffff1660c0521660e052600080546001600160a01b03191633179055426101005261013f565b80516001600160a01b03811681146100dd57600080fd5b919050565b600080600080608085870312156100f857600080fd5b610101856100c6565b935061010f602086016100c6565b9250604085015161ffff8116811461012657600080fd5b9150610134606086016100c6565b905092959194509250565b60805160a05160c05160e05161010051610dcd6101b4600039600081816102d601526108c00152600081816101d30152610352015260008181610263015261037c015260008181610163015261059f01526000818161023c015281816104d70152818161078e015261094c0152610dcd6000f3fe608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a408bb4c11610071578063a408bb4c14610298578063aaa8f2ef146102a0578063b8ea6281146102b3578063caccb667146102c8578063f905c15a146102d157600080fd5b80636bfd23a71461021b57806385f2aef21461022457806389a3027114610237578063997a03b71461025e57600080fd5b806347db1a6a116100e957806347db1a6a1461019d5780634cdad506146101a65780635e280f11146101ce57806363b4eb8d146101f557806368ecc6bc1461020857600080fd5b80621d35671461011a578063095cf5c61461012f5780631308db08146101425780633189097b1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60055481565b6040519081526020015b60405180910390f35b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b61014b60035481565b6101b96101b4366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b600154610185906001600160a01b031681565b61012d610216366004610be5565b6106f3565b61014b60025481565b600054610185906001600160a01b031681565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6102857f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101856102c1366004610c1a565b6014015190565b61014b60045481565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea26469706673582212207993ac0a14cefc113df5ea974ec076ad2ab5958e591d373203e387ffd15e8c1564736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a408bb4c11610071578063a408bb4c14610298578063aaa8f2ef146102a0578063b8ea6281146102b3578063caccb667146102c8578063f905c15a146102d157600080fd5b80636bfd23a71461021b57806385f2aef21461022457806389a3027114610237578063997a03b71461025e57600080fd5b806347db1a6a116100e957806347db1a6a1461019d5780634cdad506146101a65780635e280f11146101ce57806363b4eb8d146101f557806368ecc6bc1461020857600080fd5b80621d35671461011a578063095cf5c61461012f5780631308db08146101425780633189097b1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60055481565b6040519081526020015b60405180910390f35b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b61014b60035481565b6101b96101b4366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b600154610185906001600160a01b031681565b61012d610216366004610be5565b6106f3565b61014b60025481565b600054610185906001600160a01b031681565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6102857f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101856102c1366004610c1a565b6014015190565b61014b60045481565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea26469706673582212207993ac0a14cefc113df5ea974ec076ad2ab5958e591d373203e387ffd15e8c1564736f6c634300080d0033", + "numDeployments": 5, + "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_usdc\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_flow\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"_fantomChainId\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"_endpoint\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fantomSender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableUSDC\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableFLOW\",\"type\":\"uint256\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ELIGIBLE_WEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FLOW\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"USDC\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"toAddressBytes\",\"type\":\"bytes\"}],\"name\":\"addressFromPackedBytes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimLeftovers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endpoint\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomChainId\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_fantomSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableFLOW\",\"type\":\"uint256\"}],\"name\":\"initializeReceiverWith\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"leftoverFLOW\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"srcChainId\",\"type\":\"uint16\"},{\"internalType\":\"bytes\",\"name\":\"srcAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"lzReceive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountWEVE\",\"type\":\"uint256\"}],\"name\":\"previewRedeem\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"shareOfUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shareOfFLOW\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableFLOW\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableUSDC\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemedWEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process This contract is responsible for receiving the LZ message and distributing USDC + FLOW\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/RedemptionReceiver.sol\":\"RedemptionReceiver\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/redeem/RedemptionReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\\\";\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\n\\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\\n/// This contract is responsible for receiving the LZ message and distributing USDC + FLOW\\ncontract RedemptionReceiver is ILayerZeroReceiver {\\n IERC20 public immutable USDC;\\n IFlow public immutable FLOW;\\n\\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\\n address public immutable endpoint;\\n\\n address public team;\\n uint256 public immutable deployed;\\n\\n address public fantomSender;\\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\\n uint256 public redeemedWEVE;\\n uint256 public redeemableUSDC;\\n uint256 public redeemableFLOW;\\n uint256 public leftoverFLOW;\\n\\n constructor(\\n address _usdc,\\n address _flow,\\n uint16 _fantomChainId,\\n address _endpoint\\n ) {\\n require(_fantomChainId == 12 || _fantomChainId == 10012, \\\"CHAIN_ID_NOT_FTM\\\");\\n\\n USDC = IERC20(_usdc);\\n FLOW = IFlow(_flow);\\n\\n fantomChainId = _fantomChainId;\\n endpoint = _endpoint;\\n\\n team = msg.sender;\\n deployed = block.timestamp;\\n }\\n\\n modifier onlyTeam() {\\n require(msg.sender == team, \\\"ONLY_TEAM\\\");\\n _;\\n }\\n\\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableFLOW);\\n\\n function initializeReceiverWith(\\n address _fantomSender,\\n uint256 _redeemableUSDC,\\n uint256 _redeemableFLOW\\n ) external onlyTeam {\\n require(fantomSender == address(0), \\\"ALREADY_INITIALIZED\\\");\\n require(\\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n fantomSender = _fantomSender;\\n redeemableUSDC = _redeemableUSDC;\\n redeemableFLOW = _redeemableFLOW;\\n leftoverFLOW = _redeemableFLOW;\\n\\n emit Initialized(fantomSender, redeemableUSDC, redeemableFLOW);\\n }\\n\\n function setTeam(address _team) external onlyTeam {\\n team = _team;\\n }\\n\\n function previewRedeem(uint256 amountWEVE)\\n public\\n view\\n returns (uint256 shareOfUSDC, uint256 shareOfFLOW)\\n {\\n // pro rata USDC\\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\\n // pro rata FLOW\\n shareOfFLOW = (amountWEVE * redeemableFLOW) / ELIGIBLE_WEVE;\\n }\\n\\n function lzReceive(\\n uint16 srcChainId,\\n bytes memory srcAddress,\\n uint64,\\n bytes memory payload\\n ) external override {\\n require(fantomSender != address(0), \\\"NOT_INITIALIZED\\\");\\n require(\\n msg.sender == endpoint &&\\n srcChainId == fantomChainId &&\\n addressFromPackedBytes(srcAddress) == fantomSender,\\n \\\"UNAUTHORIZED_CALLER\\\"\\n );\\n\\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\\n payload,\\n (address, uint256)\\n );\\n\\n require(\\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\\n \\\"cannot redeem more than eligible\\\"\\n );\\n (uint256 shareOfUSDC, uint256 shareOfFLOW) = previewRedeem(amountWEVE);\\n\\n require(\\n USDC.transfer(redemptionAddress, shareOfUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n leftoverFLOW -= shareOfFLOW; // this will revert if underflows\\n require(\\n FLOW.claim(redemptionAddress, shareOfFLOW),\\n \\\"CLAIM_FAILED\\\"\\n );\\n }\\n\\n function addressFromPackedBytes(bytes memory toAddressBytes)\\n public\\n pure\\n returns (address toAddress)\\n {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n toAddress := mload(add(toAddressBytes, 20))\\n }\\n }\\n\\n function claimLeftovers() external onlyTeam {\\n require(block.timestamp >= deployed + 30 days, \\\"LEFTOVERS_NOT_CLAIMABLE\\\");\\n require(\\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n }\\n}\\n\",\"keccak256\":\"0x582d45a8db937fe4a965056bcbe7d1427f71be66e8071bb1cae76d5f36c6c314\",\"license\":\"MIT\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\nimport \\\"./ILayerZeroUserApplicationConfig.sol\\\";\\n\\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\\n // @param _dstChainId - the destination chain identifier\\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\\n // @param _payload - a custom bytes payload to send to the destination contract\\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\\n\\n // @notice used by the messaging library to publish verified payload\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source contract (as bytes) at the source chain\\n // @param _dstAddress - the address on destination chain\\n // @param _nonce - the unbound message ordering nonce\\n // @param _gasLimit - the gas limit for external contract execution\\n // @param _payload - verified payload to send to the destination contract\\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\\n\\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\\n\\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\\n // @param _srcAddress - the source chain contract address\\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\\n\\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\\n // @param _dstChainId - the destination chain identifier\\n // @param _userApplication - the user app address on this EVM chain\\n // @param _payload - the custom message to send over LayerZero\\n // @param _payInZRO - if false, user app pays the protocol fee in native token\\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\\n\\n // @notice get this Endpoint's immutable source identifier\\n function getChainId() external view returns (uint16);\\n\\n // @notice the interface to retry failed message on this Endpoint destination\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n // @param _payload - the payload to be retried\\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\\n\\n // @notice query if any STORED payload (message blocking) at the endpoint.\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\\n\\n // @notice query if the _libraryAddress is valid for sending msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getSendLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the _libraryAddress is valid for receiving msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the non-reentrancy guard for send() is on\\n // @return true if the guard is on. false otherwise\\n function isSendingPayload() external view returns (bool);\\n\\n // @notice query if the non-reentrancy guard for receive() is on\\n // @return true if the guard is on. false otherwise\\n function isReceivingPayload() external view returns (bool);\\n\\n // @notice get the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _userApplication - the contract address of the user application\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\\n\\n // @notice get the send() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getSendVersion(address _userApplication) external view returns (uint16);\\n\\n // @notice get the lzReceive() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getReceiveVersion(address _userApplication) external view returns (uint16);\\n}\\n\",\"keccak256\":\"0xbc2e0022d4d53d136830aa90037be2ed7a0966f5fd1b409bf5986185984c495f\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroReceiver {\\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\\n // @param _srcChainId - the source endpoint identifier\\n // @param _srcAddress - the source sending contract address from the source chain\\n // @param _nonce - the ordered message nonce\\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\\n}\\n\",\"keccak256\":\"0xd1617e455d90d41556bba636bc440627d301ec481de16ff04fbd520333c3c6f3\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroUserApplicationConfig {\\n // @notice set the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n // @param _config - configuration in the bytes. can encode arbitrary content.\\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\\n\\n // @notice set the send() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setSendVersion(uint16 _version) external;\\n\\n // @notice set the lzReceive() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setReceiveVersion(uint16 _version) external;\\n\\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\\n // @param _srcChainId - the chainId of the source chain\\n // @param _srcAddress - the contract address of the source contract at the source chain\\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\\n}\\n\",\"keccak256\":\"0xdc7e072cf3064081a8edf4a286ca43ddecc24330f2923d96f416f9d3f6538447\",\"license\":\"BUSL-1.1\"}},\"version\":1}", + "bytecode": "0x61012060405234801561001157600080fd5b50604051610f81380380610f81833981016040819052610030916100e2565b8161ffff16600c148061004857508161ffff1661271c145b61008b5760405162461bcd60e51b815260206004820152601060248201526f434841494e5f49445f4e4f545f46544d60801b604482015260640160405180910390fd5b6001600160a01b0393841660805291831660a05261ffff1660c0521660e052600080546001600160a01b03191633179055426101005261013f565b80516001600160a01b03811681146100dd57600080fd5b919050565b600080600080608085870312156100f857600080fd5b610101856100c6565b935061010f602086016100c6565b9250604085015161ffff8116811461012657600080fd5b9150610134606086016100c6565b905092959194509250565b60805160a05160c05160e05161010051610dcd6101b4600039600081816102d601526108c00152600081816101d30152610352015260008181610263015261037c015260008181610163015261059f01526000818161023c015281816104d70152818161078e015261094c0152610dcd6000f3fe608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a408bb4c11610071578063a408bb4c14610298578063aaa8f2ef146102a0578063b8ea6281146102b3578063caccb667146102c8578063f905c15a146102d157600080fd5b80636bfd23a71461021b57806385f2aef21461022457806389a3027114610237578063997a03b71461025e57600080fd5b806347db1a6a116100e957806347db1a6a1461019d5780634cdad506146101a65780635e280f11146101ce57806363b4eb8d146101f557806368ecc6bc1461020857600080fd5b80621d35671461011a578063095cf5c61461012f5780631308db08146101425780633189097b1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60055481565b6040519081526020015b60405180910390f35b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b61014b60035481565b6101b96101b4366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b600154610185906001600160a01b031681565b61012d610216366004610be5565b6106f3565b61014b60025481565b600054610185906001600160a01b031681565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6102857f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101856102c1366004610c1a565b6014015190565b61014b60045481565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea2646970667358221220fa48dc36406d08ebc3152e620c13d8b9f478aff977b39deae155b9b3bcb0feaa64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a408bb4c11610071578063a408bb4c14610298578063aaa8f2ef146102a0578063b8ea6281146102b3578063caccb667146102c8578063f905c15a146102d157600080fd5b80636bfd23a71461021b57806385f2aef21461022457806389a3027114610237578063997a03b71461025e57600080fd5b806347db1a6a116100e957806347db1a6a1461019d5780634cdad506146101a65780635e280f11146101ce57806363b4eb8d146101f557806368ecc6bc1461020857600080fd5b80621d35671461011a578063095cf5c61461012f5780631308db08146101425780633189097b1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60055481565b6040519081526020015b60405180910390f35b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b61014b60035481565b6101b96101b4366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b600154610185906001600160a01b031681565b61012d610216366004610be5565b6106f3565b61014b60025481565b600054610185906001600160a01b031681565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6102857f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101856102c1366004610c1a565b6014015190565b61014b60045481565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea2646970667358221220fa48dc36406d08ebc3152e620c13d8b9f478aff977b39deae155b9b3bcb0feaa64736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/RewardsDistributor.json b/deployments/arbitrumGoerli/RewardsDistributor.json index a53a14d8..4e6be817 100644 --- a/deployments/arbitrumGoerli/RewardsDistributor.json +++ b/deployments/arbitrumGoerli/RewardsDistributor.json @@ -1,5 +1,5 @@ { - "address": "0xEED0deFB831F96fC45B5e0ACb477F517F186496F", + "address": "0x85e7505be0F725AED67379Eb7F78d8561101caAE", "abi": [ { "inputs": [ @@ -351,45 +351,45 @@ "type": "function" } ], - "transactionHash": "0x75de4aad94bdd3ccf1a3abd009b69267523d51a5286ffe92105aeb7bf4e3a5c8", + "transactionHash": "0xbcdd4fe808f20d21c52d94ef1d4819b0ffa6e595bce37b1fe7b4303974eee346", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xEED0deFB831F96fC45B5e0ACb477F517F186496F", + "contractAddress": "0x85e7505be0F725AED67379Eb7F78d8561101caAE", "transactionIndex": 1, "gasUsed": "1623336", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000008000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000004000000000000000040000000000000000000000000000000000000000000000000000021000400000000000000000000000000000000000000400000000000000000000000000000000000000000000000800000000000000000000000000000000000010000000000000008000000000000000000000000000000000000000000000", - "blockHash": "0xc23e9a698a2fa91f639179617c0d79aa34767237d3ccc6d87b31ede6dd02be02", - "transactionHash": "0x75de4aad94bdd3ccf1a3abd009b69267523d51a5286ffe92105aeb7bf4e3a5c8", + "logsBloom": "0x00000000000000000000000000000000000004000000400000000000000000000000000000000000000000200010000000000000000000000004000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000800000000000000020000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xf63a14d84d9124cfc028f0ee04331c15005c46436bc1b521d09512e115713525", + "transactionHash": "0xbcdd4fe808f20d21c52d94ef1d4819b0ffa6e595bce37b1fe7b4303974eee346", "logs": [ { "transactionIndex": 1, - "blockNumber": 5716732, - "transactionHash": "0x75de4aad94bdd3ccf1a3abd009b69267523d51a5286ffe92105aeb7bf4e3a5c8", - "address": "0xf5A53c1b4072425DF6eC082f0A48B4652bc4188C", + "blockNumber": 5814435, + "transactionHash": "0xbcdd4fe808f20d21c52d94ef1d4819b0ffa6e595bce37b1fe7b4303974eee346", + "address": "0x8c35578054126d4DD063CFaBA40B7F9B63A13981", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000eed0defb831f96fc45b5e0acb477f517f186496f", - "0x000000000000000000000000c43f6ebf97f9d99ff8a3afe1413599e8dec2adb3" + "0x00000000000000000000000085e7505be0f725aed67379eb7f78d8561101caae", + "0x000000000000000000000000ad0f425b3edb0fc3a06096092b5736a280c90c40" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "logIndex": 0, - "blockHash": "0xc23e9a698a2fa91f639179617c0d79aa34767237d3ccc6d87b31ede6dd02be02" + "blockHash": "0xf63a14d84d9124cfc028f0ee04331c15005c46436bc1b521d09512e115713525" } ], - "blockNumber": 5716732, + "blockNumber": 5814435, "cumulativeGasUsed": "1623336", "status": 1, "byzantium": true }, "args": [ - "0xC43f6EbF97f9D99FF8a3aFe1413599e8DEc2aDB3" + "0xad0F425b3edB0FC3a06096092B5736A280C90C40" ], - "numDeployments": 3, - "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voting_escrow\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"time\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"CheckpointToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"claim_epoch\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"max_epoch\",\"type\":\"uint256\"}],\"name\":\"Claimed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"checkpoint_token\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint_total_supply\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"_tokenIds\",\"type\":\"uint256[]\"}],\"name\":\"claim_many\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_token_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"}],\"name\":\"setDepositor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"start_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"time_cursor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"time_cursor_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token_last_balance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"tokens_per_week\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_epoch_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"ve_for_at\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ve_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voting_escrow\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RewardsDistributor.sol\":\"RewardsDistributor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/*\\n\\n@title Curve Fee Distribution modified for ve(3,3) emissions\\n@author Curve Finance, andrecronje\\n@license MIT\\n\\n*/\\n\\ncontract RewardsDistributor is IRewardsDistributor {\\n event CheckpointToken(uint256 time, uint256 tokens);\\n\\n event Claimed(\\n uint256 tokenId,\\n uint256 amount,\\n uint256 claim_epoch,\\n uint256 max_epoch\\n );\\n\\n uint256 constant WEEK = 7 * 86400;\\n\\n uint256 public start_time;\\n uint256 public time_cursor;\\n mapping(uint256 => uint256) public time_cursor_of;\\n mapping(uint256 => uint256) public user_epoch_of;\\n\\n uint256 public last_token_time;\\n uint256[1000000000000000] public tokens_per_week;\\n\\n address public voting_escrow;\\n address public token;\\n uint256 public token_last_balance;\\n\\n uint256[1000000000000000] public ve_supply;\\n\\n address public depositor;\\n\\n constructor(address _voting_escrow) {\\n uint256 _t = (block.timestamp / WEEK) * WEEK;\\n start_time = _t;\\n last_token_time = _t;\\n time_cursor = _t;\\n address _token = IVotingEscrow(_voting_escrow).token();\\n token = _token;\\n voting_escrow = _voting_escrow;\\n depositor = msg.sender;\\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\\n }\\n\\n function timestamp() external view returns (uint256) {\\n return (block.timestamp / WEEK) * WEEK;\\n }\\n\\n function _checkpoint_token() internal {\\n uint256 token_balance = IERC20(token).balanceOf(address(this));\\n uint256 to_distribute = token_balance - token_last_balance;\\n token_last_balance = token_balance;\\n\\n uint256 t = last_token_time;\\n uint256 since_last = block.timestamp - t;\\n last_token_time = block.timestamp;\\n uint256 this_week = (t / WEEK) * WEEK;\\n uint256 next_week = 0;\\n\\n for (uint256 i = 0; i < 20; i++) {\\n next_week = this_week + WEEK;\\n if (block.timestamp < next_week) {\\n if (since_last == 0 && block.timestamp == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (block.timestamp - t)) /\\n since_last;\\n }\\n break;\\n } else {\\n if (since_last == 0 && next_week == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (next_week - t)) /\\n since_last;\\n }\\n }\\n t = next_week;\\n this_week = next_week;\\n }\\n emit CheckpointToken(block.timestamp, to_distribute);\\n }\\n\\n function checkpoint_token() external {\\n assert(msg.sender == depositor);\\n _checkpoint_token();\\n }\\n\\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\\n internal\\n view\\n returns (uint256)\\n {\\n uint256 _min = 0;\\n uint256 _max = IVotingEscrow(ve).epoch();\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n _mid\\n );\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function _find_timestamp_user_epoch(\\n address ve,\\n uint256 tokenId,\\n uint256 _timestamp,\\n uint256 max_user_epoch\\n ) internal view returns (uint256) {\\n uint256 _min = 0;\\n uint256 _max = max_user_epoch;\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\\n .user_point_history(tokenId, _mid);\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\\n external\\n view\\n returns (uint256)\\n {\\n address ve = voting_escrow;\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _timestamp,\\n max_user_epoch\\n );\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n epoch\\n );\\n return\\n MathDunks.max(\\n uint256(\\n int256(\\n pt.bias -\\n pt.slope *\\n (int128(int256(_timestamp - pt.ts)))\\n )\\n ),\\n 0\\n );\\n }\\n\\n function _checkpoint_total_supply() internal {\\n address ve = voting_escrow;\\n uint256 t = time_cursor;\\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\\n IVotingEscrow(ve).checkpoint();\\n\\n for (uint256 i = 0; i < 20; i++) {\\n if (t > rounded_timestamp) {\\n break;\\n } else {\\n uint256 epoch = _find_timestamp_epoch(ve, t);\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n epoch\\n );\\n int128 dt = 0;\\n if (t > pt.ts) {\\n dt = int128(int256(t - pt.ts));\\n }\\n ve_supply[t] = MathDunks.max(\\n uint256(int256(pt.bias - pt.slope * dt)),\\n 0\\n );\\n }\\n t += WEEK;\\n }\\n time_cursor = t;\\n }\\n\\n function checkpoint_total_supply() external {\\n _checkpoint_total_supply();\\n }\\n\\n function _claim(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\\n user_epoch_of[_tokenId] = user_epoch;\\n time_cursor_of[_tokenId] = week_cursor;\\n\\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\\n\\n return to_distribute;\\n }\\n\\n function _claimable(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal view returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n return to_distribute;\\n }\\n\\n function claimable(uint256 _tokenId) external view returns (uint256) {\\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\\n return _claimable(_tokenId, voting_escrow, _last_token_time);\\n }\\n\\n function claim(uint256 _tokenId) external returns (uint256) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\\n token_last_balance -= amount;\\n }\\n return amount;\\n }\\n\\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n address _voting_escrow = voting_escrow;\\n uint256 total = 0;\\n\\n for (uint256 i = 0; i < _tokenIds.length; i++) {\\n uint256 _tokenId = _tokenIds[i];\\n if (_tokenId == 0) break;\\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\\n total += amount;\\n }\\n }\\n if (total != 0) {\\n token_last_balance -= total;\\n }\\n\\n return true;\\n }\\n\\n // Once off event on contract initialize\\n function setDepositor(address _depositor) external {\\n require(msg.sender == depositor);\\n depositor = _depositor;\\n }\\n}\\n\",\"keccak256\":\"0xc3e7c3c7944974ce250313d2794fbfa3a98786e2040c685dc250c71ff9002829\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b5060405162001b9f38038062001b9f83398101604081905262000034916200019f565b600062093a80620000468142620001d1565b620000529190620001f4565b90508060008190555080600481905550806001819055506000826001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000aa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d091906200019f565b66038d7ea4c6800680546001600160a01b038381166001600160a01b0319928316811790935566038d7ea4c6800580549188169183168217905566071afd498d00088054909216331790915560405163095ea7b360e01b8152600481019190915260001960248201529192509063095ea7b3906044016020604051808303816000875af115801562000166573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200018c919062000222565b6200019657600080fd5b50505062000246565b600060208284031215620001b257600080fd5b81516001600160a01b0381168114620001ca57600080fd5b9392505050565b600082620001ef57634e487b7160e01b600052601260045260246000fd5b500490565b60008160001904831182151516156200021d57634e487b7160e01b600052601160045260246000fd5b500290565b6000602082840312156200023557600080fd5b81518015158114620001ca57600080fd5b61194980620002566000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea26469706673582212201e6c535ac80bdcc2173028ba4f75663baac29d307f03145fc4e6429a070cb05564736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea26469706673582212201e6c535ac80bdcc2173028ba4f75663baac29d307f03145fc4e6429a070cb05564736f6c634300080d0033", + "numDeployments": 5, + "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voting_escrow\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"time\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"CheckpointToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"claim_epoch\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"max_epoch\",\"type\":\"uint256\"}],\"name\":\"Claimed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"checkpoint_token\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint_total_supply\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"_tokenIds\",\"type\":\"uint256[]\"}],\"name\":\"claim_many\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_token_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"}],\"name\":\"setDepositor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"start_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"time_cursor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"time_cursor_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token_last_balance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"tokens_per_week\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_epoch_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"ve_for_at\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ve_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voting_escrow\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RewardsDistributor.sol\":\"RewardsDistributor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/*\\n\\n@title Curve Fee Distribution modified for ve(3,3) emissions\\n@author Curve Finance, andrecronje\\n@license MIT\\n\\n*/\\n\\ncontract RewardsDistributor is IRewardsDistributor {\\n event CheckpointToken(uint256 time, uint256 tokens);\\n\\n event Claimed(\\n uint256 tokenId,\\n uint256 amount,\\n uint256 claim_epoch,\\n uint256 max_epoch\\n );\\n\\n uint256 constant WEEK = 7 * 86400;\\n\\n uint256 public start_time;\\n uint256 public time_cursor;\\n mapping(uint256 => uint256) public time_cursor_of;\\n mapping(uint256 => uint256) public user_epoch_of;\\n\\n uint256 public last_token_time;\\n uint256[1000000000000000] public tokens_per_week;\\n\\n address public voting_escrow;\\n address public token;\\n uint256 public token_last_balance;\\n\\n uint256[1000000000000000] public ve_supply;\\n\\n address public depositor;\\n\\n constructor(address _voting_escrow) {\\n uint256 _t = (block.timestamp / WEEK) * WEEK;\\n start_time = _t;\\n last_token_time = _t;\\n time_cursor = _t;\\n address _token = IVotingEscrow(_voting_escrow).token();\\n token = _token;\\n voting_escrow = _voting_escrow;\\n depositor = msg.sender;\\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\\n }\\n\\n function timestamp() external view returns (uint256) {\\n return (block.timestamp / WEEK) * WEEK;\\n }\\n\\n function _checkpoint_token() internal {\\n uint256 token_balance = IERC20(token).balanceOf(address(this));\\n uint256 to_distribute = token_balance - token_last_balance;\\n token_last_balance = token_balance;\\n\\n uint256 t = last_token_time;\\n uint256 since_last = block.timestamp - t;\\n last_token_time = block.timestamp;\\n uint256 this_week = (t / WEEK) * WEEK;\\n uint256 next_week = 0;\\n\\n for (uint256 i = 0; i < 20; i++) {\\n next_week = this_week + WEEK;\\n if (block.timestamp < next_week) {\\n if (since_last == 0 && block.timestamp == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (block.timestamp - t)) /\\n since_last;\\n }\\n break;\\n } else {\\n if (since_last == 0 && next_week == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (next_week - t)) /\\n since_last;\\n }\\n }\\n t = next_week;\\n this_week = next_week;\\n }\\n emit CheckpointToken(block.timestamp, to_distribute);\\n }\\n\\n function checkpoint_token() external {\\n assert(msg.sender == depositor);\\n _checkpoint_token();\\n }\\n\\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\\n internal\\n view\\n returns (uint256)\\n {\\n uint256 _min = 0;\\n uint256 _max = IVotingEscrow(ve).epoch();\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n _mid\\n );\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function _find_timestamp_user_epoch(\\n address ve,\\n uint256 tokenId,\\n uint256 _timestamp,\\n uint256 max_user_epoch\\n ) internal view returns (uint256) {\\n uint256 _min = 0;\\n uint256 _max = max_user_epoch;\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\\n .user_point_history(tokenId, _mid);\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\\n external\\n view\\n returns (uint256)\\n {\\n address ve = voting_escrow;\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _timestamp,\\n max_user_epoch\\n );\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n epoch\\n );\\n return\\n MathDunks.max(\\n uint256(\\n int256(\\n pt.bias -\\n pt.slope *\\n (int128(int256(_timestamp - pt.ts)))\\n )\\n ),\\n 0\\n );\\n }\\n\\n function _checkpoint_total_supply() internal {\\n address ve = voting_escrow;\\n uint256 t = time_cursor;\\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\\n IVotingEscrow(ve).checkpoint();\\n\\n for (uint256 i = 0; i < 20; i++) {\\n if (t > rounded_timestamp) {\\n break;\\n } else {\\n uint256 epoch = _find_timestamp_epoch(ve, t);\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n epoch\\n );\\n int128 dt = 0;\\n if (t > pt.ts) {\\n dt = int128(int256(t - pt.ts));\\n }\\n ve_supply[t] = MathDunks.max(\\n uint256(int256(pt.bias - pt.slope * dt)),\\n 0\\n );\\n }\\n t += WEEK;\\n }\\n time_cursor = t;\\n }\\n\\n function checkpoint_total_supply() external {\\n _checkpoint_total_supply();\\n }\\n\\n function _claim(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\\n user_epoch_of[_tokenId] = user_epoch;\\n time_cursor_of[_tokenId] = week_cursor;\\n\\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\\n\\n return to_distribute;\\n }\\n\\n function _claimable(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal view returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n return to_distribute;\\n }\\n\\n function claimable(uint256 _tokenId) external view returns (uint256) {\\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\\n return _claimable(_tokenId, voting_escrow, _last_token_time);\\n }\\n\\n function claim(uint256 _tokenId) external returns (uint256) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\\n token_last_balance -= amount;\\n }\\n return amount;\\n }\\n\\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n address _voting_escrow = voting_escrow;\\n uint256 total = 0;\\n\\n for (uint256 i = 0; i < _tokenIds.length; i++) {\\n uint256 _tokenId = _tokenIds[i];\\n if (_tokenId == 0) break;\\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\\n total += amount;\\n }\\n }\\n if (total != 0) {\\n token_last_balance -= total;\\n }\\n\\n return true;\\n }\\n\\n // Once off event on contract initialize\\n function setDepositor(address _depositor) external {\\n require(msg.sender == depositor);\\n depositor = _depositor;\\n }\\n}\\n\",\"keccak256\":\"0xc3e7c3c7944974ce250313d2794fbfa3a98786e2040c685dc250c71ff9002829\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b5060405162001b9f38038062001b9f83398101604081905262000034916200019f565b600062093a80620000468142620001d1565b620000529190620001f4565b90508060008190555080600481905550806001819055506000826001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000aa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d091906200019f565b66038d7ea4c6800680546001600160a01b038381166001600160a01b0319928316811790935566038d7ea4c6800580549188169183168217905566071afd498d00088054909216331790915560405163095ea7b360e01b8152600481019190915260001960248201529192509063095ea7b3906044016020604051808303816000875af115801562000166573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200018c919062000222565b6200019657600080fd5b50505062000246565b600060208284031215620001b257600080fd5b81516001600160a01b0381168114620001ca57600080fd5b9392505050565b600082620001ef57634e487b7160e01b600052601260045260246000fd5b500490565b60008160001904831182151516156200021d57634e487b7160e01b600052601160045260246000fd5b500290565b6000602082840312156200023557600080fd5b81518015158114620001ca57600080fd5b61194980620002566000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea264697066735822122010fa9684b9cfb008f9cdfd287eddb3ae9817c769f858f828efc2818acbe56f8564736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea264697066735822122010fa9684b9cfb008f9cdfd287eddb3ae9817c769f858f828efc2818acbe56f8564736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/Router.json b/deployments/arbitrumGoerli/Router.json index 2000bb1e..067b963f 100644 --- a/deployments/arbitrumGoerli/Router.json +++ b/deployments/arbitrumGoerli/Router.json @@ -1,5 +1,5 @@ { - "address": "0x49fb251F8Ff60bcd975D2018D0011D7a6065000B", + "address": "0xD2D41340706472DEf3b8A1d6143743D03Da38fed", "abi": [ { "inputs": [ @@ -979,31 +979,31 @@ "type": "receive" } ], - "transactionHash": "0x6610f670be71188a6b66792b771e60520f5f7e7e91ee0c273e4306edfe22e182", + "transactionHash": "0x7c4a24e69aaf4df164731cb3473791991b6801f813e6f574159e65ffc4f89d4f", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x49fb251F8Ff60bcd975D2018D0011D7a6065000B", + "contractAddress": "0xD2D41340706472DEf3b8A1d6143743D03Da38fed", "transactionIndex": 1, "gasUsed": "3145971", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xcc92dd426bfe64c858819df3de6b6b806cca0f9c9e6aed184ca13cf3e58e4707", - "transactionHash": "0x6610f670be71188a6b66792b771e60520f5f7e7e91ee0c273e4306edfe22e182", + "blockHash": "0xd758637a25eeb7e41b28a5084badd5aa60779ea0a9aaff0c4ab4828c0125f7b7", + "transactionHash": "0x7c4a24e69aaf4df164731cb3473791991b6801f813e6f574159e65ffc4f89d4f", "logs": [], - "blockNumber": 5716719, + "blockNumber": 5814411, "cumulativeGasUsed": "3145971", "status": 1, "byzantium": true }, "args": [ - "0xddadFF10D1C9eb062180a870150D11673FFf7ad6", + "0xE4a96d05579a4306e19E1C36F8e6A1567c982750", "0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83" ], - "numDeployments": 3, - "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_weth\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"UNSAFE_swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"}],\"name\":\"getAmountsOut\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reserveA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"pairFor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"}],\"name\":\"quoteAddLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"name\":\"quoteRemoveLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityETHWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"}],\"name\":\"sortTokens\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactETHForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForETH\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenFrom\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenTo\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokensSimple\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weth\",\"outputs\":[{\"internalType\":\"contract IWETH\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Router.sol\":\"Router\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Router.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairFactory.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\nimport \\\"contracts/interfaces/IWETH.sol\\\";\\n\\ncontract Router is IRouter {\\n struct route {\\n address from;\\n address to;\\n bool stable;\\n }\\n\\n address public immutable factory;\\n IWETH public immutable weth;\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n bytes32 immutable pairCodeHash;\\n\\n modifier ensure(uint256 deadline) {\\n require(deadline >= block.timestamp, \\\"Router: EXPIRED\\\");\\n _;\\n }\\n\\n constructor(address _factory, address _weth) {\\n factory = _factory;\\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\\n weth = IWETH(_weth);\\n }\\n\\n receive() external payable {\\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\\n }\\n\\n function sortTokens(address tokenA, address tokenB)\\n public\\n pure\\n returns (address token0, address token1)\\n {\\n require(tokenA != tokenB, \\\"Router: IDENTICAL_ADDRESSES\\\");\\n (token0, token1) = tokenA < tokenB\\n ? (tokenA, tokenB)\\n : (tokenB, tokenA);\\n require(token0 != address(0), \\\"Router: ZERO_ADDRESS\\\");\\n }\\n\\n // calculates the CREATE2 address for a pair without making any external calls\\n function pairFor(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (address pair) {\\n (address token0, address token1) = sortTokens(tokenA, tokenB);\\n pair = address(\\n uint160(\\n uint256(\\n keccak256(\\n abi.encodePacked(\\n hex\\\"ff\\\",\\n factory,\\n keccak256(abi.encodePacked(token0, token1, stable)),\\n pairCodeHash // init code hash\\n )\\n )\\n )\\n )\\n );\\n }\\n\\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\\n function quoteLiquidity(\\n uint256 amountA,\\n uint256 reserveA,\\n uint256 reserveB\\n ) internal pure returns (uint256 amountB) {\\n require(amountA > 0, \\\"Router: INSUFFICIENT_AMOUNT\\\");\\n require(reserveA > 0 && reserveB > 0, \\\"Router: INSUFFICIENT_LIQUIDITY\\\");\\n amountB = (amountA * reserveB) / reserveA;\\n }\\n\\n // fetches and sorts the reserves for a pair\\n function getReserves(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (uint256 reserveA, uint256 reserveB) {\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (uint256 reserve0, uint256 reserve1, ) = IPair(\\n pairFor(tokenA, tokenB, stable)\\n ).getReserves();\\n (reserveA, reserveB) = tokenA == token0\\n ? (reserve0, reserve1)\\n : (reserve1, reserve0);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n address tokenOut\\n ) external view returns (uint256 amount, bool stable) {\\n address pair = pairFor(tokenIn, tokenOut, true);\\n uint256 amountStable;\\n uint256 amountVolatile;\\n if (IPairFactory(factory).isPair(pair)) {\\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n pair = pairFor(tokenIn, tokenOut, false);\\n if (IPairFactory(factory).isPair(pair)) {\\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n return\\n amountStable > amountVolatile\\n ? (amountStable, true)\\n : (amountVolatile, false);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountsOut(uint256 amountIn, route[] memory routes)\\n public\\n view\\n returns (uint256[] memory amounts)\\n {\\n require(routes.length >= 1, \\\"Router: INVALID_PATH\\\");\\n amounts = new uint256[](routes.length + 1);\\n amounts[0] = amountIn;\\n for (uint256 i = 0; i < routes.length; i++) {\\n address pair = pairFor(\\n routes[i].from,\\n routes[i].to,\\n routes[i].stable\\n );\\n if (IPairFactory(factory).isPair(pair)) {\\n amounts[i + 1] = IPair(pair).getAmountOut(\\n amounts[i],\\n routes[i].from\\n );\\n }\\n }\\n }\\n\\n function isPair(address pair) external view returns (bool) {\\n return IPairFactory(factory).isPair(pair);\\n }\\n\\n function quoteAddLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired\\n )\\n external\\n view\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n (uint256 reserveA, uint256 reserveB) = (0, 0);\\n uint256 _totalSupply = 0;\\n if (_pair != address(0)) {\\n _totalSupply = IERC20(_pair).totalSupply();\\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\\n }\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n }\\n }\\n }\\n\\n function quoteRemoveLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity\\n ) external view returns (uint256 amountA, uint256 amountB) {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n\\n if (_pair == address(0)) {\\n return (0, 0);\\n }\\n\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n uint256 _totalSupply = IERC20(_pair).totalSupply();\\n\\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\\n }\\n\\n function _addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin\\n ) internal returns (uint256 amountA, uint256 amountB) {\\n require(amountADesired >= amountAMin);\\n require(amountBDesired >= amountBMin);\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n if (_pair == address(0)) {\\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\\n }\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n require(\\n amountBOptimal >= amountBMin,\\n \\\"Router: INSUFFICIENT_B_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n assert(amountAOptimal <= amountADesired);\\n require(\\n amountAOptimal >= amountAMin,\\n \\\"Router: INSUFFICIENT_A_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n }\\n }\\n }\\n\\n function addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n ensure(deadline)\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n (amountA, amountB) = _addLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n amountADesired,\\n amountBDesired,\\n amountAMin,\\n amountBMin\\n );\\n address pair = pairFor(tokenA, tokenB, stable);\\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\\n liquidity = IPair(pair).mint(to);\\n }\\n\\n function addLiquidityETH(\\n address token,\\n bool stable,\\n uint256 amountTokenDesired,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n payable\\n ensure(deadline)\\n returns (\\n uint256 amountToken,\\n uint256 amountETH,\\n uint256 liquidity\\n )\\n {\\n (amountToken, amountETH) = _addLiquidity(\\n token,\\n address(weth),\\n stable,\\n amountTokenDesired,\\n msg.value,\\n amountTokenMin,\\n amountETHMin\\n );\\n address pair = pairFor(token, address(weth), stable);\\n _safeTransferFrom(token, msg.sender, pair, amountToken);\\n weth.deposit{value: amountETH}();\\n assert(weth.transfer(pair, amountETH));\\n liquidity = IPair(pair).mint(to);\\n // refund dust eth, if any\\n if (msg.value > amountETH)\\n _safeTransferETH(msg.sender, msg.value - amountETH);\\n }\\n\\n // **** REMOVE LIQUIDITY ****\\n function removeLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (amountA, amountB) = tokenA == token0\\n ? (amount0, amount1)\\n : (amount1, amount0);\\n require(amountA >= amountAMin, \\\"Router: INSUFFICIENT_A_AMOUNT\\\");\\n require(amountB >= amountBMin, \\\"Router: INSUFFICIENT_B_AMOUNT\\\");\\n }\\n\\n function removeLiquidityETH(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\\n (amountToken, amountETH) = removeLiquidity(\\n token,\\n address(weth),\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n address(this),\\n deadline\\n );\\n _safeTransfer(token, to, amountToken);\\n weth.withdraw(amountETH);\\n _safeTransferETH(to, amountETH);\\n }\\n\\n function removeLiquidityWithPermit(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n {\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(\\n msg.sender,\\n address(this),\\n value,\\n deadline,\\n v,\\n r,\\n s\\n );\\n }\\n\\n (amountA, amountB) = removeLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n liquidity,\\n amountAMin,\\n amountBMin,\\n to,\\n deadline\\n );\\n }\\n\\n function removeLiquidityETHWithPermit(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountToken, uint256 amountETH) {\\n address pair = pairFor(token, address(weth), stable);\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\\n (amountToken, amountETH) = removeLiquidityETH(\\n token,\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n to,\\n deadline\\n );\\n }\\n\\n // **** SWAP ****\\n // requires the initial amount to have already been sent to the first pair\\n function _swap(\\n uint256[] memory amounts,\\n route[] memory routes,\\n address _to\\n ) internal virtual {\\n for (uint256 i = 0; i < routes.length; i++) {\\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\\n uint256 amountOut = amounts[i + 1];\\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\\n ? (uint256(0), amountOut)\\n : (amountOut, uint256(0));\\n address to = i < routes.length - 1\\n ? pairFor(\\n routes[i + 1].from,\\n routes[i + 1].to,\\n routes[i + 1].stable\\n )\\n : _to;\\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\\n amount0Out,\\n amount1Out,\\n to,\\n new bytes(0)\\n );\\n }\\n }\\n\\n function swapExactTokensForTokensSimple(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n address tokenFrom,\\n address tokenTo,\\n bool stable,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n route[] memory routes = new route[](1);\\n routes[0].from = tokenFrom;\\n routes[0].to = tokenTo;\\n routes[0].stable = stable;\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForTokens(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactETHForTokens(\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\\n require(routes[0].from == address(weth), \\\"Router: INVALID_PATH\\\");\\n amounts = getAmountsOut(msg.value, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n weth.deposit{value: amounts[0]}();\\n assert(\\n weth.transfer(\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n )\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForETH(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n require(\\n routes[routes.length - 1].to == address(weth),\\n \\\"Router: INVALID_PATH\\\"\\n );\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, address(this));\\n weth.withdraw(amounts[amounts.length - 1]);\\n _safeTransferETH(to, amounts[amounts.length - 1]);\\n }\\n\\n function UNSAFE_swapExactTokensForTokens(\\n uint256[] memory amounts,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory) {\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n return amounts;\\n }\\n\\n function _safeTransferETH(address to, uint256 value) internal {\\n (bool success, ) = to.call{value: value}(new bytes(0));\\n require(success, \\\"TransferHelper: ETH_TRANSFER_FAILED\\\");\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x3d84c846129d645eec66c37a493bb7fb401a2524497f450eaced155088305ead\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"},\"contracts/interfaces/IWETH.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n function transfer(address to, uint256 value) external returns (bool);\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0x20ad0b3a319a36e3430f0d8512ee3755de8f85a80effe78d06f333f5326ee3d7\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x60e06040523480156200001157600080fd5b50604051620039bc380380620039bc8339810160408190526200003491620000d8565b6001600160a01b038216608081905260408051631355724960e31b81529051639aab9248916004808201926020929091908290030181865afa1580156200007f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000a5919062000110565b60c0526001600160a01b031660a052506200012a565b80516001600160a01b0381168114620000d357600080fd5b919050565b60008060408385031215620000ec57600080fd5b620000f783620000bb565b91506200010760208401620000bb565b90509250929050565b6000602082840312156200012357600080fd5b5051919050565b60805160a05160c0516137c8620001f46000396000610ef901526000818161013e0152818161020b0152818161091901528181610b5801528181610da901528181611470015281816115830152818161161101528181611de901528181611e1f01528181611e5401528181611ee901528181612028015261207801526000818161042d01528181610c3e01528181610ebe015281816111770152818161128b0152818161199601528181611b0a01528181612115015281816126ff01526127a001526137c86000f3fe60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea26469706673582212207f76fe8e2aef1f06aeeb37f313c0f0f346548f28b5ac3c1f1e24c72c7e4bab4764736f6c634300080d0033", - "deployedBytecode": "0x60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea26469706673582212207f76fe8e2aef1f06aeeb37f313c0f0f346548f28b5ac3c1f1e24c72c7e4bab4764736f6c634300080d0033", + "numDeployments": 5, + "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_weth\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"UNSAFE_swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"}],\"name\":\"getAmountsOut\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reserveA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"pairFor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"}],\"name\":\"quoteAddLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"name\":\"quoteRemoveLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityETHWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"}],\"name\":\"sortTokens\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactETHForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForETH\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenFrom\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenTo\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokensSimple\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weth\",\"outputs\":[{\"internalType\":\"contract IWETH\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Router.sol\":\"Router\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Router.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairFactory.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\nimport \\\"contracts/interfaces/IWETH.sol\\\";\\n\\ncontract Router is IRouter {\\n struct route {\\n address from;\\n address to;\\n bool stable;\\n }\\n\\n address public immutable factory;\\n IWETH public immutable weth;\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n bytes32 immutable pairCodeHash;\\n\\n modifier ensure(uint256 deadline) {\\n require(deadline >= block.timestamp, \\\"Router: EXPIRED\\\");\\n _;\\n }\\n\\n constructor(address _factory, address _weth) {\\n factory = _factory;\\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\\n weth = IWETH(_weth);\\n }\\n\\n receive() external payable {\\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\\n }\\n\\n function sortTokens(address tokenA, address tokenB)\\n public\\n pure\\n returns (address token0, address token1)\\n {\\n require(tokenA != tokenB, \\\"Router: IDENTICAL_ADDRESSES\\\");\\n (token0, token1) = tokenA < tokenB\\n ? (tokenA, tokenB)\\n : (tokenB, tokenA);\\n require(token0 != address(0), \\\"Router: ZERO_ADDRESS\\\");\\n }\\n\\n // calculates the CREATE2 address for a pair without making any external calls\\n function pairFor(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (address pair) {\\n (address token0, address token1) = sortTokens(tokenA, tokenB);\\n pair = address(\\n uint160(\\n uint256(\\n keccak256(\\n abi.encodePacked(\\n hex\\\"ff\\\",\\n factory,\\n keccak256(abi.encodePacked(token0, token1, stable)),\\n pairCodeHash // init code hash\\n )\\n )\\n )\\n )\\n );\\n }\\n\\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\\n function quoteLiquidity(\\n uint256 amountA,\\n uint256 reserveA,\\n uint256 reserveB\\n ) internal pure returns (uint256 amountB) {\\n require(amountA > 0, \\\"Router: INSUFFICIENT_AMOUNT\\\");\\n require(reserveA > 0 && reserveB > 0, \\\"Router: INSUFFICIENT_LIQUIDITY\\\");\\n amountB = (amountA * reserveB) / reserveA;\\n }\\n\\n // fetches and sorts the reserves for a pair\\n function getReserves(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (uint256 reserveA, uint256 reserveB) {\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (uint256 reserve0, uint256 reserve1, ) = IPair(\\n pairFor(tokenA, tokenB, stable)\\n ).getReserves();\\n (reserveA, reserveB) = tokenA == token0\\n ? (reserve0, reserve1)\\n : (reserve1, reserve0);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n address tokenOut\\n ) external view returns (uint256 amount, bool stable) {\\n address pair = pairFor(tokenIn, tokenOut, true);\\n uint256 amountStable;\\n uint256 amountVolatile;\\n if (IPairFactory(factory).isPair(pair)) {\\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n pair = pairFor(tokenIn, tokenOut, false);\\n if (IPairFactory(factory).isPair(pair)) {\\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n return\\n amountStable > amountVolatile\\n ? (amountStable, true)\\n : (amountVolatile, false);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountsOut(uint256 amountIn, route[] memory routes)\\n public\\n view\\n returns (uint256[] memory amounts)\\n {\\n require(routes.length >= 1, \\\"Router: INVALID_PATH\\\");\\n amounts = new uint256[](routes.length + 1);\\n amounts[0] = amountIn;\\n for (uint256 i = 0; i < routes.length; i++) {\\n address pair = pairFor(\\n routes[i].from,\\n routes[i].to,\\n routes[i].stable\\n );\\n if (IPairFactory(factory).isPair(pair)) {\\n amounts[i + 1] = IPair(pair).getAmountOut(\\n amounts[i],\\n routes[i].from\\n );\\n }\\n }\\n }\\n\\n function isPair(address pair) external view returns (bool) {\\n return IPairFactory(factory).isPair(pair);\\n }\\n\\n function quoteAddLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired\\n )\\n external\\n view\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n (uint256 reserveA, uint256 reserveB) = (0, 0);\\n uint256 _totalSupply = 0;\\n if (_pair != address(0)) {\\n _totalSupply = IERC20(_pair).totalSupply();\\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\\n }\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n }\\n }\\n }\\n\\n function quoteRemoveLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity\\n ) external view returns (uint256 amountA, uint256 amountB) {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n\\n if (_pair == address(0)) {\\n return (0, 0);\\n }\\n\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n uint256 _totalSupply = IERC20(_pair).totalSupply();\\n\\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\\n }\\n\\n function _addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin\\n ) internal returns (uint256 amountA, uint256 amountB) {\\n require(amountADesired >= amountAMin);\\n require(amountBDesired >= amountBMin);\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n if (_pair == address(0)) {\\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\\n }\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n require(\\n amountBOptimal >= amountBMin,\\n \\\"Router: INSUFFICIENT_B_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n assert(amountAOptimal <= amountADesired);\\n require(\\n amountAOptimal >= amountAMin,\\n \\\"Router: INSUFFICIENT_A_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n }\\n }\\n }\\n\\n function addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n ensure(deadline)\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n (amountA, amountB) = _addLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n amountADesired,\\n amountBDesired,\\n amountAMin,\\n amountBMin\\n );\\n address pair = pairFor(tokenA, tokenB, stable);\\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\\n liquidity = IPair(pair).mint(to);\\n }\\n\\n function addLiquidityETH(\\n address token,\\n bool stable,\\n uint256 amountTokenDesired,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n payable\\n ensure(deadline)\\n returns (\\n uint256 amountToken,\\n uint256 amountETH,\\n uint256 liquidity\\n )\\n {\\n (amountToken, amountETH) = _addLiquidity(\\n token,\\n address(weth),\\n stable,\\n amountTokenDesired,\\n msg.value,\\n amountTokenMin,\\n amountETHMin\\n );\\n address pair = pairFor(token, address(weth), stable);\\n _safeTransferFrom(token, msg.sender, pair, amountToken);\\n weth.deposit{value: amountETH}();\\n assert(weth.transfer(pair, amountETH));\\n liquidity = IPair(pair).mint(to);\\n // refund dust eth, if any\\n if (msg.value > amountETH)\\n _safeTransferETH(msg.sender, msg.value - amountETH);\\n }\\n\\n // **** REMOVE LIQUIDITY ****\\n function removeLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (amountA, amountB) = tokenA == token0\\n ? (amount0, amount1)\\n : (amount1, amount0);\\n require(amountA >= amountAMin, \\\"Router: INSUFFICIENT_A_AMOUNT\\\");\\n require(amountB >= amountBMin, \\\"Router: INSUFFICIENT_B_AMOUNT\\\");\\n }\\n\\n function removeLiquidityETH(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\\n (amountToken, amountETH) = removeLiquidity(\\n token,\\n address(weth),\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n address(this),\\n deadline\\n );\\n _safeTransfer(token, to, amountToken);\\n weth.withdraw(amountETH);\\n _safeTransferETH(to, amountETH);\\n }\\n\\n function removeLiquidityWithPermit(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n {\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(\\n msg.sender,\\n address(this),\\n value,\\n deadline,\\n v,\\n r,\\n s\\n );\\n }\\n\\n (amountA, amountB) = removeLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n liquidity,\\n amountAMin,\\n amountBMin,\\n to,\\n deadline\\n );\\n }\\n\\n function removeLiquidityETHWithPermit(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountToken, uint256 amountETH) {\\n address pair = pairFor(token, address(weth), stable);\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\\n (amountToken, amountETH) = removeLiquidityETH(\\n token,\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n to,\\n deadline\\n );\\n }\\n\\n // **** SWAP ****\\n // requires the initial amount to have already been sent to the first pair\\n function _swap(\\n uint256[] memory amounts,\\n route[] memory routes,\\n address _to\\n ) internal virtual {\\n for (uint256 i = 0; i < routes.length; i++) {\\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\\n uint256 amountOut = amounts[i + 1];\\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\\n ? (uint256(0), amountOut)\\n : (amountOut, uint256(0));\\n address to = i < routes.length - 1\\n ? pairFor(\\n routes[i + 1].from,\\n routes[i + 1].to,\\n routes[i + 1].stable\\n )\\n : _to;\\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\\n amount0Out,\\n amount1Out,\\n to,\\n new bytes(0)\\n );\\n }\\n }\\n\\n function swapExactTokensForTokensSimple(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n address tokenFrom,\\n address tokenTo,\\n bool stable,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n route[] memory routes = new route[](1);\\n routes[0].from = tokenFrom;\\n routes[0].to = tokenTo;\\n routes[0].stable = stable;\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForTokens(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactETHForTokens(\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\\n require(routes[0].from == address(weth), \\\"Router: INVALID_PATH\\\");\\n amounts = getAmountsOut(msg.value, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n weth.deposit{value: amounts[0]}();\\n assert(\\n weth.transfer(\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n )\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForETH(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n require(\\n routes[routes.length - 1].to == address(weth),\\n \\\"Router: INVALID_PATH\\\"\\n );\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, address(this));\\n weth.withdraw(amounts[amounts.length - 1]);\\n _safeTransferETH(to, amounts[amounts.length - 1]);\\n }\\n\\n function UNSAFE_swapExactTokensForTokens(\\n uint256[] memory amounts,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory) {\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n return amounts;\\n }\\n\\n function _safeTransferETH(address to, uint256 value) internal {\\n (bool success, ) = to.call{value: value}(new bytes(0));\\n require(success, \\\"TransferHelper: ETH_TRANSFER_FAILED\\\");\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x3d84c846129d645eec66c37a493bb7fb401a2524497f450eaced155088305ead\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"},\"contracts/interfaces/IWETH.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n function transfer(address to, uint256 value) external returns (bool);\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0x20ad0b3a319a36e3430f0d8512ee3755de8f85a80effe78d06f333f5326ee3d7\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x60e06040523480156200001157600080fd5b50604051620039bc380380620039bc8339810160408190526200003491620000d8565b6001600160a01b038216608081905260408051631355724960e31b81529051639aab9248916004808201926020929091908290030181865afa1580156200007f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000a5919062000110565b60c0526001600160a01b031660a052506200012a565b80516001600160a01b0381168114620000d357600080fd5b919050565b60008060408385031215620000ec57600080fd5b620000f783620000bb565b91506200010760208401620000bb565b90509250929050565b6000602082840312156200012357600080fd5b5051919050565b60805160a05160c0516137c8620001f46000396000610ef901526000818161013e0152818161020b0152818161091901528181610b5801528181610da901528181611470015281816115830152818161161101528181611de901528181611e1f01528181611e5401528181611ee901528181612028015261207801526000818161042d01528181610c3e01528181610ebe015281816111770152818161128b0152818161199601528181611b0a01528181612115015281816126ff01526127a001526137c86000f3fe60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea2646970667358221220409357aa500e4ad5c5df258cdff4526c8b9ff8fedf890227a8ca1c5c4c6ea9d964736f6c634300080d0033", + "deployedBytecode": "0x60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea2646970667358221220409357aa500e4ad5c5df258cdff4526c8b9ff8fedf890227a8ca1c5c4c6ea9d964736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/VeArtProxy.json b/deployments/arbitrumGoerli/VeArtProxy.json index 52e58bed..27792c1c 100644 --- a/deployments/arbitrumGoerli/VeArtProxy.json +++ b/deployments/arbitrumGoerli/VeArtProxy.json @@ -1,5 +1,5 @@ { - "address": "0xDe032908A79276B257d1ae80f0C0A2c070eDa1F4", + "address": "0xfC27470547FA0b96D19146C0490cc444a18A71a9", "abi": [ { "inputs": [ @@ -36,28 +36,28 @@ "type": "function" } ], - "transactionHash": "0xab177b1c3f70b542f397bafe504efd889bd5359783e389177712edeedef956a9", + "transactionHash": "0xcc3e7c5e17dc740d5fcfc82647d4216ced66ebd4bde18bfe153d6e2cb4359c39", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xDe032908A79276B257d1ae80f0C0A2c070eDa1F4", + "contractAddress": "0xfC27470547FA0b96D19146C0490cc444a18A71a9", "transactionIndex": 1, - "gasUsed": "615440", + "gasUsed": "615428", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xf86a5efdf9931e00138c17d04166a3294ec57a48e574d95f13403048937ea8f0", - "transactionHash": "0xab177b1c3f70b542f397bafe504efd889bd5359783e389177712edeedef956a9", + "blockHash": "0x3347a930d9e57684ba326a35e06d296d30ed8ad1e9e06f99505184d5d7f24ed2", + "transactionHash": "0xcc3e7c5e17dc740d5fcfc82647d4216ced66ebd4bde18bfe153d6e2cb4359c39", "logs": [], - "blockNumber": 5716723, - "cumulativeGasUsed": "615440", + "blockNumber": 5814426, + "cumulativeGasUsed": "615428", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 3, - "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_locked_end\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"_tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"output\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VeArtProxy.sol\":\"VeArtProxy\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\nimport {Base64} from \\\"contracts/libraries/Base64.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\n\\ncontract VeArtProxy is IVeArtProxy {\\n function toString(uint value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT license\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint temp = value;\\n uint digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\\n output = '';\\n output = string(abi.encodePacked(output, \\\"token \\\", toString(_tokenId), ''));\\n output = string(abi.encodePacked(output, \\\"balanceOf \\\", toString(_balanceOf), ''));\\n output = string(abi.encodePacked(output, \\\"locked_end \\\", toString(_locked_end), ''));\\n output = string(abi.encodePacked(output, \\\"value \\\", toString(_value), ''));\\n\\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\\\"name\\\": \\\"lock #', toString(_tokenId), '\\\", \\\"description\\\": \\\"Velocimeter locks, can be used to boost gauge yields, vote on token emission, and receive bribes\\\", \\\"image\\\": \\\"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\\\"}'))));\\n output = string(abi.encodePacked('data:application/json;base64,', json));\\n }\\n}\\n\",\"keccak256\":\"0xc526ae7232c93412d664837d1171f1bf5d231a4ea33bcc7a8d0b4e3fa6a9e227\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/libraries/Base64.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n/// [MIT License]\\n/// @title Base64\\n/// @notice Provides a function for encoding some bytes in base64\\n/// @author Brecht Devos \\nlibrary Base64 {\\n bytes internal constant TABLE = \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\";\\n\\n /// @notice Encodes some bytes to the base64 representation\\n function encode(bytes memory data) internal pure returns (string memory) {\\n uint len = data.length;\\n if (len == 0) return \\\"\\\";\\n\\n // multiply by 4/3 rounded up\\n uint encodedLen = 4 * ((len + 2) / 3);\\n\\n // Add some extra buffer at the end\\n bytes memory result = new bytes(encodedLen + 32);\\n\\n bytes memory table = TABLE;\\n\\n assembly {\\n let tablePtr := add(table, 1)\\n let resultPtr := add(result, 32)\\n\\n for {\\n let i := 0\\n } lt(i, len) {\\n\\n } {\\n i := add(i, 3)\\n let input := and(mload(add(data, i)), 0xffffff)\\n\\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\\n out := shl(224, out)\\n\\n mstore(resultPtr, out)\\n\\n resultPtr := add(resultPtr, 4)\\n }\\n\\n switch mod(len, 3)\\n case 1 {\\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\\n }\\n case 2 {\\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\\n }\\n\\n mstore(result, encodedLen)\\n }\\n\\n return string(result);\\n }\\n}\\n\",\"keccak256\":\"0x55535e1e0a14bbac370fe5f25df23aa88c678b915af53517672130f9a54f7e3e\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50610a2b806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f63696d65746572206c6010918401918201527f6f636b732c2063616e206265207573656420746f20626f6f737420676175676560308201527f207969656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c60508201527f20616e64207265636569766520627269626573222c2022696d616765223a202260708201527f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000609082015283516107718160aa840160208801610435565b61227d60f01b60aa929091019182015260ac01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa264697066735822122060ab03393b15ef9eba3bfe6f65af595952a170fe24d2e6f613a8448a0eb4d69364736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f63696d65746572206c6010918401918201527f6f636b732c2063616e206265207573656420746f20626f6f737420676175676560308201527f207969656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c60508201527f20616e64207265636569766520627269626573222c2022696d616765223a202260708201527f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000609082015283516107718160aa840160208801610435565b61227d60f01b60aa929091019182015260ac01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa264697066735822122060ab03393b15ef9eba3bfe6f65af595952a170fe24d2e6f613a8448a0eb4d69364736f6c634300080d0033", + "numDeployments": 5, + "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_locked_end\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"_tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"output\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VeArtProxy.sol\":\"VeArtProxy\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\nimport {Base64} from \\\"contracts/libraries/Base64.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\n\\ncontract VeArtProxy is IVeArtProxy {\\n function toString(uint value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT license\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint temp = value;\\n uint digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\\n output = '';\\n output = string(abi.encodePacked(output, \\\"token \\\", toString(_tokenId), ''));\\n output = string(abi.encodePacked(output, \\\"balanceOf \\\", toString(_balanceOf), ''));\\n output = string(abi.encodePacked(output, \\\"locked_end \\\", toString(_locked_end), ''));\\n output = string(abi.encodePacked(output, \\\"value \\\", toString(_value), ''));\\n\\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\\\"name\\\": \\\"lock #', toString(_tokenId), '\\\", \\\"description\\\": \\\"Velocimeter locks, can be used to boost gauge yields, vote on token emission, and receive bribes\\\", \\\"image\\\": \\\"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\\\"}'))));\\n output = string(abi.encodePacked('data:application/json;base64,', json));\\n }\\n}\\n\",\"keccak256\":\"0xc526ae7232c93412d664837d1171f1bf5d231a4ea33bcc7a8d0b4e3fa6a9e227\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/libraries/Base64.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n/// [MIT License]\\n/// @title Base64\\n/// @notice Provides a function for encoding some bytes in base64\\n/// @author Brecht Devos \\nlibrary Base64 {\\n bytes internal constant TABLE = \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\";\\n\\n /// @notice Encodes some bytes to the base64 representation\\n function encode(bytes memory data) internal pure returns (string memory) {\\n uint len = data.length;\\n if (len == 0) return \\\"\\\";\\n\\n // multiply by 4/3 rounded up\\n uint encodedLen = 4 * ((len + 2) / 3);\\n\\n // Add some extra buffer at the end\\n bytes memory result = new bytes(encodedLen + 32);\\n\\n bytes memory table = TABLE;\\n\\n assembly {\\n let tablePtr := add(table, 1)\\n let resultPtr := add(result, 32)\\n\\n for {\\n let i := 0\\n } lt(i, len) {\\n\\n } {\\n i := add(i, 3)\\n let input := and(mload(add(data, i)), 0xffffff)\\n\\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\\n out := shl(224, out)\\n\\n mstore(resultPtr, out)\\n\\n resultPtr := add(resultPtr, 4)\\n }\\n\\n switch mod(len, 3)\\n case 1 {\\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\\n }\\n case 2 {\\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\\n }\\n\\n mstore(result, encodedLen)\\n }\\n\\n return string(result);\\n }\\n}\\n\",\"keccak256\":\"0x55535e1e0a14bbac370fe5f25df23aa88c678b915af53517672130f9a54f7e3e\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610a2b806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f63696d65746572206c6010918401918201527f6f636b732c2063616e206265207573656420746f20626f6f737420676175676560308201527f207969656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c60508201527f20616e64207265636569766520627269626573222c2022696d616765223a202260708201527f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000609082015283516107718160aa840160208801610435565b61227d60f01b60aa929091019182015260ac01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220d32850b2e04daace866129af9d711d9b5045829d473d001adcabace3bd6d30c764736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f63696d65746572206c6010918401918201527f6f636b732c2063616e206265207573656420746f20626f6f737420676175676560308201527f207969656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c60508201527f20616e64207265636569766520627269626573222c2022696d616765223a202260708201527f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000609082015283516107718160aa840160208801610435565b61227d60f01b60aa929091019182015260ac01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220d32850b2e04daace866129af9d711d9b5045829d473d001adcabace3bd6d30c764736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/VeloGovernor.json b/deployments/arbitrumGoerli/VeloGovernor.json index a147e7e6..3fe08805 100644 --- a/deployments/arbitrumGoerli/VeloGovernor.json +++ b/deployments/arbitrumGoerli/VeloGovernor.json @@ -1,5 +1,5 @@ { - "address": "0xB843444d08bee4f79f571Bd34D13Ec71D4194b40", + "address": "0x02b7Ed5Bb16ed471C281ab2E34CC41f94aF53651", "abi": [ { "inputs": [ @@ -1055,43 +1055,43 @@ "type": "receive" } ], - "transactionHash": "0x374952c327cc474cb69c07f492ddeac4cd2ccac618e6fe1b132e7c295c1d8513", + "transactionHash": "0x0a1bdcff96c4c1b114f8350524da9927872c969605440d290bd00cb57718a144", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xB843444d08bee4f79f571Bd34D13Ec71D4194b40", + "contractAddress": "0x02b7Ed5Bb16ed471C281ab2E34CC41f94aF53651", "transactionIndex": 1, "gasUsed": "2742890", - "logsBloom": "0x00000000000000000100000000001000040000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000080000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xbda9204981d328ee926ac35a2c718d8177974cd4bd8a94c4e2acc571cc1c6c11", - "transactionHash": "0x374952c327cc474cb69c07f492ddeac4cd2ccac618e6fe1b132e7c295c1d8513", + "logsBloom": "0x00000000000000000100000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000008000000000000000000000000000000000000000000000000000000000000020000000080000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x5c6dc00c3df8bf4a0f368dad2c1a298cae0fe0376a719f184449114d2d1c80e1", + "transactionHash": "0x0a1bdcff96c4c1b114f8350524da9927872c969605440d290bd00cb57718a144", "logs": [ { "transactionIndex": 1, - "blockNumber": 5716742, - "transactionHash": "0x374952c327cc474cb69c07f492ddeac4cd2ccac618e6fe1b132e7c295c1d8513", - "address": "0xB843444d08bee4f79f571Bd34D13Ec71D4194b40", + "blockNumber": 5814091, + "transactionHash": "0x0a1bdcff96c4c1b114f8350524da9927872c969605440d290bd00cb57718a144", + "address": "0x02b7Ed5Bb16ed471C281ab2E34CC41f94aF53651", "topics": [ "0x0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997" ], "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004", "logIndex": 0, - "blockHash": "0xbda9204981d328ee926ac35a2c718d8177974cd4bd8a94c4e2acc571cc1c6c11" + "blockHash": "0x5c6dc00c3df8bf4a0f368dad2c1a298cae0fe0376a719f184449114d2d1c80e1" } ], - "blockNumber": 5716742, + "blockNumber": 5814091, "cumulativeGasUsed": "2742890", "status": 1, "byzantium": true }, "args": [ - "0xC43f6EbF97f9D99FF8a3aFe1413599e8DEc2aDB3" + "0x5EfA4BBD5BcF5D113683512483c71D37Af61942F" ], - "numDeployments": 3, - "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"_ve\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"Empty\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"proposer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"string[]\",\"name\":\"signatures\",\"type\":\"string[]\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"ProposalCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldQuorumNumerator\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"QuorumNumeratorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"VoteCast\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"VoteCastWithParams\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"COUNTING_MODE\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EXTENDED_BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_PROPOSAL_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROPOSAL_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"}],\"name\":\"castVote\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"castVoteWithReason\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"castVoteWithReasonAndParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteWithReasonAndParamsBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"execute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"getVotesWithParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasVoted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"hashProposal\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalDeadline\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalSnapshot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"againstVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"forVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"abstainVotes\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"propose\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"quorum\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumDenominator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"}],\"name\":\"setProposalNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTeam\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"state\",\"outputs\":[{\"internalType\":\"enum IGovernor.ProposalState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"updateQuorumNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"Empty()\":[{\"details\":\"An operation (e.g. {front}) couldn't be completed due to the queue being empty.\"}]},\"kind\":\"dev\",\"methods\":{\"COUNTING_MODE()\":{\"details\":\"See {IGovernor-COUNTING_MODE}.\"},\"castVote(uint256,uint8)\":{\"details\":\"See {IGovernor-castVote}.\"},\"castVoteBySig(uint256,uint8,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteBySig}.\"},\"castVoteWithReason(uint256,uint8,string)\":{\"details\":\"See {IGovernor-castVoteWithReason}.\"},\"castVoteWithReasonAndParams(uint256,uint8,string,bytes)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParams}.\"},\"castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParamsBySig}.\"},\"execute(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-execute}.\"},\"getVotes(address,uint256)\":{\"details\":\"See {IGovernor-getVotes}.\"},\"getVotesWithParams(address,uint256,bytes)\":{\"details\":\"See {IGovernor-getVotesWithParams}.\"},\"hasVoted(uint256,address)\":{\"details\":\"See {IGovernor-hasVoted}.\"},\"hashProposal(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-hashProposal}. The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in advance, before the proposal is submitted. Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the same proposal (with same operation and same description) will have the same id if submitted on multiple governors across multiple networks. This also means that in order to execute the same operation twice (on the same governor) the proposer will have to change the description in order to avoid proposal id conflicts.\"},\"name()\":{\"details\":\"See {IGovernor-name}.\"},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155BatchReceived}.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155Received}.\"},\"onERC721Received(address,address,uint256,bytes)\":{\"details\":\"See {IERC721Receiver-onERC721Received}.\"},\"proposalDeadline(uint256)\":{\"details\":\"See {IGovernor-proposalDeadline}.\"},\"proposalSnapshot(uint256)\":{\"details\":\"See {IGovernor-proposalSnapshot}.\"},\"proposalThreshold()\":{\"details\":\"Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\"},\"proposalVotes(uint256)\":{\"details\":\"Accessor to the internal vote counts.\"},\"propose(address[],uint256[],bytes[],string)\":{\"details\":\"See {IGovernor-propose}.\"},\"quorum(uint256)\":{\"details\":\"Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\"},\"quorumDenominator()\":{\"details\":\"Returns the quorum denominator. Defaults to 100, but may be overridden.\"},\"quorumNumerator()\":{\"details\":\"Returns the current quorum numerator. See {quorumDenominator}.\"},\"relay(address,uint256,bytes)\":{\"details\":\"Relays a transaction or function call to an arbitrary target. In cases where the governance executor is some contract other than the governor itself, like when using a timelock, this function can be invoked in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake. Note that if the executor is simply the governor itself, use of `relay` is redundant.\"},\"state(uint256)\":{\"details\":\"See {IGovernor-state}.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"updateQuorumNumerator(uint256)\":{\"details\":\"Changes the quorum numerator. Emits a {QuorumNumeratorUpdated} event. Requirements: - Must be called through a governance proposal. - New numerator must be smaller or equal to the denominator.\"},\"version()\":{\"details\":\"See {IGovernor-version}.\"},\"votingDelay()\":{\"details\":\"Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\"},\"votingPeriod()\":{\"details\":\"Delay, in number of blocks, between the vote start and vote ends. NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting duration compared to the voting delay.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"votingDelay()\":{\"notice\":\"module:user-config\"},\"votingPeriod()\":{\"notice\":\"module:user-config\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/FlowGovernor.sol\":\"VeloGovernor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/FlowGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IGovernor} from \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\nimport {L2GovernorCountingSimple} from \\\"contracts/governance/L2GovernorCountingSimple.sol\\\";\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\nimport {L2GovernorVotesQuorumFraction} from \\\"contracts/governance/L2GovernorVotesQuorumFraction.sol\\\";\\n\\ncontract VeloGovernor is\\n L2Governor,\\n L2GovernorCountingSimple,\\n L2GovernorVotes,\\n L2GovernorVotesQuorumFraction\\n{\\n address public team;\\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\\n uint256 public proposalNumerator = 2; // start at 0.02%\\n\\n constructor(IVotes _ve)\\n L2Governor(\\\"Velocimeter Governor\\\")\\n L2GovernorVotes(_ve)\\n L2GovernorVotesQuorumFraction(4) // 4%\\n {\\n team = msg.sender;\\n }\\n\\n function votingDelay() public pure override(IGovernor) returns (uint256) {\\n return 15 minutes; // 1 block\\n }\\n\\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\\n return 1 weeks;\\n }\\n\\n function setTeam(address newTeam) external {\\n require(msg.sender == team, \\\"not team\\\");\\n team = newTeam;\\n }\\n\\n function setProposalNumerator(uint256 numerator) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \\\"numerator too high\\\");\\n proposalNumerator = numerator;\\n }\\n\\n function proposalThreshold()\\n public\\n view\\n override(L2Governor)\\n returns (uint256)\\n {\\n return\\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\\n PROPOSAL_DENOMINATOR;\\n }\\n}\\n\",\"keccak256\":\"0x0386aabd5b5db4aee3d584995ec6e3546dbfdcd2c9006c125918bcfd2d496020\",\"license\":\"MIT\"},\"contracts/governance/L2Governor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Address.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Context.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\\n *\\n * @dev Core of the governance system, designed to be extended though various modules.\\n *\\n * This contract is abstract and requires several function to be implemented in various modules:\\n *\\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\\n * - A voting module must implement {_getVotes}\\n * - Additionanly, the {votingPeriod} must also be implemented\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\\n using SafeCast for uint256;\\n using Timers for Timers.Timestamp;\\n\\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\\\"Ballot(uint256 proposalId,uint8 support)\\\");\\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\\n keccak256(\\\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\\\");\\n\\n struct ProposalCore {\\n Timers.Timestamp voteStart;\\n Timers.Timestamp voteEnd;\\n bool executed;\\n bool canceled;\\n }\\n\\n string private _name;\\n\\n mapping(uint256 => ProposalCore) private _proposals;\\n\\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\\n\\n /**\\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\\n * parameter setters in {GovernorSettings} are protected using this modifier.\\n *\\n * The governance executing address may be different from the Governor's own address, for example it could be a\\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\\n * for example, additional timelock proposers are not able to change governance parameters without going through the\\n * governance protocol (since v4.6).\\n */\\n modifier onlyGovernance() {\\n require(_msgSender() == _executor(), \\\"Governor: onlyGovernance\\\");\\n if (_executor() != address(this)) {\\n bytes32 msgDataHash = keccak256(_msgData());\\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\\n while (_governanceCall.popFront() != msgDataHash) {}\\n }\\n _;\\n }\\n\\n /**\\n * @dev Sets the value for {name} and {version}\\n */\\n constructor(string memory name_) EIP712(name_, version()) {\\n _name = name_;\\n }\\n\\n /**\\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\\n */\\n receive() external payable virtual {\\n require(_executor() == address(this));\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\\n // include the castVoteWithReasonAndParams() function as standard\\n return\\n interfaceId ==\\n (type(IGovernor).interfaceId ^\\n this.castVoteWithReasonAndParams.selector ^\\n this.castVoteWithReasonAndParamsBySig.selector ^\\n this.getVotesWithParams.selector) ||\\n interfaceId == type(IGovernor).interfaceId ||\\n interfaceId == type(IERC1155Receiver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IGovernor-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IGovernor-version}.\\n */\\n function version() public view virtual override returns (string memory) {\\n return \\\"1\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hashProposal}.\\n *\\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\\n * advance, before the proposal is submitted.\\n *\\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual override returns (uint256) {\\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\\n }\\n\\n /**\\n * @dev See {IGovernor-state}.\\n */\\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n\\n if (proposal.executed) {\\n return ProposalState.Executed;\\n }\\n\\n if (proposal.canceled) {\\n return ProposalState.Canceled;\\n }\\n\\n uint256 start = proposalSnapshot(proposalId);\\n\\n if (start == 0) {\\n revert(\\\"Governor: unknown proposal id\\\");\\n }\\n\\n if (start >= block.timestamp) {\\n return ProposalState.Pending;\\n }\\n\\n uint256 deadline = proposalDeadline(proposalId);\\n\\n if (deadline >= block.timestamp) {\\n return ProposalState.Active;\\n }\\n\\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\\n return ProposalState.Succeeded;\\n } else {\\n return ProposalState.Defeated;\\n }\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalSnapshot}.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteStart.getDeadline();\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalDeadline}.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteEnd.getDeadline();\\n }\\n\\n /**\\n * @dev Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\\n */\\n function proposalThreshold() public view virtual returns (uint256) {\\n return 0;\\n }\\n\\n /**\\n * @dev Amount of votes already cast passes the threshold limit.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Is the proposal successful or not.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) internal view virtual returns (uint256);\\n\\n /**\\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\\n *\\n * Note: Support is generic and can represent various things depending on the voting system used.\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory params\\n ) internal virtual;\\n\\n /**\\n * @dev Default additional encoded parameters used by castVote methods that don't include them\\n *\\n * Note: Should be overridden by specific implementations to use an appropriate value, the\\n * meaning of the additional params, in the context of that implementation\\n */\\n function _defaultParams() internal view virtual returns (bytes memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-propose}.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual override returns (uint256) {\\n require(\\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\\n \\\"Governor: proposer votes below proposal threshold\\\"\\n );\\n\\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\\n\\n require(targets.length == values.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length == calldatas.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length > 0, \\\"Governor: empty proposal\\\");\\n\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(proposal.voteStart.isUnset(), \\\"Governor: proposal already exists\\\");\\n\\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\\n uint64 deadline = start + votingPeriod().toUint64();\\n\\n proposal.voteStart.setDeadline(start);\\n proposal.voteEnd.setDeadline(deadline);\\n\\n emit ProposalCreated(\\n proposalId,\\n _msgSender(),\\n targets,\\n values,\\n new string[](targets.length),\\n calldatas,\\n start,\\n deadline,\\n description\\n );\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-execute}.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual override returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n\\n ProposalState status = state(proposalId);\\n require(\\n status == ProposalState.Succeeded || status == ProposalState.Queued,\\n \\\"Governor: proposal not successful\\\"\\n );\\n _proposals[proposalId].executed = true;\\n\\n emit ProposalExecuted(proposalId);\\n\\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\\n _execute(proposalId, targets, values, calldatas, descriptionHash);\\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\\n */\\n function _execute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n string memory errorMessage = \\\"Governor: call reverted without message\\\";\\n for (uint256 i = 0; i < targets.length; ++i) {\\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\\n Address.verifyCallResult(success, returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Hook before execution is triggered.\\n */\\n function _beforeExecute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory, /* values */\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n for (uint256 i = 0; i < targets.length; ++i) {\\n if (targets[i] == address(this)) {\\n _governanceCall.pushBack(keccak256(calldatas[i]));\\n }\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook after execution is triggered.\\n */\\n function _afterExecute(\\n uint256, /* proposalId */\\n address[] memory, /* targets */\\n uint256[] memory, /* values */\\n bytes[] memory, /* calldatas */\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n if (!_governanceCall.empty()) {\\n _governanceCall.clear();\\n }\\n }\\n }\\n\\n /**\\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\\n * canceled to allow distinguishing it from executed proposals.\\n *\\n * Emits a {IGovernor-ProposalCanceled} event.\\n */\\n function _cancel(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) internal virtual returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n ProposalState status = state(proposalId);\\n\\n require(\\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\\n \\\"Governor: proposal not active\\\"\\n );\\n _proposals[proposalId].canceled = true;\\n\\n emit ProposalCanceled(proposalId);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotes}.\\n */\\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, _defaultParams());\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotesWithParams}.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVote}.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReason}.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteBySig}.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\\n v,\\n r,\\n s\\n );\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(\\n keccak256(\\n abi.encode(\\n EXTENDED_BALLOT_TYPEHASH,\\n proposalId,\\n support,\\n keccak256(bytes(reason)),\\n keccak256(params)\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason\\n ) internal virtual returns (uint256) {\\n return _castVote(proposalId, account, support, reason, _defaultParams());\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason,\\n bytes memory params\\n ) internal virtual returns (uint256) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(state(proposalId) == ProposalState.Active, \\\"Governor: vote not currently active\\\");\\n\\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\\n _countVote(proposalId, account, support, weight, params);\\n\\n if (params.length == 0) {\\n emit VoteCast(account, proposalId, support, weight, reason);\\n } else {\\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\\n }\\n\\n return weight;\\n }\\n\\n /**\\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\\n */\\n function relay(\\n address target,\\n uint256 value,\\n bytes calldata data\\n ) external virtual onlyGovernance {\\n Address.functionCallWithValue(target, data, value);\\n }\\n\\n /**\\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\\n * through another contract such as a timelock.\\n */\\n function _executor() internal view virtual returns (address) {\\n return address(this);\\n }\\n\\n /**\\n * @dev See {IERC721Receiver-onERC721Received}.\\n */\\n function onERC721Received(\\n address,\\n address,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155Received}.\\n */\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\\n */\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] memory,\\n uint256[] memory,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155BatchReceived.selector;\\n }\\n}\\n\",\"keccak256\":\"0xa2846313b89a871807cdebd0225b0bf8f23b17505ab8b3288549ec54a5a4a71b\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorCountingSimple.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\\n *\\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorCountingSimple is L2Governor {\\n /**\\n * @dev Supported vote types. Matches Governor Bravo ordering.\\n */\\n enum VoteType {\\n Against,\\n For,\\n Abstain\\n }\\n\\n struct ProposalVote {\\n uint256 againstVotes;\\n uint256 forVotes;\\n uint256 abstainVotes;\\n mapping(address => bool) hasVoted;\\n }\\n\\n mapping(uint256 => ProposalVote) private _proposalVotes;\\n\\n /**\\n * @dev See {IGovernor-COUNTING_MODE}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual override returns (string memory) {\\n return \\\"support=bravo&quorum=for,abstain\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hasVoted}.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\\n return _proposalVotes[proposalId].hasVoted[account];\\n }\\n\\n /**\\n * @dev Accessor to the internal vote counts.\\n */\\n function proposalVotes(uint256 proposalId)\\n public\\n view\\n virtual\\n returns (\\n uint256 againstVotes,\\n uint256 forVotes,\\n uint256 abstainVotes\\n )\\n {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\\n }\\n\\n /**\\n * @dev See {Governor-_quorumReached}.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return proposalvote.forVotes > proposalvote.againstVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory // params\\n ) internal virtual override {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n require(!proposalvote.hasVoted[account], \\\"GovernorVotingSimple: vote already cast\\\");\\n proposalvote.hasVoted[account] = true;\\n\\n if (support == uint8(VoteType.Against)) {\\n proposalvote.againstVotes += weight;\\n } else if (support == uint8(VoteType.For)) {\\n proposalvote.forVotes += weight;\\n } else if (support == uint8(VoteType.Abstain)) {\\n proposalvote.abstainVotes += weight;\\n } else {\\n revert(\\\"GovernorVotingSimple: invalid value for enum VoteType\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xdc37daa24118a6e6ba5208b4abefa1632af2ff340135ca6c6d7237f70102d5db\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotes is L2Governor {\\n IVotes public immutable token;\\n\\n constructor(IVotes tokenAddress) {\\n token = tokenAddress;\\n }\\n\\n /**\\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory /*params*/\\n ) internal view virtual override returns (uint256) {\\n return token.getPastVotes(account, blockTimestamp);\\n }\\n}\\n\",\"keccak256\":\"0x605a7de71228dda3cb8fd878cac313a86bc5841fd34d7344214346ba46e63af1\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotesQuorumFraction.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\\n * fraction of the total supply.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\\n uint256 private _quorumNumerator;\\n\\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\\n\\n /**\\n * @dev Initialize quorum as a fraction of the token's total supply.\\n *\\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\\n * customized by overriding {quorumDenominator}.\\n */\\n constructor(uint256 quorumNumeratorValue) {\\n _updateQuorumNumerator(quorumNumeratorValue);\\n }\\n\\n /**\\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\\n */\\n function quorumNumerator() public view virtual returns (uint256) {\\n return _quorumNumerator;\\n }\\n\\n /**\\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\\n */\\n function quorumDenominator() public view virtual returns (uint256) {\\n return 100;\\n }\\n\\n /**\\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\\n */\\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - Must be called through a governance proposal.\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\\n _updateQuorumNumerator(newQuorumNumerator);\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\\n require(\\n newQuorumNumerator <= quorumDenominator(),\\n \\\"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\\\"\\n );\\n\\n uint256 oldQuorumNumerator = _quorumNumerator;\\n _quorumNumerator = newQuorumNumerator;\\n\\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\\n }\\n}\\n\",\"keccak256\":\"0xe66d29c0ffd2274de933d80e11d68891f3acc3f078be4560a2b493b7d88dcb7f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Interface of the {Governor} core.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract IGovernor is IERC165 {\\n enum ProposalState {\\n Pending,\\n Active,\\n Canceled,\\n Defeated,\\n Succeeded,\\n Queued,\\n Expired,\\n Executed\\n }\\n\\n /**\\n * @dev Emitted when a proposal is created.\\n */\\n event ProposalCreated(\\n uint256 proposalId,\\n address proposer,\\n address[] targets,\\n uint256[] values,\\n string[] signatures,\\n bytes[] calldatas,\\n uint256 startBlock,\\n uint256 endBlock,\\n string description\\n );\\n\\n /**\\n * @dev Emitted when a proposal is canceled.\\n */\\n event ProposalCanceled(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a proposal is executed.\\n */\\n event ProposalExecuted(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a vote is cast without params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n */\\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\\n\\n /**\\n * @dev Emitted when a vote is cast with params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\\n */\\n event VoteCastWithParams(\\n address indexed voter,\\n uint256 proposalId,\\n uint8 support,\\n uint256 weight,\\n string reason,\\n bytes params\\n );\\n\\n /**\\n * @notice module:core\\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\\n */\\n function name() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \\\"1\\\"\\n */\\n function version() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:voting\\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\\n *\\n * There are 2 standard keys: `support` and `quorum`.\\n *\\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\\n * - `quorum=bravo` means that only For votes are counted towards quorum.\\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\\n *\\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\\n * name that describes the behavior. For example:\\n *\\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\\n *\\n * NOTE: The string can be decoded by the standard\\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\\n * JavaScript class.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Current state of a proposal, following Compound's convention\\n */\\n function state(uint256 proposalId) public view virtual returns (ProposalState);\\n\\n /**\\n * @notice module:core\\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\\n * beginning of the following block.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\\n * during this block.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\\n */\\n function votingDelay() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of blocks, between the vote start and vote ends.\\n *\\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\\n * duration compared to the voting delay.\\n */\\n function votingPeriod() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Minimum number of cast voted required for a proposal to be successful.\\n *\\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\\n */\\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber`.\\n *\\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\\n * multiple), {ERC20Votes} tokens.\\n */\\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockNumber,\\n bytes memory params\\n ) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:voting\\n * @dev Returns whether `account` has cast a vote on `proposalId`.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\\n\\n /**\\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\\n * {IGovernor-votingPeriod} blocks after the voting starts.\\n *\\n * Emits a {ProposalCreated} event.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\\n * deadline to be reached.\\n *\\n * Emits a {ProposalExecuted} event.\\n *\\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Cast a vote\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xa52d593ff06a2353f78fa149da31f2ca94f03d1eff99bde41977fa2fe985a92f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2e53602b96c1bf97c731ed3e2a981b4f85e23a9410a5ebd36e549a4cc93340dc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x2626d8ab3dfdad0fad630c212ad146d59473d0f48b771784c61a7c1dbbea1f3f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Tooling for timepoints, timers and delays\\n */\\nlibrary Timers {\\n struct Timestamp {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(Timestamp storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(Timestamp memory timer) internal view returns (bool) {\\n return timer._deadline > block.timestamp;\\n }\\n\\n function isExpired(Timestamp memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.timestamp;\\n }\\n\\n struct BlockNumber {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(BlockNumber storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(BlockNumber memory timer) internal view returns (bool) {\\n return timer._deadline > block.number;\\n }\\n\\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.number;\\n }\\n}\\n\",\"keccak256\":\"0x29791a62950a7983e02a673639c1a781d1e448691800456c2ce4b99715391b14\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS,\\n InvalidSignatureV // Deprecated in v4.8\\n }\\n\\n function _throwError(RecoverError error) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert(\\\"ECDSA: invalid signature\\\");\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert(\\\"ECDSA: invalid signature 's' value\\\");\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature` or error string. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\\n if (signature.length == 65) {\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n /// @solidity memory-safe-assembly\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n return tryRecover(hash, v, r, s);\\n } else {\\n return (address(0), RecoverError.InvalidSignatureLength);\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, signature);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n *\\n * _Available since v4.2._\\n */\\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature);\\n }\\n\\n return (signer, RecoverError.NoError);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from `s`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", Strings.toString(s.length), s));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Typed Data, created from a\\n * `domainSeparator` and a `structHash`. This produces hash corresponding\\n * to the one signed with the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\\n * JSON-RPC method as part of EIP-712.\\n *\\n * See {recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n }\\n}\\n\",\"keccak256\":\"0x54ee424bfc83ce63b2a918b9a1efb5090a0fb68dbd1de3b10bc667776885dd4f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ECDSA.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n /* solhint-disable var-name-mixedcase */\\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n // invalidate the cached domain separator if the chain id changes.\\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n uint256 private immutable _CACHED_CHAIN_ID;\\n address private immutable _CACHED_THIS;\\n\\n bytes32 private immutable _HASHED_NAME;\\n bytes32 private immutable _HASHED_VERSION;\\n bytes32 private immutable _TYPE_HASH;\\n\\n /* solhint-enable var-name-mixedcase */\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n constructor(string memory name, string memory version) {\\n bytes32 hashedName = keccak256(bytes(name));\\n bytes32 hashedVersion = keccak256(bytes(version));\\n bytes32 typeHash = keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n );\\n _HASHED_NAME = hashedName;\\n _HASHED_VERSION = hashedVersion;\\n _CACHED_CHAIN_ID = block.chainid;\\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n _CACHED_THIS = address(this);\\n _TYPE_HASH = typeHash;\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\\n return _CACHED_DOMAIN_SEPARATOR;\\n } else {\\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n }\\n }\\n\\n function _buildDomainSeparator(\\n bytes32 typeHash,\\n bytes32 nameHash,\\n bytes32 versionHash\\n ) private view returns (bytes32) {\\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\\n }\\n}\\n\",\"keccak256\":\"0x948d8b2d18f38141ec78c5229d770d950ebc781ed3f44cc9e3ccbb9fded5846a\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\\n\\nimport \\\"./EIP712.sol\\\";\\n\",\"keccak256\":\"0xea30c402170bc240354b74e6c6f6a8e5bdb1935d90d168cc58c0654461c6a72b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3546b156d97633f7f8cad536d5454c81d1d604687c02b2eb105fdc33cb962b41\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\\npragma solidity ^0.8.4;\\n\\nimport \\\"../math/SafeCast.sol\\\";\\n\\n/**\\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\\n * the existing queue contents are left in storage.\\n *\\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\\n * used in storage, and not in memory.\\n * ```\\n * DoubleEndedQueue.Bytes32Deque queue;\\n * ```\\n *\\n * _Available since v4.6._\\n */\\nlibrary DoubleEndedQueue {\\n /**\\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\\n */\\n error Empty();\\n\\n /**\\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\\n */\\n error OutOfBounds();\\n\\n /**\\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\\n *\\n * Struct members have an underscore prefix indicating that they are \\\"private\\\" and should not be read or written to\\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\\n * lead to unexpected behavior.\\n *\\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\\n * data[end - 1].\\n */\\n struct Bytes32Deque {\\n int128 _begin;\\n int128 _end;\\n mapping(int128 => bytes32) _data;\\n }\\n\\n /**\\n * @dev Inserts an item at the end of the queue.\\n */\\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 backIndex = deque._end;\\n deque._data[backIndex] = value;\\n unchecked {\\n deque._end = backIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Removes the item at the end of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n value = deque._data[backIndex];\\n delete deque._data[backIndex];\\n deque._end = backIndex;\\n }\\n\\n /**\\n * @dev Inserts an item at the beginning of the queue.\\n */\\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 frontIndex;\\n unchecked {\\n frontIndex = deque._begin - 1;\\n }\\n deque._data[frontIndex] = value;\\n deque._begin = frontIndex;\\n }\\n\\n /**\\n * @dev Removes the item at the beginning of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n value = deque._data[frontIndex];\\n delete deque._data[frontIndex];\\n unchecked {\\n deque._begin = frontIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Returns the item at the beginning of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n return deque._data[frontIndex];\\n }\\n\\n /**\\n * @dev Returns the item at the end of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n return deque._data[backIndex];\\n }\\n\\n /**\\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\\n * `length(deque) - 1`.\\n *\\n * Reverts with `OutOfBounds` if the index is out of bounds.\\n */\\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\\n // int256(deque._begin) is a safe upcast\\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\\n if (idx >= deque._end) revert OutOfBounds();\\n return deque._data[idx];\\n }\\n\\n /**\\n * @dev Resets the queue back to being empty.\\n *\\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\\n * out on potential gas refunds.\\n */\\n function clear(Bytes32Deque storage deque) internal {\\n deque._begin = 0;\\n deque._end = 0;\\n }\\n\\n /**\\n * @dev Returns the number of items in the queue.\\n */\\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\\n // We also assume there are at most int256.max items in the queue.\\n unchecked {\\n return uint256(int256(deque._end) - int256(deque._begin));\\n }\\n }\\n\\n /**\\n * @dev Returns true if the queue is empty.\\n */\\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\\n return deque._end <= deque._begin;\\n }\\n}\\n\",\"keccak256\":\"0x4859ffd6dd69382a1462930c00b6e394007da80e78e510f56930271034737bf2\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x61016060405260026007553480156200001757600080fd5b506040516200329a3803806200329a8339810160408190526200003a91620002ec565b6004816040518060400160405280601481526020017f56656c6f63696d6574657220476f7665726e6f7200000000000000000000000081525080620000846200015e60201b60201c565b815160208084019190912082518383012060e08290526101008190524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81880181905281830187905260608201869052608082019490945230818401528151808203909301835260c00190528051940193909320919290916080523060c05261012052505082516200012a925060009150602084019062000246565b50506001600160a01b031661014052620001448162000179565b5050600680546001600160a01b031916331790556200035a565b6040805180820190915260018152603160f81b602082015290565b6064811115620002015760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a40160405180910390fd5b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b82805462000254906200031e565b90600052602060002090601f016020900481019282620002785760008555620002c3565b82601f106200029357805160ff1916838001178555620002c3565b82800160010185558215620002c3579182015b82811115620002c3578251825591602001919060010190620002a6565b50620002d1929150620002d5565b5090565b5b80821115620002d15760008155600101620002d6565b600060208284031215620002ff57600080fd5b81516001600160a01b03811681146200031757600080fd5b9392505050565b600181811c908216806200033357607f821691505b6020821081036200035457634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e051610100516101205161014051612ed0620003ca600039600081816107df0152818161120f015281816113e40152611a0601526000611b2301526000611b7201526000611b4d01526000611aa601526000611ad001526000611afa0152612ed06000f3fe6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a264697066735822122077c95b1c95819f79104e702c1ed3b671348a3db770c4a3cdd65fea31281584db64736f6c634300080d0033", - "deployedBytecode": "0x6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a264697066735822122077c95b1c95819f79104e702c1ed3b671348a3db770c4a3cdd65fea31281584db64736f6c634300080d0033", + "numDeployments": 4, + "solcInputHash": "87c2a0284a68497703d818e47e6d0a63", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"_ve\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"Empty\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"proposer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"string[]\",\"name\":\"signatures\",\"type\":\"string[]\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"ProposalCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldQuorumNumerator\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"QuorumNumeratorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"VoteCast\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"VoteCastWithParams\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"COUNTING_MODE\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EXTENDED_BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_PROPOSAL_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROPOSAL_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"}],\"name\":\"castVote\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"castVoteWithReason\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"castVoteWithReasonAndParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteWithReasonAndParamsBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"execute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"getVotesWithParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasVoted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"hashProposal\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalDeadline\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalSnapshot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"againstVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"forVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"abstainVotes\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"propose\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"quorum\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumDenominator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"}],\"name\":\"setProposalNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTeam\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"state\",\"outputs\":[{\"internalType\":\"enum IGovernor.ProposalState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"updateQuorumNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"Empty()\":[{\"details\":\"An operation (e.g. {front}) couldn't be completed due to the queue being empty.\"}]},\"kind\":\"dev\",\"methods\":{\"COUNTING_MODE()\":{\"details\":\"See {IGovernor-COUNTING_MODE}.\"},\"castVote(uint256,uint8)\":{\"details\":\"See {IGovernor-castVote}.\"},\"castVoteBySig(uint256,uint8,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteBySig}.\"},\"castVoteWithReason(uint256,uint8,string)\":{\"details\":\"See {IGovernor-castVoteWithReason}.\"},\"castVoteWithReasonAndParams(uint256,uint8,string,bytes)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParams}.\"},\"castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParamsBySig}.\"},\"execute(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-execute}.\"},\"getVotes(address,uint256)\":{\"details\":\"See {IGovernor-getVotes}.\"},\"getVotesWithParams(address,uint256,bytes)\":{\"details\":\"See {IGovernor-getVotesWithParams}.\"},\"hasVoted(uint256,address)\":{\"details\":\"See {IGovernor-hasVoted}.\"},\"hashProposal(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-hashProposal}. The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in advance, before the proposal is submitted. Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the same proposal (with same operation and same description) will have the same id if submitted on multiple governors across multiple networks. This also means that in order to execute the same operation twice (on the same governor) the proposer will have to change the description in order to avoid proposal id conflicts.\"},\"name()\":{\"details\":\"See {IGovernor-name}.\"},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155BatchReceived}.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155Received}.\"},\"onERC721Received(address,address,uint256,bytes)\":{\"details\":\"See {IERC721Receiver-onERC721Received}.\"},\"proposalDeadline(uint256)\":{\"details\":\"See {IGovernor-proposalDeadline}.\"},\"proposalSnapshot(uint256)\":{\"details\":\"See {IGovernor-proposalSnapshot}.\"},\"proposalThreshold()\":{\"details\":\"Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\"},\"proposalVotes(uint256)\":{\"details\":\"Accessor to the internal vote counts.\"},\"propose(address[],uint256[],bytes[],string)\":{\"details\":\"See {IGovernor-propose}.\"},\"quorum(uint256)\":{\"details\":\"Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\"},\"quorumDenominator()\":{\"details\":\"Returns the quorum denominator. Defaults to 100, but may be overridden.\"},\"quorumNumerator()\":{\"details\":\"Returns the current quorum numerator. See {quorumDenominator}.\"},\"relay(address,uint256,bytes)\":{\"details\":\"Relays a transaction or function call to an arbitrary target. In cases where the governance executor is some contract other than the governor itself, like when using a timelock, this function can be invoked in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake. Note that if the executor is simply the governor itself, use of `relay` is redundant.\"},\"state(uint256)\":{\"details\":\"See {IGovernor-state}.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"updateQuorumNumerator(uint256)\":{\"details\":\"Changes the quorum numerator. Emits a {QuorumNumeratorUpdated} event. Requirements: - Must be called through a governance proposal. - New numerator must be smaller or equal to the denominator.\"},\"version()\":{\"details\":\"See {IGovernor-version}.\"},\"votingDelay()\":{\"details\":\"Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\"},\"votingPeriod()\":{\"details\":\"Delay, in number of blocks, between the vote start and vote ends. NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting duration compared to the voting delay.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"votingDelay()\":{\"notice\":\"module:user-config\"},\"votingPeriod()\":{\"notice\":\"module:user-config\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/FlowGovernor.sol\":\"VeloGovernor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736303733333539\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/FlowGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IGovernor} from \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\nimport {L2GovernorCountingSimple} from \\\"contracts/governance/L2GovernorCountingSimple.sol\\\";\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\nimport {L2GovernorVotesQuorumFraction} from \\\"contracts/governance/L2GovernorVotesQuorumFraction.sol\\\";\\n\\ncontract VeloGovernor is\\n L2Governor,\\n L2GovernorCountingSimple,\\n L2GovernorVotes,\\n L2GovernorVotesQuorumFraction\\n{\\n address public team;\\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\\n uint256 public proposalNumerator = 2; // start at 0.02%\\n\\n constructor(IVotes _ve)\\n L2Governor(\\\"Velocimeter Governor\\\")\\n L2GovernorVotes(_ve)\\n L2GovernorVotesQuorumFraction(4) // 4%\\n {\\n team = msg.sender;\\n }\\n\\n function votingDelay() public pure override(IGovernor) returns (uint256) {\\n return 15 minutes; // 1 block\\n }\\n\\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\\n return 1 weeks;\\n }\\n\\n function setTeam(address newTeam) external {\\n require(msg.sender == team, \\\"not team\\\");\\n team = newTeam;\\n }\\n\\n function setProposalNumerator(uint256 numerator) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \\\"numerator too high\\\");\\n proposalNumerator = numerator;\\n }\\n\\n function proposalThreshold()\\n public\\n view\\n override(L2Governor)\\n returns (uint256)\\n {\\n return\\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\\n PROPOSAL_DENOMINATOR;\\n }\\n}\\n\",\"keccak256\":\"0x0386aabd5b5db4aee3d584995ec6e3546dbfdcd2c9006c125918bcfd2d496020\",\"license\":\"MIT\"},\"contracts/governance/L2Governor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Address.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Context.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\\n *\\n * @dev Core of the governance system, designed to be extended though various modules.\\n *\\n * This contract is abstract and requires several function to be implemented in various modules:\\n *\\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\\n * - A voting module must implement {_getVotes}\\n * - Additionanly, the {votingPeriod} must also be implemented\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\\n using SafeCast for uint256;\\n using Timers for Timers.Timestamp;\\n\\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\\\"Ballot(uint256 proposalId,uint8 support)\\\");\\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\\n keccak256(\\\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\\\");\\n\\n struct ProposalCore {\\n Timers.Timestamp voteStart;\\n Timers.Timestamp voteEnd;\\n bool executed;\\n bool canceled;\\n }\\n\\n string private _name;\\n\\n mapping(uint256 => ProposalCore) private _proposals;\\n\\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\\n\\n /**\\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\\n * parameter setters in {GovernorSettings} are protected using this modifier.\\n *\\n * The governance executing address may be different from the Governor's own address, for example it could be a\\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\\n * for example, additional timelock proposers are not able to change governance parameters without going through the\\n * governance protocol (since v4.6).\\n */\\n modifier onlyGovernance() {\\n require(_msgSender() == _executor(), \\\"Governor: onlyGovernance\\\");\\n if (_executor() != address(this)) {\\n bytes32 msgDataHash = keccak256(_msgData());\\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\\n while (_governanceCall.popFront() != msgDataHash) {}\\n }\\n _;\\n }\\n\\n /**\\n * @dev Sets the value for {name} and {version}\\n */\\n constructor(string memory name_) EIP712(name_, version()) {\\n _name = name_;\\n }\\n\\n /**\\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\\n */\\n receive() external payable virtual {\\n require(_executor() == address(this));\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\\n // include the castVoteWithReasonAndParams() function as standard\\n return\\n interfaceId ==\\n (type(IGovernor).interfaceId ^\\n this.castVoteWithReasonAndParams.selector ^\\n this.castVoteWithReasonAndParamsBySig.selector ^\\n this.getVotesWithParams.selector) ||\\n interfaceId == type(IGovernor).interfaceId ||\\n interfaceId == type(IERC1155Receiver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IGovernor-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IGovernor-version}.\\n */\\n function version() public view virtual override returns (string memory) {\\n return \\\"1\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hashProposal}.\\n *\\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\\n * advance, before the proposal is submitted.\\n *\\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual override returns (uint256) {\\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\\n }\\n\\n /**\\n * @dev See {IGovernor-state}.\\n */\\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n\\n if (proposal.executed) {\\n return ProposalState.Executed;\\n }\\n\\n if (proposal.canceled) {\\n return ProposalState.Canceled;\\n }\\n\\n uint256 start = proposalSnapshot(proposalId);\\n\\n if (start == 0) {\\n revert(\\\"Governor: unknown proposal id\\\");\\n }\\n\\n if (start >= block.timestamp) {\\n return ProposalState.Pending;\\n }\\n\\n uint256 deadline = proposalDeadline(proposalId);\\n\\n if (deadline >= block.timestamp) {\\n return ProposalState.Active;\\n }\\n\\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\\n return ProposalState.Succeeded;\\n } else {\\n return ProposalState.Defeated;\\n }\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalSnapshot}.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteStart.getDeadline();\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalDeadline}.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteEnd.getDeadline();\\n }\\n\\n /**\\n * @dev Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\\n */\\n function proposalThreshold() public view virtual returns (uint256) {\\n return 0;\\n }\\n\\n /**\\n * @dev Amount of votes already cast passes the threshold limit.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Is the proposal successful or not.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) internal view virtual returns (uint256);\\n\\n /**\\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\\n *\\n * Note: Support is generic and can represent various things depending on the voting system used.\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory params\\n ) internal virtual;\\n\\n /**\\n * @dev Default additional encoded parameters used by castVote methods that don't include them\\n *\\n * Note: Should be overridden by specific implementations to use an appropriate value, the\\n * meaning of the additional params, in the context of that implementation\\n */\\n function _defaultParams() internal view virtual returns (bytes memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-propose}.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual override returns (uint256) {\\n require(\\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\\n \\\"Governor: proposer votes below proposal threshold\\\"\\n );\\n\\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\\n\\n require(targets.length == values.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length == calldatas.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length > 0, \\\"Governor: empty proposal\\\");\\n\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(proposal.voteStart.isUnset(), \\\"Governor: proposal already exists\\\");\\n\\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\\n uint64 deadline = start + votingPeriod().toUint64();\\n\\n proposal.voteStart.setDeadline(start);\\n proposal.voteEnd.setDeadline(deadline);\\n\\n emit ProposalCreated(\\n proposalId,\\n _msgSender(),\\n targets,\\n values,\\n new string[](targets.length),\\n calldatas,\\n start,\\n deadline,\\n description\\n );\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-execute}.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual override returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n\\n ProposalState status = state(proposalId);\\n require(\\n status == ProposalState.Succeeded || status == ProposalState.Queued,\\n \\\"Governor: proposal not successful\\\"\\n );\\n _proposals[proposalId].executed = true;\\n\\n emit ProposalExecuted(proposalId);\\n\\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\\n _execute(proposalId, targets, values, calldatas, descriptionHash);\\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\\n */\\n function _execute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n string memory errorMessage = \\\"Governor: call reverted without message\\\";\\n for (uint256 i = 0; i < targets.length; ++i) {\\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\\n Address.verifyCallResult(success, returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Hook before execution is triggered.\\n */\\n function _beforeExecute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory, /* values */\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n for (uint256 i = 0; i < targets.length; ++i) {\\n if (targets[i] == address(this)) {\\n _governanceCall.pushBack(keccak256(calldatas[i]));\\n }\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook after execution is triggered.\\n */\\n function _afterExecute(\\n uint256, /* proposalId */\\n address[] memory, /* targets */\\n uint256[] memory, /* values */\\n bytes[] memory, /* calldatas */\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n if (!_governanceCall.empty()) {\\n _governanceCall.clear();\\n }\\n }\\n }\\n\\n /**\\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\\n * canceled to allow distinguishing it from executed proposals.\\n *\\n * Emits a {IGovernor-ProposalCanceled} event.\\n */\\n function _cancel(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) internal virtual returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n ProposalState status = state(proposalId);\\n\\n require(\\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\\n \\\"Governor: proposal not active\\\"\\n );\\n _proposals[proposalId].canceled = true;\\n\\n emit ProposalCanceled(proposalId);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotes}.\\n */\\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, _defaultParams());\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotesWithParams}.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVote}.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReason}.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteBySig}.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\\n v,\\n r,\\n s\\n );\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(\\n keccak256(\\n abi.encode(\\n EXTENDED_BALLOT_TYPEHASH,\\n proposalId,\\n support,\\n keccak256(bytes(reason)),\\n keccak256(params)\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason\\n ) internal virtual returns (uint256) {\\n return _castVote(proposalId, account, support, reason, _defaultParams());\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason,\\n bytes memory params\\n ) internal virtual returns (uint256) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(state(proposalId) == ProposalState.Active, \\\"Governor: vote not currently active\\\");\\n\\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\\n _countVote(proposalId, account, support, weight, params);\\n\\n if (params.length == 0) {\\n emit VoteCast(account, proposalId, support, weight, reason);\\n } else {\\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\\n }\\n\\n return weight;\\n }\\n\\n /**\\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\\n */\\n function relay(\\n address target,\\n uint256 value,\\n bytes calldata data\\n ) external virtual onlyGovernance {\\n Address.functionCallWithValue(target, data, value);\\n }\\n\\n /**\\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\\n * through another contract such as a timelock.\\n */\\n function _executor() internal view virtual returns (address) {\\n return address(this);\\n }\\n\\n /**\\n * @dev See {IERC721Receiver-onERC721Received}.\\n */\\n function onERC721Received(\\n address,\\n address,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155Received}.\\n */\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\\n */\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] memory,\\n uint256[] memory,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155BatchReceived.selector;\\n }\\n}\\n\",\"keccak256\":\"0xa2846313b89a871807cdebd0225b0bf8f23b17505ab8b3288549ec54a5a4a71b\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorCountingSimple.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\\n *\\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorCountingSimple is L2Governor {\\n /**\\n * @dev Supported vote types. Matches Governor Bravo ordering.\\n */\\n enum VoteType {\\n Against,\\n For,\\n Abstain\\n }\\n\\n struct ProposalVote {\\n uint256 againstVotes;\\n uint256 forVotes;\\n uint256 abstainVotes;\\n mapping(address => bool) hasVoted;\\n }\\n\\n mapping(uint256 => ProposalVote) private _proposalVotes;\\n\\n /**\\n * @dev See {IGovernor-COUNTING_MODE}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual override returns (string memory) {\\n return \\\"support=bravo&quorum=for,abstain\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hasVoted}.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\\n return _proposalVotes[proposalId].hasVoted[account];\\n }\\n\\n /**\\n * @dev Accessor to the internal vote counts.\\n */\\n function proposalVotes(uint256 proposalId)\\n public\\n view\\n virtual\\n returns (\\n uint256 againstVotes,\\n uint256 forVotes,\\n uint256 abstainVotes\\n )\\n {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\\n }\\n\\n /**\\n * @dev See {Governor-_quorumReached}.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return proposalvote.forVotes > proposalvote.againstVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory // params\\n ) internal virtual override {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n require(!proposalvote.hasVoted[account], \\\"GovernorVotingSimple: vote already cast\\\");\\n proposalvote.hasVoted[account] = true;\\n\\n if (support == uint8(VoteType.Against)) {\\n proposalvote.againstVotes += weight;\\n } else if (support == uint8(VoteType.For)) {\\n proposalvote.forVotes += weight;\\n } else if (support == uint8(VoteType.Abstain)) {\\n proposalvote.abstainVotes += weight;\\n } else {\\n revert(\\\"GovernorVotingSimple: invalid value for enum VoteType\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xdc37daa24118a6e6ba5208b4abefa1632af2ff340135ca6c6d7237f70102d5db\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotes is L2Governor {\\n IVotes public immutable token;\\n\\n constructor(IVotes tokenAddress) {\\n token = tokenAddress;\\n }\\n\\n /**\\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory /*params*/\\n ) internal view virtual override returns (uint256) {\\n return token.getPastVotes(account, blockTimestamp);\\n }\\n}\\n\",\"keccak256\":\"0x605a7de71228dda3cb8fd878cac313a86bc5841fd34d7344214346ba46e63af1\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotesQuorumFraction.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\\n * fraction of the total supply.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\\n uint256 private _quorumNumerator;\\n\\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\\n\\n /**\\n * @dev Initialize quorum as a fraction of the token's total supply.\\n *\\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\\n * customized by overriding {quorumDenominator}.\\n */\\n constructor(uint256 quorumNumeratorValue) {\\n _updateQuorumNumerator(quorumNumeratorValue);\\n }\\n\\n /**\\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\\n */\\n function quorumNumerator() public view virtual returns (uint256) {\\n return _quorumNumerator;\\n }\\n\\n /**\\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\\n */\\n function quorumDenominator() public view virtual returns (uint256) {\\n return 100;\\n }\\n\\n /**\\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\\n */\\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - Must be called through a governance proposal.\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\\n _updateQuorumNumerator(newQuorumNumerator);\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\\n require(\\n newQuorumNumerator <= quorumDenominator(),\\n \\\"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\\\"\\n );\\n\\n uint256 oldQuorumNumerator = _quorumNumerator;\\n _quorumNumerator = newQuorumNumerator;\\n\\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\\n }\\n}\\n\",\"keccak256\":\"0xe66d29c0ffd2274de933d80e11d68891f3acc3f078be4560a2b493b7d88dcb7f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Interface of the {Governor} core.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract IGovernor is IERC165 {\\n enum ProposalState {\\n Pending,\\n Active,\\n Canceled,\\n Defeated,\\n Succeeded,\\n Queued,\\n Expired,\\n Executed\\n }\\n\\n /**\\n * @dev Emitted when a proposal is created.\\n */\\n event ProposalCreated(\\n uint256 proposalId,\\n address proposer,\\n address[] targets,\\n uint256[] values,\\n string[] signatures,\\n bytes[] calldatas,\\n uint256 startBlock,\\n uint256 endBlock,\\n string description\\n );\\n\\n /**\\n * @dev Emitted when a proposal is canceled.\\n */\\n event ProposalCanceled(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a proposal is executed.\\n */\\n event ProposalExecuted(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a vote is cast without params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n */\\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\\n\\n /**\\n * @dev Emitted when a vote is cast with params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\\n */\\n event VoteCastWithParams(\\n address indexed voter,\\n uint256 proposalId,\\n uint8 support,\\n uint256 weight,\\n string reason,\\n bytes params\\n );\\n\\n /**\\n * @notice module:core\\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\\n */\\n function name() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \\\"1\\\"\\n */\\n function version() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:voting\\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\\n *\\n * There are 2 standard keys: `support` and `quorum`.\\n *\\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\\n * - `quorum=bravo` means that only For votes are counted towards quorum.\\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\\n *\\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\\n * name that describes the behavior. For example:\\n *\\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\\n *\\n * NOTE: The string can be decoded by the standard\\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\\n * JavaScript class.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Current state of a proposal, following Compound's convention\\n */\\n function state(uint256 proposalId) public view virtual returns (ProposalState);\\n\\n /**\\n * @notice module:core\\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\\n * beginning of the following block.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\\n * during this block.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\\n */\\n function votingDelay() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of blocks, between the vote start and vote ends.\\n *\\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\\n * duration compared to the voting delay.\\n */\\n function votingPeriod() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Minimum number of cast voted required for a proposal to be successful.\\n *\\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\\n */\\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber`.\\n *\\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\\n * multiple), {ERC20Votes} tokens.\\n */\\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockNumber,\\n bytes memory params\\n ) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:voting\\n * @dev Returns whether `account` has cast a vote on `proposalId`.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\\n\\n /**\\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\\n * {IGovernor-votingPeriod} blocks after the voting starts.\\n *\\n * Emits a {ProposalCreated} event.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\\n * deadline to be reached.\\n *\\n * Emits a {ProposalExecuted} event.\\n *\\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Cast a vote\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xa52d593ff06a2353f78fa149da31f2ca94f03d1eff99bde41977fa2fe985a92f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2e53602b96c1bf97c731ed3e2a981b4f85e23a9410a5ebd36e549a4cc93340dc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x2626d8ab3dfdad0fad630c212ad146d59473d0f48b771784c61a7c1dbbea1f3f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Tooling for timepoints, timers and delays\\n */\\nlibrary Timers {\\n struct Timestamp {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(Timestamp storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(Timestamp memory timer) internal view returns (bool) {\\n return timer._deadline > block.timestamp;\\n }\\n\\n function isExpired(Timestamp memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.timestamp;\\n }\\n\\n struct BlockNumber {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(BlockNumber storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(BlockNumber memory timer) internal view returns (bool) {\\n return timer._deadline > block.number;\\n }\\n\\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.number;\\n }\\n}\\n\",\"keccak256\":\"0x29791a62950a7983e02a673639c1a781d1e448691800456c2ce4b99715391b14\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS,\\n InvalidSignatureV // Deprecated in v4.8\\n }\\n\\n function _throwError(RecoverError error) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert(\\\"ECDSA: invalid signature\\\");\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert(\\\"ECDSA: invalid signature 's' value\\\");\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature` or error string. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\\n if (signature.length == 65) {\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n /// @solidity memory-safe-assembly\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n return tryRecover(hash, v, r, s);\\n } else {\\n return (address(0), RecoverError.InvalidSignatureLength);\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, signature);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n *\\n * _Available since v4.2._\\n */\\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature);\\n }\\n\\n return (signer, RecoverError.NoError);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from `s`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", Strings.toString(s.length), s));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Typed Data, created from a\\n * `domainSeparator` and a `structHash`. This produces hash corresponding\\n * to the one signed with the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\\n * JSON-RPC method as part of EIP-712.\\n *\\n * See {recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n }\\n}\\n\",\"keccak256\":\"0x54ee424bfc83ce63b2a918b9a1efb5090a0fb68dbd1de3b10bc667776885dd4f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ECDSA.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n /* solhint-disable var-name-mixedcase */\\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n // invalidate the cached domain separator if the chain id changes.\\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n uint256 private immutable _CACHED_CHAIN_ID;\\n address private immutable _CACHED_THIS;\\n\\n bytes32 private immutable _HASHED_NAME;\\n bytes32 private immutable _HASHED_VERSION;\\n bytes32 private immutable _TYPE_HASH;\\n\\n /* solhint-enable var-name-mixedcase */\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n constructor(string memory name, string memory version) {\\n bytes32 hashedName = keccak256(bytes(name));\\n bytes32 hashedVersion = keccak256(bytes(version));\\n bytes32 typeHash = keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n );\\n _HASHED_NAME = hashedName;\\n _HASHED_VERSION = hashedVersion;\\n _CACHED_CHAIN_ID = block.chainid;\\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n _CACHED_THIS = address(this);\\n _TYPE_HASH = typeHash;\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\\n return _CACHED_DOMAIN_SEPARATOR;\\n } else {\\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n }\\n }\\n\\n function _buildDomainSeparator(\\n bytes32 typeHash,\\n bytes32 nameHash,\\n bytes32 versionHash\\n ) private view returns (bytes32) {\\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\\n }\\n}\\n\",\"keccak256\":\"0x948d8b2d18f38141ec78c5229d770d950ebc781ed3f44cc9e3ccbb9fded5846a\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\\n\\nimport \\\"./EIP712.sol\\\";\\n\",\"keccak256\":\"0xea30c402170bc240354b74e6c6f6a8e5bdb1935d90d168cc58c0654461c6a72b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3546b156d97633f7f8cad536d5454c81d1d604687c02b2eb105fdc33cb962b41\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\\npragma solidity ^0.8.4;\\n\\nimport \\\"../math/SafeCast.sol\\\";\\n\\n/**\\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\\n * the existing queue contents are left in storage.\\n *\\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\\n * used in storage, and not in memory.\\n * ```\\n * DoubleEndedQueue.Bytes32Deque queue;\\n * ```\\n *\\n * _Available since v4.6._\\n */\\nlibrary DoubleEndedQueue {\\n /**\\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\\n */\\n error Empty();\\n\\n /**\\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\\n */\\n error OutOfBounds();\\n\\n /**\\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\\n *\\n * Struct members have an underscore prefix indicating that they are \\\"private\\\" and should not be read or written to\\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\\n * lead to unexpected behavior.\\n *\\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\\n * data[end - 1].\\n */\\n struct Bytes32Deque {\\n int128 _begin;\\n int128 _end;\\n mapping(int128 => bytes32) _data;\\n }\\n\\n /**\\n * @dev Inserts an item at the end of the queue.\\n */\\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 backIndex = deque._end;\\n deque._data[backIndex] = value;\\n unchecked {\\n deque._end = backIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Removes the item at the end of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n value = deque._data[backIndex];\\n delete deque._data[backIndex];\\n deque._end = backIndex;\\n }\\n\\n /**\\n * @dev Inserts an item at the beginning of the queue.\\n */\\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 frontIndex;\\n unchecked {\\n frontIndex = deque._begin - 1;\\n }\\n deque._data[frontIndex] = value;\\n deque._begin = frontIndex;\\n }\\n\\n /**\\n * @dev Removes the item at the beginning of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n value = deque._data[frontIndex];\\n delete deque._data[frontIndex];\\n unchecked {\\n deque._begin = frontIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Returns the item at the beginning of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n return deque._data[frontIndex];\\n }\\n\\n /**\\n * @dev Returns the item at the end of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n return deque._data[backIndex];\\n }\\n\\n /**\\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\\n * `length(deque) - 1`.\\n *\\n * Reverts with `OutOfBounds` if the index is out of bounds.\\n */\\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\\n // int256(deque._begin) is a safe upcast\\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\\n if (idx >= deque._end) revert OutOfBounds();\\n return deque._data[idx];\\n }\\n\\n /**\\n * @dev Resets the queue back to being empty.\\n *\\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\\n * out on potential gas refunds.\\n */\\n function clear(Bytes32Deque storage deque) internal {\\n deque._begin = 0;\\n deque._end = 0;\\n }\\n\\n /**\\n * @dev Returns the number of items in the queue.\\n */\\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\\n // We also assume there are at most int256.max items in the queue.\\n unchecked {\\n return uint256(int256(deque._end) - int256(deque._begin));\\n }\\n }\\n\\n /**\\n * @dev Returns true if the queue is empty.\\n */\\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\\n return deque._end <= deque._begin;\\n }\\n}\\n\",\"keccak256\":\"0x4859ffd6dd69382a1462930c00b6e394007da80e78e510f56930271034737bf2\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x61016060405260026007553480156200001757600080fd5b506040516200329a3803806200329a8339810160408190526200003a91620002ec565b6004816040518060400160405280601481526020017f56656c6f63696d6574657220476f7665726e6f7200000000000000000000000081525080620000846200015e60201b60201c565b815160208084019190912082518383012060e08290526101008190524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81880181905281830187905260608201869052608082019490945230818401528151808203909301835260c00190528051940193909320919290916080523060c05261012052505082516200012a925060009150602084019062000246565b50506001600160a01b031661014052620001448162000179565b5050600680546001600160a01b031916331790556200035a565b6040805180820190915260018152603160f81b602082015290565b6064811115620002015760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a40160405180910390fd5b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b82805462000254906200031e565b90600052602060002090601f016020900481019282620002785760008555620002c3565b82601f106200029357805160ff1916838001178555620002c3565b82800160010185558215620002c3579182015b82811115620002c3578251825591602001919060010190620002a6565b50620002d1929150620002d5565b5090565b5b80821115620002d15760008155600101620002d6565b600060208284031215620002ff57600080fd5b81516001600160a01b03811681146200031757600080fd5b9392505050565b600181811c908216806200033357607f821691505b6020821081036200035457634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e051610100516101205161014051612ed0620003ca600039600081816107df0152818161120f015281816113e40152611a0601526000611b2301526000611b7201526000611b4d01526000611aa601526000611ad001526000611afa0152612ed06000f3fe6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a26469706673582212206f0f82bb23a18ee7761f1fc6bb1fd57e88de4c2a0483dd749cbd707fba2dbedd64736f6c634300080d0033", + "deployedBytecode": "0x6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a26469706673582212206f0f82bb23a18ee7761f1fc6bb1fd57e88de4c2a0483dd749cbd707fba2dbedd64736f6c634300080d0033", "devdoc": { "errors": { "Empty()": [ diff --git a/deployments/arbitrumGoerli/VelocimeterLibrary.json b/deployments/arbitrumGoerli/VelocimeterLibrary.json index b0350496..a75b7503 100644 --- a/deployments/arbitrumGoerli/VelocimeterLibrary.json +++ b/deployments/arbitrumGoerli/VelocimeterLibrary.json @@ -1,5 +1,5 @@ { - "address": "0x243fC1E928E4bce603669CAf4512B6Db9B965aB0", + "address": "0x7AFfb8901B7D43241068bc804004373147c7c34c", "abi": [ { "inputs": [ @@ -188,30 +188,30 @@ "type": "function" } ], - "transactionHash": "0x7e47a9bfe362a2dd18c5dad505da3b112c7b732ce5dc4df27cb81f227b153f22", + "transactionHash": "0x84b182f1ae5440071a4c19fa636d33f91d5d1b24f207b34e290248aec1d62114", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x243fC1E928E4bce603669CAf4512B6Db9B965aB0", + "contractAddress": "0x7AFfb8901B7D43241068bc804004373147c7c34c", "transactionIndex": 1, - "gasUsed": "904016", + "gasUsed": "904028", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x0ae6a21fe96adf8c5886840e18cf11b782c5f3ae1426ab99af5bc79c3acda8ae", - "transactionHash": "0x7e47a9bfe362a2dd18c5dad505da3b112c7b732ce5dc4df27cb81f227b153f22", + "blockHash": "0x6a8800e70c3e5abfa90cd04dcb2fe67133c4724d963602d12a1f4ffd6f1b28f9", + "transactionHash": "0x84b182f1ae5440071a4c19fa636d33f91d5d1b24f207b34e290248aec1d62114", "logs": [], - "blockNumber": 5716721, - "cumulativeGasUsed": "904016", + "blockNumber": 5814417, + "cumulativeGasUsed": "904028", "status": 1, "byzantium": true }, "args": [ - "0x49fb251F8Ff60bcd975D2018D0011D7a6065000B" + "0xD2D41340706472DEf3b8A1d6143743D03Da38fed" ], - "numDeployments": 2, - "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getMinimumValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getSample\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VelocimeterLibrary.sol\":\"VelocimeterLibrary\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VelocimeterLibrary.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\n\\ncontract VelocimeterLibrary {\\n IRouter internal immutable router;\\n\\n constructor(address _router) {\\n router = IRouter(_router);\\n }\\n\\n function _f(uint x0, uint y) internal pure returns (uint) {\\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\\n }\\n\\n function _d(uint x0, uint y) internal pure returns (uint) {\\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\\n }\\n\\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\\n for (uint i = 0; i < 255; i++) {\\n uint y_prev = y;\\n uint k = _f(x0, y);\\n if (k < xy) {\\n uint dy = (xy - k)*1e18/_d(x0, y);\\n y = y + dy;\\n } else {\\n uint dy = (k - xy)*1e18/_d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n }\\n\\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return (sample, r0, r1);\\n }\\n\\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\\n if (stable) {\\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\\n _reserve0 = _reserve0 * 1e18 / decimals0;\\n _reserve1 = _reserve1 * 1e18 / decimals1;\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\\n } else {\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n return amountIn * reserveB / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\\n if (stable) {\\n uint _x = x * 1e18 / decimals0;\\n uint _y = y * 1e18 / decimals1;\\n uint _a = (_x * _y) / 1e18;\\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return _a * _b / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n \\n}\\n\",\"keccak256\":\"0x8fa888fd7bda7d3d44a2cc0fd62aeb594c767907f24e7cd390a5fe998d60f388\",\"license\":\"MIT\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"}},\"version\":1}", - "bytecode": "0x60a060405234801561001057600080fd5b5060405161100238038061100283398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051610f626100a06000396000818161010c015281816102730152818161043701526105cb0152610f626000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea26469706673582212208b940b1f6efe2e8ce8c8f5a04b173ea4d5a3c085b7baf2282534cc04ab4a313764736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea26469706673582212208b940b1f6efe2e8ce8c8f5a04b173ea4d5a3c085b7baf2282534cc04ab4a313764736f6c634300080d0033", + "numDeployments": 4, + "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getMinimumValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getSample\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VelocimeterLibrary.sol\":\"VelocimeterLibrary\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VelocimeterLibrary.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\n\\ncontract VelocimeterLibrary {\\n IRouter internal immutable router;\\n\\n constructor(address _router) {\\n router = IRouter(_router);\\n }\\n\\n function _f(uint x0, uint y) internal pure returns (uint) {\\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\\n }\\n\\n function _d(uint x0, uint y) internal pure returns (uint) {\\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\\n }\\n\\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\\n for (uint i = 0; i < 255; i++) {\\n uint y_prev = y;\\n uint k = _f(x0, y);\\n if (k < xy) {\\n uint dy = (xy - k)*1e18/_d(x0, y);\\n y = y + dy;\\n } else {\\n uint dy = (k - xy)*1e18/_d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n }\\n\\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return (sample, r0, r1);\\n }\\n\\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\\n if (stable) {\\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\\n _reserve0 = _reserve0 * 1e18 / decimals0;\\n _reserve1 = _reserve1 * 1e18 / decimals1;\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\\n } else {\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n return amountIn * reserveB / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\\n if (stable) {\\n uint _x = x * 1e18 / decimals0;\\n uint _y = y * 1e18 / decimals1;\\n uint _a = (_x * _y) / 1e18;\\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return _a * _b / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n \\n}\\n\",\"keccak256\":\"0x8fa888fd7bda7d3d44a2cc0fd62aeb594c767907f24e7cd390a5fe998d60f388\",\"license\":\"MIT\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"}},\"version\":1}", + "bytecode": "0x60a060405234801561001057600080fd5b5060405161100238038061100283398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051610f626100a06000396000818161010c015281816102730152818161043701526105cb0152610f626000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea2646970667358221220dbb4fa9d04c8f4c99ed7b55c6cda8fa05e9ceb4b7047d53d1879f8abe0b6da4464736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea2646970667358221220dbb4fa9d04c8f4c99ed7b55c6cda8fa05e9ceb4b7047d53d1879f8abe0b6da4464736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/Voter.json b/deployments/arbitrumGoerli/Voter.json index 2ece2c95..4aa02cd5 100644 --- a/deployments/arbitrumGoerli/Voter.json +++ b/deployments/arbitrumGoerli/Voter.json @@ -1,5 +1,5 @@ { - "address": "0x362502b7139761937067cf81a73Dc18D315f10A0", + "address": "0xfD6108E8FDD2e6D125f71E68C7B8eD48f997c2Ad", "abi": [ { "inputs": [ @@ -1141,33 +1141,33 @@ "type": "function" } ], - "transactionHash": "0x79541f2305b40b18d21ee3506c24f656279ba2a3bb80a1b5e8e3234e977c216e", + "transactionHash": "0xe6e46dfdae997cda4d724b4e5e2e614bd2faad5809fd9348881232fe6e94f383", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x362502b7139761937067cf81a73Dc18D315f10A0", + "contractAddress": "0xfD6108E8FDD2e6D125f71E68C7B8eD48f997c2Ad", "transactionIndex": 1, "gasUsed": "3013820", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x977e938152a0962481b4cd190adc69d2e590eb04a972595c42e0e6e54d0a3357", - "transactionHash": "0x79541f2305b40b18d21ee3506c24f656279ba2a3bb80a1b5e8e3234e977c216e", + "blockHash": "0xc595717945fe967d6e9616e7f803588e2526f7305e1069ec94d42e05ea427906", + "transactionHash": "0xe6e46dfdae997cda4d724b4e5e2e614bd2faad5809fd9348881232fe6e94f383", "logs": [], - "blockNumber": 5716736, + "blockNumber": 5814437, "cumulativeGasUsed": "3013820", "status": 1, "byzantium": true }, "args": [ - "0xC43f6EbF97f9D99FF8a3aFe1413599e8DEc2aDB3", - "0xddadFF10D1C9eb062180a870150D11673FFf7ad6", - "0xA957E3958C7ed4590a28C5564438E89238b34EC1", - "0x5cD2336a80E72bf0480ae704df021e4531A09671" + "0xad0F425b3edB0FC3a06096092B5736A280C90C40", + "0xE4a96d05579a4306e19E1C36F8e6A1567c982750", + "0x18B8e4fEf12a17BFe35f0A1a4ca3cA7208F30123", + "0xb6270b92939c7b3676dcecA9a32D50Be27Db1291" ], - "numDeployments": 3, - "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_gauges\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_bribes\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Abstained\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Attach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Detach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributeReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"internal_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"external_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"name\":\"GaugeCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeKilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeRevived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"reward\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NotifyReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Voted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"whitelister\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"Whitelisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"attachTokenToGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bribefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_bribes\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimBribes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_fees\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"}],\"name\":\"claimRewards\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"detachTokenFromGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"finish\",\"type\":\"uint256\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distributeFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distro\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"emergencyCouncil\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"external_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gaugefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"gauges\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_tokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"internal_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isAlive\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isGauge\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isWhitelisted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"killGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"lastVoted\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"length\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"notifyRewardAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"poke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolForGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"poolVote\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"reset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"reviveGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_council\",\"type\":\"address\"}],\"name\":\"setEmergencyCouncil\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"setGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalWeight\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"updateFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"name\":\"updateForRange\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"updateGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedWeights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"_poolVote\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_weights\",\"type\":\"uint256[]\"}],\"name\":\"vote\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"votes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"weights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"whitelist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Voter.sol\":\"Voter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Voter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/libraries/Math.sol';\\nimport 'contracts/interfaces/IBribe.sol';\\nimport 'contracts/interfaces/IBribeFactory.sol';\\nimport 'contracts/interfaces/IGauge.sol';\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/interfaces/IERC20.sol';\\nimport 'contracts/interfaces/IMinter.sol';\\nimport 'contracts/interfaces/IPair.sol';\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/interfaces/IVoter.sol';\\nimport 'contracts/interfaces/IVotingEscrow.sol';\\n\\ncontract Voter is IVoter {\\n\\n address public immutable _ve; // the ve token that governs these contracts\\n address public immutable factory; // the PairFactory\\n address internal immutable base;\\n address public immutable gaugefactory;\\n address public immutable bribefactory;\\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\\n address public minter;\\n address public governor; // should be set to an IGovernor\\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\\n\\n uint public totalWeight; // total voting weight\\n\\n address[] public pools; // all pools viable for incentives\\n mapping(address => address) public gauges; // pool => gauge\\n mapping(address => address) public poolForGauge; // gauge => pool\\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\\n mapping(address => uint256) public weights; // pool => weight\\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\\n mapping(uint => address[]) public poolVote; // nft => pools\\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\\n mapping(address => bool) public isGauge;\\n mapping(address => bool) public isWhitelisted;\\n mapping(address => bool) public isAlive;\\n\\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\\n event GaugeKilled(address indexed gauge);\\n event GaugeRevived(address indexed gauge);\\n event Voted(address indexed voter, uint tokenId, uint256 weight);\\n event Abstained(uint tokenId, uint256 weight);\\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\\n event Whitelisted(address indexed whitelister, address indexed token);\\n\\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\\n _ve = __ve;\\n factory = _factory;\\n base = IVotingEscrow(__ve).token();\\n gaugefactory = _gauges;\\n bribefactory = _bribes;\\n minter = msg.sender;\\n governor = msg.sender;\\n emergencyCouncil = msg.sender;\\n }\\n\\n // simple re-entrancy check\\n uint internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n modifier onlyNewEpoch(uint _tokenId) {\\n // ensure new epoch since last vote \\n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \\\"TOKEN_ALREADY_VOTED_THIS_EPOCH\\\");\\n _;\\n }\\n\\n function initialize(address[] memory _tokens, address _minter) external {\\n require(msg.sender == minter);\\n for (uint i = 0; i < _tokens.length; i++) {\\n _whitelist(_tokens[i]);\\n }\\n minter = _minter;\\n }\\n\\n function setGovernor(address _governor) public {\\n require(msg.sender == governor);\\n governor = _governor;\\n }\\n\\n function setEmergencyCouncil(address _council) public {\\n require(msg.sender == emergencyCouncil);\\n emergencyCouncil = _council;\\n }\\n\\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n lastVoted[_tokenId] = block.timestamp;\\n _reset(_tokenId);\\n IVotingEscrow(_ve).abstain(_tokenId);\\n }\\n\\n function _reset(uint _tokenId) internal {\\n address[] storage _poolVote = poolVote[_tokenId];\\n uint _poolVoteCnt = _poolVote.length;\\n uint256 _totalWeight = 0;\\n\\n for (uint i = 0; i < _poolVoteCnt; i ++) {\\n address _pool = _poolVote[i];\\n uint256 _votes = votes[_tokenId][_pool];\\n\\n if (_votes != 0) {\\n _updateFor(gauges[_pool]);\\n weights[_pool] -= _votes;\\n votes[_tokenId][_pool] -= _votes;\\n if (_votes > 0) {\\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n _totalWeight += _votes;\\n } else {\\n _totalWeight -= _votes;\\n }\\n emit Abstained(_tokenId, _votes);\\n }\\n }\\n totalWeight -= uint256(_totalWeight);\\n usedWeights[_tokenId] = 0;\\n delete poolVote[_tokenId];\\n }\\n\\n function poke(uint _tokenId) external {\\n address[] memory _poolVote = poolVote[_tokenId];\\n uint _poolCnt = _poolVote.length;\\n uint256[] memory _weights = new uint256[](_poolCnt);\\n\\n for (uint i = 0; i < _poolCnt; i ++) {\\n _weights[i] = votes[_tokenId][_poolVote[i]];\\n }\\n\\n _vote(_tokenId, _poolVote, _weights);\\n }\\n\\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\\n _reset(_tokenId);\\n uint _poolCnt = _poolVote.length;\\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\\n uint256 _totalVoteWeight = 0;\\n uint256 _totalWeight = 0;\\n uint256 _usedWeight = 0;\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n _totalVoteWeight += _weights[i];\\n }\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n address _pool = _poolVote[i];\\n address _gauge = gauges[_pool];\\n\\n if (isGauge[_gauge]) {\\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\\n require(votes[_tokenId][_pool] == 0);\\n require(_poolWeight != 0);\\n _updateFor(_gauge);\\n\\n poolVote[_tokenId].push(_pool);\\n\\n weights[_pool] += _poolWeight;\\n votes[_tokenId][_pool] += _poolWeight;\\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n _usedWeight += _poolWeight;\\n _totalWeight += _poolWeight;\\n emit Voted(msg.sender, _tokenId, _poolWeight);\\n }\\n }\\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\\n totalWeight += uint256(_totalWeight);\\n usedWeights[_tokenId] = uint256(_usedWeight);\\n }\\n\\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n require(_poolVote.length == _weights.length);\\n lastVoted[tokenId] = block.timestamp;\\n _vote(tokenId, _poolVote, _weights);\\n }\\n\\n function whitelist(address _token) public {\\n require(msg.sender == governor);\\n _whitelist(_token);\\n }\\n\\n function _whitelist(address _token) internal {\\n require(!isWhitelisted[_token]);\\n isWhitelisted[_token] = true;\\n emit Whitelisted(msg.sender, _token);\\n }\\n\\n function createGauge(address _pool) external returns (address) {\\n require(gauges[_pool] == address(0x0), \\\"exists\\\");\\n address[] memory allowedRewards = new address[](3);\\n address[] memory internalRewards = new address[](2);\\n bool isPair = IPairFactory(factory).isPair(_pool);\\n address tokenA;\\n address tokenB;\\n\\n if (isPair) {\\n (tokenA, tokenB) = IPair(_pool).tokens();\\n allowedRewards[0] = tokenA;\\n allowedRewards[1] = tokenB;\\n internalRewards[0] = tokenA;\\n internalRewards[1] = tokenB;\\n\\n if (base != tokenA && base != tokenB) {\\n allowedRewards[2] = base;\\n }\\n }\\n\\n if (msg.sender != governor) { // gov can create for any pool, even non-Velocimeter pairs\\n require(isPair, \\\"!_pool\\\");\\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \\\"!whitelisted\\\");\\n }\\n\\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\\n\\n IERC20(base).approve(_gauge, type(uint).max);\\n internal_bribes[_gauge] = _internal_bribe;\\n external_bribes[_gauge] = _external_bribe;\\n gauges[_pool] = _gauge;\\n poolForGauge[_gauge] = _pool;\\n isGauge[_gauge] = true;\\n isAlive[_gauge] = true;\\n _updateFor(_gauge);\\n pools.push(_pool);\\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\\n return _gauge;\\n }\\n\\n function killGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(isAlive[_gauge], \\\"gauge already dead\\\");\\n isAlive[_gauge] = false;\\n claimable[_gauge] = 0;\\n emit GaugeKilled(_gauge);\\n }\\n\\n function reviveGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(!isAlive[_gauge], \\\"gauge already alive\\\");\\n isAlive[_gauge] = true;\\n emit GaugeRevived(_gauge);\\n }\\n\\n function attachTokenToGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\\n emit Attach(account, msg.sender, tokenId);\\n }\\n\\n function emitDeposit(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]);\\n emit Deposit(account, msg.sender, tokenId, amount);\\n }\\n\\n function detachTokenFromGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\\n emit Detach(account, msg.sender, tokenId);\\n }\\n\\n function emitWithdraw(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n emit Withdraw(account, msg.sender, tokenId, amount);\\n }\\n\\n function length() external view returns (uint) {\\n return pools.length;\\n }\\n\\n uint internal index;\\n mapping(address => uint) internal supplyIndex;\\n mapping(address => uint) public claimable;\\n\\n function notifyRewardAmount(uint amount) external {\\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index += _ratio;\\n }\\n emit NotifyReward(msg.sender, base, amount);\\n }\\n\\n function updateFor(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n _updateFor(_gauges[i]);\\n }\\n }\\n\\n function updateForRange(uint start, uint end) public {\\n for (uint i = start; i < end; i++) {\\n _updateFor(gauges[pools[i]]);\\n }\\n }\\n\\n function updateAll() external {\\n updateForRange(0, pools.length);\\n }\\n\\n function updateGauge(address _gauge) external {\\n _updateFor(_gauge);\\n }\\n\\n function _updateFor(address _gauge) internal {\\n address _pool = poolForGauge[_gauge];\\n uint256 _supplied = weights[_pool];\\n if (_supplied > 0) {\\n uint _supplyIndex = supplyIndex[_gauge];\\n uint _index = index; // get global index0 for accumulated distro\\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\\n if (_delta > 0) {\\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\\n if (isAlive[_gauge]) {\\n claimable[_gauge] += _share;\\n }\\n }\\n } else {\\n supplyIndex[_gauge] = index; // new users are set to the default global state\\n }\\n }\\n\\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\\n }\\n }\\n\\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _bribes.length; i++) {\\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _fees.length; i++) {\\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function distributeFees(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n if (IGauge(_gauges[i]).isForPair()){\\n IGauge(_gauges[i]).claimFees();\\n }\\n }\\n }\\n\\n function distribute(address _gauge) public lock {\\n IMinter(minter).update_period();\\n _updateFor(_gauge); // should set claimable to 0 if killed\\n uint _claimable = claimable[_gauge];\\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\\n claimable[_gauge] = 0;\\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\\n emit DistributeReward(msg.sender, _gauge, _claimable);\\n }\\n }\\n\\n function distro() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute(uint start, uint finish) public {\\n for (uint x = start; x < finish; x++) {\\n distribute(gauges[pools[x]]);\\n }\\n }\\n\\n function distribute(address[] memory _gauges) external {\\n for (uint x = 0; x < _gauges.length; x++) {\\n distribute(_gauges[x]);\\n }\\n }\\n\\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x16f98751f0144d1758ecb2bec2062be56c718e18d65f0b948fd2a1404b37e6f8\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x61012060405260016011553480156200001757600080fd5b5060405162003656380380620036568339810160408190526200003a916200011c565b6001600160a01b03808516608081905290841660a05260408051637e062a3560e11b8152905163fc0c546a916004808201926020929091908290030181865afa1580156200008c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b2919062000179565b6001600160a01b0390811660c05291821660e0521661010052505060008054336001600160a01b03199182168117909255600180548216831790556002805490911690911790556200019e565b80516001600160a01b03811681146200011757600080fd5b919050565b600080600080608085870312156200013357600080fd5b6200013e85620000ff565b93506200014e60208601620000ff565b92506200015e60408601620000ff565b91506200016e60608601620000ff565b905092959194509250565b6000602082840312156200018c57600080fd5b6200019782620000ff565b9392505050565b60805160a05160c05160e051610100516133e062000276600039600081816103e701528181611c680152611ce60152600081816104d30152611d79015260008181610b9401528181610c0d01528181610edd01528181610f9901528181611acd01528181611b0601528181611b380152611e5a0152600081816106fc015261192401526000818161058c0152818161092b015281816109d701528181610c9a01528181611069015281816111ea0152818161131a015281816114d901528181611dab015281816125e501526129a801526133e06000f3fe608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea264697066735822122037b1584fd5e73726f301a3b06836497dcb851acadb4f734682e2b0825bddc10264736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea264697066735822122037b1584fd5e73726f301a3b06836497dcb851acadb4f734682e2b0825bddc10264736f6c634300080d0033", + "numDeployments": 5, + "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_gauges\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_bribes\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Abstained\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Attach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Detach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributeReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"internal_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"external_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"name\":\"GaugeCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeKilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeRevived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"reward\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NotifyReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Voted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"whitelister\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"Whitelisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"attachTokenToGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bribefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_bribes\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimBribes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_fees\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"}],\"name\":\"claimRewards\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"detachTokenFromGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"finish\",\"type\":\"uint256\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distributeFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distro\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"emergencyCouncil\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"external_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gaugefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"gauges\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_tokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"internal_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isAlive\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isGauge\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isWhitelisted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"killGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"lastVoted\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"length\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"notifyRewardAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"poke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolForGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"poolVote\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"reset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"reviveGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_council\",\"type\":\"address\"}],\"name\":\"setEmergencyCouncil\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"setGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalWeight\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"updateFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"name\":\"updateForRange\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"updateGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedWeights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"_poolVote\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_weights\",\"type\":\"uint256[]\"}],\"name\":\"vote\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"votes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"weights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"whitelist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Voter.sol\":\"Voter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Voter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/libraries/Math.sol';\\nimport 'contracts/interfaces/IBribe.sol';\\nimport 'contracts/interfaces/IBribeFactory.sol';\\nimport 'contracts/interfaces/IGauge.sol';\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/interfaces/IERC20.sol';\\nimport 'contracts/interfaces/IMinter.sol';\\nimport 'contracts/interfaces/IPair.sol';\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/interfaces/IVoter.sol';\\nimport 'contracts/interfaces/IVotingEscrow.sol';\\n\\ncontract Voter is IVoter {\\n\\n address public immutable _ve; // the ve token that governs these contracts\\n address public immutable factory; // the PairFactory\\n address internal immutable base;\\n address public immutable gaugefactory;\\n address public immutable bribefactory;\\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\\n address public minter;\\n address public governor; // should be set to an IGovernor\\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\\n\\n uint public totalWeight; // total voting weight\\n\\n address[] public pools; // all pools viable for incentives\\n mapping(address => address) public gauges; // pool => gauge\\n mapping(address => address) public poolForGauge; // gauge => pool\\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\\n mapping(address => uint256) public weights; // pool => weight\\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\\n mapping(uint => address[]) public poolVote; // nft => pools\\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\\n mapping(address => bool) public isGauge;\\n mapping(address => bool) public isWhitelisted;\\n mapping(address => bool) public isAlive;\\n\\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\\n event GaugeKilled(address indexed gauge);\\n event GaugeRevived(address indexed gauge);\\n event Voted(address indexed voter, uint tokenId, uint256 weight);\\n event Abstained(uint tokenId, uint256 weight);\\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\\n event Whitelisted(address indexed whitelister, address indexed token);\\n\\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\\n _ve = __ve;\\n factory = _factory;\\n base = IVotingEscrow(__ve).token();\\n gaugefactory = _gauges;\\n bribefactory = _bribes;\\n minter = msg.sender;\\n governor = msg.sender;\\n emergencyCouncil = msg.sender;\\n }\\n\\n // simple re-entrancy check\\n uint internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n modifier onlyNewEpoch(uint _tokenId) {\\n // ensure new epoch since last vote \\n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \\\"TOKEN_ALREADY_VOTED_THIS_EPOCH\\\");\\n _;\\n }\\n\\n function initialize(address[] memory _tokens, address _minter) external {\\n require(msg.sender == minter);\\n for (uint i = 0; i < _tokens.length; i++) {\\n _whitelist(_tokens[i]);\\n }\\n minter = _minter;\\n }\\n\\n function setGovernor(address _governor) public {\\n require(msg.sender == governor);\\n governor = _governor;\\n }\\n\\n function setEmergencyCouncil(address _council) public {\\n require(msg.sender == emergencyCouncil);\\n emergencyCouncil = _council;\\n }\\n\\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n lastVoted[_tokenId] = block.timestamp;\\n _reset(_tokenId);\\n IVotingEscrow(_ve).abstain(_tokenId);\\n }\\n\\n function _reset(uint _tokenId) internal {\\n address[] storage _poolVote = poolVote[_tokenId];\\n uint _poolVoteCnt = _poolVote.length;\\n uint256 _totalWeight = 0;\\n\\n for (uint i = 0; i < _poolVoteCnt; i ++) {\\n address _pool = _poolVote[i];\\n uint256 _votes = votes[_tokenId][_pool];\\n\\n if (_votes != 0) {\\n _updateFor(gauges[_pool]);\\n weights[_pool] -= _votes;\\n votes[_tokenId][_pool] -= _votes;\\n if (_votes > 0) {\\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n _totalWeight += _votes;\\n } else {\\n _totalWeight -= _votes;\\n }\\n emit Abstained(_tokenId, _votes);\\n }\\n }\\n totalWeight -= uint256(_totalWeight);\\n usedWeights[_tokenId] = 0;\\n delete poolVote[_tokenId];\\n }\\n\\n function poke(uint _tokenId) external {\\n address[] memory _poolVote = poolVote[_tokenId];\\n uint _poolCnt = _poolVote.length;\\n uint256[] memory _weights = new uint256[](_poolCnt);\\n\\n for (uint i = 0; i < _poolCnt; i ++) {\\n _weights[i] = votes[_tokenId][_poolVote[i]];\\n }\\n\\n _vote(_tokenId, _poolVote, _weights);\\n }\\n\\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\\n _reset(_tokenId);\\n uint _poolCnt = _poolVote.length;\\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\\n uint256 _totalVoteWeight = 0;\\n uint256 _totalWeight = 0;\\n uint256 _usedWeight = 0;\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n _totalVoteWeight += _weights[i];\\n }\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n address _pool = _poolVote[i];\\n address _gauge = gauges[_pool];\\n\\n if (isGauge[_gauge]) {\\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\\n require(votes[_tokenId][_pool] == 0);\\n require(_poolWeight != 0);\\n _updateFor(_gauge);\\n\\n poolVote[_tokenId].push(_pool);\\n\\n weights[_pool] += _poolWeight;\\n votes[_tokenId][_pool] += _poolWeight;\\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n _usedWeight += _poolWeight;\\n _totalWeight += _poolWeight;\\n emit Voted(msg.sender, _tokenId, _poolWeight);\\n }\\n }\\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\\n totalWeight += uint256(_totalWeight);\\n usedWeights[_tokenId] = uint256(_usedWeight);\\n }\\n\\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n require(_poolVote.length == _weights.length);\\n lastVoted[tokenId] = block.timestamp;\\n _vote(tokenId, _poolVote, _weights);\\n }\\n\\n function whitelist(address _token) public {\\n require(msg.sender == governor);\\n _whitelist(_token);\\n }\\n\\n function _whitelist(address _token) internal {\\n require(!isWhitelisted[_token]);\\n isWhitelisted[_token] = true;\\n emit Whitelisted(msg.sender, _token);\\n }\\n\\n function createGauge(address _pool) external returns (address) {\\n require(gauges[_pool] == address(0x0), \\\"exists\\\");\\n address[] memory allowedRewards = new address[](3);\\n address[] memory internalRewards = new address[](2);\\n bool isPair = IPairFactory(factory).isPair(_pool);\\n address tokenA;\\n address tokenB;\\n\\n if (isPair) {\\n (tokenA, tokenB) = IPair(_pool).tokens();\\n allowedRewards[0] = tokenA;\\n allowedRewards[1] = tokenB;\\n internalRewards[0] = tokenA;\\n internalRewards[1] = tokenB;\\n\\n if (base != tokenA && base != tokenB) {\\n allowedRewards[2] = base;\\n }\\n }\\n\\n if (msg.sender != governor) { // gov can create for any pool, even non-Velocimeter pairs\\n require(isPair, \\\"!_pool\\\");\\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \\\"!whitelisted\\\");\\n }\\n\\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\\n\\n IERC20(base).approve(_gauge, type(uint).max);\\n internal_bribes[_gauge] = _internal_bribe;\\n external_bribes[_gauge] = _external_bribe;\\n gauges[_pool] = _gauge;\\n poolForGauge[_gauge] = _pool;\\n isGauge[_gauge] = true;\\n isAlive[_gauge] = true;\\n _updateFor(_gauge);\\n pools.push(_pool);\\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\\n return _gauge;\\n }\\n\\n function killGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(isAlive[_gauge], \\\"gauge already dead\\\");\\n isAlive[_gauge] = false;\\n claimable[_gauge] = 0;\\n emit GaugeKilled(_gauge);\\n }\\n\\n function reviveGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(!isAlive[_gauge], \\\"gauge already alive\\\");\\n isAlive[_gauge] = true;\\n emit GaugeRevived(_gauge);\\n }\\n\\n function attachTokenToGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\\n emit Attach(account, msg.sender, tokenId);\\n }\\n\\n function emitDeposit(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]);\\n emit Deposit(account, msg.sender, tokenId, amount);\\n }\\n\\n function detachTokenFromGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\\n emit Detach(account, msg.sender, tokenId);\\n }\\n\\n function emitWithdraw(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n emit Withdraw(account, msg.sender, tokenId, amount);\\n }\\n\\n function length() external view returns (uint) {\\n return pools.length;\\n }\\n\\n uint internal index;\\n mapping(address => uint) internal supplyIndex;\\n mapping(address => uint) public claimable;\\n\\n function notifyRewardAmount(uint amount) external {\\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index += _ratio;\\n }\\n emit NotifyReward(msg.sender, base, amount);\\n }\\n\\n function updateFor(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n _updateFor(_gauges[i]);\\n }\\n }\\n\\n function updateForRange(uint start, uint end) public {\\n for (uint i = start; i < end; i++) {\\n _updateFor(gauges[pools[i]]);\\n }\\n }\\n\\n function updateAll() external {\\n updateForRange(0, pools.length);\\n }\\n\\n function updateGauge(address _gauge) external {\\n _updateFor(_gauge);\\n }\\n\\n function _updateFor(address _gauge) internal {\\n address _pool = poolForGauge[_gauge];\\n uint256 _supplied = weights[_pool];\\n if (_supplied > 0) {\\n uint _supplyIndex = supplyIndex[_gauge];\\n uint _index = index; // get global index0 for accumulated distro\\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\\n if (_delta > 0) {\\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\\n if (isAlive[_gauge]) {\\n claimable[_gauge] += _share;\\n }\\n }\\n } else {\\n supplyIndex[_gauge] = index; // new users are set to the default global state\\n }\\n }\\n\\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\\n }\\n }\\n\\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _bribes.length; i++) {\\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _fees.length; i++) {\\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function distributeFees(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n if (IGauge(_gauges[i]).isForPair()){\\n IGauge(_gauges[i]).claimFees();\\n }\\n }\\n }\\n\\n function distribute(address _gauge) public lock {\\n IMinter(minter).update_period();\\n _updateFor(_gauge); // should set claimable to 0 if killed\\n uint _claimable = claimable[_gauge];\\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\\n claimable[_gauge] = 0;\\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\\n emit DistributeReward(msg.sender, _gauge, _claimable);\\n }\\n }\\n\\n function distro() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute(uint start, uint finish) public {\\n for (uint x = start; x < finish; x++) {\\n distribute(gauges[pools[x]]);\\n }\\n }\\n\\n function distribute(address[] memory _gauges) external {\\n for (uint x = 0; x < _gauges.length; x++) {\\n distribute(_gauges[x]);\\n }\\n }\\n\\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x16f98751f0144d1758ecb2bec2062be56c718e18d65f0b948fd2a1404b37e6f8\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x61012060405260016011553480156200001757600080fd5b5060405162003656380380620036568339810160408190526200003a916200011c565b6001600160a01b03808516608081905290841660a05260408051637e062a3560e11b8152905163fc0c546a916004808201926020929091908290030181865afa1580156200008c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b2919062000179565b6001600160a01b0390811660c05291821660e0521661010052505060008054336001600160a01b03199182168117909255600180548216831790556002805490911690911790556200019e565b80516001600160a01b03811681146200011757600080fd5b919050565b600080600080608085870312156200013357600080fd5b6200013e85620000ff565b93506200014e60208601620000ff565b92506200015e60408601620000ff565b91506200016e60608601620000ff565b905092959194509250565b6000602082840312156200018c57600080fd5b6200019782620000ff565b9392505050565b60805160a05160c05160e051610100516133e062000276600039600081816103e701528181611c680152611ce60152600081816104d30152611d79015260008181610b9401528181610c0d01528181610edd01528181610f9901528181611acd01528181611b0601528181611b380152611e5a0152600081816106fc015261192401526000818161058c0152818161092b015281816109d701528181610c9a01528181611069015281816111ea0152818161131a015281816114d901528181611dab015281816125e501526129a801526133e06000f3fe608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea264697066735822122025be4046326372dd6cda8be695c22be10d8182eeaeb93fef3c4d85b3e87398fe64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea264697066735822122025be4046326372dd6cda8be695c22be10d8182eeaeb93fef3c4d85b3e87398fe64736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/VotingEscrow.json b/deployments/arbitrumGoerli/VotingEscrow.json index 7e639417..b79a084e 100644 --- a/deployments/arbitrumGoerli/VotingEscrow.json +++ b/deployments/arbitrumGoerli/VotingEscrow.json @@ -1,5 +1,5 @@ { - "address": "0xC43f6EbF97f9D99FF8a3aFe1413599e8DEc2aDB3", + "address": "0xad0F425b3edB0FC3a06096092B5736A280C90C40", "abi": [ { "inputs": [ @@ -1521,62 +1521,62 @@ "type": "function" } ], - "transactionHash": "0x27f78542ce64b4f54e5d963978165833f7d926c7239dd264b9109d541b2ada45", + "transactionHash": "0x3ea792695fe60b47c21fe408f7140a3e8138225c7e1bc8ade003f69f772c9ae2", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xC43f6EbF97f9D99FF8a3aFe1413599e8DEc2aDB3", + "contractAddress": "0xad0F425b3edB0FC3a06096092B5736A280C90C40", "transactionIndex": 1, "gasUsed": "4240754", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000008000400000000000000000000000000000000000000000000020000000000000000000800000000000000000000000010004000000000000000000000000000000000000000000000000000000000000000000000000000400000000080000000000000000000000000000000000000000000000000000002000000000000000000000000040000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x6da0f879c4d4a6a88011182380eaead5f8835b7a19b3e7cc322b791c7d9503bb", - "transactionHash": "0x27f78542ce64b4f54e5d963978165833f7d926c7239dd264b9109d541b2ada45", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000200010000000000000000000000000000000000000000000000000000000000008000000000000000000000004000000000000000000000000020400000000000000000800000000000000000000000010000000000000000000000000000000000000040000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xec24a5c8aa055782bd421029ecf458252e5f0195a2d9fc5f2a2ca0ad0a4d2eaa", + "transactionHash": "0x3ea792695fe60b47c21fe408f7140a3e8138225c7e1bc8ade003f69f772c9ae2", "logs": [ { "transactionIndex": 1, - "blockNumber": 5716730, - "transactionHash": "0x27f78542ce64b4f54e5d963978165833f7d926c7239dd264b9109d541b2ada45", - "address": "0xC43f6EbF97f9D99FF8a3aFe1413599e8DEc2aDB3", + "blockNumber": 5814431, + "transactionHash": "0x3ea792695fe60b47c21fe408f7140a3e8138225c7e1bc8ade003f69f772c9ae2", + "address": "0xad0F425b3edB0FC3a06096092B5736A280C90C40", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000c43f6ebf97f9d99ff8a3afe1413599e8dec2adb3", + "0x000000000000000000000000ad0f425b3edb0fc3a06096092b5736a280c90c40", "0x0000000000000000000000000000000000000000000000000000000000000000" ], "data": "0x", "logIndex": 0, - "blockHash": "0x6da0f879c4d4a6a88011182380eaead5f8835b7a19b3e7cc322b791c7d9503bb" + "blockHash": "0xec24a5c8aa055782bd421029ecf458252e5f0195a2d9fc5f2a2ca0ad0a4d2eaa" }, { "transactionIndex": 1, - "blockNumber": 5716730, - "transactionHash": "0x27f78542ce64b4f54e5d963978165833f7d926c7239dd264b9109d541b2ada45", - "address": "0xC43f6EbF97f9D99FF8a3aFe1413599e8DEc2aDB3", + "blockNumber": 5814431, + "transactionHash": "0x3ea792695fe60b47c21fe408f7140a3e8138225c7e1bc8ade003f69f772c9ae2", + "address": "0xad0F425b3edB0FC3a06096092B5736A280C90C40", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x000000000000000000000000c43f6ebf97f9d99ff8a3afe1413599e8dec2adb3", + "0x000000000000000000000000ad0f425b3edb0fc3a06096092b5736a280c90c40", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000" ], "data": "0x", "logIndex": 1, - "blockHash": "0x6da0f879c4d4a6a88011182380eaead5f8835b7a19b3e7cc322b791c7d9503bb" + "blockHash": "0xec24a5c8aa055782bd421029ecf458252e5f0195a2d9fc5f2a2ca0ad0a4d2eaa" } ], - "blockNumber": 5716730, + "blockNumber": 5814431, "cumulativeGasUsed": "4240754", "status": 1, "byzantium": true }, "args": [ - "0xf5A53c1b4072425DF6eC082f0A48B4652bc4188C", - "0xDe032908A79276B257d1ae80f0C0A2c070eDa1F4" + "0x8c35578054126d4DD063CFaBA40B7F9B63A13981", + "0xfC27470547FA0b96D19146C0490cc444a18A71a9" ], - "numDeployments": 3, - "solcInputHash": "4fb7d8e79af343f7b73620261b95024e", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token_addr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"art_proxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromDelegate\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toDelegate\",\"type\":\"address\"}],\"name\":\"DelegateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"DelegateVotesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"locktime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum VotingEscrow.DepositType\",\"name\":\"deposit_type\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"prevSupply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"supply\",\"type\":\"uint256\"}],\"name\":\"Supply\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DELEGATION_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_DELEGATES\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"abstain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_approved\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"artProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"attach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"attachments\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"balanceOfAtNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_t\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFTAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"block_number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"checkpoints\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"create_lock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"create_lock_for\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"}],\"name\":\"delegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"delegateBySig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"}],\"name\":\"delegates\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"deposit_for\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"detach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastTotalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotesIndex\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"get_last_user_slope\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"increase_amount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"increase_unlock_time\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"isApprovedOrOwner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"locked\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"amount\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"locked__end\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_from\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_to\",\"type\":\"uint256\"}],\"name\":\"merge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"numCheckpoints\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ownership_change\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_proxy\",\"type\":\"address\"}],\"name\":\"setArtProxy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voter\",\"type\":\"address\"}],\"name\":\"setVoter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"slope_changes\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenIndex\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"t\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAtT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_idx\",\"type\":\"uint256\"}],\"name\":\"user_point_history__ts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"voted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"voting\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\",\"details\":\"Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\",\"kind\":\"dev\",\"methods\":{\"approve(address,uint256)\":{\"details\":\"Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address. Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner. Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP) Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"Address to be approved for the given NFT ID.\",\"_tokenId\":\"ID of the token to be approved.\"}},\"balanceOf(address)\":{\"details\":\"Returns the number of NFTs owned by `_owner`. Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\",\"params\":{\"_owner\":\"Address for whom to query the balance.\"}},\"constructor\":{\"params\":{\"token_addr\":\"`FLOW` token address\"}},\"create_lock(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_value\":\"Amount to deposit\"}},\"create_lock_for(uint256,uint256,address)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_to\":\"Address to deposit\",\"_value\":\"Amount to deposit\"}},\"delegate(address)\":{\"params\":{\"delegatee\":\"The address to delegate votes to\"}},\"delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Delegates votes from signer to `delegatee`.\"},\"deposit_for(uint256,uint256)\":{\"details\":\"Anyone (even a smart contract) can deposit for someone else, but cannot extend their locktime and deposit for a brand new user\",\"params\":{\"_tokenId\":\"lock NFT\",\"_value\":\"Amount to add to user's lock\"}},\"getApproved(uint256)\":{\"details\":\"Get the approved address for a single NFT.\",\"params\":{\"_tokenId\":\"ID of the NFT to query the approval of.\"}},\"getVotes(address)\":{\"params\":{\"account\":\"The address to get votes balance\"},\"returns\":{\"_0\":\"The number of current votes for `account`\"}},\"get_last_user_slope(uint256)\":{\"params\":{\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Value of the slope\"}},\"increase_amount(uint256,uint256)\":{\"params\":{\"_value\":\"Amount of tokens to deposit and add to the lock\"}},\"increase_unlock_time(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"New number of seconds until tokens unlock\"}},\"isApprovedForAll(address,address)\":{\"details\":\"Checks if `_operator` is an approved operator for `_owner`.\",\"params\":{\"_operator\":\"The address that acts on behalf of the owner.\",\"_owner\":\"The address that owns the NFTs.\"}},\"locked__end(uint256)\":{\"params\":{\"_tokenId\":\"User NFT\"},\"returns\":{\"_0\":\"Epoch time of the lock end\"}},\"ownerOf(uint256)\":{\"details\":\"Returns the address of the owner of the NFT.\",\"params\":{\"_tokenId\":\"The identifier for an NFT.\"}},\"safeTransferFrom(address,address,uint256)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"safeTransferFrom(address,address,uint256,bytes)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_data\":\"Additional data with no specified format, sent in call to `_to`.\",\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"details\":\"Enables or disables approval for a third party (\\\"operator\\\") to manage all of `msg.sender`'s assets. It also emits the ApprovalForAll event. Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"True if the operators is approved, false to revoke approval.\",\"_operator\":\"Address to add to the set of authorized operators.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Interface identification is specified in ERC-165.\",\"params\":{\"_interfaceID\":\"Id of the interface\"}},\"tokenOfOwnerByIndex(address,uint256)\":{\"details\":\"Get token by index\"},\"tokenURI(uint256)\":{\"details\":\"Returns current token URI metadata\",\"params\":{\"_tokenId\":\"Token ID to fetch URI for.\"}},\"totalSupplyAt(uint256)\":{\"params\":{\"_block\":\"Block to calculate the total voting power at\"},\"returns\":{\"_0\":\"Total voting power at `_block`\"}},\"totalSupplyAtT(uint256)\":{\"details\":\"Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\",\"returns\":{\"_0\":\"Total voting power\"}},\"transferFrom(address,address,uint256)\":{\"details\":\"Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"user_point_history__ts(uint256,uint256)\":{\"params\":{\"_idx\":\"User epoch number\",\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Epoch time of the checkpoint\"}},\"withdraw(uint256)\":{\"details\":\"Only possible if the lock has expired\"}},\"stateVariables\":{\"ERC165_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC165\"},\"ERC721_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721\"},\"ERC721_METADATA_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721Metadata\"},\"_not_entered\":{\"details\":\"reentrancy guard\"},\"idToApprovals\":{\"details\":\"Mapping from NFT ID to approved address.\"},\"idToOwner\":{\"details\":\"Mapping from NFT ID to the address that owns it.\"},\"name\":{\"details\":\"Returns the token collection name.\"},\"ownerToNFTokenCount\":{\"details\":\"Mapping from owner address to count of his tokens.\"},\"ownerToNFTokenIdList\":{\"details\":\"Mapping from owner address to mapping of index to tokenIds\"},\"ownerToOperators\":{\"details\":\"Mapping from owner address to mapping of operator addresses.\"},\"supportedInterfaces\":{\"details\":\"Mapping of interface id to bool about whether or not it's supported\"},\"symbol\":{\"details\":\"Returns the token collection symbol.\"},\"tokenId\":{\"details\":\"Current count of token\"},\"tokenToOwnerIndex\":{\"details\":\"Mapping from NFT ID to index of owner\"}},\"title\":\"Voting Escrow\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DELEGATION_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the delegation struct used by the contract\"},\"DOMAIN_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the contract's domain\"},\"checkpoint()\":{\"notice\":\"Record global data to checkpoint\"},\"checkpoints(address,uint32)\":{\"notice\":\"A record of delegated token checkpoints for each account, by index\"},\"constructor\":{\"notice\":\"Contract constructor\"},\"create_lock(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\"},\"create_lock_for(uint256,uint256,address)\":{\"notice\":\"Deposit `_value` tokens for `_to` and lock for `_lock_duration`\"},\"delegate(address)\":{\"notice\":\"Delegate votes from `msg.sender` to `delegatee`\"},\"delegates(address)\":{\"notice\":\"Overrides the standard `Comp.sol` delegates mapping to return the delegator's own address if they haven't delegated. This avoids having to delegate to oneself.\"},\"deposit_for(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `_tokenId` and add to the lock\"},\"getVotes(address)\":{\"notice\":\"Gets the current votes balance for `account`\"},\"get_last_user_slope(uint256)\":{\"notice\":\"Get the most recently recorded rate of voting power decrease for `_tokenId`\"},\"increase_amount(uint256,uint256)\":{\"notice\":\"Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\"},\"increase_unlock_time(uint256,uint256)\":{\"notice\":\"Extend the unlock time for `_tokenId`\"},\"locked__end(uint256)\":{\"notice\":\"Get timestamp when `_tokenId`'s lock finishes\"},\"nonces(address)\":{\"notice\":\"A record of states for signing / validating signatures\"},\"numCheckpoints(address)\":{\"notice\":\"The number of checkpoints for each account\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"This works even if sender doesn't own any tokens at the time.\"},\"totalSupplyAt(uint256)\":{\"notice\":\"Calculate total voting power at some point in the past\"},\"totalSupplyAtT(uint256)\":{\"notice\":\"Calculate total voting power\"},\"transferFrom(address,address,uint256)\":{\"notice\":\"The caller is responsible to confirm that `_to` is capable of receiving NFTs or else they maybe be permanently lost.\"},\"user_point_history__ts(uint256,uint256)\":{\"notice\":\"Get the timestamp for checkpoint `_idx` for `_tokenId`\"},\"withdraw(uint256)\":{\"notice\":\"Withdraw all tokens for `_tokenId`\"}},\"notice\":\"veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFTVotes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VotingEscrow.sol\":\"VotingEscrow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734373930343136383836\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VotingEscrow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IERC721, IERC721Metadata} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {IERC721Receiver} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {IERC20} from \\\"contracts/interfaces/IERC20.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\nimport {IVotingEscrow} from \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/// @title Voting Escrow\\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\\n enum DepositType {\\n DEPOSIT_FOR_TYPE,\\n CREATE_LOCK_TYPE,\\n INCREASE_LOCK_AMOUNT,\\n INCREASE_UNLOCK_TIME,\\n MERGE_TYPE\\n }\\n\\n struct LockedBalance {\\n int128 amount;\\n uint end;\\n }\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint ts;\\n uint blk; // block\\n }\\n /* We cannot really do block numbers per se b/c slope is per time, not per block\\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\\n * What we can do is to extrapolate ***At functions */\\n\\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\\n struct Checkpoint {\\n uint timestamp;\\n uint[] tokenIds;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Deposit(\\n address indexed provider,\\n uint tokenId,\\n uint value,\\n uint indexed locktime,\\n DepositType deposit_type,\\n uint ts\\n );\\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\\n event Supply(uint prevSupply, uint supply);\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n address public immutable token;\\n address public voter;\\n address public team;\\n address public artProxy;\\n\\n mapping(uint => Point) public point_history; // epoch -> unsigned point\\n\\n /// @dev Mapping of interface id to bool about whether or not it's supported\\n mapping(bytes4 => bool) internal supportedInterfaces;\\n\\n /// @dev ERC165 interface ID of ERC165\\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\\n\\n /// @dev ERC165 interface ID of ERC721\\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\\n\\n /// @dev ERC165 interface ID of ERC721Metadata\\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\\n\\n /// @dev Current count of token\\n uint internal tokenId;\\n\\n /// @notice Contract constructor\\n /// @param token_addr `FLOW` token address\\n constructor(address token_addr, address art_proxy) {\\n token = token_addr;\\n voter = msg.sender;\\n team = msg.sender;\\n artProxy = art_proxy;\\n\\n point_history[0].blk = block.number;\\n point_history[0].ts = block.timestamp;\\n\\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\\n\\n // mint-ish\\n emit Transfer(address(0), address(this), tokenId);\\n // burn-ish\\n emit Transfer(address(this), address(0), tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n MODIFIERS\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev reentrancy guard\\n uint8 internal constant _not_entered = 1;\\n uint8 internal constant _entered = 2;\\n uint8 internal _entered_state = 1;\\n modifier nonreentrant() {\\n require(_entered_state == _not_entered);\\n _entered_state = _entered;\\n _;\\n _entered_state = _not_entered;\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string constant public name = \\\"veNFT\\\";\\n string constant public symbol = \\\"veNFT\\\";\\n string constant public version = \\\"1.0.0\\\";\\n uint8 constant public decimals = 18;\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team);\\n team = _team;\\n }\\n\\n function setArtProxy(address _proxy) external {\\n require(msg.sender == team);\\n artProxy = _proxy;\\n }\\n\\n /// @dev Returns current token URI metadata\\n /// @param _tokenId Token ID to fetch URI for.\\n function tokenURI(uint _tokenId) external view returns (string memory) {\\n require(idToOwner[_tokenId] != address(0), \\\"Query for nonexistent token\\\");\\n LockedBalance memory _locked = locked[_tokenId];\\n return IVeArtProxy(artProxy)._tokenURI(\\n _tokenId,\\n _balanceOfNFT(_tokenId, block.timestamp),\\n _locked.end,\\n uint(int256(_locked.amount))\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 BALANCE/OWNER STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to the address that owns it.\\n mapping(uint => address) internal idToOwner;\\n\\n /// @dev Mapping from owner address to count of his tokens.\\n mapping(address => uint) internal ownerToNFTokenCount;\\n\\n /// @dev Returns the address of the owner of the NFT.\\n /// @param _tokenId The identifier for an NFT.\\n function ownerOf(uint _tokenId) public view returns (address) {\\n return idToOwner[_tokenId];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function _balance(address _owner) internal view returns (uint) {\\n return ownerToNFTokenCount[_owner];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function balanceOf(address _owner) external view returns (uint) {\\n return _balance(_owner);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 APPROVAL STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to approved address.\\n mapping(uint => address) internal idToApprovals;\\n\\n /// @dev Mapping from owner address to mapping of operator addresses.\\n mapping(address => mapping(address => bool)) internal ownerToOperators;\\n\\n mapping(uint => uint) public ownership_change;\\n\\n /// @dev Get the approved address for a single NFT.\\n /// @param _tokenId ID of the NFT to query the approval of.\\n function getApproved(uint _tokenId) external view returns (address) {\\n return idToApprovals[_tokenId];\\n }\\n\\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\\n /// @param _owner The address that owns the NFTs.\\n /// @param _operator The address that acts on behalf of the owner.\\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\\n return (ownerToOperators[_owner])[_operator];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\\n /// @param _approved Address to be approved for the given NFT ID.\\n /// @param _tokenId ID of the token to be approved.\\n function approve(address _approved, uint _tokenId) public {\\n address owner = idToOwner[_tokenId];\\n // Throws if `_tokenId` is not a valid NFT\\n require(owner != address(0));\\n // Throws if `_approved` is the current owner\\n require(_approved != owner);\\n // Check requirements\\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\\n require(senderIsOwner || senderIsApprovedForAll);\\n // Set the approval\\n idToApprovals[_tokenId] = _approved;\\n emit Approval(owner, _approved, _tokenId);\\n }\\n\\n /// @dev Enables or disables approval for a third party (\\\"operator\\\") to manage all of\\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\\n /// @notice This works even if sender doesn't own any tokens at the time.\\n /// @param _operator Address to add to the set of authorized operators.\\n /// @param _approved True if the operators is approved, false to revoke approval.\\n function setApprovalForAll(address _operator, bool _approved) external {\\n // Throws if `_operator` is the `msg.sender`\\n assert(_operator != msg.sender);\\n ownerToOperators[msg.sender][_operator] = _approved;\\n emit ApprovalForAll(msg.sender, _operator, _approved);\\n }\\n\\n /* TRANSFER FUNCTIONS */\\n /// @dev Clear an approval of a given address\\n /// Throws if `_owner` is not the current owner.\\n function _clearApproval(address _owner, uint _tokenId) internal {\\n // Throws if `_owner` is not the current owner\\n assert(idToOwner[_tokenId] == _owner);\\n if (idToApprovals[_tokenId] != address(0)) {\\n // Reset approvals\\n idToApprovals[_tokenId] = address(0);\\n }\\n }\\n\\n /// @dev Returns whether the given spender can transfer a given token ID\\n /// @param _spender address of the spender to query\\n /// @param _tokenId uint ID of the token to be transferred\\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\\n address owner = idToOwner[_tokenId];\\n bool spenderIsOwner = owner == _spender;\\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\\n }\\n\\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\\n return _isApprovedOrOwner(_spender, _tokenId);\\n }\\n\\n /// @dev Exeute transfer of a NFT.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_tokenId` is not a valid NFT.\\n function _transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n address _sender\\n ) internal {\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n // Check requirements\\n require(_isApprovedOrOwner(_sender, _tokenId));\\n // Clear approval. Throws if `_from` is not the current owner\\n _clearApproval(_from, _tokenId);\\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\\n _removeTokenFrom(_from, _tokenId);\\n // auto re-delegate\\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\\n // Add NFT\\n _addTokenTo(_to, _tokenId);\\n // Set the block of ownership transfer (for Flash NFT protection)\\n ownership_change[_tokenId] = block.number;\\n // Log the transfer\\n emit Transfer(_from, _to, _tokenId);\\n }\\n\\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\\n /// they maybe be permanently lost.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n safeTransferFrom(_from, _to, _tokenId, \\\"\\\");\\n }\\n\\n function _isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n uint size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n /// @param _data Additional data with no specified format, sent in call to `_to`.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n bytes memory _data\\n ) public {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n\\n if (_isContract(_to)) {\\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\\n revert(\\\"ERC721: ERC721Receiver rejected tokens\\\");\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert('ERC721: transfer to non ERC721Receiver implementer');\\n } else {\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC165 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Interface identification is specified in ERC-165.\\n /// @param _interfaceID Id of the interface\\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\\n return supportedInterfaces[_interfaceID];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from owner address to mapping of index to tokenIds\\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\\n\\n /// @dev Mapping from NFT ID to index of owner\\n mapping(uint => uint) internal tokenToOwnerIndex;\\n\\n /// @dev Get token by index\\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\\n return ownerToNFTokenIdList[_owner][_tokenIndex];\\n }\\n\\n /// @dev Add a NFT to an index mapping to a given address\\n /// @param _to address of the receiver\\n /// @param _tokenId uint ID Of the token to be added\\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\\n uint current_count = _balance(_to);\\n\\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\\n tokenToOwnerIndex[_tokenId] = current_count;\\n }\\n\\n /// @dev Add a NFT to a given address\\n /// Throws if `_tokenId` is owned by someone.\\n function _addTokenTo(address _to, uint _tokenId) internal {\\n // Throws if `_tokenId` is owned by someone\\n assert(idToOwner[_tokenId] == address(0));\\n // Change the owner\\n idToOwner[_tokenId] = _to;\\n // Update owner token index tracking\\n _addTokenToOwnerList(_to, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_to] += 1;\\n }\\n\\n /// @dev Function to mint tokens\\n /// Throws if `_to` is zero address.\\n /// Throws if `_tokenId` is owned by someone.\\n /// @param _to The address that will receive the minted tokens.\\n /// @param _tokenId The token id to mint.\\n /// @return A boolean that indicates if the operation was successful.\\n function _mint(address _to, uint _tokenId) internal returns (bool) {\\n // Throws if `_to` is zero address\\n assert(_to != address(0));\\n // checkpoint for gov\\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\\n // Add NFT. Throws if `_tokenId` is owned by someone\\n _addTokenTo(_to, _tokenId);\\n emit Transfer(address(0), _to, _tokenId);\\n return true;\\n }\\n\\n /// @dev Remove a NFT from an index mapping to a given address\\n /// @param _from address of the sender\\n /// @param _tokenId uint ID Of the token to be removed\\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\\n // Delete\\n uint current_count = _balance(_from) - 1;\\n uint current_index = tokenToOwnerIndex[_tokenId];\\n\\n if (current_count == current_index) {\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n } else {\\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\\n\\n // Add\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[lastTokenId] = current_index;\\n\\n // Delete\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n }\\n }\\n\\n /// @dev Remove a NFT from a given address\\n /// Throws if `_from` is not the current owner.\\n function _removeTokenFrom(address _from, uint _tokenId) internal {\\n // Throws if `_from` is not the current owner\\n assert(idToOwner[_tokenId] == _from);\\n // Change the owner\\n idToOwner[_tokenId] = address(0);\\n // Update owner token index tracking\\n _removeTokenFromOwnerList(_from, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_from] -= 1;\\n }\\n\\n function _burn(uint _tokenId) internal {\\n require(_isApprovedOrOwner(msg.sender, _tokenId), \\\"caller is not owner nor approved\\\");\\n\\n address owner = ownerOf(_tokenId);\\n\\n // Clear approval\\n approve(address(0), _tokenId);\\n // checkpoint for gov\\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\\n // Remove token\\n _removeTokenFrom(msg.sender, _tokenId);\\n emit Transfer(owner, address(0), _tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public user_point_epoch;\\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\\n mapping(uint => LockedBalance) public locked;\\n uint public epoch;\\n mapping(uint => int128) public slope_changes; // time -> signed slope change\\n uint public supply;\\n\\n uint internal constant WEEK = 1 weeks;\\n uint internal constant MAXTIME = 4 * 365 * 86400;\\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\\n uint internal constant MULTIPLIER = 1 ether;\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @return Value of the slope\\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\\n uint uepoch = user_point_epoch[_tokenId];\\n return user_point_history[_tokenId][uepoch].slope;\\n }\\n\\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @param _idx User epoch number\\n /// @return Epoch time of the checkpoint\\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\\n return user_point_history[_tokenId][_idx].ts;\\n }\\n\\n /// @notice Get timestamp when `_tokenId`'s lock finishes\\n /// @param _tokenId User NFT\\n /// @return Epoch time of the lock end\\n function locked__end(uint _tokenId) external view returns (uint) {\\n return locked[_tokenId].end;\\n }\\n\\n /// @notice Record global and per-user data to checkpoint\\n /// @param _tokenId NFT token ID. No user checkpoint if 0\\n /// @param old_locked Pevious locked amount / end lock time for the user\\n /// @param new_locked New locked amount / end lock time for the user\\n function _checkpoint(\\n uint _tokenId,\\n LockedBalance memory old_locked,\\n LockedBalance memory new_locked\\n ) internal {\\n Point memory u_old;\\n Point memory u_new;\\n int128 old_dslope = 0;\\n int128 new_dslope = 0;\\n uint _epoch = epoch;\\n\\n if (_tokenId != 0) {\\n // Calculate slopes and biases\\n // Kept at zero when they have to\\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\\n u_old.slope = old_locked.amount / iMAXTIME;\\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\\n }\\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\\n u_new.slope = new_locked.amount / iMAXTIME;\\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\\n }\\n\\n // Read values of scheduled changes in the slope\\n // old_locked.end can be in the past and in the future\\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\\n old_dslope = slope_changes[old_locked.end];\\n if (new_locked.end != 0) {\\n if (new_locked.end == old_locked.end) {\\n new_dslope = old_dslope;\\n } else {\\n new_dslope = slope_changes[new_locked.end];\\n }\\n }\\n }\\n\\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\\n if (_epoch > 0) {\\n last_point = point_history[_epoch];\\n }\\n uint last_checkpoint = last_point.ts;\\n // initial_last_point is used for extrapolation to calculate block number\\n // (approximately, for *At methods) and save them\\n // as we cannot figure that out exactly from inside the contract\\n Point memory initial_last_point = last_point;\\n uint block_slope = 0; // dblock/dt\\n if (block.timestamp > last_point.ts) {\\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\\n }\\n // If last point is already recorded in this block, slope=0\\n // But that's ok b/c we know the block in such case\\n\\n // Go over weeks to fill history and calculate what the current point is\\n {\\n uint t_i = (last_checkpoint / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n // Hopefully it won't happen that this won't get used in 5 years!\\n // If it does, users will be able to withdraw but vote weight will be broken\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > block.timestamp) {\\n t_i = block.timestamp;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\\n last_point.slope += d_slope;\\n if (last_point.bias < 0) {\\n // This can happen\\n last_point.bias = 0;\\n }\\n if (last_point.slope < 0) {\\n // This cannot happen - just in case\\n last_point.slope = 0;\\n }\\n last_checkpoint = t_i;\\n last_point.ts = t_i;\\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\\n _epoch += 1;\\n if (t_i == block.timestamp) {\\n last_point.blk = block.number;\\n break;\\n } else {\\n point_history[_epoch] = last_point;\\n }\\n }\\n }\\n\\n epoch = _epoch;\\n // Now point_history is filled until t=now\\n\\n if (_tokenId != 0) {\\n // If last point was in this block, the slope change has been applied already\\n // But in such case we have 0 slope(s)\\n last_point.slope += (u_new.slope - u_old.slope);\\n last_point.bias += (u_new.bias - u_old.bias);\\n if (last_point.slope < 0) {\\n last_point.slope = 0;\\n }\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n }\\n\\n // Record the changed point into history\\n point_history[_epoch] = last_point;\\n\\n if (_tokenId != 0) {\\n // Schedule the slope changes (slope is going down)\\n // We subtract new_user_slope from [new_locked.end]\\n // and add old_user_slope to [old_locked.end]\\n if (old_locked.end > block.timestamp) {\\n // old_dslope was - u_old.slope, so we cancel that\\n old_dslope += u_old.slope;\\n if (new_locked.end == old_locked.end) {\\n old_dslope -= u_new.slope; // It was a new deposit, not extension\\n }\\n slope_changes[old_locked.end] = old_dslope;\\n }\\n\\n if (new_locked.end > block.timestamp) {\\n if (new_locked.end > old_locked.end) {\\n new_dslope -= u_new.slope; // old slope disappeared at this point\\n slope_changes[new_locked.end] = new_dslope;\\n }\\n // else: we recorded it already in old_dslope\\n }\\n // Now handle user history\\n uint user_epoch = user_point_epoch[_tokenId] + 1;\\n\\n user_point_epoch[_tokenId] = user_epoch;\\n u_new.ts = block.timestamp;\\n u_new.blk = block.number;\\n user_point_history[_tokenId][user_epoch] = u_new;\\n }\\n }\\n\\n /// @notice Deposit and lock tokens for a user\\n /// @param _tokenId NFT that holds lock\\n /// @param _value Amount to deposit\\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\\n /// @param locked_balance Previous locked amount / timestamp\\n /// @param deposit_type The type of deposit\\n function _deposit_for(\\n uint _tokenId,\\n uint _value,\\n uint unlock_time,\\n LockedBalance memory locked_balance,\\n DepositType deposit_type\\n ) internal {\\n LockedBalance memory _locked = locked_balance;\\n uint supply_before = supply;\\n\\n supply = supply_before + _value;\\n LockedBalance memory old_locked;\\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\\n // Adding to existing lock, or if a lock is expired - creating a new one\\n _locked.amount += int128(int256(_value));\\n if (unlock_time != 0) {\\n _locked.end = unlock_time;\\n }\\n locked[_tokenId] = _locked;\\n\\n // Possibilities:\\n // Both old_locked.end could be current or expired (>/< block.timestamp)\\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\\n // _locked.end > block.timestamp (always)\\n _checkpoint(_tokenId, old_locked, _locked);\\n\\n address from = msg.sender;\\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\\n assert(IERC20(token).transferFrom(from, address(this), _value));\\n }\\n\\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\\n emit Supply(supply_before, supply_before + _value);\\n }\\n\\n function block_number() external view returns (uint) {\\n return block.number;\\n }\\n\\n /// @notice Record global data to checkpoint\\n function checkpoint() external {\\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\\n }\\n\\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\\n /// cannot extend their locktime and deposit for a brand new user\\n /// @param _tokenId lock NFT\\n /// @param _value Amount to add to user's lock\\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n require(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_value > 0); // dev: need non-zero value\\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n ++tokenId;\\n uint _tokenId = tokenId;\\n _mint(_to, _tokenId);\\n\\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\\n return _tokenId;\\n }\\n\\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, msg.sender);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, _to);\\n }\\n\\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\\n /// @param _value Amount of tokens to deposit and add to the lock\\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n assert(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\\n }\\n\\n /// @notice Extend the unlock time for `_tokenId`\\n /// @param _lock_duration New number of seconds until tokens unlock\\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_locked.end > block.timestamp, 'Lock expired');\\n require(_locked.amount > 0, 'Nothing is locked');\\n require(unlock_time > _locked.end, 'Can only increase lock duration');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\\n }\\n\\n /// @notice Withdraw all tokens for `_tokenId`\\n /// @dev Only possible if the lock has expired\\n function withdraw(uint _tokenId) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n require(block.timestamp >= _locked.end, \\\"The lock didn't expire\\\");\\n uint value = uint(int256(_locked.amount));\\n\\n locked[_tokenId] = LockedBalance(0,0);\\n uint supply_before = supply;\\n supply = supply_before - value;\\n\\n // old_locked can have either expired <= timestamp or zero end\\n // _locked has only 0 end\\n // Both can have >= 0 amount\\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\\n\\n assert(IERC20(token).transfer(msg.sender, value));\\n\\n // Burn the NFT\\n _burn(_tokenId);\\n\\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\\n emit Supply(supply_before, supply_before - value);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\\n // They measure the weights for the purpose of voting, so they don't represent\\n // real coins.\\n\\n /// @notice Binary search to estimate timestamp for block number\\n /// @param _block Block to find\\n /// @param max_epoch Don't go beyond this epoch\\n /// @return Approximate timestamp for block\\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\\n // Binary search\\n uint _min = 0;\\n uint _max = max_epoch;\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (point_history[_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n /// @notice Get the current voting power for `_tokenId`\\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\\n /// @param _tokenId NFT for lock\\n /// @param _t Epoch time to return voting power at\\n /// @return User voting power\\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\\n uint _epoch = user_point_epoch[_tokenId];\\n if (_epoch == 0) {\\n return 0;\\n } else {\\n Point memory last_point = user_point_history[_tokenId][_epoch];\\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(int256(last_point.bias));\\n }\\n }\\n\\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\\n if (ownership_change[_tokenId] == block.number) return 0;\\n return _balanceOfNFT(_tokenId, block.timestamp);\\n }\\n\\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\\n return _balanceOfNFT(_tokenId, _t);\\n }\\n\\n /// @notice Measure voting power of `_tokenId` at block height `_block`\\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\\n /// @param _tokenId User's wallet NFT\\n /// @param _block Block to calculate the voting power at\\n /// @return Voting power\\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\\n // Copying and pasting totalSupply code because Vyper cannot pass by\\n // reference yet\\n assert(_block <= block.number);\\n\\n // Binary search\\n uint _min = 0;\\n uint _max = user_point_epoch[_tokenId];\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (user_point_history[_tokenId][_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n\\n Point memory upoint = user_point_history[_tokenId][_min];\\n\\n uint max_epoch = epoch;\\n uint _epoch = _find_block_epoch(_block, max_epoch);\\n Point memory point_0 = point_history[_epoch];\\n uint d_block = 0;\\n uint d_t = 0;\\n if (_epoch < max_epoch) {\\n Point memory point_1 = point_history[_epoch + 1];\\n d_block = point_1.blk - point_0.blk;\\n d_t = point_1.ts - point_0.ts;\\n } else {\\n d_block = block.number - point_0.blk;\\n d_t = block.timestamp - point_0.ts;\\n }\\n uint block_time = point_0.ts;\\n if (d_block != 0) {\\n block_time += (d_t * (_block - point_0.blk)) / d_block;\\n }\\n\\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\\n if (upoint.bias >= 0) {\\n return uint(uint128(upoint.bias));\\n } else {\\n return 0;\\n }\\n }\\n\\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\\n return _balanceOfAtNFT(_tokenId, _block);\\n }\\n\\n /// @notice Calculate total voting power at some point in the past\\n /// @param _block Block to calculate the total voting power at\\n /// @return Total voting power at `_block`\\n function totalSupplyAt(uint _block) external view returns (uint) {\\n assert(_block <= block.number);\\n uint _epoch = epoch;\\n uint target_epoch = _find_block_epoch(_block, _epoch);\\n\\n Point memory point = point_history[target_epoch];\\n uint dt = 0;\\n if (target_epoch < _epoch) {\\n Point memory point_next = point_history[target_epoch + 1];\\n if (point.blk != point_next.blk) {\\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\\n }\\n } else {\\n if (point.blk != block.number) {\\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\\n }\\n }\\n // Now dt contains info on how far are we beyond point\\n return _supply_at(point, point.ts + dt);\\n }\\n /// @notice Calculate total voting power at some point in the past\\n /// @param point The point (bias/slope) to start search from\\n /// @param t Time to calculate the total voting power at\\n /// @return Total voting power at that time\\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\\n Point memory last_point = point;\\n uint t_i = (last_point.ts / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > t) {\\n t_i = t;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\\n if (t_i == t) {\\n break;\\n }\\n last_point.slope += d_slope;\\n last_point.ts = t_i;\\n }\\n\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(uint128(last_point.bias));\\n }\\n\\n function totalSupply() external view returns (uint) {\\n return totalSupplyAtT(block.timestamp);\\n }\\n\\n /// @notice Calculate total voting power\\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\\n /// @return Total voting power\\n function totalSupplyAtT(uint t) public view returns (uint) {\\n uint _epoch = epoch;\\n Point memory last_point = point_history[_epoch];\\n return _supply_at(last_point, t);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public attachments;\\n mapping(uint => bool) public voted;\\n\\n function setVoter(address _voter) external {\\n require(msg.sender == voter);\\n voter = _voter;\\n }\\n\\n function voting(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = true;\\n }\\n\\n function abstain(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = false;\\n }\\n\\n function attach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] + 1;\\n }\\n\\n function detach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] - 1;\\n }\\n\\n function merge(uint _from, uint _to) external {\\n require(attachments[_from] == 0 && !voted[_from], \\\"attached\\\");\\n require(_from != _to);\\n require(_isApprovedOrOwner(msg.sender, _from));\\n require(_isApprovedOrOwner(msg.sender, _to));\\n\\n LockedBalance memory _locked0 = locked[_from];\\n LockedBalance memory _locked1 = locked[_to];\\n uint value0 = uint(int256(_locked0.amount));\\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\\n\\n locked[_from] = LockedBalance(0, 0);\\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\\n _burn(_from);\\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of each accounts delegate\\n mapping(address => address) private _delegates;\\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\\n\\n /// @notice A record of delegated token checkpoints for each account, by index\\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint32) public numCheckpoints;\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping(address => uint) public nonces;\\n\\n /**\\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\\n * the delegator's own address if they haven't delegated.\\n * This avoids having to delegate to oneself.\\n */\\n function delegates(address delegator) public view returns (address) {\\n address current = _delegates[delegator];\\n return current == address(0) ? delegator : current;\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getVotes(address account) external view returns (uint) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n votes = votes + _balanceOfNFT(tId, block.timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint storage cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPastVotes(address account, uint timestamp)\\n public\\n view\\n returns (uint)\\n {\\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\\n // Sum votes\\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n // Use the provided input timestamp here to get the right decay\\n votes = votes + _balanceOfNFT(tId, timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\\n return totalSupplyAtT(timestamp);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _moveTokenDelegates(\\n address srcRep,\\n address dstRep,\\n uint _tokenId\\n ) internal {\\n if (srcRep != dstRep && _tokenId > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except _tokenId\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (tId != _tokenId) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n // All the same plus _tokenId\\n require(\\n dstRepOld.length + 1 <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n dstRepNew.push(_tokenId);\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _findWhatCheckpointToWrite(address account)\\n internal\\n view\\n returns (uint32)\\n {\\n uint _timestamp = block.timestamp;\\n uint32 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n return _nCheckPoints - 1;\\n } else {\\n return _nCheckPoints;\\n }\\n }\\n\\n function _moveAllDelegates(\\n address owner,\\n address srcRep,\\n address dstRep\\n ) internal {\\n // You can only redelegate what you own\\n if (srcRep != dstRep) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except what owner owns\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (idToOwner[tId] != owner) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n uint ownerTokenCount = ownerToNFTokenCount[owner];\\n require(\\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n // All the same\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n // Plus all that's owned\\n for (uint i = 0; i < ownerTokenCount; i++) {\\n uint tId = ownerToNFTokenIdList[owner][i];\\n dstRepNew.push(tId);\\n }\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\\n address currentDelegate = delegates(delegator);\\n\\n _delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n _moveAllDelegates(delegator, currentDelegate, delegatee);\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n if (delegatee == address(0)) delegatee = msg.sender;\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n function delegateBySig(\\n address delegatee,\\n uint nonce,\\n uint expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public {\\n bytes32 domainSeparator = keccak256(\\n abi.encode(\\n DOMAIN_TYPEHASH,\\n keccak256(bytes(name)),\\n keccak256(bytes(version)),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 structHash = keccak256(\\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash)\\n );\\n address signatory = ecrecover(digest, v, r, s);\\n require(\\n signatory != address(0),\\n \\\"VotingEscrow::delegateBySig: invalid signature\\\"\\n );\\n require(\\n nonce == nonces[signatory]++,\\n \\\"VotingEscrow::delegateBySig: invalid nonce\\\"\\n );\\n require(\\n block.timestamp <= expiry,\\n \\\"VotingEscrow::delegateBySig: signature expired\\\"\\n );\\n return _delegate(signatory, delegatee);\\n }\\n}\\n\",\"keccak256\":\"0x7109ed9d84b5504fe5d4c73d5a10997a0b73f2f4d45813ce5e161997d405fd73\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x41bbb2c41036ca64b2f6c9e973e8cfaa113ebc42af86702cd0d267f915a7e886\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60a06040526006805460ff191660011790553480156200001e57600080fd5b5060405162004a1c38038062004a1c8339810160408190526200004191620001b8565b6001600160a01b0382811660805260008054336001600160a01b031991821681178355600180548316909117815560028054909216938516939093179055437f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f0155427f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f005560046020527f9fe05126d2d9ecf60592e254dead906a4b2e492f36cca727682c38e9008c6ac1805460ff1990811684179091557f4267c0a6fd96b7a87f183ee8744f24d011423cd0e0142b3f563f183d8d9a456b8054821684179055635b5e139f60e01b82527e24030bcf4927897dffe721c2d8dda4bfd8910861687c42b03a463b43b04147805490911690921790915560055460405190913091600080516020620049fc833981519152908290a46005546040516000903090600080516020620049fc833981519152908390a45050620001f0565b80516001600160a01b0381168114620001b357600080fd5b919050565b60008060408385031215620001cc57600080fd5b620001d7836200019b565b9150620001e7602084016200019b565b90509250929050565b6080516147e26200021a60003960008181610b220152818161101801526133b501526147e26000f3fe608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea26469706673582212206e4938af8652c6d7c3a2e86f49c422f443b67b5bce3c2f44cf77757a7f5057ea64736f6c634300080d0033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea26469706673582212206e4938af8652c6d7c3a2e86f49c422f443b67b5bce3c2f44cf77757a7f5057ea64736f6c634300080d0033", + "numDeployments": 5, + "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token_addr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"art_proxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromDelegate\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toDelegate\",\"type\":\"address\"}],\"name\":\"DelegateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"DelegateVotesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"locktime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum VotingEscrow.DepositType\",\"name\":\"deposit_type\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"prevSupply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"supply\",\"type\":\"uint256\"}],\"name\":\"Supply\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DELEGATION_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_DELEGATES\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"abstain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_approved\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"artProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"attach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"attachments\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"balanceOfAtNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_t\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFTAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"block_number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"checkpoints\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"create_lock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"create_lock_for\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"}],\"name\":\"delegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"delegateBySig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"}],\"name\":\"delegates\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"deposit_for\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"detach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastTotalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotesIndex\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"get_last_user_slope\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"increase_amount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"increase_unlock_time\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"isApprovedOrOwner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"locked\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"amount\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"locked__end\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_from\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_to\",\"type\":\"uint256\"}],\"name\":\"merge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"numCheckpoints\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ownership_change\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_proxy\",\"type\":\"address\"}],\"name\":\"setArtProxy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voter\",\"type\":\"address\"}],\"name\":\"setVoter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"slope_changes\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenIndex\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"t\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAtT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_idx\",\"type\":\"uint256\"}],\"name\":\"user_point_history__ts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"voted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"voting\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\",\"details\":\"Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\",\"kind\":\"dev\",\"methods\":{\"approve(address,uint256)\":{\"details\":\"Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address. Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner. Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP) Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"Address to be approved for the given NFT ID.\",\"_tokenId\":\"ID of the token to be approved.\"}},\"balanceOf(address)\":{\"details\":\"Returns the number of NFTs owned by `_owner`. Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\",\"params\":{\"_owner\":\"Address for whom to query the balance.\"}},\"constructor\":{\"params\":{\"token_addr\":\"`FLOW` token address\"}},\"create_lock(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_value\":\"Amount to deposit\"}},\"create_lock_for(uint256,uint256,address)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_to\":\"Address to deposit\",\"_value\":\"Amount to deposit\"}},\"delegate(address)\":{\"params\":{\"delegatee\":\"The address to delegate votes to\"}},\"delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Delegates votes from signer to `delegatee`.\"},\"deposit_for(uint256,uint256)\":{\"details\":\"Anyone (even a smart contract) can deposit for someone else, but cannot extend their locktime and deposit for a brand new user\",\"params\":{\"_tokenId\":\"lock NFT\",\"_value\":\"Amount to add to user's lock\"}},\"getApproved(uint256)\":{\"details\":\"Get the approved address for a single NFT.\",\"params\":{\"_tokenId\":\"ID of the NFT to query the approval of.\"}},\"getVotes(address)\":{\"params\":{\"account\":\"The address to get votes balance\"},\"returns\":{\"_0\":\"The number of current votes for `account`\"}},\"get_last_user_slope(uint256)\":{\"params\":{\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Value of the slope\"}},\"increase_amount(uint256,uint256)\":{\"params\":{\"_value\":\"Amount of tokens to deposit and add to the lock\"}},\"increase_unlock_time(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"New number of seconds until tokens unlock\"}},\"isApprovedForAll(address,address)\":{\"details\":\"Checks if `_operator` is an approved operator for `_owner`.\",\"params\":{\"_operator\":\"The address that acts on behalf of the owner.\",\"_owner\":\"The address that owns the NFTs.\"}},\"locked__end(uint256)\":{\"params\":{\"_tokenId\":\"User NFT\"},\"returns\":{\"_0\":\"Epoch time of the lock end\"}},\"ownerOf(uint256)\":{\"details\":\"Returns the address of the owner of the NFT.\",\"params\":{\"_tokenId\":\"The identifier for an NFT.\"}},\"safeTransferFrom(address,address,uint256)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"safeTransferFrom(address,address,uint256,bytes)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_data\":\"Additional data with no specified format, sent in call to `_to`.\",\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"details\":\"Enables or disables approval for a third party (\\\"operator\\\") to manage all of `msg.sender`'s assets. It also emits the ApprovalForAll event. Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"True if the operators is approved, false to revoke approval.\",\"_operator\":\"Address to add to the set of authorized operators.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Interface identification is specified in ERC-165.\",\"params\":{\"_interfaceID\":\"Id of the interface\"}},\"tokenOfOwnerByIndex(address,uint256)\":{\"details\":\"Get token by index\"},\"tokenURI(uint256)\":{\"details\":\"Returns current token URI metadata\",\"params\":{\"_tokenId\":\"Token ID to fetch URI for.\"}},\"totalSupplyAt(uint256)\":{\"params\":{\"_block\":\"Block to calculate the total voting power at\"},\"returns\":{\"_0\":\"Total voting power at `_block`\"}},\"totalSupplyAtT(uint256)\":{\"details\":\"Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\",\"returns\":{\"_0\":\"Total voting power\"}},\"transferFrom(address,address,uint256)\":{\"details\":\"Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"user_point_history__ts(uint256,uint256)\":{\"params\":{\"_idx\":\"User epoch number\",\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Epoch time of the checkpoint\"}},\"withdraw(uint256)\":{\"details\":\"Only possible if the lock has expired\"}},\"stateVariables\":{\"ERC165_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC165\"},\"ERC721_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721\"},\"ERC721_METADATA_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721Metadata\"},\"_not_entered\":{\"details\":\"reentrancy guard\"},\"idToApprovals\":{\"details\":\"Mapping from NFT ID to approved address.\"},\"idToOwner\":{\"details\":\"Mapping from NFT ID to the address that owns it.\"},\"name\":{\"details\":\"Returns the token collection name.\"},\"ownerToNFTokenCount\":{\"details\":\"Mapping from owner address to count of his tokens.\"},\"ownerToNFTokenIdList\":{\"details\":\"Mapping from owner address to mapping of index to tokenIds\"},\"ownerToOperators\":{\"details\":\"Mapping from owner address to mapping of operator addresses.\"},\"supportedInterfaces\":{\"details\":\"Mapping of interface id to bool about whether or not it's supported\"},\"symbol\":{\"details\":\"Returns the token collection symbol.\"},\"tokenId\":{\"details\":\"Current count of token\"},\"tokenToOwnerIndex\":{\"details\":\"Mapping from NFT ID to index of owner\"}},\"title\":\"Voting Escrow\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DELEGATION_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the delegation struct used by the contract\"},\"DOMAIN_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the contract's domain\"},\"checkpoint()\":{\"notice\":\"Record global data to checkpoint\"},\"checkpoints(address,uint32)\":{\"notice\":\"A record of delegated token checkpoints for each account, by index\"},\"constructor\":{\"notice\":\"Contract constructor\"},\"create_lock(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\"},\"create_lock_for(uint256,uint256,address)\":{\"notice\":\"Deposit `_value` tokens for `_to` and lock for `_lock_duration`\"},\"delegate(address)\":{\"notice\":\"Delegate votes from `msg.sender` to `delegatee`\"},\"delegates(address)\":{\"notice\":\"Overrides the standard `Comp.sol` delegates mapping to return the delegator's own address if they haven't delegated. This avoids having to delegate to oneself.\"},\"deposit_for(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `_tokenId` and add to the lock\"},\"getVotes(address)\":{\"notice\":\"Gets the current votes balance for `account`\"},\"get_last_user_slope(uint256)\":{\"notice\":\"Get the most recently recorded rate of voting power decrease for `_tokenId`\"},\"increase_amount(uint256,uint256)\":{\"notice\":\"Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\"},\"increase_unlock_time(uint256,uint256)\":{\"notice\":\"Extend the unlock time for `_tokenId`\"},\"locked__end(uint256)\":{\"notice\":\"Get timestamp when `_tokenId`'s lock finishes\"},\"nonces(address)\":{\"notice\":\"A record of states for signing / validating signatures\"},\"numCheckpoints(address)\":{\"notice\":\"The number of checkpoints for each account\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"This works even if sender doesn't own any tokens at the time.\"},\"totalSupplyAt(uint256)\":{\"notice\":\"Calculate total voting power at some point in the past\"},\"totalSupplyAtT(uint256)\":{\"notice\":\"Calculate total voting power\"},\"transferFrom(address,address,uint256)\":{\"notice\":\"The caller is responsible to confirm that `_to` is capable of receiving NFTs or else they maybe be permanently lost.\"},\"user_point_history__ts(uint256,uint256)\":{\"notice\":\"Get the timestamp for checkpoint `_idx` for `_tokenId`\"},\"withdraw(uint256)\":{\"notice\":\"Withdraw all tokens for `_tokenId`\"}},\"notice\":\"veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFTVotes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VotingEscrow.sol\":\"VotingEscrow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VotingEscrow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IERC721, IERC721Metadata} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {IERC721Receiver} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {IERC20} from \\\"contracts/interfaces/IERC20.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\nimport {IVotingEscrow} from \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/// @title Voting Escrow\\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\\n enum DepositType {\\n DEPOSIT_FOR_TYPE,\\n CREATE_LOCK_TYPE,\\n INCREASE_LOCK_AMOUNT,\\n INCREASE_UNLOCK_TIME,\\n MERGE_TYPE\\n }\\n\\n struct LockedBalance {\\n int128 amount;\\n uint end;\\n }\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint ts;\\n uint blk; // block\\n }\\n /* We cannot really do block numbers per se b/c slope is per time, not per block\\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\\n * What we can do is to extrapolate ***At functions */\\n\\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\\n struct Checkpoint {\\n uint timestamp;\\n uint[] tokenIds;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Deposit(\\n address indexed provider,\\n uint tokenId,\\n uint value,\\n uint indexed locktime,\\n DepositType deposit_type,\\n uint ts\\n );\\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\\n event Supply(uint prevSupply, uint supply);\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n address public immutable token;\\n address public voter;\\n address public team;\\n address public artProxy;\\n\\n mapping(uint => Point) public point_history; // epoch -> unsigned point\\n\\n /// @dev Mapping of interface id to bool about whether or not it's supported\\n mapping(bytes4 => bool) internal supportedInterfaces;\\n\\n /// @dev ERC165 interface ID of ERC165\\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\\n\\n /// @dev ERC165 interface ID of ERC721\\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\\n\\n /// @dev ERC165 interface ID of ERC721Metadata\\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\\n\\n /// @dev Current count of token\\n uint internal tokenId;\\n\\n /// @notice Contract constructor\\n /// @param token_addr `FLOW` token address\\n constructor(address token_addr, address art_proxy) {\\n token = token_addr;\\n voter = msg.sender;\\n team = msg.sender;\\n artProxy = art_proxy;\\n\\n point_history[0].blk = block.number;\\n point_history[0].ts = block.timestamp;\\n\\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\\n\\n // mint-ish\\n emit Transfer(address(0), address(this), tokenId);\\n // burn-ish\\n emit Transfer(address(this), address(0), tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n MODIFIERS\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev reentrancy guard\\n uint8 internal constant _not_entered = 1;\\n uint8 internal constant _entered = 2;\\n uint8 internal _entered_state = 1;\\n modifier nonreentrant() {\\n require(_entered_state == _not_entered);\\n _entered_state = _entered;\\n _;\\n _entered_state = _not_entered;\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string constant public name = \\\"veNFT\\\";\\n string constant public symbol = \\\"veNFT\\\";\\n string constant public version = \\\"1.0.0\\\";\\n uint8 constant public decimals = 18;\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team);\\n team = _team;\\n }\\n\\n function setArtProxy(address _proxy) external {\\n require(msg.sender == team);\\n artProxy = _proxy;\\n }\\n\\n /// @dev Returns current token URI metadata\\n /// @param _tokenId Token ID to fetch URI for.\\n function tokenURI(uint _tokenId) external view returns (string memory) {\\n require(idToOwner[_tokenId] != address(0), \\\"Query for nonexistent token\\\");\\n LockedBalance memory _locked = locked[_tokenId];\\n return IVeArtProxy(artProxy)._tokenURI(\\n _tokenId,\\n _balanceOfNFT(_tokenId, block.timestamp),\\n _locked.end,\\n uint(int256(_locked.amount))\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 BALANCE/OWNER STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to the address that owns it.\\n mapping(uint => address) internal idToOwner;\\n\\n /// @dev Mapping from owner address to count of his tokens.\\n mapping(address => uint) internal ownerToNFTokenCount;\\n\\n /// @dev Returns the address of the owner of the NFT.\\n /// @param _tokenId The identifier for an NFT.\\n function ownerOf(uint _tokenId) public view returns (address) {\\n return idToOwner[_tokenId];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function _balance(address _owner) internal view returns (uint) {\\n return ownerToNFTokenCount[_owner];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function balanceOf(address _owner) external view returns (uint) {\\n return _balance(_owner);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 APPROVAL STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to approved address.\\n mapping(uint => address) internal idToApprovals;\\n\\n /// @dev Mapping from owner address to mapping of operator addresses.\\n mapping(address => mapping(address => bool)) internal ownerToOperators;\\n\\n mapping(uint => uint) public ownership_change;\\n\\n /// @dev Get the approved address for a single NFT.\\n /// @param _tokenId ID of the NFT to query the approval of.\\n function getApproved(uint _tokenId) external view returns (address) {\\n return idToApprovals[_tokenId];\\n }\\n\\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\\n /// @param _owner The address that owns the NFTs.\\n /// @param _operator The address that acts on behalf of the owner.\\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\\n return (ownerToOperators[_owner])[_operator];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\\n /// @param _approved Address to be approved for the given NFT ID.\\n /// @param _tokenId ID of the token to be approved.\\n function approve(address _approved, uint _tokenId) public {\\n address owner = idToOwner[_tokenId];\\n // Throws if `_tokenId` is not a valid NFT\\n require(owner != address(0));\\n // Throws if `_approved` is the current owner\\n require(_approved != owner);\\n // Check requirements\\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\\n require(senderIsOwner || senderIsApprovedForAll);\\n // Set the approval\\n idToApprovals[_tokenId] = _approved;\\n emit Approval(owner, _approved, _tokenId);\\n }\\n\\n /// @dev Enables or disables approval for a third party (\\\"operator\\\") to manage all of\\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\\n /// @notice This works even if sender doesn't own any tokens at the time.\\n /// @param _operator Address to add to the set of authorized operators.\\n /// @param _approved True if the operators is approved, false to revoke approval.\\n function setApprovalForAll(address _operator, bool _approved) external {\\n // Throws if `_operator` is the `msg.sender`\\n assert(_operator != msg.sender);\\n ownerToOperators[msg.sender][_operator] = _approved;\\n emit ApprovalForAll(msg.sender, _operator, _approved);\\n }\\n\\n /* TRANSFER FUNCTIONS */\\n /// @dev Clear an approval of a given address\\n /// Throws if `_owner` is not the current owner.\\n function _clearApproval(address _owner, uint _tokenId) internal {\\n // Throws if `_owner` is not the current owner\\n assert(idToOwner[_tokenId] == _owner);\\n if (idToApprovals[_tokenId] != address(0)) {\\n // Reset approvals\\n idToApprovals[_tokenId] = address(0);\\n }\\n }\\n\\n /// @dev Returns whether the given spender can transfer a given token ID\\n /// @param _spender address of the spender to query\\n /// @param _tokenId uint ID of the token to be transferred\\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\\n address owner = idToOwner[_tokenId];\\n bool spenderIsOwner = owner == _spender;\\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\\n }\\n\\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\\n return _isApprovedOrOwner(_spender, _tokenId);\\n }\\n\\n /// @dev Exeute transfer of a NFT.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_tokenId` is not a valid NFT.\\n function _transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n address _sender\\n ) internal {\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n // Check requirements\\n require(_isApprovedOrOwner(_sender, _tokenId));\\n // Clear approval. Throws if `_from` is not the current owner\\n _clearApproval(_from, _tokenId);\\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\\n _removeTokenFrom(_from, _tokenId);\\n // auto re-delegate\\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\\n // Add NFT\\n _addTokenTo(_to, _tokenId);\\n // Set the block of ownership transfer (for Flash NFT protection)\\n ownership_change[_tokenId] = block.number;\\n // Log the transfer\\n emit Transfer(_from, _to, _tokenId);\\n }\\n\\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\\n /// they maybe be permanently lost.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n safeTransferFrom(_from, _to, _tokenId, \\\"\\\");\\n }\\n\\n function _isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n uint size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n /// @param _data Additional data with no specified format, sent in call to `_to`.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n bytes memory _data\\n ) public {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n\\n if (_isContract(_to)) {\\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\\n revert(\\\"ERC721: ERC721Receiver rejected tokens\\\");\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert('ERC721: transfer to non ERC721Receiver implementer');\\n } else {\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC165 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Interface identification is specified in ERC-165.\\n /// @param _interfaceID Id of the interface\\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\\n return supportedInterfaces[_interfaceID];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from owner address to mapping of index to tokenIds\\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\\n\\n /// @dev Mapping from NFT ID to index of owner\\n mapping(uint => uint) internal tokenToOwnerIndex;\\n\\n /// @dev Get token by index\\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\\n return ownerToNFTokenIdList[_owner][_tokenIndex];\\n }\\n\\n /// @dev Add a NFT to an index mapping to a given address\\n /// @param _to address of the receiver\\n /// @param _tokenId uint ID Of the token to be added\\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\\n uint current_count = _balance(_to);\\n\\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\\n tokenToOwnerIndex[_tokenId] = current_count;\\n }\\n\\n /// @dev Add a NFT to a given address\\n /// Throws if `_tokenId` is owned by someone.\\n function _addTokenTo(address _to, uint _tokenId) internal {\\n // Throws if `_tokenId` is owned by someone\\n assert(idToOwner[_tokenId] == address(0));\\n // Change the owner\\n idToOwner[_tokenId] = _to;\\n // Update owner token index tracking\\n _addTokenToOwnerList(_to, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_to] += 1;\\n }\\n\\n /// @dev Function to mint tokens\\n /// Throws if `_to` is zero address.\\n /// Throws if `_tokenId` is owned by someone.\\n /// @param _to The address that will receive the minted tokens.\\n /// @param _tokenId The token id to mint.\\n /// @return A boolean that indicates if the operation was successful.\\n function _mint(address _to, uint _tokenId) internal returns (bool) {\\n // Throws if `_to` is zero address\\n assert(_to != address(0));\\n // checkpoint for gov\\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\\n // Add NFT. Throws if `_tokenId` is owned by someone\\n _addTokenTo(_to, _tokenId);\\n emit Transfer(address(0), _to, _tokenId);\\n return true;\\n }\\n\\n /// @dev Remove a NFT from an index mapping to a given address\\n /// @param _from address of the sender\\n /// @param _tokenId uint ID Of the token to be removed\\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\\n // Delete\\n uint current_count = _balance(_from) - 1;\\n uint current_index = tokenToOwnerIndex[_tokenId];\\n\\n if (current_count == current_index) {\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n } else {\\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\\n\\n // Add\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[lastTokenId] = current_index;\\n\\n // Delete\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n }\\n }\\n\\n /// @dev Remove a NFT from a given address\\n /// Throws if `_from` is not the current owner.\\n function _removeTokenFrom(address _from, uint _tokenId) internal {\\n // Throws if `_from` is not the current owner\\n assert(idToOwner[_tokenId] == _from);\\n // Change the owner\\n idToOwner[_tokenId] = address(0);\\n // Update owner token index tracking\\n _removeTokenFromOwnerList(_from, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_from] -= 1;\\n }\\n\\n function _burn(uint _tokenId) internal {\\n require(_isApprovedOrOwner(msg.sender, _tokenId), \\\"caller is not owner nor approved\\\");\\n\\n address owner = ownerOf(_tokenId);\\n\\n // Clear approval\\n approve(address(0), _tokenId);\\n // checkpoint for gov\\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\\n // Remove token\\n _removeTokenFrom(msg.sender, _tokenId);\\n emit Transfer(owner, address(0), _tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public user_point_epoch;\\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\\n mapping(uint => LockedBalance) public locked;\\n uint public epoch;\\n mapping(uint => int128) public slope_changes; // time -> signed slope change\\n uint public supply;\\n\\n uint internal constant WEEK = 1 weeks;\\n uint internal constant MAXTIME = 4 * 365 * 86400;\\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\\n uint internal constant MULTIPLIER = 1 ether;\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @return Value of the slope\\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\\n uint uepoch = user_point_epoch[_tokenId];\\n return user_point_history[_tokenId][uepoch].slope;\\n }\\n\\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @param _idx User epoch number\\n /// @return Epoch time of the checkpoint\\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\\n return user_point_history[_tokenId][_idx].ts;\\n }\\n\\n /// @notice Get timestamp when `_tokenId`'s lock finishes\\n /// @param _tokenId User NFT\\n /// @return Epoch time of the lock end\\n function locked__end(uint _tokenId) external view returns (uint) {\\n return locked[_tokenId].end;\\n }\\n\\n /// @notice Record global and per-user data to checkpoint\\n /// @param _tokenId NFT token ID. No user checkpoint if 0\\n /// @param old_locked Pevious locked amount / end lock time for the user\\n /// @param new_locked New locked amount / end lock time for the user\\n function _checkpoint(\\n uint _tokenId,\\n LockedBalance memory old_locked,\\n LockedBalance memory new_locked\\n ) internal {\\n Point memory u_old;\\n Point memory u_new;\\n int128 old_dslope = 0;\\n int128 new_dslope = 0;\\n uint _epoch = epoch;\\n\\n if (_tokenId != 0) {\\n // Calculate slopes and biases\\n // Kept at zero when they have to\\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\\n u_old.slope = old_locked.amount / iMAXTIME;\\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\\n }\\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\\n u_new.slope = new_locked.amount / iMAXTIME;\\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\\n }\\n\\n // Read values of scheduled changes in the slope\\n // old_locked.end can be in the past and in the future\\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\\n old_dslope = slope_changes[old_locked.end];\\n if (new_locked.end != 0) {\\n if (new_locked.end == old_locked.end) {\\n new_dslope = old_dslope;\\n } else {\\n new_dslope = slope_changes[new_locked.end];\\n }\\n }\\n }\\n\\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\\n if (_epoch > 0) {\\n last_point = point_history[_epoch];\\n }\\n uint last_checkpoint = last_point.ts;\\n // initial_last_point is used for extrapolation to calculate block number\\n // (approximately, for *At methods) and save them\\n // as we cannot figure that out exactly from inside the contract\\n Point memory initial_last_point = last_point;\\n uint block_slope = 0; // dblock/dt\\n if (block.timestamp > last_point.ts) {\\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\\n }\\n // If last point is already recorded in this block, slope=0\\n // But that's ok b/c we know the block in such case\\n\\n // Go over weeks to fill history and calculate what the current point is\\n {\\n uint t_i = (last_checkpoint / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n // Hopefully it won't happen that this won't get used in 5 years!\\n // If it does, users will be able to withdraw but vote weight will be broken\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > block.timestamp) {\\n t_i = block.timestamp;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\\n last_point.slope += d_slope;\\n if (last_point.bias < 0) {\\n // This can happen\\n last_point.bias = 0;\\n }\\n if (last_point.slope < 0) {\\n // This cannot happen - just in case\\n last_point.slope = 0;\\n }\\n last_checkpoint = t_i;\\n last_point.ts = t_i;\\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\\n _epoch += 1;\\n if (t_i == block.timestamp) {\\n last_point.blk = block.number;\\n break;\\n } else {\\n point_history[_epoch] = last_point;\\n }\\n }\\n }\\n\\n epoch = _epoch;\\n // Now point_history is filled until t=now\\n\\n if (_tokenId != 0) {\\n // If last point was in this block, the slope change has been applied already\\n // But in such case we have 0 slope(s)\\n last_point.slope += (u_new.slope - u_old.slope);\\n last_point.bias += (u_new.bias - u_old.bias);\\n if (last_point.slope < 0) {\\n last_point.slope = 0;\\n }\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n }\\n\\n // Record the changed point into history\\n point_history[_epoch] = last_point;\\n\\n if (_tokenId != 0) {\\n // Schedule the slope changes (slope is going down)\\n // We subtract new_user_slope from [new_locked.end]\\n // and add old_user_slope to [old_locked.end]\\n if (old_locked.end > block.timestamp) {\\n // old_dslope was - u_old.slope, so we cancel that\\n old_dslope += u_old.slope;\\n if (new_locked.end == old_locked.end) {\\n old_dslope -= u_new.slope; // It was a new deposit, not extension\\n }\\n slope_changes[old_locked.end] = old_dslope;\\n }\\n\\n if (new_locked.end > block.timestamp) {\\n if (new_locked.end > old_locked.end) {\\n new_dslope -= u_new.slope; // old slope disappeared at this point\\n slope_changes[new_locked.end] = new_dslope;\\n }\\n // else: we recorded it already in old_dslope\\n }\\n // Now handle user history\\n uint user_epoch = user_point_epoch[_tokenId] + 1;\\n\\n user_point_epoch[_tokenId] = user_epoch;\\n u_new.ts = block.timestamp;\\n u_new.blk = block.number;\\n user_point_history[_tokenId][user_epoch] = u_new;\\n }\\n }\\n\\n /// @notice Deposit and lock tokens for a user\\n /// @param _tokenId NFT that holds lock\\n /// @param _value Amount to deposit\\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\\n /// @param locked_balance Previous locked amount / timestamp\\n /// @param deposit_type The type of deposit\\n function _deposit_for(\\n uint _tokenId,\\n uint _value,\\n uint unlock_time,\\n LockedBalance memory locked_balance,\\n DepositType deposit_type\\n ) internal {\\n LockedBalance memory _locked = locked_balance;\\n uint supply_before = supply;\\n\\n supply = supply_before + _value;\\n LockedBalance memory old_locked;\\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\\n // Adding to existing lock, or if a lock is expired - creating a new one\\n _locked.amount += int128(int256(_value));\\n if (unlock_time != 0) {\\n _locked.end = unlock_time;\\n }\\n locked[_tokenId] = _locked;\\n\\n // Possibilities:\\n // Both old_locked.end could be current or expired (>/< block.timestamp)\\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\\n // _locked.end > block.timestamp (always)\\n _checkpoint(_tokenId, old_locked, _locked);\\n\\n address from = msg.sender;\\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\\n assert(IERC20(token).transferFrom(from, address(this), _value));\\n }\\n\\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\\n emit Supply(supply_before, supply_before + _value);\\n }\\n\\n function block_number() external view returns (uint) {\\n return block.number;\\n }\\n\\n /// @notice Record global data to checkpoint\\n function checkpoint() external {\\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\\n }\\n\\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\\n /// cannot extend their locktime and deposit for a brand new user\\n /// @param _tokenId lock NFT\\n /// @param _value Amount to add to user's lock\\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n require(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_value > 0); // dev: need non-zero value\\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n ++tokenId;\\n uint _tokenId = tokenId;\\n _mint(_to, _tokenId);\\n\\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\\n return _tokenId;\\n }\\n\\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, msg.sender);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, _to);\\n }\\n\\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\\n /// @param _value Amount of tokens to deposit and add to the lock\\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n assert(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\\n }\\n\\n /// @notice Extend the unlock time for `_tokenId`\\n /// @param _lock_duration New number of seconds until tokens unlock\\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_locked.end > block.timestamp, 'Lock expired');\\n require(_locked.amount > 0, 'Nothing is locked');\\n require(unlock_time > _locked.end, 'Can only increase lock duration');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\\n }\\n\\n /// @notice Withdraw all tokens for `_tokenId`\\n /// @dev Only possible if the lock has expired\\n function withdraw(uint _tokenId) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n require(block.timestamp >= _locked.end, \\\"The lock didn't expire\\\");\\n uint value = uint(int256(_locked.amount));\\n\\n locked[_tokenId] = LockedBalance(0,0);\\n uint supply_before = supply;\\n supply = supply_before - value;\\n\\n // old_locked can have either expired <= timestamp or zero end\\n // _locked has only 0 end\\n // Both can have >= 0 amount\\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\\n\\n assert(IERC20(token).transfer(msg.sender, value));\\n\\n // Burn the NFT\\n _burn(_tokenId);\\n\\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\\n emit Supply(supply_before, supply_before - value);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\\n // They measure the weights for the purpose of voting, so they don't represent\\n // real coins.\\n\\n /// @notice Binary search to estimate timestamp for block number\\n /// @param _block Block to find\\n /// @param max_epoch Don't go beyond this epoch\\n /// @return Approximate timestamp for block\\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\\n // Binary search\\n uint _min = 0;\\n uint _max = max_epoch;\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (point_history[_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n /// @notice Get the current voting power for `_tokenId`\\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\\n /// @param _tokenId NFT for lock\\n /// @param _t Epoch time to return voting power at\\n /// @return User voting power\\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\\n uint _epoch = user_point_epoch[_tokenId];\\n if (_epoch == 0) {\\n return 0;\\n } else {\\n Point memory last_point = user_point_history[_tokenId][_epoch];\\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(int256(last_point.bias));\\n }\\n }\\n\\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\\n if (ownership_change[_tokenId] == block.number) return 0;\\n return _balanceOfNFT(_tokenId, block.timestamp);\\n }\\n\\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\\n return _balanceOfNFT(_tokenId, _t);\\n }\\n\\n /// @notice Measure voting power of `_tokenId` at block height `_block`\\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\\n /// @param _tokenId User's wallet NFT\\n /// @param _block Block to calculate the voting power at\\n /// @return Voting power\\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\\n // Copying and pasting totalSupply code because Vyper cannot pass by\\n // reference yet\\n assert(_block <= block.number);\\n\\n // Binary search\\n uint _min = 0;\\n uint _max = user_point_epoch[_tokenId];\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (user_point_history[_tokenId][_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n\\n Point memory upoint = user_point_history[_tokenId][_min];\\n\\n uint max_epoch = epoch;\\n uint _epoch = _find_block_epoch(_block, max_epoch);\\n Point memory point_0 = point_history[_epoch];\\n uint d_block = 0;\\n uint d_t = 0;\\n if (_epoch < max_epoch) {\\n Point memory point_1 = point_history[_epoch + 1];\\n d_block = point_1.blk - point_0.blk;\\n d_t = point_1.ts - point_0.ts;\\n } else {\\n d_block = block.number - point_0.blk;\\n d_t = block.timestamp - point_0.ts;\\n }\\n uint block_time = point_0.ts;\\n if (d_block != 0) {\\n block_time += (d_t * (_block - point_0.blk)) / d_block;\\n }\\n\\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\\n if (upoint.bias >= 0) {\\n return uint(uint128(upoint.bias));\\n } else {\\n return 0;\\n }\\n }\\n\\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\\n return _balanceOfAtNFT(_tokenId, _block);\\n }\\n\\n /// @notice Calculate total voting power at some point in the past\\n /// @param _block Block to calculate the total voting power at\\n /// @return Total voting power at `_block`\\n function totalSupplyAt(uint _block) external view returns (uint) {\\n assert(_block <= block.number);\\n uint _epoch = epoch;\\n uint target_epoch = _find_block_epoch(_block, _epoch);\\n\\n Point memory point = point_history[target_epoch];\\n uint dt = 0;\\n if (target_epoch < _epoch) {\\n Point memory point_next = point_history[target_epoch + 1];\\n if (point.blk != point_next.blk) {\\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\\n }\\n } else {\\n if (point.blk != block.number) {\\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\\n }\\n }\\n // Now dt contains info on how far are we beyond point\\n return _supply_at(point, point.ts + dt);\\n }\\n /// @notice Calculate total voting power at some point in the past\\n /// @param point The point (bias/slope) to start search from\\n /// @param t Time to calculate the total voting power at\\n /// @return Total voting power at that time\\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\\n Point memory last_point = point;\\n uint t_i = (last_point.ts / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > t) {\\n t_i = t;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\\n if (t_i == t) {\\n break;\\n }\\n last_point.slope += d_slope;\\n last_point.ts = t_i;\\n }\\n\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(uint128(last_point.bias));\\n }\\n\\n function totalSupply() external view returns (uint) {\\n return totalSupplyAtT(block.timestamp);\\n }\\n\\n /// @notice Calculate total voting power\\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\\n /// @return Total voting power\\n function totalSupplyAtT(uint t) public view returns (uint) {\\n uint _epoch = epoch;\\n Point memory last_point = point_history[_epoch];\\n return _supply_at(last_point, t);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public attachments;\\n mapping(uint => bool) public voted;\\n\\n function setVoter(address _voter) external {\\n require(msg.sender == voter);\\n voter = _voter;\\n }\\n\\n function voting(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = true;\\n }\\n\\n function abstain(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = false;\\n }\\n\\n function attach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] + 1;\\n }\\n\\n function detach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] - 1;\\n }\\n\\n function merge(uint _from, uint _to) external {\\n require(attachments[_from] == 0 && !voted[_from], \\\"attached\\\");\\n require(_from != _to);\\n require(_isApprovedOrOwner(msg.sender, _from));\\n require(_isApprovedOrOwner(msg.sender, _to));\\n\\n LockedBalance memory _locked0 = locked[_from];\\n LockedBalance memory _locked1 = locked[_to];\\n uint value0 = uint(int256(_locked0.amount));\\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\\n\\n locked[_from] = LockedBalance(0, 0);\\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\\n _burn(_from);\\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of each accounts delegate\\n mapping(address => address) private _delegates;\\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\\n\\n /// @notice A record of delegated token checkpoints for each account, by index\\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint32) public numCheckpoints;\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping(address => uint) public nonces;\\n\\n /**\\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\\n * the delegator's own address if they haven't delegated.\\n * This avoids having to delegate to oneself.\\n */\\n function delegates(address delegator) public view returns (address) {\\n address current = _delegates[delegator];\\n return current == address(0) ? delegator : current;\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getVotes(address account) external view returns (uint) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n votes = votes + _balanceOfNFT(tId, block.timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint storage cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPastVotes(address account, uint timestamp)\\n public\\n view\\n returns (uint)\\n {\\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\\n // Sum votes\\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n // Use the provided input timestamp here to get the right decay\\n votes = votes + _balanceOfNFT(tId, timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\\n return totalSupplyAtT(timestamp);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _moveTokenDelegates(\\n address srcRep,\\n address dstRep,\\n uint _tokenId\\n ) internal {\\n if (srcRep != dstRep && _tokenId > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except _tokenId\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (tId != _tokenId) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n // All the same plus _tokenId\\n require(\\n dstRepOld.length + 1 <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n dstRepNew.push(_tokenId);\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _findWhatCheckpointToWrite(address account)\\n internal\\n view\\n returns (uint32)\\n {\\n uint _timestamp = block.timestamp;\\n uint32 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n return _nCheckPoints - 1;\\n } else {\\n return _nCheckPoints;\\n }\\n }\\n\\n function _moveAllDelegates(\\n address owner,\\n address srcRep,\\n address dstRep\\n ) internal {\\n // You can only redelegate what you own\\n if (srcRep != dstRep) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except what owner owns\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (idToOwner[tId] != owner) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n uint ownerTokenCount = ownerToNFTokenCount[owner];\\n require(\\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n // All the same\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n // Plus all that's owned\\n for (uint i = 0; i < ownerTokenCount; i++) {\\n uint tId = ownerToNFTokenIdList[owner][i];\\n dstRepNew.push(tId);\\n }\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\\n address currentDelegate = delegates(delegator);\\n\\n _delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n _moveAllDelegates(delegator, currentDelegate, delegatee);\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n if (delegatee == address(0)) delegatee = msg.sender;\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n function delegateBySig(\\n address delegatee,\\n uint nonce,\\n uint expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public {\\n bytes32 domainSeparator = keccak256(\\n abi.encode(\\n DOMAIN_TYPEHASH,\\n keccak256(bytes(name)),\\n keccak256(bytes(version)),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 structHash = keccak256(\\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash)\\n );\\n address signatory = ecrecover(digest, v, r, s);\\n require(\\n signatory != address(0),\\n \\\"VotingEscrow::delegateBySig: invalid signature\\\"\\n );\\n require(\\n nonce == nonces[signatory]++,\\n \\\"VotingEscrow::delegateBySig: invalid nonce\\\"\\n );\\n require(\\n block.timestamp <= expiry,\\n \\\"VotingEscrow::delegateBySig: signature expired\\\"\\n );\\n return _delegate(signatory, delegatee);\\n }\\n}\\n\",\"keccak256\":\"0x7109ed9d84b5504fe5d4c73d5a10997a0b73f2f4d45813ce5e161997d405fd73\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x41bbb2c41036ca64b2f6c9e973e8cfaa113ebc42af86702cd0d267f915a7e886\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a06040526006805460ff191660011790553480156200001e57600080fd5b5060405162004a1c38038062004a1c8339810160408190526200004191620001b8565b6001600160a01b0382811660805260008054336001600160a01b031991821681178355600180548316909117815560028054909216938516939093179055437f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f0155427f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f005560046020527f9fe05126d2d9ecf60592e254dead906a4b2e492f36cca727682c38e9008c6ac1805460ff1990811684179091557f4267c0a6fd96b7a87f183ee8744f24d011423cd0e0142b3f563f183d8d9a456b8054821684179055635b5e139f60e01b82527e24030bcf4927897dffe721c2d8dda4bfd8910861687c42b03a463b43b04147805490911690921790915560055460405190913091600080516020620049fc833981519152908290a46005546040516000903090600080516020620049fc833981519152908390a45050620001f0565b80516001600160a01b0381168114620001b357600080fd5b919050565b60008060408385031215620001cc57600080fd5b620001d7836200019b565b9150620001e7602084016200019b565b90509250929050565b6080516147e26200021a60003960008181610b220152818161101801526133b501526147e26000f3fe608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea26469706673582212206c2b69851a7522f6049cd18d9499b246a4af4b4db4af524e781f547e9873d04764736f6c634300080d0033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea26469706673582212206c2b69851a7522f6049cd18d9499b246a4af4b4db4af524e781f547e9873d04764736f6c634300080d0033", "devdoc": { "author": "Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)", "details": "Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).", diff --git a/deployments/arbitrumGoerli/solcInputs/1dbda4b04c9e26660611556bc8d2a346.json b/deployments/arbitrumGoerli/solcInputs/1dbda4b04c9e26660611556bc8d2a346.json new file mode 100644 index 00000000..0d153047 --- /dev/null +++ b/deployments/arbitrumGoerli/solcInputs/1dbda4b04c9e26660611556bc8d2a346.json @@ -0,0 +1,238 @@ +{ + "language": "Solidity", + "sources": { + "contracts/ExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/factories/BribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n\n// if this imports int and ext bribe why is the the gauge factory asking for those address as if they are deployed to an address.\n" + }, + "contracts/factories/GaugeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" + }, + "contracts/factories/PairFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" + }, + "contracts/factories/WrappedExternalBribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" + }, + "contracts/Flow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IFlow.sol\";\n\ncontract Flow is IFlow {\n\n string public constant name = \"Velocimeter\";\n string public constant symbol = \"FLOW\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" + }, + "contracts/FlowGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract FlowGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velocimeter Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" + }, + "contracts/Gauge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/governance/L2Governor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" + }, + "contracts/governance/L2GovernorCountingSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" + }, + "contracts/governance/L2GovernorVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" + }, + "contracts/governance/L2GovernorVotesQuorumFraction.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" + }, + "contracts/interfaces/IBribe.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IBribeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IERC20.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" + }, + "contracts/interfaces/IFlow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IFlow {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" + }, + "contracts/interfaces/IGauge.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" + }, + "contracts/interfaces/IGaugeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IMinter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" + }, + "contracts/interfaces/IPair.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IPairCallee.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" + }, + "contracts/interfaces/IPairFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" + }, + "contracts/interfaces/IRewardsDistributor.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" + }, + "contracts/interfaces/IRouter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" + }, + "contracts/interfaces/IVeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" + }, + "contracts/interfaces/IVoter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" + }, + "contracts/interfaces/IVotingEscrow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" + }, + "contracts/interfaces/IWETH.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" + }, + "contracts/InternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/libraries/Base64.sol": { + "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" + }, + "contracts/libraries/Math.sol": { + "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" + }, + "contracts/Minter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IFlow.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IFlow public immutable _flow;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M FLOW (FLOW has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _flow = IFlow(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _flow.mint(address(this), max);\n _flow.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _flow.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _flowTotal = _flow.totalSupply();\n return\n (((((_minted * _veTotal) / _flowTotal) * _veTotal) / _flowTotal) *\n _veTotal) /\n _flowTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _flow.balanceOf(address(this));\n if (_balanceOf < _required) {\n _flow.mint(address(this), _required - _balanceOf);\n }\n\n require(_flow.transfer(team, _teamEmissions));\n require(_flow.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _flow.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" + }, + "contracts/Pair.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/PairFees.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" + }, + "contracts/redeem/MerkleClaim.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IFlow} from \"contracts/interfaces/IFlow.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims FLOW for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice FLOW token to claim\n IFlow public immutable FLOW;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _flow address\n /// @param _merkleRoot of claimees\n constructor(address _flow, bytes32 _merkleRoot) {\n FLOW = IFlow(_flow);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(FLOW.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" + }, + "contracts/redeem/RedemptionReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IFlow.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + FLOW\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IFlow public immutable FLOW;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableFLOW;\n uint256 public leftoverFLOW;\n\n constructor(\n address _usdc,\n address _flow,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n FLOW = IFlow(_flow);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableFLOW);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableFLOW\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableFLOW = _redeemableFLOW;\n leftoverFLOW = _redeemableFLOW;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableFLOW);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfFLOW)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata FLOW\n shareOfFLOW = (amountWEVE * redeemableFLOW) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfFLOW) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverFLOW -= shareOfFLOW; // this will revert if underflows\n require(\n FLOW.claim(redemptionAddress, shareOfFLOW),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" + }, + "contracts/redeem/RedemptionSender.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" + }, + "contracts/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" + }, + "contracts/Router.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velocimeter locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" + }, + "contracts/VelocimeterLibrary.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelocimeterLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" + }, + "contracts/Voter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velocimeter pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VotingEscrow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `FLOW` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" + }, + "contracts/WrappedExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + }, + "libraries": { + "": { + "__CACHE_BREAKER__": "0x0000000000000031363734383736373131383433" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/87c2a0284a68497703d818e47e6d0a63.json b/deployments/arbitrumGoerli/solcInputs/87c2a0284a68497703d818e47e6d0a63.json new file mode 100644 index 00000000..66b1f5f1 --- /dev/null +++ b/deployments/arbitrumGoerli/solcInputs/87c2a0284a68497703d818e47e6d0a63.json @@ -0,0 +1,238 @@ +{ + "language": "Solidity", + "sources": { + "contracts/ExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/factories/BribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n\n// if this imports int and ext bribe why is the the gauge factory asking for those address as if they are deployed to an address.\n" + }, + "contracts/factories/GaugeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" + }, + "contracts/factories/PairFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" + }, + "contracts/factories/WrappedExternalBribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" + }, + "contracts/Flow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IFlow.sol\";\n\ncontract Flow is IFlow {\n\n string public constant name = \"Velocimeter\";\n string public constant symbol = \"FLOW\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" + }, + "contracts/FlowGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velocimeter Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" + }, + "contracts/Gauge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/governance/L2Governor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" + }, + "contracts/governance/L2GovernorCountingSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" + }, + "contracts/governance/L2GovernorVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" + }, + "contracts/governance/L2GovernorVotesQuorumFraction.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" + }, + "contracts/interfaces/IBribe.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IBribeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IERC20.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" + }, + "contracts/interfaces/IFlow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IFlow {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" + }, + "contracts/interfaces/IGauge.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" + }, + "contracts/interfaces/IGaugeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IMinter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" + }, + "contracts/interfaces/IPair.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IPairCallee.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" + }, + "contracts/interfaces/IPairFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" + }, + "contracts/interfaces/IRewardsDistributor.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" + }, + "contracts/interfaces/IRouter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" + }, + "contracts/interfaces/IVeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" + }, + "contracts/interfaces/IVoter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" + }, + "contracts/interfaces/IVotingEscrow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" + }, + "contracts/interfaces/IWETH.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" + }, + "contracts/InternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/libraries/Base64.sol": { + "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" + }, + "contracts/libraries/Math.sol": { + "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" + }, + "contracts/Minter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IFlow.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IFlow public immutable _flow;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M FLOW (FLOW has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _flow = IFlow(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _flow.mint(address(this), max);\n _flow.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _flow.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _flowTotal = _flow.totalSupply();\n return\n (((((_minted * _veTotal) / _flowTotal) * _veTotal) / _flowTotal) *\n _veTotal) /\n _flowTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _flow.balanceOf(address(this));\n if (_balanceOf < _required) {\n _flow.mint(address(this), _required - _balanceOf);\n }\n\n require(_flow.transfer(team, _teamEmissions));\n require(_flow.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _flow.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" + }, + "contracts/Pair.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/PairFees.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" + }, + "contracts/redeem/MerkleClaim.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IFlow} from \"contracts/interfaces/IFlow.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims FLOW for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice FLOW token to claim\n IFlow public immutable FLOW;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _flow address\n /// @param _merkleRoot of claimees\n constructor(address _flow, bytes32 _merkleRoot) {\n FLOW = IFlow(_flow);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(FLOW.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" + }, + "contracts/redeem/RedemptionReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IFlow.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + FLOW\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IFlow public immutable FLOW;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableFLOW;\n uint256 public leftoverFLOW;\n\n constructor(\n address _usdc,\n address _flow,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n FLOW = IFlow(_flow);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableFLOW);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableFLOW\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableFLOW = _redeemableFLOW;\n leftoverFLOW = _redeemableFLOW;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableFLOW);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfFLOW)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata FLOW\n shareOfFLOW = (amountWEVE * redeemableFLOW) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfFLOW) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverFLOW -= shareOfFLOW; // this will revert if underflows\n require(\n FLOW.claim(redemptionAddress, shareOfFLOW),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" + }, + "contracts/redeem/RedemptionSender.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" + }, + "contracts/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" + }, + "contracts/Router.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velocimeter locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" + }, + "contracts/VelocimeterLibrary.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelocimeterLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" + }, + "contracts/Voter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velocimeter pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VotingEscrow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `FLOW` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" + }, + "contracts/WrappedExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + }, + "libraries": { + "": { + "__CACHE_BREAKER__": "0x0000000000000031363734383736303733333539" + } + } + } +} \ No newline at end of file diff --git a/dist/deploy/12_veloGovernor.js b/dist/deploy/12_veloGovernor.js index a8debabc..e5e1293f 100644 --- a/dist/deploy/12_veloGovernor.js +++ b/dist/deploy/12_veloGovernor.js @@ -5,7 +5,7 @@ const func = async function (hre) { const { deploy } = deployments const { deployer } = await getNamedAccounts() const escrow = await deployments.get('VotingEscrow') - await deploy('VeloGovernor', { + await deploy('FlowGovernor', { from: deployer, args: [escrow.address], log: true, @@ -13,5 +13,5 @@ const func = async function (hre) { }) } exports.default = func -func.tags = ['VeloGovernor'] -func.id = 'veloGovernor' +func.tags = ['FlowGovernor'] +func.id = 'FlowGovernor' diff --git a/dist/deploy/15_init.js b/dist/deploy/15_init.js index aa5083f9..9f2bb6fa 100644 --- a/dist/deploy/15_init.js +++ b/dist/deploy/15_init.js @@ -6,7 +6,7 @@ var __importDefault = } Object.defineProperty(exports, '__esModule', { value: true }) const arbTestnetConfig_1 = __importDefault( - require('../tasks/deploy/constants/arbTestnetConfig') + require('../tasks/deploy/constants/arbConfig') // update to arbConfig ) const ARB_TEST_CONFIG = arbTestnetConfig_1.default const func = async function (hre) { @@ -16,7 +16,7 @@ const func = async function (hre) { const escrow = await ethers.getContract('VotingEscrow') const voter = await ethers.getContract('Voter') const distributor = await ethers.getContract('RewardsDistributor') - const governor = await ethers.getContract('VeloGovernor') + const governor = await ethers.getContract('FlowGovernor') const minter = await ethers.getContract('Minter') const receiver = await ethers.getContract('RedemptionReceiver') const claim = await deployments.get('MerkleClaim') diff --git a/dist/tasks/deploy/arb.js b/dist/tasks/deploy/arb.js index 8475fb62..64b25b66 100644 --- a/dist/tasks/deploy/arb.js +++ b/dist/tasks/deploy/arb.js @@ -40,7 +40,7 @@ const testFantomConfig_1 = __importDefault( RewardsDistributor, Voter, Minter, - VeloGovernor, + FlowGovernor, RedemptionReceiver, MerkleClaim ] = await Promise.all([ @@ -55,7 +55,7 @@ const testFantomConfig_1 = __importDefault( ethers.getContractFactory('RewardsDistributor'), ethers.getContractFactory('Voter'), ethers.getContractFactory('Minter'), - ethers.getContractFactory('VeloGovernor'), + ethers.getContractFactory('FlowGovernor'), ethers.getContractFactory('RedemptionReceiver'), ethers.getContractFactory('MerkleClaim') ]) @@ -136,9 +136,9 @@ const testFantomConfig_1 = __importDefault( ARB_CONFIG.lzEndpoint, '\n' ) - const governor = await VeloGovernor.deploy(escrow.address) + const governor = await FlowGovernor.deploy(escrow.address) await governor.deployed() - console.log('VeloGovernor deployed to: ', governor.address) + console.log('FlowGovernor deployed to: ', governor.address) console.log('Args: ', escrow.address, '\n') // Airdrop const claim = await MerkleClaim.deploy(flow.address, ARB_CONFIG.merkleRoot) diff --git a/dist/tasks/deploy/arbHardhat.js b/dist/tasks/deploy/arbHardhat.js index 0720dd0e..e1a36a5f 100644 --- a/dist/tasks/deploy/arbHardhat.js +++ b/dist/tasks/deploy/arbHardhat.js @@ -40,7 +40,7 @@ const testFantomConfig_1 = __importDefault( RewardsDistributor, Voter, Minter, - VeloGovernor, + FlowGovernor, RedemptionReceiver, MerkleClaim ] = await Promise.all([ @@ -55,7 +55,7 @@ const testFantomConfig_1 = __importDefault( ethers.getContractFactory('RewardsDistributor'), ethers.getContractFactory('Voter'), ethers.getContractFactory('Minter'), - ethers.getContractFactory('VeloGovernor'), + ethers.getContractFactory('FlowGovernor'), ethers.getContractFactory('RedemptionReceiver'), ethers.getContractFactory('MerkleClaim') ]) @@ -136,9 +136,9 @@ const testFantomConfig_1 = __importDefault( ARB_CONFIG.lzEndpoint, '\n' ) - const governor = await VeloGovernor.deploy(escrow.address) + const governor = await FlowGovernor.deploy(escrow.address) await governor.deployed() - console.log('VeloGovernor deployed to: ', governor.address) + console.log('FlowGovernor deployed to: ', governor.address) console.log('Args: ', escrow.address, '\n') // Airdrop const claim = await MerkleClaim.deploy(flow.address, ARB_CONFIG.merkleRoot) diff --git a/dist/tasks/deploy/arbTest.js b/dist/tasks/deploy/arbTest.js index 07566daa..89c6b544 100644 --- a/dist/tasks/deploy/arbTest.js +++ b/dist/tasks/deploy/arbTest.js @@ -37,7 +37,7 @@ const testFantomConfig_1 = __importDefault( RewardsDistributor, Voter, Minter, - VeloGovernor, + FlowGovernor, RedemptionReceiver, MerkleClaim ] = await Promise.all([ @@ -52,7 +52,7 @@ const testFantomConfig_1 = __importDefault( ethers.getContractFactory('RewardsDistributor'), ethers.getContractFactory('Voter'), ethers.getContractFactory('Minter'), - ethers.getContractFactory('VeloGovernor'), + ethers.getContractFactory('FlowGovernor'), ethers.getContractFactory('RedemptionReceiver'), ethers.getContractFactory('MerkleClaim') ]) @@ -187,9 +187,9 @@ const testFantomConfig_1 = __importDefault( OP_CONFIG.lzEndpoint, '\n' ) - const governor = await VeloGovernor.deploy(escrow.address) + const governor = await FlowGovernor.deploy(escrow.address) await governor.deployed() - console.log('VeloGovernor deployed to: ', governor.address) + console.log('FlowGovernor deployed to: ', governor.address) console.log('Args: ', escrow.address, '\n') // Airdrop // const claim = await MerkleClaim.deploy(flow.address, OP_CONFIG.merkleRoot) diff --git a/dist/tasks/deploy/constants/arbConfig.js b/dist/tasks/deploy/constants/arbConfig.js index d70c0474..83452314 100644 --- a/dist/tasks/deploy/constants/arbConfig.js +++ b/dist/tasks/deploy/constants/arbConfig.js @@ -46,6 +46,10 @@ const arbConfig = { wtck: TEAM_EOA, torbik: TEAM_EOA, velodromeMultisig: TEAM_EOA, + arbitrumTeam: TEAM_MULTISIG, + velodromeMultisig: TEAM_MULTISIG, + anton: TEAM_MULTISIG, + andre: TEAM_MULTISIG, emergencyCouncil: '0xcC2D01030eC2cd187346F70bFc483F24488C32E8', merkleRoot: @@ -74,105 +78,107 @@ const arbConfig = { // "", // HOP -- N/A ], partnerAddrs: [ - TEAM_MULTISIG, // Protocol owned NFT 64m - '0x069e85D4F1010DD961897dC8C095FBB5FF297434', // dunks - '0x3c5Aac016EF2F178e8699D6208796A2D67557fe2', // ceazor - '0x03B88DacB7c21B54cEfEcC297D981E5b721A9dF1', //coolie - - - ''//faeflow, - '0x78e801136F77805239A7F533521A7a5570F572C8', //wtck, - '0x0b776552c1Aef1Dc33005DD25AcDA22493b6615d',//torbik, - velodromeMultisig, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG, - TEAM_MULTISIG // 38 x protcol / partner NFTs + TEAM_MULTISIG, // 1 Protocol owned NFT 64m + '0x069e85D4F1010DD961897dC8C095FBB5FF297434', // 2 dunks + '0x3c5Aac016EF2F178e8699D6208796A2D67557fe2', // 3 ceazor + '0x03B88DacB7c21B54cEfEcC297D981E5b721A9dF1', // 4coolie + + '0xf78da0B8Ae888C318e1A19415d593729A61Ac0c3', // 5 faeflow, + '0x78e801136F77805239A7F533521A7a5570F572C8', // 6 wtck, + '0x0b776552c1Aef1Dc33005DD25AcDA22493b6615d', // 7 torbik, + velodromeMultisig, // 8 should we split this up? + anton, // 9 half % + andre, // 10 half % + arbitrumTeam, // 11 minimum 1% could be more if they help us + TEAM_MULTISIG, // 12 + TEAM_MULTISIG, // 13 + TEAM_MULTISIG, // 14 + TEAM_MULTISIG, // 15 + TEAM_MULTISIG, // 16 + TEAM_MULTISIG, // 17 + TEAM_MULTISIG, // 18 + TEAM_MULTISIG, // 19 + TEAM_MULTISIG, // 20 + TEAM_MULTISIG, // 21 + TEAM_MULTISIG, // 22 + TEAM_MULTISIG, // 23 + TEAM_MULTISIG, // 24 + TEAM_MULTISIG, // 25 + TEAM_MULTISIG, // 26 + TEAM_MULTISIG, // 27 + TEAM_MULTISIG, // 28 + TEAM_MULTISIG, // 29 + TEAM_MULTISIG, // 30 + TEAM_MULTISIG, // 31 + TEAM_MULTISIG, // 32 + TEAM_MULTISIG, // 33 + TEAM_MULTISIG, // 34 + TEAM_MULTISIG, // 35 + TEAM_MULTISIG, // 36 + TEAM_MULTISIG, // 37 + TEAM_MULTISIG, // 38 + TEAM_MULTISIG, // 39 + TEAM_MULTISIG, // 40 + TEAM_MULTISIG, // 41 + TEAM_MULTISIG, // 42 + TEAM_MULTISIG, // 43 + TEAM_MULTISIG, // 44 + TEAM_MULTISIG, // 45 + TEAM_MULTISIG, // 46 + TEAM_MULTISIG, // 47 + TEAM_MULTISIG, // 48 + TEAM_MULTISIG // 38 x protcol / partner NFTs # 49 ], partnerAmts: [ - SIXTY_MILLION, // 60 million for protcol owned NFT 15% - TWO_MILLION, // dunks presale - TWO_MILLION, // ceazor presale - FOUR_MILLION, // team veFLOW 1% - FOUR_MILLION, // team veFLOW 1% - FOUR_MILLION, // team veFLOW 1% - FOUR_MILLION, // team veFLOW 1% - FOUR_MILLION, // team veFLOW 1% - FOUR_MILLION, // team veFLOW 1% - FOUR_MILLION, // tribute to velodrome (need to get their arb address DO NOT USE MULTISIG FROM OP) - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION // 1% to each partner x 38 partners + SIXTY_MILLION, // 60 million for protcol owned NFT 15% 1 + TWO_MILLION, // dunks presale 2 + TWO_MILLION, // ceazor presale 3 + FOUR_MILLION, // team veFLOW 1% 4 + FOUR_MILLION, // team veFLOW 1% 5 + FOUR_MILLION, // team veFLOW 1% 6 + FOUR_MILLION, // team veFLOW 1% 7 + FOUR_MILLION, // team veFLOW 1% 8 + FOUR_MILLION, // team veFLOW 1% 9 + FOUR_MILLION, // 10 tribute to velodrome (need to get their arb address DO NOT USE MULTISIG FROM OP) + FOUR_MILLION, //11 + FOUR_MILLION, // 12 + FOUR_MILLION, // 13 + FOUR_MILLION, // 14 + FOUR_MILLION, // 15 + FOUR_MILLION, // 16 + FOUR_MILLION, // 17 + FOUR_MILLION, // 18 + FOUR_MILLION, // 19 + FOUR_MILLION, // 20 + FOUR_MILLION, // 21 + FOUR_MILLION, // 22 + FOUR_MILLION, // 23 + FOUR_MILLION, // 24 + FOUR_MILLION, // 25 + FOUR_MILLION, // 26 + FOUR_MILLION, // 27 + FOUR_MILLION, // 28 + FOUR_MILLION, // 29 + FOUR_MILLION, // 30 + FOUR_MILLION, // 31 + FOUR_MILLION, // 32 + FOUR_MILLION, // 33 + FOUR_MILLION, // 34 + FOUR_MILLION, // 35 + FOUR_MILLION, // 36 + FOUR_MILLION, // 37 + FOUR_MILLION, // 38 + FOUR_MILLION, // 39 + FOUR_MILLION, // 40 + FOUR_MILLION, // 41 + FOUR_MILLION, // 42 + FOUR_MILLION, // 43 + FOUR_MILLION, // 44 + FOUR_MILLION, // 45 + FOUR_MILLION, // 46 + FOUR_MILLION, // 47 + FOUR_MILLION, // 48 + FOUR_MILLION // 1% to each partner x 38 partners # 49 ], partnerMax: PARTNER_MAX } diff --git a/dist/tasks/deploy/op.js b/dist/tasks/deploy/op.js index 6de39dd8..e9a6fb01 100644 --- a/dist/tasks/deploy/op.js +++ b/dist/tasks/deploy/op.js @@ -36,7 +36,7 @@ const testFantomConfig_1 = __importDefault( RewardsDistributor, Voter, Minter, - VeloGovernor, + FlowGovernor, RedemptionReceiver, MerkleClaim ] = await Promise.all([ @@ -51,7 +51,7 @@ const testFantomConfig_1 = __importDefault( ethers.getContractFactory('RewardsDistributor'), ethers.getContractFactory('Voter'), ethers.getContractFactory('Minter'), - ethers.getContractFactory('VeloGovernor'), + ethers.getContractFactory('FlowGovernor'), ethers.getContractFactory('RedemptionReceiver'), ethers.getContractFactory('MerkleClaim') ]) @@ -132,9 +132,9 @@ const testFantomConfig_1 = __importDefault( OP_CONFIG.lzEndpoint, '\n' ) - const governor = await VeloGovernor.deploy(escrow.address) + const governor = await FlowGovernor.deploy(escrow.address) await governor.deployed() - console.log('VeloGovernor deployed to: ', governor.address) + console.log('FlowGovernor deployed to: ', governor.address) console.log('Args: ', escrow.address, '\n') // Airdrop const claim = await MerkleClaim.deploy(flow.address, OP_CONFIG.merkleRoot) diff --git a/readme.md b/readme.md index 50bc4811..1b1eb366 100644 --- a/readme.md +++ b/readme.md @@ -24,7 +24,7 @@ npx hardhat --network arbitrumGoerli export --export ./exported.json Router: '0x1B0aC6bf6f35E638f6cce8D69C6074561273dc52', VeArtProxy: '0x821B98D42D3AB509AF4F54205f0c52B019b9E2D5', Flow: '0x84Ca387E7ede764A3284c67Ff8c68a305a9030a0', - VeloGovernor: '0x1a79b9daa3E741774bf67732F8a8B5820De8A53a', + FlowGovernor: '0x1a79b9daa3E741774bf67732F8a8B5820De8A53a', VelocimeterLibrary: '0xcbE4714A95f866EB9C2eB50856F431f9E7353Ab6', Voter: '0x854086d39955d28317aE3856399312b8Edb1B473', VotingEscrow: '0xBf05364D6cf1586852c18c6b1CbEe218E3e09885' @@ -76,7 +76,7 @@ The Velocimeter team engaged with Code 4rena for a security review. The results | BribeFactory | [0xA84EA94Aa705F7d009CDDF2a60f65c0d446b748E](https://optimistic.etherscan.io/address/0xA84EA94Aa705F7d009CDDF2a60f65c0d446b748E#code) | | GaugeFactory | [0xC5be2c918EB04B091962fDF095A217A55CFA42C5](https://optimistic.etherscan.io/address/0xC5be2c918EB04B091962fDF095A217A55CFA42C5#code) | | Voter | [0x09236cfF45047DBee6B921e00704bed6D6B8Cf7e](https://optimistic.etherscan.io/address/0x09236cfF45047DBee6B921e00704bed6D6B8Cf7e#code) | -| VeloGovernor | [0x64DD805aa894dc001f8505e000c7535179D96C9E](https://optimistic.etherscan.io/address/0x64DD805aa894dc001f8505e000c7535179D96C9E#code) | +| FlowGovernor | [0x64DD805aa894dc001f8505e000c7535179D96C9E](https://optimistic.etherscan.io/address/0x64DD805aa894dc001f8505e000c7535179D96C9E#code) | | VotingEscrow | [0x9c7305eb78a432ced5C4D14Cac27E8Ed569A2e26](https://optimistic.etherscan.io/address/0x9c7305eb78a432ced5C4D14Cac27E8Ed569A2e26#code) | | VeArtProxy | [0x5F2f6721Ca0C5AC522BC875fA3F09bF693dcFa1D](https://optimistic.etherscan.io/address/0x5F2f6721Ca0C5AC522BC875fA3F09bF693dcFa1D#code) | | RewardsDistributor | [0x5d5Bea9f0Fc13d967511668a60a3369fD53F784F](https://optimistic.etherscan.io/address/0x5d5Bea9f0Fc13d967511668a60a3369fD53F784F#code) | diff --git a/tasks/deploy/arb.ts b/tasks/deploy/arb.ts index 3958cd65..fe7166e3 100644 --- a/tasks/deploy/arb.ts +++ b/tasks/deploy/arb.ts @@ -36,7 +36,7 @@ task('deploy:arb', 'Deploys Arbitrum contracts').setAction(async function ( RewardsDistributor, Voter, Minter, - VeloGovernor, + FlowGovernor, RedemptionReceiver, MerkleClaim ] = await Promise.all([ @@ -51,7 +51,7 @@ task('deploy:arb', 'Deploys Arbitrum contracts').setAction(async function ( ethers.getContractFactory('RewardsDistributor'), ethers.getContractFactory('Voter'), ethers.getContractFactory('Minter'), - ethers.getContractFactory('VeloGovernor'), + ethers.getContractFactory('FlowGovernor'), ethers.getContractFactory('RedemptionReceiver'), ethers.getContractFactory('MerkleClaim') ]) @@ -145,9 +145,9 @@ task('deploy:arb', 'Deploys Arbitrum contracts').setAction(async function ( '\n' ) - const governor = await VeloGovernor.deploy(escrow.address) + const governor = await FlowGovernor.deploy(escrow.address) await governor.deployed() - console.log('VeloGovernor deployed to: ', governor.address) + console.log('FlowGovernor deployed to: ', governor.address) console.log('Args: ', escrow.address, '\n') // Airdrop diff --git a/tasks/deploy/arbHardhat.ts b/tasks/deploy/arbHardhat.ts index 87b08b73..1ef3e463 100644 --- a/tasks/deploy/arbHardhat.ts +++ b/tasks/deploy/arbHardhat.ts @@ -33,7 +33,7 @@ task('deploy:arbHardhat', 'Deploys Arbitrum forked chain contracts').setAction( RewardsDistributor, Voter, Minter, - VeloGovernor, + FlowGovernor, RedemptionReceiver, MerkleClaim ] = await Promise.all([ @@ -48,7 +48,7 @@ task('deploy:arbHardhat', 'Deploys Arbitrum forked chain contracts').setAction( ethers.getContractFactory('RewardsDistributor'), ethers.getContractFactory('Voter'), ethers.getContractFactory('Minter'), - ethers.getContractFactory('VeloGovernor'), + ethers.getContractFactory('FlowGovernor'), ethers.getContractFactory('RedemptionReceiver'), ethers.getContractFactory('MerkleClaim') ]) @@ -142,9 +142,9 @@ task('deploy:arbHardhat', 'Deploys Arbitrum forked chain contracts').setAction( '\n' ) - const governor = await VeloGovernor.deploy(escrow.address) + const governor = await FlowGovernor.deploy(escrow.address) await governor.deployed() - console.log('VeloGovernor deployed to: ', governor.address) + console.log('FlowGovernor deployed to: ', governor.address) console.log('Args: ', escrow.address, '\n') // Airdrop diff --git a/tasks/deploy/arbTest.ts b/tasks/deploy/arbTest.ts index d342c00c..e03b62fc 100644 --- a/tasks/deploy/arbTest.ts +++ b/tasks/deploy/arbTest.ts @@ -30,7 +30,7 @@ task('deploy:arbTest', 'Deploys Optimism contracts').setAction(async function ( RewardsDistributor, Voter, Minter, - VeloGovernor, + FlowGovernor, RedemptionReceiver, MerkleClaim ] = await Promise.all([ @@ -45,7 +45,7 @@ task('deploy:arbTest', 'Deploys Optimism contracts').setAction(async function ( ethers.getContractFactory('RewardsDistributor'), ethers.getContractFactory('Voter'), ethers.getContractFactory('Minter'), - ethers.getContractFactory('VeloGovernor'), + ethers.getContractFactory('FlowGovernor'), ethers.getContractFactory('RedemptionReceiver'), ethers.getContractFactory('MerkleClaim') ]) @@ -204,9 +204,9 @@ task('deploy:arbTest', 'Deploys Optimism contracts').setAction(async function ( '\n' ) - const governor = await VeloGovernor.deploy(escrow.address) + const governor = await FlowGovernor.deploy(escrow.address) await governor.deployed() - console.log('VeloGovernor deployed to: ', governor.address) + console.log('FlowGovernor deployed to: ', governor.address) console.log('Args: ', escrow.address, '\n') // Airdrop diff --git a/tasks/deploy/op.ts b/tasks/deploy/op.ts index d1042b90..cd0c5f77 100644 --- a/tasks/deploy/op.ts +++ b/tasks/deploy/op.ts @@ -28,7 +28,7 @@ task('deploy:op', 'Deploys Optimism contracts').setAction(async function ( RewardsDistributor, Voter, Minter, - VeloGovernor, + FlowGovernor, RedemptionReceiver, MerkleClaim ] = await Promise.all([ @@ -43,7 +43,7 @@ task('deploy:op', 'Deploys Optimism contracts').setAction(async function ( ethers.getContractFactory('RewardsDistributor'), ethers.getContractFactory('Voter'), ethers.getContractFactory('Minter'), - ethers.getContractFactory('VeloGovernor'), + ethers.getContractFactory('FlowGovernor'), ethers.getContractFactory('RedemptionReceiver'), ethers.getContractFactory('MerkleClaim') ]) @@ -137,9 +137,9 @@ task('deploy:op', 'Deploys Optimism contracts').setAction(async function ( '\n' ) - const governor = await VeloGovernor.deploy(escrow.address) + const governor = await FlowGovernor.deploy(escrow.address) await governor.deployed() - console.log('VeloGovernor deployed to: ', governor.address) + console.log('FlowGovernor deployed to: ', governor.address) console.log('Args: ', escrow.address, '\n') // Airdrop diff --git a/test/VeloGovernor.t.sol b/test/VeloGovernor.t.sol index 458b1715..810f39b1 100644 --- a/test/VeloGovernor.t.sol +++ b/test/VeloGovernor.t.sol @@ -1,9 +1,9 @@ pragma solidity 0.8.13; import "./BaseTest.sol"; -import "contracts/VeloGovernor.sol"; +import "contracts/FlowGovernor.sol"; -contract VeloGovernorTest is BaseTest { +contract FlowGovernorTest is BaseTest { VotingEscrow escrow; GaugeFactory gaugeFactory; BribeFactory bribeFactory; @@ -12,7 +12,7 @@ contract VeloGovernorTest is BaseTest { Minter minter; Gauge gauge; InternalBribe bribe; - VeloGovernor governor; + FlowGovernor governor; function setUp() public { deployOwners(); @@ -63,7 +63,7 @@ contract VeloGovernorTest is BaseTest { gauge = Gauge(gaugeAddress); bribe = InternalBribe(bribeAddress); - governor = new VeloGovernor(escrow); + governor = new FlowGovernor(escrow); voter.setGovernor(address(governor)); } From 78324f325d03b628ddd1a075bb656aabaa43f606 Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Sat, 28 Jan 2023 21:20:16 +1100 Subject: [PATCH 23/43] deploy script with arbConfig makes it to the very last step then fails --- deploy/05_router.ts | 4 +- deploy/13_redemptionReceiver.ts | 4 +- deploy/14_merkleClaim.ts | 4 +- deploy/15_init.ts | 6 + deploy/16_whitelist.ts | 4 +- deploy/17_dist.ts | 4 +- deployments/arbitrumGoerli/.migrations.json | 5 - deployments/arbitrumGoerli/BribeFactory.json | 22 +- deployments/arbitrumGoerli/Flow.json | 32 +- deployments/arbitrumGoerli/FlowGovernor.json | 38 +- deployments/arbitrumGoerli/GaugeFactory.json | 22 +- deployments/arbitrumGoerli/MerkleClaim.json | 28 +- deployments/arbitrumGoerli/Minter.json | 28 +- deployments/arbitrumGoerli/PairFactory.json | 28 +- .../arbitrumGoerli/RedemptionReceiver.json | 24 +- .../arbitrumGoerli/RewardsDistributor.json | 38 +- deployments/arbitrumGoerli/Router.json | 26 +- deployments/arbitrumGoerli/VeArtProxy.json | 26 +- deployments/arbitrumGoerli/Velo.json | 522 ------ deployments/arbitrumGoerli/VeloGovernor.json | 1459 ----------------- .../arbitrumGoerli/VelocimeterLibrary.json | 24 +- .../arbitrumGoerli/VelodromeLibrary.json | 229 --- deployments/arbitrumGoerli/Voter.json | 30 +- deployments/arbitrumGoerli/VotingEscrow.json | 48 +- .../0faaa79d8b79020b765ba7705413c447.json | 238 --- .../1bc83d498cf3ed68f4ca9abac087a4fd.json | 238 --- .../230cd08a65e08d438d74567532df4760.json | 238 --- .../2aff87e12ab2599f097157a40df1b1f2.json | 238 --- .../44ac1d7fba4690e053e773a8c0d73438.json | 238 --- .../52dedb568751596f5f7bda36f8e139c0.json | 238 --- ... => 539b862778415c77e4d39b17addb6c5e.json} | 2 +- .../55f774ad815c4347b8fbe726bc77554f.json | 238 --- ... => 5e3bd610e528b3bcf2b3d4c538d2d553.json} | 4 +- .../6045e31091c7162ece1e348fdb6fb21d.json | 238 --- .../7fabbf584e02c1cd20d7799a434dc4a7.json | 238 --- .../97fe41ab3f7afe2e310d7855146d97a7.json | 238 --- ... => 98b870afa86e9d5388a96f4e867892a9.json} | 4 +- .../a6a0d6751205558353275c1f5e5364e9.json | 238 --- .../b32caaa26f5963725c04cc29c5c19ad6.json | 238 --- .../bb56ebd0528f2e0f691b8bc31f08a7c1.json | 238 --- .../d10aa8d28a580b2f5faf1ce0f5049c27.json | 238 --- .../d1b0dfe2e40ce60c1a0cf04472752ec9.json | 238 --- .../e6fbf9feea298b0eb6ed1dc19df1c5ab.json | 238 --- dist/deploy/00_velo.d.ts | 6 +- dist/deploy/05_router.js | 2 +- dist/deploy/13_redemptionReceiver.js | 2 +- dist/deploy/14_merkleClaim.js | 2 +- dist/deploy/15_init.js | 4 +- dist/deploy/16_whitelist.js | 2 +- dist/deploy/17_dist.js | 44 +- dist/hardhat.config.js | 2 +- dist/tasks/deploy/arb.js | 12 +- dist/tasks/deploy/constants/arbConfig.js | 44 +- hardhat.config.ts | 1 + tasks/deploy/arb.ts | 2 +- tasks/deploy/arbTest.ts | 2 +- tasks/deploy/constants/arbConfig.ts | 184 ++- 57 files changed, 427 insertions(+), 6355 deletions(-) delete mode 100644 deployments/arbitrumGoerli/.migrations.json delete mode 100644 deployments/arbitrumGoerli/Velo.json delete mode 100644 deployments/arbitrumGoerli/VeloGovernor.json delete mode 100644 deployments/arbitrumGoerli/VelodromeLibrary.json delete mode 100644 deployments/arbitrumGoerli/solcInputs/0faaa79d8b79020b765ba7705413c447.json delete mode 100644 deployments/arbitrumGoerli/solcInputs/1bc83d498cf3ed68f4ca9abac087a4fd.json delete mode 100644 deployments/arbitrumGoerli/solcInputs/230cd08a65e08d438d74567532df4760.json delete mode 100644 deployments/arbitrumGoerli/solcInputs/2aff87e12ab2599f097157a40df1b1f2.json delete mode 100644 deployments/arbitrumGoerli/solcInputs/44ac1d7fba4690e053e773a8c0d73438.json delete mode 100644 deployments/arbitrumGoerli/solcInputs/52dedb568751596f5f7bda36f8e139c0.json rename deployments/arbitrumGoerli/solcInputs/{1dbda4b04c9e26660611556bc8d2a346.json => 539b862778415c77e4d39b17addb6c5e.json} (99%) delete mode 100644 deployments/arbitrumGoerli/solcInputs/55f774ad815c4347b8fbe726bc77554f.json rename deployments/arbitrumGoerli/solcInputs/{4fb7d8e79af343f7b73620261b95024e.json => 5e3bd610e528b3bcf2b3d4c538d2d553.json} (99%) delete mode 100644 deployments/arbitrumGoerli/solcInputs/6045e31091c7162ece1e348fdb6fb21d.json delete mode 100644 deployments/arbitrumGoerli/solcInputs/7fabbf584e02c1cd20d7799a434dc4a7.json delete mode 100644 deployments/arbitrumGoerli/solcInputs/97fe41ab3f7afe2e310d7855146d97a7.json rename deployments/arbitrumGoerli/solcInputs/{87c2a0284a68497703d818e47e6d0a63.json => 98b870afa86e9d5388a96f4e867892a9.json} (99%) delete mode 100644 deployments/arbitrumGoerli/solcInputs/a6a0d6751205558353275c1f5e5364e9.json delete mode 100644 deployments/arbitrumGoerli/solcInputs/b32caaa26f5963725c04cc29c5c19ad6.json delete mode 100644 deployments/arbitrumGoerli/solcInputs/bb56ebd0528f2e0f691b8bc31f08a7c1.json delete mode 100644 deployments/arbitrumGoerli/solcInputs/d10aa8d28a580b2f5faf1ce0f5049c27.json delete mode 100644 deployments/arbitrumGoerli/solcInputs/d1b0dfe2e40ce60c1a0cf04472752ec9.json delete mode 100644 deployments/arbitrumGoerli/solcInputs/e6fbf9feea298b0eb6ed1dc19df1c5ab.json diff --git a/deploy/05_router.ts b/deploy/05_router.ts index 33050b5b..9cb552eb 100644 --- a/deploy/05_router.ts +++ b/deploy/05_router.ts @@ -1,8 +1,8 @@ import { HardhatRuntimeEnvironment } from 'hardhat/types' import { DeployFunction } from 'hardhat-deploy/types' -import arbTestnetConfig from '../tasks/deploy/constants/arbTestnetConfig' -const ARB_TEST_CONFIG = arbTestnetConfig +import arbConfig from '../tasks/deploy/constants/arbConfig' +const ARB_TEST_CONFIG = arbConfig const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, getNamedAccounts } = hre diff --git a/deploy/13_redemptionReceiver.ts b/deploy/13_redemptionReceiver.ts index 6ef22fa7..e54f10e9 100644 --- a/deploy/13_redemptionReceiver.ts +++ b/deploy/13_redemptionReceiver.ts @@ -1,10 +1,10 @@ import { HardhatRuntimeEnvironment } from 'hardhat/types' import { DeployFunction } from 'hardhat-deploy/types' -import arbTestnetConfig from '../tasks/deploy/constants/arbTestnetConfig' +import arbConfig from '../tasks/deploy/constants/arbConfig' import testFantomConfig from '../tasks/deploy/constants/testFantomConfig' -const ARB_TEST_CONFIG = arbTestnetConfig +const ARB_TEST_CONFIG = arbConfig const FTM_CONFIG = testFantomConfig const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { diff --git a/deploy/14_merkleClaim.ts b/deploy/14_merkleClaim.ts index b5e013b7..eb7ace46 100644 --- a/deploy/14_merkleClaim.ts +++ b/deploy/14_merkleClaim.ts @@ -2,9 +2,9 @@ import { HardhatRuntimeEnvironment } from 'hardhat/types' import { DeployFunction } from 'hardhat-deploy/types' //import arbTestnetConfig from '../tasks/deploy/constants/arbTestnetConfig' -import arbHardhatConfig from '../tasks/deploy/constants/arbHardhatConfig' +import arbConfig from '../tasks/deploy/constants/arbConfig' -const ARB_TEST_CONFIG = arbHardhatConfig +const ARB_TEST_CONFIG = arbConfig const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, getNamedAccounts } = hre diff --git a/deploy/15_init.ts b/deploy/15_init.ts index 2ef1ae36..19422806 100644 --- a/deploy/15_init.ts +++ b/deploy/15_init.ts @@ -65,6 +65,12 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { await minter.setTeam(ARB_TEST_CONFIG.teamMultisig) console.log('Team set for minter') + await minter.initialize( + ARB_TEST_CONFIG.partnerAddrs, + ARB_TEST_CONFIG.partnerAmts, + ARB_TEST_CONFIG.partnerMax + ) + // create pair // provide liq // etc etc diff --git a/deploy/16_whitelist.ts b/deploy/16_whitelist.ts index f94df781..8354d3f6 100644 --- a/deploy/16_whitelist.ts +++ b/deploy/16_whitelist.ts @@ -1,9 +1,9 @@ import { HardhatRuntimeEnvironment } from 'hardhat/types' import { DeployFunction } from 'hardhat-deploy/types' -import arbTestnetConfig from '../tasks/deploy/constants/arbTestnetConfig' +import arbConfig from '../tasks/deploy/constants/arbConfig' -const ARB_TEST_CONFIG = arbTestnetConfig +const ARB_TEST_CONFIG = arbConfig const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { ethers } = hre diff --git a/deploy/17_dist.ts b/deploy/17_dist.ts index 294d1678..e7e940fb 100644 --- a/deploy/17_dist.ts +++ b/deploy/17_dist.ts @@ -3,9 +3,9 @@ import { DeployFunction } from 'hardhat-deploy/types' // import * as tasks1 from 'tasks/deploy/arbHardhat' import arbTestnetConfig from '../tasks/deploy/constants/arbTestnetConfig' -import arbHardhatConfig from '../tasks/deploy/constants/arbHardhatConfig' +import arbConfig from '../tasks/deploy/constants/arbConfig' -const ARB_TEST_CONFIG = arbHardhatConfig +const ARB_TEST_CONFIG = arbConfig const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { ethers } = hre diff --git a/deployments/arbitrumGoerli/.migrations.json b/deployments/arbitrumGoerli/.migrations.json deleted file mode 100644 index 1049d810..00000000 --- a/deployments/arbitrumGoerli/.migrations.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "init_deploy": 1673742596, - "whitelist": 1673742599, - "initial_dist": 1673742601 -} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/BribeFactory.json b/deployments/arbitrumGoerli/BribeFactory.json index 324b3fee..cd43dee4 100644 --- a/deployments/arbitrumGoerli/BribeFactory.json +++ b/deployments/arbitrumGoerli/BribeFactory.json @@ -1,5 +1,5 @@ { - "address": "0xb6270b92939c7b3676dcecA9a32D50Be27Db1291", + "address": "0x6e724702DfB7bCd31Af55852D67aa6A785aB85e6", "abi": [ { "inputs": [ @@ -66,28 +66,28 @@ "type": "function" } ], - "transactionHash": "0x5bfd3edf05b7fe48dd4be98c83fc8c210c97b29ea50f41fd052a9e6cf2ca1059", + "transactionHash": "0xcc125e746b6b8fd4fe60cc4ae7f7248997195abe16df333a04048a93d88e40ae", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xb6270b92939c7b3676dcecA9a32D50Be27Db1291", + "contractAddress": "0x6e724702DfB7bCd31Af55852D67aa6A785aB85e6", "transactionIndex": 1, "gasUsed": "4288891", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xd6379e3f2c35fc33daa6ea3033b9ec75c8819a84755580d9ce9b41fac1444914", - "transactionHash": "0x5bfd3edf05b7fe48dd4be98c83fc8c210c97b29ea50f41fd052a9e6cf2ca1059", + "blockHash": "0x810ac78f8b633bb0e98ce382ad637e1e66fb5ce73e61d9191fda39b2d44f5a6c", + "transactionHash": "0xcc125e746b6b8fd4fe60cc4ae7f7248997195abe16df333a04048a93d88e40ae", "logs": [], - "blockNumber": 5814401, + "blockNumber": 5849144, "cumulativeGasUsed": "4288891", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 5, - "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createExternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createInternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_external_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_internal_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/BribeFactory.sol\":\"BribeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/ExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract ExternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve; // \\u5929\\u4f7f\\u306e\\u305f\\u307e\\u3054\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balanceOf;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n _prevSupply = supplyCheckpoints[\\n getPriorSupplyIndex(_nextEpochStart + DURATION)\\n ].supply;\\n prevRewards.balanceOf =\\n (cp0.balanceOf *\\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (block.timestamp > _lastEpochEnd) {\\n reward +=\\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\\n }\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0xfe1e53dea8a63ce448c5856a740ed73038ad29a9dcd0f2a2752049b146bb4eb0\",\"license\":\"MIT\"},\"contracts/InternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract InternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve;\\n\\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 public constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n mapping(address => mapping(uint256 => uint256))\\n public userRewardPerTokenStored;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (totalSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / totalSupply);\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\\n _startTimestamp = endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][tokenId],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][tokenId]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n require(isReward[token]);\\n\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2dc302de5dfd95018d1fba7a3a1916d2c1fcf32859d19d38648767f13422a694\",\"license\":\"MIT\"},\"contracts/factories/BribeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IBribeFactory.sol\\\";\\nimport 'contracts/InternalBribe.sol';\\nimport 'contracts/ExternalBribe.sol';\\n\\ncontract BribeFactory is IBribeFactory {\\n address public last_internal_bribe;\\n address public last_external_bribe;\\n\\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\\n return last_internal_bribe;\\n }\\n\\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\\n return last_external_bribe;\\n }\\n}\\n\\n// if this imports int and ext bribe why is the the gauge factory asking for those address as if they are deployed to an address.\\n\",\"keccak256\":\"0xd107fb5a520bae9b655bec4ad2eb11d598e74d0eeda0db547e2526a907dea7ec\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50614cca806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea264697066735822122099fa841b90b874d1d8e3877992e98699cca22eb466c2095187adf17c4142358164736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea2646970667358221220108cbdd951d42091601d20569bfe784ae172226099bd78015371ae45d69bad1b64736f6c634300080d0033a264697066735822122075eeee7578461764c8547abe69c1b3d9c2cbce0bf0444eac1122b06c51a763bf64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea264697066735822122099fa841b90b874d1d8e3877992e98699cca22eb466c2095187adf17c4142358164736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea2646970667358221220108cbdd951d42091601d20569bfe784ae172226099bd78015371ae45d69bad1b64736f6c634300080d0033a264697066735822122075eeee7578461764c8547abe69c1b3d9c2cbce0bf0444eac1122b06c51a763bf64736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createExternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createInternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_external_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_internal_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/BribeFactory.sol\":\"BribeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/ExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract ExternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve; // \\u5929\\u4f7f\\u306e\\u305f\\u307e\\u3054\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balanceOf;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n _prevSupply = supplyCheckpoints[\\n getPriorSupplyIndex(_nextEpochStart + DURATION)\\n ].supply;\\n prevRewards.balanceOf =\\n (cp0.balanceOf *\\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (block.timestamp > _lastEpochEnd) {\\n reward +=\\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\\n }\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0xfe1e53dea8a63ce448c5856a740ed73038ad29a9dcd0f2a2752049b146bb4eb0\",\"license\":\"MIT\"},\"contracts/InternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract InternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve;\\n\\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 public constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n mapping(address => mapping(uint256 => uint256))\\n public userRewardPerTokenStored;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (totalSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / totalSupply);\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\\n _startTimestamp = endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][tokenId],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][tokenId]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n require(isReward[token]);\\n\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2dc302de5dfd95018d1fba7a3a1916d2c1fcf32859d19d38648767f13422a694\",\"license\":\"MIT\"},\"contracts/factories/BribeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IBribeFactory.sol\\\";\\nimport 'contracts/InternalBribe.sol';\\nimport 'contracts/ExternalBribe.sol';\\n\\ncontract BribeFactory is IBribeFactory {\\n address public last_internal_bribe;\\n address public last_external_bribe;\\n\\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\\n return last_internal_bribe;\\n }\\n\\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\\n return last_external_bribe;\\n }\\n}\\n\\n// if this imports int and ext bribe why is the the gauge factory asking for those address as if they are deployed to an address.\\n\",\"keccak256\":\"0xd107fb5a520bae9b655bec4ad2eb11d598e74d0eeda0db547e2526a907dea7ec\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50614cca806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea2646970667358221220b581a61c6270850b4ca41ed18a6ced4bddec0f335ea7da2f7e34bb8187fe5b5464736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea2646970667358221220bb88ad6720126cf96e24b2d25a87d3a518e2b3e2ae6d01962b74725b221784e964736f6c634300080d0033a2646970667358221220a28d90b20162c34cdc6c87f90d393aba381d7fe1852a758375129d7d68d7128564736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea2646970667358221220b581a61c6270850b4ca41ed18a6ced4bddec0f335ea7da2f7e34bb8187fe5b5464736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea2646970667358221220bb88ad6720126cf96e24b2d25a87d3a518e2b3e2ae6d01962b74725b221784e964736f6c634300080d0033a2646970667358221220a28d90b20162c34cdc6c87f90d393aba381d7fe1852a758375129d7d68d7128564736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/Flow.json b/deployments/arbitrumGoerli/Flow.json index 4f8a060e..7e63be64 100644 --- a/deployments/arbitrumGoerli/Flow.json +++ b/deployments/arbitrumGoerli/Flow.json @@ -1,5 +1,5 @@ { - "address": "0x8c35578054126d4DD063CFaBA40B7F9B63A13981", + "address": "0x0432f39386A9B1d0339c8Ba0af617b16C86ADA05", "abi": [ { "inputs": [], @@ -381,22 +381,22 @@ "type": "function" } ], - "transactionHash": "0x791ea54fe41f0c5d4cc08281af6429e5313c9ca4ca5cc513ce7a67502bce5d19", + "transactionHash": "0x95f802a247d08a2c2f937a273690354da6f7361458e7e0ab710b1bf088d4e810", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x8c35578054126d4DD063CFaBA40B7F9B63A13981", + "contractAddress": "0x0432f39386A9B1d0339c8Ba0af617b16C86ADA05", "transactionIndex": 1, "gasUsed": "537302", - "logsBloom": "0x00000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000008000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000010000000000000000000000000000000000000000000100000000000000800000000000000000000000000000000000000000000000000000000000000000000004000000000000002000000000000000000000000000000000000000000000000000020000000000000000000000000080000000000000000000000000000000000000000", - "blockHash": "0x96cef44b85f7609794f6a375423cbc39f740b41d7fb33010efa7fc9d0c3cb840", - "transactionHash": "0x791ea54fe41f0c5d4cc08281af6429e5313c9ca4ca5cc513ce7a67502bce5d19", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000020000000000020000000800000000000000000000000010000000000000000000000000000002000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000002000000000000000000000000000000000000000000000000000030000000000000000000000000080000000000000000000000000000000000000000", + "blockHash": "0x731e2358819105e46d82ccbebb1eb9fe1431f71da577ebac1de89b9e060a4474", + "transactionHash": "0x95f802a247d08a2c2f937a273690354da6f7361458e7e0ab710b1bf088d4e810", "logs": [ { "transactionIndex": 1, - "blockNumber": 5814391, - "transactionHash": "0x791ea54fe41f0c5d4cc08281af6429e5313c9ca4ca5cc513ce7a67502bce5d19", - "address": "0x8c35578054126d4DD063CFaBA40B7F9B63A13981", + "blockNumber": 5849121, + "transactionHash": "0x95f802a247d08a2c2f937a273690354da6f7361458e7e0ab710b1bf088d4e810", + "address": "0x0432f39386A9B1d0339c8Ba0af617b16C86ADA05", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x0000000000000000000000000000000000000000000000000000000000000000", @@ -404,20 +404,20 @@ ], "data": "0x0000000000000000000000000000000000000000000000000000000000000000", "logIndex": 0, - "blockHash": "0x96cef44b85f7609794f6a375423cbc39f740b41d7fb33010efa7fc9d0c3cb840" + "blockHash": "0x731e2358819105e46d82ccbebb1eb9fe1431f71da577ebac1de89b9e060a4474" } ], - "blockNumber": 5814391, + "blockNumber": 5849121, "cumulativeGasUsed": "537302", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 5, - "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"initialMint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialMinted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleClaim\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redemptionReceiver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_merkleClaim\",\"type\":\"address\"}],\"name\":\"setMerkleClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"setMinter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_receiver\",\"type\":\"address\"}],\"name\":\"setRedemptionReceiver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Flow.sol\":\"Flow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Flow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\n\\ncontract Flow is IFlow {\\n\\n string public constant name = \\\"Velocimeter\\\";\\n string public constant symbol = \\\"FLOW\\\";\\n uint8 public constant decimals = 18;\\n uint public totalSupply = 0;\\n\\n mapping(address => uint) public balanceOf;\\n mapping(address => mapping(address => uint)) public allowance;\\n\\n bool public initialMinted;\\n address public minter;\\n address public redemptionReceiver;\\n address public merkleClaim;\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n\\n constructor() {\\n minter = msg.sender;\\n _mint(msg.sender, 0);\\n }\\n\\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\\n function setMinter(address _minter) external {\\n require(msg.sender == minter);\\n minter = _minter;\\n }\\n\\n function setRedemptionReceiver(address _receiver) external {\\n require(msg.sender == minter);\\n redemptionReceiver = _receiver;\\n }\\n\\n function setMerkleClaim(address _merkleClaim) external {\\n require(msg.sender == minter);\\n merkleClaim = _merkleClaim;\\n }\\n\\n // Initial mint: total 82M\\n // 4M for \\\"Genesis\\\" pools\\n // 30M for liquid team allocation (40M excl init veNFT)\\n // 48M for future partners\\n function initialMint(address _recipient) external {\\n require(msg.sender == minter && !initialMinted);\\n initialMinted = true;\\n _mint(_recipient, 82 * 1e6 * 1e18);\\n }\\n\\n function approve(address _spender, uint _value) external returns (bool) {\\n allowance[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n function _mint(address _to, uint _amount) internal returns (bool) {\\n totalSupply += _amount;\\n unchecked {\\n balanceOf[_to] += _amount;\\n }\\n emit Transfer(address(0x0), _to, _amount);\\n return true;\\n }\\n\\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\\n balanceOf[_from] -= _value;\\n unchecked {\\n balanceOf[_to] += _value;\\n }\\n emit Transfer(_from, _to, _value);\\n return true;\\n }\\n\\n function transfer(address _to, uint _value) external returns (bool) {\\n return _transfer(msg.sender, _to, _value);\\n }\\n\\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\\n uint allowed_from = allowance[_from][msg.sender];\\n if (allowed_from != type(uint).max) {\\n allowance[_from][msg.sender] -= _value;\\n }\\n return _transfer(_from, _to, _value);\\n }\\n\\n function mint(address account, uint amount) external returns (bool) {\\n require(msg.sender == minter);\\n _mint(account, amount);\\n return true;\\n }\\n\\n function claim(address account, uint amount) external returns (bool) {\\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\\n _mint(account, amount);\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xe98c291786f74c8f02edb3673870ba99d6b9adac299bbe42f1df42c740d737ac\",\"license\":\"MIT\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"}},\"version\":1}", - "bytecode": "0x60806040526000805534801561001457600080fd5b5060038054610100600160a81b0319163361010081029190911790915561003c906000610042565b506100d9565b60008160008082825461005591906100b3565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a350600192915050565b600082198211156100d457634e487b7160e01b600052601160045260246000fd5b500190565b61082e806100e86000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ae578063dd62ed3e146102c1578063e752c44a146102ec578063ec676a25146102ff578063fca3b5aa1461031257600080fd5b806395d89b4114610243578063a9059cbb14610266578063aad3ec9614610279578063c268f9ba1461028c578063ca1c4de9146102a157600080fd5b806323b872dd116100f457806323b872dd146101d0578063313ce567146101e357806340c10f19146101fd5780635e05fe501461021057806370a082311461022357600080fd5b806306fdde03146101265780630754617214610166578063095ea7b31461019657806318160ddd146101b9575b600080fd5b6101506040518060400160405280600b81526020016a2b32b637b1b4b6b2ba32b960a91b81525081565b60405161015d919061068e565b60405180910390f35b60035461017e9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015d565b6101a96101a43660046106ff565b610325565b604051901515815260200161015d565b6101c260005481565b60405190815260200161015d565b6101a96101de366004610729565b610391565b6101eb601281565b60405160ff909116815260200161015d565b6101a961020b3660046106ff565b61040b565b60045461017e906001600160a01b031681565b6101c2610231366004610765565b60016020526000908152604090205481565b61015060405180604001604052806004815260200163464c4f5760e01b81525081565b6101a96102743660046106ff565b61043e565b6101a96102873660046106ff565b610452565b61029f61029a366004610765565b610481565b005b6003546101a99060ff1681565b61029f6102bc366004610765565b6104d2565b6101c26102cf366004610780565b600260209081526000928352604080842090915290825290205481565b60055461017e906001600160a01b031681565b61029f61030d366004610765565b610510565b61029f610320366004610765565b61054e565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103809086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f7576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103f19084906107c9565b90915550505b610402858585610592565b95945050505050565b60035460009061010090046001600160a01b0316331461042a57600080fd5b6104348383610629565b5060019392505050565b600061044b338484610592565b9392505050565b6004546000906001600160a01b031633148061047857506005546001600160a01b031633145b61042a57600080fd5b60035461010090046001600160a01b0316331480156104a3575060035460ff16155b6104ac57600080fd5b6003805460ff191660011790556104ce816a43d42ce83da41d92000000610629565b5050565b60035461010090046001600160a01b031633146104ee57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052c57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056a57600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105bc9084906107c9565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106179086815260200190565b60405180910390a35060019392505050565b60008160008082825461063c91906107e0565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610380565b600060208083528351808285015260005b818110156106bb5785810183015185820160400152820161069f565b818111156106cd576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106fa57600080fd5b919050565b6000806040838503121561071257600080fd5b61071b836106e3565b946020939093013593505050565b60008060006060848603121561073e57600080fd5b610747846106e3565b9250610755602085016106e3565b9150604084013590509250925092565b60006020828403121561077757600080fd5b61044b826106e3565b6000806040838503121561079357600080fd5b61079c836106e3565b91506107aa602084016106e3565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107db576107db6107b3565b500390565b600082198211156107f3576107f36107b3565b50019056fea26469706673582212204d79ba21f3f516cb55fa2c0931b0d4e06d3f09a2681f5ab33064f7374590d31e64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ae578063dd62ed3e146102c1578063e752c44a146102ec578063ec676a25146102ff578063fca3b5aa1461031257600080fd5b806395d89b4114610243578063a9059cbb14610266578063aad3ec9614610279578063c268f9ba1461028c578063ca1c4de9146102a157600080fd5b806323b872dd116100f457806323b872dd146101d0578063313ce567146101e357806340c10f19146101fd5780635e05fe501461021057806370a082311461022357600080fd5b806306fdde03146101265780630754617214610166578063095ea7b31461019657806318160ddd146101b9575b600080fd5b6101506040518060400160405280600b81526020016a2b32b637b1b4b6b2ba32b960a91b81525081565b60405161015d919061068e565b60405180910390f35b60035461017e9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015d565b6101a96101a43660046106ff565b610325565b604051901515815260200161015d565b6101c260005481565b60405190815260200161015d565b6101a96101de366004610729565b610391565b6101eb601281565b60405160ff909116815260200161015d565b6101a961020b3660046106ff565b61040b565b60045461017e906001600160a01b031681565b6101c2610231366004610765565b60016020526000908152604090205481565b61015060405180604001604052806004815260200163464c4f5760e01b81525081565b6101a96102743660046106ff565b61043e565b6101a96102873660046106ff565b610452565b61029f61029a366004610765565b610481565b005b6003546101a99060ff1681565b61029f6102bc366004610765565b6104d2565b6101c26102cf366004610780565b600260209081526000928352604080842090915290825290205481565b60055461017e906001600160a01b031681565b61029f61030d366004610765565b610510565b61029f610320366004610765565b61054e565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103809086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f7576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103f19084906107c9565b90915550505b610402858585610592565b95945050505050565b60035460009061010090046001600160a01b0316331461042a57600080fd5b6104348383610629565b5060019392505050565b600061044b338484610592565b9392505050565b6004546000906001600160a01b031633148061047857506005546001600160a01b031633145b61042a57600080fd5b60035461010090046001600160a01b0316331480156104a3575060035460ff16155b6104ac57600080fd5b6003805460ff191660011790556104ce816a43d42ce83da41d92000000610629565b5050565b60035461010090046001600160a01b031633146104ee57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052c57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056a57600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105bc9084906107c9565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106179086815260200190565b60405180910390a35060019392505050565b60008160008082825461063c91906107e0565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610380565b600060208083528351808285015260005b818110156106bb5785810183015185820160400152820161069f565b818111156106cd576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106fa57600080fd5b919050565b6000806040838503121561071257600080fd5b61071b836106e3565b946020939093013593505050565b60008060006060848603121561073e57600080fd5b610747846106e3565b9250610755602085016106e3565b9150604084013590509250925092565b60006020828403121561077757600080fd5b61044b826106e3565b6000806040838503121561079357600080fd5b61079c836106e3565b91506107aa602084016106e3565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107db576107db6107b3565b500390565b600082198211156107f3576107f36107b3565b50019056fea26469706673582212204d79ba21f3f516cb55fa2c0931b0d4e06d3f09a2681f5ab33064f7374590d31e64736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"initialMint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialMinted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleClaim\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redemptionReceiver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_merkleClaim\",\"type\":\"address\"}],\"name\":\"setMerkleClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"setMinter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_receiver\",\"type\":\"address\"}],\"name\":\"setRedemptionReceiver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Flow.sol\":\"Flow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Flow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\n\\ncontract Flow is IFlow {\\n\\n string public constant name = \\\"Velocimeter\\\";\\n string public constant symbol = \\\"FLOW\\\";\\n uint8 public constant decimals = 18;\\n uint public totalSupply = 0;\\n\\n mapping(address => uint) public balanceOf;\\n mapping(address => mapping(address => uint)) public allowance;\\n\\n bool public initialMinted;\\n address public minter;\\n address public redemptionReceiver;\\n address public merkleClaim;\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n\\n constructor() {\\n minter = msg.sender;\\n _mint(msg.sender, 0);\\n }\\n\\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\\n function setMinter(address _minter) external {\\n require(msg.sender == minter);\\n minter = _minter;\\n }\\n\\n function setRedemptionReceiver(address _receiver) external {\\n require(msg.sender == minter);\\n redemptionReceiver = _receiver;\\n }\\n\\n function setMerkleClaim(address _merkleClaim) external {\\n require(msg.sender == minter);\\n merkleClaim = _merkleClaim;\\n }\\n\\n // Initial mint: total 82M\\n // 4M for \\\"Genesis\\\" pools\\n // 30M for liquid team allocation (40M excl init veNFT)\\n // 48M for future partners\\n function initialMint(address _recipient) external {\\n require(msg.sender == minter && !initialMinted);\\n initialMinted = true;\\n _mint(_recipient, 82 * 1e6 * 1e18);\\n }\\n\\n function approve(address _spender, uint _value) external returns (bool) {\\n allowance[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n function _mint(address _to, uint _amount) internal returns (bool) {\\n totalSupply += _amount;\\n unchecked {\\n balanceOf[_to] += _amount;\\n }\\n emit Transfer(address(0x0), _to, _amount);\\n return true;\\n }\\n\\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\\n balanceOf[_from] -= _value;\\n unchecked {\\n balanceOf[_to] += _value;\\n }\\n emit Transfer(_from, _to, _value);\\n return true;\\n }\\n\\n function transfer(address _to, uint _value) external returns (bool) {\\n return _transfer(msg.sender, _to, _value);\\n }\\n\\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\\n uint allowed_from = allowance[_from][msg.sender];\\n if (allowed_from != type(uint).max) {\\n allowance[_from][msg.sender] -= _value;\\n }\\n return _transfer(_from, _to, _value);\\n }\\n\\n function mint(address account, uint amount) external returns (bool) {\\n require(msg.sender == minter);\\n _mint(account, amount);\\n return true;\\n }\\n\\n function claim(address account, uint amount) external returns (bool) {\\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\\n _mint(account, amount);\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xe98c291786f74c8f02edb3673870ba99d6b9adac299bbe42f1df42c740d737ac\",\"license\":\"MIT\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"}},\"version\":1}", + "bytecode": "0x60806040526000805534801561001457600080fd5b5060038054610100600160a81b0319163361010081029190911790915561003c906000610042565b506100d9565b60008160008082825461005591906100b3565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a350600192915050565b600082198211156100d457634e487b7160e01b600052601160045260246000fd5b500190565b61082e806100e86000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ae578063dd62ed3e146102c1578063e752c44a146102ec578063ec676a25146102ff578063fca3b5aa1461031257600080fd5b806395d89b4114610243578063a9059cbb14610266578063aad3ec9614610279578063c268f9ba1461028c578063ca1c4de9146102a157600080fd5b806323b872dd116100f457806323b872dd146101d0578063313ce567146101e357806340c10f19146101fd5780635e05fe501461021057806370a082311461022357600080fd5b806306fdde03146101265780630754617214610166578063095ea7b31461019657806318160ddd146101b9575b600080fd5b6101506040518060400160405280600b81526020016a2b32b637b1b4b6b2ba32b960a91b81525081565b60405161015d919061068e565b60405180910390f35b60035461017e9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015d565b6101a96101a43660046106ff565b610325565b604051901515815260200161015d565b6101c260005481565b60405190815260200161015d565b6101a96101de366004610729565b610391565b6101eb601281565b60405160ff909116815260200161015d565b6101a961020b3660046106ff565b61040b565b60045461017e906001600160a01b031681565b6101c2610231366004610765565b60016020526000908152604090205481565b61015060405180604001604052806004815260200163464c4f5760e01b81525081565b6101a96102743660046106ff565b61043e565b6101a96102873660046106ff565b610452565b61029f61029a366004610765565b610481565b005b6003546101a99060ff1681565b61029f6102bc366004610765565b6104d2565b6101c26102cf366004610780565b600260209081526000928352604080842090915290825290205481565b60055461017e906001600160a01b031681565b61029f61030d366004610765565b610510565b61029f610320366004610765565b61054e565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103809086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f7576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103f19084906107c9565b90915550505b610402858585610592565b95945050505050565b60035460009061010090046001600160a01b0316331461042a57600080fd5b6104348383610629565b5060019392505050565b600061044b338484610592565b9392505050565b6004546000906001600160a01b031633148061047857506005546001600160a01b031633145b61042a57600080fd5b60035461010090046001600160a01b0316331480156104a3575060035460ff16155b6104ac57600080fd5b6003805460ff191660011790556104ce816a43d42ce83da41d92000000610629565b5050565b60035461010090046001600160a01b031633146104ee57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052c57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056a57600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105bc9084906107c9565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106179086815260200190565b60405180910390a35060019392505050565b60008160008082825461063c91906107e0565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610380565b600060208083528351808285015260005b818110156106bb5785810183015185820160400152820161069f565b818111156106cd576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106fa57600080fd5b919050565b6000806040838503121561071257600080fd5b61071b836106e3565b946020939093013593505050565b60008060006060848603121561073e57600080fd5b610747846106e3565b9250610755602085016106e3565b9150604084013590509250925092565b60006020828403121561077757600080fd5b61044b826106e3565b6000806040838503121561079357600080fd5b61079c836106e3565b91506107aa602084016106e3565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107db576107db6107b3565b500390565b600082198211156107f3576107f36107b3565b50019056fea26469706673582212204ffbadb8f52de29017f5adfb84dd15b297992d688e48de234f666a9925afdf5664736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ae578063dd62ed3e146102c1578063e752c44a146102ec578063ec676a25146102ff578063fca3b5aa1461031257600080fd5b806395d89b4114610243578063a9059cbb14610266578063aad3ec9614610279578063c268f9ba1461028c578063ca1c4de9146102a157600080fd5b806323b872dd116100f457806323b872dd146101d0578063313ce567146101e357806340c10f19146101fd5780635e05fe501461021057806370a082311461022357600080fd5b806306fdde03146101265780630754617214610166578063095ea7b31461019657806318160ddd146101b9575b600080fd5b6101506040518060400160405280600b81526020016a2b32b637b1b4b6b2ba32b960a91b81525081565b60405161015d919061068e565b60405180910390f35b60035461017e9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015d565b6101a96101a43660046106ff565b610325565b604051901515815260200161015d565b6101c260005481565b60405190815260200161015d565b6101a96101de366004610729565b610391565b6101eb601281565b60405160ff909116815260200161015d565b6101a961020b3660046106ff565b61040b565b60045461017e906001600160a01b031681565b6101c2610231366004610765565b60016020526000908152604090205481565b61015060405180604001604052806004815260200163464c4f5760e01b81525081565b6101a96102743660046106ff565b61043e565b6101a96102873660046106ff565b610452565b61029f61029a366004610765565b610481565b005b6003546101a99060ff1681565b61029f6102bc366004610765565b6104d2565b6101c26102cf366004610780565b600260209081526000928352604080842090915290825290205481565b60055461017e906001600160a01b031681565b61029f61030d366004610765565b610510565b61029f610320366004610765565b61054e565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103809086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f7576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103f19084906107c9565b90915550505b610402858585610592565b95945050505050565b60035460009061010090046001600160a01b0316331461042a57600080fd5b6104348383610629565b5060019392505050565b600061044b338484610592565b9392505050565b6004546000906001600160a01b031633148061047857506005546001600160a01b031633145b61042a57600080fd5b60035461010090046001600160a01b0316331480156104a3575060035460ff16155b6104ac57600080fd5b6003805460ff191660011790556104ce816a43d42ce83da41d92000000610629565b5050565b60035461010090046001600160a01b031633146104ee57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052c57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056a57600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105bc9084906107c9565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106179086815260200190565b60405180910390a35060019392505050565b60008160008082825461063c91906107e0565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610380565b600060208083528351808285015260005b818110156106bb5785810183015185820160400152820161069f565b818111156106cd576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106fa57600080fd5b919050565b6000806040838503121561071257600080fd5b61071b836106e3565b946020939093013593505050565b60008060006060848603121561073e57600080fd5b610747846106e3565b9250610755602085016106e3565b9150604084013590509250925092565b60006020828403121561077757600080fd5b61044b826106e3565b6000806040838503121561079357600080fd5b61079c836106e3565b91506107aa602084016106e3565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107db576107db6107b3565b500390565b600082198211156107f3576107f36107b3565b50019056fea26469706673582212204ffbadb8f52de29017f5adfb84dd15b297992d688e48de234f666a9925afdf5664736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/FlowGovernor.json b/deployments/arbitrumGoerli/FlowGovernor.json index cf1abe5c..48852662 100644 --- a/deployments/arbitrumGoerli/FlowGovernor.json +++ b/deployments/arbitrumGoerli/FlowGovernor.json @@ -1,5 +1,5 @@ { - "address": "0x82659caE4Dd0C19F7FBf47A5492E31Ad9501CA73", + "address": "0x98d89Bcf02e1142c8EB31959A38F498EcFCfAe57", "abi": [ { "inputs": [ @@ -1055,43 +1055,43 @@ "type": "receive" } ], - "transactionHash": "0xf8b26b26f3fabd0df348a04581c229369d345799b41ca81d52273d35f68fa56c", + "transactionHash": "0x0eb80b49c044205bc02d913cff01f5fc43f92657c8afc9b835a517cea0b5ab3f", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x82659caE4Dd0C19F7FBf47A5492E31Ad9501CA73", + "contractAddress": "0x98d89Bcf02e1142c8EB31959A38F498EcFCfAe57", "transactionIndex": 1, - "gasUsed": "2742878", - "logsBloom": "0x00000000000000000100000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x50fd06f452de54148b6f2afaa4711612696cb06d46db28f2d5a06a90140e9cb2", - "transactionHash": "0xf8b26b26f3fabd0df348a04581c229369d345799b41ca81d52273d35f68fa56c", + "gasUsed": "2742890", + "logsBloom": "0x00000000000000000100000000001000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x8a074d3df27305fa89663da6e667b01058e1ed0bdf7e7d827a3f7f21e99b4904", + "transactionHash": "0x0eb80b49c044205bc02d913cff01f5fc43f92657c8afc9b835a517cea0b5ab3f", "logs": [ { "transactionIndex": 1, - "blockNumber": 5814442, - "transactionHash": "0xf8b26b26f3fabd0df348a04581c229369d345799b41ca81d52273d35f68fa56c", - "address": "0x82659caE4Dd0C19F7FBf47A5492E31Ad9501CA73", + "blockNumber": 5849249, + "transactionHash": "0x0eb80b49c044205bc02d913cff01f5fc43f92657c8afc9b835a517cea0b5ab3f", + "address": "0x98d89Bcf02e1142c8EB31959A38F498EcFCfAe57", "topics": [ "0x0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997" ], "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004", "logIndex": 0, - "blockHash": "0x50fd06f452de54148b6f2afaa4711612696cb06d46db28f2d5a06a90140e9cb2" + "blockHash": "0x8a074d3df27305fa89663da6e667b01058e1ed0bdf7e7d827a3f7f21e99b4904" } ], - "blockNumber": 5814442, - "cumulativeGasUsed": "2742878", + "blockNumber": 5849249, + "cumulativeGasUsed": "2742890", "status": 1, "byzantium": true }, "args": [ - "0xad0F425b3edB0FC3a06096092B5736A280C90C40" + "0xF003091B78974ee3F99ec70fC5F42fc9810664EC" ], - "numDeployments": 1, - "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"_ve\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"Empty\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"proposer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"string[]\",\"name\":\"signatures\",\"type\":\"string[]\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"ProposalCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldQuorumNumerator\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"QuorumNumeratorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"VoteCast\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"VoteCastWithParams\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"COUNTING_MODE\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EXTENDED_BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_PROPOSAL_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROPOSAL_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"}],\"name\":\"castVote\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"castVoteWithReason\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"castVoteWithReasonAndParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteWithReasonAndParamsBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"execute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"getVotesWithParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasVoted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"hashProposal\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalDeadline\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalSnapshot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"againstVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"forVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"abstainVotes\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"propose\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"quorum\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumDenominator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"}],\"name\":\"setProposalNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTeam\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"state\",\"outputs\":[{\"internalType\":\"enum IGovernor.ProposalState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"updateQuorumNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"Empty()\":[{\"details\":\"An operation (e.g. {front}) couldn't be completed due to the queue being empty.\"}]},\"kind\":\"dev\",\"methods\":{\"COUNTING_MODE()\":{\"details\":\"See {IGovernor-COUNTING_MODE}.\"},\"castVote(uint256,uint8)\":{\"details\":\"See {IGovernor-castVote}.\"},\"castVoteBySig(uint256,uint8,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteBySig}.\"},\"castVoteWithReason(uint256,uint8,string)\":{\"details\":\"See {IGovernor-castVoteWithReason}.\"},\"castVoteWithReasonAndParams(uint256,uint8,string,bytes)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParams}.\"},\"castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParamsBySig}.\"},\"execute(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-execute}.\"},\"getVotes(address,uint256)\":{\"details\":\"See {IGovernor-getVotes}.\"},\"getVotesWithParams(address,uint256,bytes)\":{\"details\":\"See {IGovernor-getVotesWithParams}.\"},\"hasVoted(uint256,address)\":{\"details\":\"See {IGovernor-hasVoted}.\"},\"hashProposal(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-hashProposal}. The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in advance, before the proposal is submitted. Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the same proposal (with same operation and same description) will have the same id if submitted on multiple governors across multiple networks. This also means that in order to execute the same operation twice (on the same governor) the proposer will have to change the description in order to avoid proposal id conflicts.\"},\"name()\":{\"details\":\"See {IGovernor-name}.\"},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155BatchReceived}.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155Received}.\"},\"onERC721Received(address,address,uint256,bytes)\":{\"details\":\"See {IERC721Receiver-onERC721Received}.\"},\"proposalDeadline(uint256)\":{\"details\":\"See {IGovernor-proposalDeadline}.\"},\"proposalSnapshot(uint256)\":{\"details\":\"See {IGovernor-proposalSnapshot}.\"},\"proposalThreshold()\":{\"details\":\"Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\"},\"proposalVotes(uint256)\":{\"details\":\"Accessor to the internal vote counts.\"},\"propose(address[],uint256[],bytes[],string)\":{\"details\":\"See {IGovernor-propose}.\"},\"quorum(uint256)\":{\"details\":\"Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\"},\"quorumDenominator()\":{\"details\":\"Returns the quorum denominator. Defaults to 100, but may be overridden.\"},\"quorumNumerator()\":{\"details\":\"Returns the current quorum numerator. See {quorumDenominator}.\"},\"relay(address,uint256,bytes)\":{\"details\":\"Relays a transaction or function call to an arbitrary target. In cases where the governance executor is some contract other than the governor itself, like when using a timelock, this function can be invoked in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake. Note that if the executor is simply the governor itself, use of `relay` is redundant.\"},\"state(uint256)\":{\"details\":\"See {IGovernor-state}.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"updateQuorumNumerator(uint256)\":{\"details\":\"Changes the quorum numerator. Emits a {QuorumNumeratorUpdated} event. Requirements: - Must be called through a governance proposal. - New numerator must be smaller or equal to the denominator.\"},\"version()\":{\"details\":\"See {IGovernor-version}.\"},\"votingDelay()\":{\"details\":\"Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\"},\"votingPeriod()\":{\"details\":\"Delay, in number of blocks, between the vote start and vote ends. NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting duration compared to the voting delay.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"votingDelay()\":{\"notice\":\"module:user-config\"},\"votingPeriod()\":{\"notice\":\"module:user-config\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/FlowGovernor.sol\":\"FlowGovernor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/FlowGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IGovernor} from \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\nimport {L2GovernorCountingSimple} from \\\"contracts/governance/L2GovernorCountingSimple.sol\\\";\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\nimport {L2GovernorVotesQuorumFraction} from \\\"contracts/governance/L2GovernorVotesQuorumFraction.sol\\\";\\n\\ncontract FlowGovernor is\\n L2Governor,\\n L2GovernorCountingSimple,\\n L2GovernorVotes,\\n L2GovernorVotesQuorumFraction\\n{\\n address public team;\\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\\n uint256 public proposalNumerator = 2; // start at 0.02%\\n\\n constructor(IVotes _ve)\\n L2Governor(\\\"Velocimeter Governor\\\")\\n L2GovernorVotes(_ve)\\n L2GovernorVotesQuorumFraction(4) // 4%\\n {\\n team = msg.sender;\\n }\\n\\n function votingDelay() public pure override(IGovernor) returns (uint256) {\\n return 15 minutes; // 1 block\\n }\\n\\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\\n return 1 weeks;\\n }\\n\\n function setTeam(address newTeam) external {\\n require(msg.sender == team, \\\"not team\\\");\\n team = newTeam;\\n }\\n\\n function setProposalNumerator(uint256 numerator) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \\\"numerator too high\\\");\\n proposalNumerator = numerator;\\n }\\n\\n function proposalThreshold()\\n public\\n view\\n override(L2Governor)\\n returns (uint256)\\n {\\n return\\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\\n PROPOSAL_DENOMINATOR;\\n }\\n}\\n\",\"keccak256\":\"0xbf02f2fa1b0179b06bba2274ce6720c31ba3783f899502567cc25a093b27edb6\",\"license\":\"MIT\"},\"contracts/governance/L2Governor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Address.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Context.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\\n *\\n * @dev Core of the governance system, designed to be extended though various modules.\\n *\\n * This contract is abstract and requires several function to be implemented in various modules:\\n *\\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\\n * - A voting module must implement {_getVotes}\\n * - Additionanly, the {votingPeriod} must also be implemented\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\\n using SafeCast for uint256;\\n using Timers for Timers.Timestamp;\\n\\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\\\"Ballot(uint256 proposalId,uint8 support)\\\");\\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\\n keccak256(\\\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\\\");\\n\\n struct ProposalCore {\\n Timers.Timestamp voteStart;\\n Timers.Timestamp voteEnd;\\n bool executed;\\n bool canceled;\\n }\\n\\n string private _name;\\n\\n mapping(uint256 => ProposalCore) private _proposals;\\n\\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\\n\\n /**\\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\\n * parameter setters in {GovernorSettings} are protected using this modifier.\\n *\\n * The governance executing address may be different from the Governor's own address, for example it could be a\\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\\n * for example, additional timelock proposers are not able to change governance parameters without going through the\\n * governance protocol (since v4.6).\\n */\\n modifier onlyGovernance() {\\n require(_msgSender() == _executor(), \\\"Governor: onlyGovernance\\\");\\n if (_executor() != address(this)) {\\n bytes32 msgDataHash = keccak256(_msgData());\\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\\n while (_governanceCall.popFront() != msgDataHash) {}\\n }\\n _;\\n }\\n\\n /**\\n * @dev Sets the value for {name} and {version}\\n */\\n constructor(string memory name_) EIP712(name_, version()) {\\n _name = name_;\\n }\\n\\n /**\\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\\n */\\n receive() external payable virtual {\\n require(_executor() == address(this));\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\\n // include the castVoteWithReasonAndParams() function as standard\\n return\\n interfaceId ==\\n (type(IGovernor).interfaceId ^\\n this.castVoteWithReasonAndParams.selector ^\\n this.castVoteWithReasonAndParamsBySig.selector ^\\n this.getVotesWithParams.selector) ||\\n interfaceId == type(IGovernor).interfaceId ||\\n interfaceId == type(IERC1155Receiver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IGovernor-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IGovernor-version}.\\n */\\n function version() public view virtual override returns (string memory) {\\n return \\\"1\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hashProposal}.\\n *\\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\\n * advance, before the proposal is submitted.\\n *\\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual override returns (uint256) {\\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\\n }\\n\\n /**\\n * @dev See {IGovernor-state}.\\n */\\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n\\n if (proposal.executed) {\\n return ProposalState.Executed;\\n }\\n\\n if (proposal.canceled) {\\n return ProposalState.Canceled;\\n }\\n\\n uint256 start = proposalSnapshot(proposalId);\\n\\n if (start == 0) {\\n revert(\\\"Governor: unknown proposal id\\\");\\n }\\n\\n if (start >= block.timestamp) {\\n return ProposalState.Pending;\\n }\\n\\n uint256 deadline = proposalDeadline(proposalId);\\n\\n if (deadline >= block.timestamp) {\\n return ProposalState.Active;\\n }\\n\\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\\n return ProposalState.Succeeded;\\n } else {\\n return ProposalState.Defeated;\\n }\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalSnapshot}.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteStart.getDeadline();\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalDeadline}.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteEnd.getDeadline();\\n }\\n\\n /**\\n * @dev Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\\n */\\n function proposalThreshold() public view virtual returns (uint256) {\\n return 0;\\n }\\n\\n /**\\n * @dev Amount of votes already cast passes the threshold limit.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Is the proposal successful or not.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) internal view virtual returns (uint256);\\n\\n /**\\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\\n *\\n * Note: Support is generic and can represent various things depending on the voting system used.\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory params\\n ) internal virtual;\\n\\n /**\\n * @dev Default additional encoded parameters used by castVote methods that don't include them\\n *\\n * Note: Should be overridden by specific implementations to use an appropriate value, the\\n * meaning of the additional params, in the context of that implementation\\n */\\n function _defaultParams() internal view virtual returns (bytes memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-propose}.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual override returns (uint256) {\\n require(\\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\\n \\\"Governor: proposer votes below proposal threshold\\\"\\n );\\n\\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\\n\\n require(targets.length == values.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length == calldatas.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length > 0, \\\"Governor: empty proposal\\\");\\n\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(proposal.voteStart.isUnset(), \\\"Governor: proposal already exists\\\");\\n\\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\\n uint64 deadline = start + votingPeriod().toUint64();\\n\\n proposal.voteStart.setDeadline(start);\\n proposal.voteEnd.setDeadline(deadline);\\n\\n emit ProposalCreated(\\n proposalId,\\n _msgSender(),\\n targets,\\n values,\\n new string[](targets.length),\\n calldatas,\\n start,\\n deadline,\\n description\\n );\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-execute}.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual override returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n\\n ProposalState status = state(proposalId);\\n require(\\n status == ProposalState.Succeeded || status == ProposalState.Queued,\\n \\\"Governor: proposal not successful\\\"\\n );\\n _proposals[proposalId].executed = true;\\n\\n emit ProposalExecuted(proposalId);\\n\\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\\n _execute(proposalId, targets, values, calldatas, descriptionHash);\\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\\n */\\n function _execute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n string memory errorMessage = \\\"Governor: call reverted without message\\\";\\n for (uint256 i = 0; i < targets.length; ++i) {\\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\\n Address.verifyCallResult(success, returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Hook before execution is triggered.\\n */\\n function _beforeExecute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory, /* values */\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n for (uint256 i = 0; i < targets.length; ++i) {\\n if (targets[i] == address(this)) {\\n _governanceCall.pushBack(keccak256(calldatas[i]));\\n }\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook after execution is triggered.\\n */\\n function _afterExecute(\\n uint256, /* proposalId */\\n address[] memory, /* targets */\\n uint256[] memory, /* values */\\n bytes[] memory, /* calldatas */\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n if (!_governanceCall.empty()) {\\n _governanceCall.clear();\\n }\\n }\\n }\\n\\n /**\\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\\n * canceled to allow distinguishing it from executed proposals.\\n *\\n * Emits a {IGovernor-ProposalCanceled} event.\\n */\\n function _cancel(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) internal virtual returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n ProposalState status = state(proposalId);\\n\\n require(\\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\\n \\\"Governor: proposal not active\\\"\\n );\\n _proposals[proposalId].canceled = true;\\n\\n emit ProposalCanceled(proposalId);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotes}.\\n */\\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, _defaultParams());\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotesWithParams}.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVote}.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReason}.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteBySig}.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\\n v,\\n r,\\n s\\n );\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(\\n keccak256(\\n abi.encode(\\n EXTENDED_BALLOT_TYPEHASH,\\n proposalId,\\n support,\\n keccak256(bytes(reason)),\\n keccak256(params)\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason\\n ) internal virtual returns (uint256) {\\n return _castVote(proposalId, account, support, reason, _defaultParams());\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason,\\n bytes memory params\\n ) internal virtual returns (uint256) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(state(proposalId) == ProposalState.Active, \\\"Governor: vote not currently active\\\");\\n\\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\\n _countVote(proposalId, account, support, weight, params);\\n\\n if (params.length == 0) {\\n emit VoteCast(account, proposalId, support, weight, reason);\\n } else {\\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\\n }\\n\\n return weight;\\n }\\n\\n /**\\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\\n */\\n function relay(\\n address target,\\n uint256 value,\\n bytes calldata data\\n ) external virtual onlyGovernance {\\n Address.functionCallWithValue(target, data, value);\\n }\\n\\n /**\\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\\n * through another contract such as a timelock.\\n */\\n function _executor() internal view virtual returns (address) {\\n return address(this);\\n }\\n\\n /**\\n * @dev See {IERC721Receiver-onERC721Received}.\\n */\\n function onERC721Received(\\n address,\\n address,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155Received}.\\n */\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\\n */\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] memory,\\n uint256[] memory,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155BatchReceived.selector;\\n }\\n}\\n\",\"keccak256\":\"0xa2846313b89a871807cdebd0225b0bf8f23b17505ab8b3288549ec54a5a4a71b\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorCountingSimple.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\\n *\\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorCountingSimple is L2Governor {\\n /**\\n * @dev Supported vote types. Matches Governor Bravo ordering.\\n */\\n enum VoteType {\\n Against,\\n For,\\n Abstain\\n }\\n\\n struct ProposalVote {\\n uint256 againstVotes;\\n uint256 forVotes;\\n uint256 abstainVotes;\\n mapping(address => bool) hasVoted;\\n }\\n\\n mapping(uint256 => ProposalVote) private _proposalVotes;\\n\\n /**\\n * @dev See {IGovernor-COUNTING_MODE}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual override returns (string memory) {\\n return \\\"support=bravo&quorum=for,abstain\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hasVoted}.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\\n return _proposalVotes[proposalId].hasVoted[account];\\n }\\n\\n /**\\n * @dev Accessor to the internal vote counts.\\n */\\n function proposalVotes(uint256 proposalId)\\n public\\n view\\n virtual\\n returns (\\n uint256 againstVotes,\\n uint256 forVotes,\\n uint256 abstainVotes\\n )\\n {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\\n }\\n\\n /**\\n * @dev See {Governor-_quorumReached}.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return proposalvote.forVotes > proposalvote.againstVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory // params\\n ) internal virtual override {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n require(!proposalvote.hasVoted[account], \\\"GovernorVotingSimple: vote already cast\\\");\\n proposalvote.hasVoted[account] = true;\\n\\n if (support == uint8(VoteType.Against)) {\\n proposalvote.againstVotes += weight;\\n } else if (support == uint8(VoteType.For)) {\\n proposalvote.forVotes += weight;\\n } else if (support == uint8(VoteType.Abstain)) {\\n proposalvote.abstainVotes += weight;\\n } else {\\n revert(\\\"GovernorVotingSimple: invalid value for enum VoteType\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xdc37daa24118a6e6ba5208b4abefa1632af2ff340135ca6c6d7237f70102d5db\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotes is L2Governor {\\n IVotes public immutable token;\\n\\n constructor(IVotes tokenAddress) {\\n token = tokenAddress;\\n }\\n\\n /**\\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory /*params*/\\n ) internal view virtual override returns (uint256) {\\n return token.getPastVotes(account, blockTimestamp);\\n }\\n}\\n\",\"keccak256\":\"0x605a7de71228dda3cb8fd878cac313a86bc5841fd34d7344214346ba46e63af1\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotesQuorumFraction.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\\n * fraction of the total supply.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\\n uint256 private _quorumNumerator;\\n\\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\\n\\n /**\\n * @dev Initialize quorum as a fraction of the token's total supply.\\n *\\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\\n * customized by overriding {quorumDenominator}.\\n */\\n constructor(uint256 quorumNumeratorValue) {\\n _updateQuorumNumerator(quorumNumeratorValue);\\n }\\n\\n /**\\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\\n */\\n function quorumNumerator() public view virtual returns (uint256) {\\n return _quorumNumerator;\\n }\\n\\n /**\\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\\n */\\n function quorumDenominator() public view virtual returns (uint256) {\\n return 100;\\n }\\n\\n /**\\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\\n */\\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - Must be called through a governance proposal.\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\\n _updateQuorumNumerator(newQuorumNumerator);\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\\n require(\\n newQuorumNumerator <= quorumDenominator(),\\n \\\"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\\\"\\n );\\n\\n uint256 oldQuorumNumerator = _quorumNumerator;\\n _quorumNumerator = newQuorumNumerator;\\n\\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\\n }\\n}\\n\",\"keccak256\":\"0xe66d29c0ffd2274de933d80e11d68891f3acc3f078be4560a2b493b7d88dcb7f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Interface of the {Governor} core.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract IGovernor is IERC165 {\\n enum ProposalState {\\n Pending,\\n Active,\\n Canceled,\\n Defeated,\\n Succeeded,\\n Queued,\\n Expired,\\n Executed\\n }\\n\\n /**\\n * @dev Emitted when a proposal is created.\\n */\\n event ProposalCreated(\\n uint256 proposalId,\\n address proposer,\\n address[] targets,\\n uint256[] values,\\n string[] signatures,\\n bytes[] calldatas,\\n uint256 startBlock,\\n uint256 endBlock,\\n string description\\n );\\n\\n /**\\n * @dev Emitted when a proposal is canceled.\\n */\\n event ProposalCanceled(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a proposal is executed.\\n */\\n event ProposalExecuted(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a vote is cast without params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n */\\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\\n\\n /**\\n * @dev Emitted when a vote is cast with params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\\n */\\n event VoteCastWithParams(\\n address indexed voter,\\n uint256 proposalId,\\n uint8 support,\\n uint256 weight,\\n string reason,\\n bytes params\\n );\\n\\n /**\\n * @notice module:core\\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\\n */\\n function name() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \\\"1\\\"\\n */\\n function version() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:voting\\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\\n *\\n * There are 2 standard keys: `support` and `quorum`.\\n *\\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\\n * - `quorum=bravo` means that only For votes are counted towards quorum.\\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\\n *\\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\\n * name that describes the behavior. For example:\\n *\\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\\n *\\n * NOTE: The string can be decoded by the standard\\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\\n * JavaScript class.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Current state of a proposal, following Compound's convention\\n */\\n function state(uint256 proposalId) public view virtual returns (ProposalState);\\n\\n /**\\n * @notice module:core\\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\\n * beginning of the following block.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\\n * during this block.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\\n */\\n function votingDelay() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of blocks, between the vote start and vote ends.\\n *\\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\\n * duration compared to the voting delay.\\n */\\n function votingPeriod() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Minimum number of cast voted required for a proposal to be successful.\\n *\\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\\n */\\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber`.\\n *\\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\\n * multiple), {ERC20Votes} tokens.\\n */\\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockNumber,\\n bytes memory params\\n ) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:voting\\n * @dev Returns whether `account` has cast a vote on `proposalId`.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\\n\\n /**\\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\\n * {IGovernor-votingPeriod} blocks after the voting starts.\\n *\\n * Emits a {ProposalCreated} event.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\\n * deadline to be reached.\\n *\\n * Emits a {ProposalExecuted} event.\\n *\\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Cast a vote\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xa52d593ff06a2353f78fa149da31f2ca94f03d1eff99bde41977fa2fe985a92f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2e53602b96c1bf97c731ed3e2a981b4f85e23a9410a5ebd36e549a4cc93340dc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x2626d8ab3dfdad0fad630c212ad146d59473d0f48b771784c61a7c1dbbea1f3f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Tooling for timepoints, timers and delays\\n */\\nlibrary Timers {\\n struct Timestamp {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(Timestamp storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(Timestamp memory timer) internal view returns (bool) {\\n return timer._deadline > block.timestamp;\\n }\\n\\n function isExpired(Timestamp memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.timestamp;\\n }\\n\\n struct BlockNumber {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(BlockNumber storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(BlockNumber memory timer) internal view returns (bool) {\\n return timer._deadline > block.number;\\n }\\n\\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.number;\\n }\\n}\\n\",\"keccak256\":\"0x29791a62950a7983e02a673639c1a781d1e448691800456c2ce4b99715391b14\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS,\\n InvalidSignatureV // Deprecated in v4.8\\n }\\n\\n function _throwError(RecoverError error) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert(\\\"ECDSA: invalid signature\\\");\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert(\\\"ECDSA: invalid signature 's' value\\\");\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature` or error string. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\\n if (signature.length == 65) {\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n /// @solidity memory-safe-assembly\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n return tryRecover(hash, v, r, s);\\n } else {\\n return (address(0), RecoverError.InvalidSignatureLength);\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, signature);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n *\\n * _Available since v4.2._\\n */\\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature);\\n }\\n\\n return (signer, RecoverError.NoError);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from `s`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", Strings.toString(s.length), s));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Typed Data, created from a\\n * `domainSeparator` and a `structHash`. This produces hash corresponding\\n * to the one signed with the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\\n * JSON-RPC method as part of EIP-712.\\n *\\n * See {recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n }\\n}\\n\",\"keccak256\":\"0x54ee424bfc83ce63b2a918b9a1efb5090a0fb68dbd1de3b10bc667776885dd4f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ECDSA.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n /* solhint-disable var-name-mixedcase */\\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n // invalidate the cached domain separator if the chain id changes.\\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n uint256 private immutable _CACHED_CHAIN_ID;\\n address private immutable _CACHED_THIS;\\n\\n bytes32 private immutable _HASHED_NAME;\\n bytes32 private immutable _HASHED_VERSION;\\n bytes32 private immutable _TYPE_HASH;\\n\\n /* solhint-enable var-name-mixedcase */\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n constructor(string memory name, string memory version) {\\n bytes32 hashedName = keccak256(bytes(name));\\n bytes32 hashedVersion = keccak256(bytes(version));\\n bytes32 typeHash = keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n );\\n _HASHED_NAME = hashedName;\\n _HASHED_VERSION = hashedVersion;\\n _CACHED_CHAIN_ID = block.chainid;\\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n _CACHED_THIS = address(this);\\n _TYPE_HASH = typeHash;\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\\n return _CACHED_DOMAIN_SEPARATOR;\\n } else {\\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n }\\n }\\n\\n function _buildDomainSeparator(\\n bytes32 typeHash,\\n bytes32 nameHash,\\n bytes32 versionHash\\n ) private view returns (bytes32) {\\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\\n }\\n}\\n\",\"keccak256\":\"0x948d8b2d18f38141ec78c5229d770d950ebc781ed3f44cc9e3ccbb9fded5846a\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\\n\\nimport \\\"./EIP712.sol\\\";\\n\",\"keccak256\":\"0xea30c402170bc240354b74e6c6f6a8e5bdb1935d90d168cc58c0654461c6a72b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3546b156d97633f7f8cad536d5454c81d1d604687c02b2eb105fdc33cb962b41\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\\npragma solidity ^0.8.4;\\n\\nimport \\\"../math/SafeCast.sol\\\";\\n\\n/**\\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\\n * the existing queue contents are left in storage.\\n *\\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\\n * used in storage, and not in memory.\\n * ```\\n * DoubleEndedQueue.Bytes32Deque queue;\\n * ```\\n *\\n * _Available since v4.6._\\n */\\nlibrary DoubleEndedQueue {\\n /**\\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\\n */\\n error Empty();\\n\\n /**\\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\\n */\\n error OutOfBounds();\\n\\n /**\\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\\n *\\n * Struct members have an underscore prefix indicating that they are \\\"private\\\" and should not be read or written to\\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\\n * lead to unexpected behavior.\\n *\\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\\n * data[end - 1].\\n */\\n struct Bytes32Deque {\\n int128 _begin;\\n int128 _end;\\n mapping(int128 => bytes32) _data;\\n }\\n\\n /**\\n * @dev Inserts an item at the end of the queue.\\n */\\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 backIndex = deque._end;\\n deque._data[backIndex] = value;\\n unchecked {\\n deque._end = backIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Removes the item at the end of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n value = deque._data[backIndex];\\n delete deque._data[backIndex];\\n deque._end = backIndex;\\n }\\n\\n /**\\n * @dev Inserts an item at the beginning of the queue.\\n */\\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 frontIndex;\\n unchecked {\\n frontIndex = deque._begin - 1;\\n }\\n deque._data[frontIndex] = value;\\n deque._begin = frontIndex;\\n }\\n\\n /**\\n * @dev Removes the item at the beginning of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n value = deque._data[frontIndex];\\n delete deque._data[frontIndex];\\n unchecked {\\n deque._begin = frontIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Returns the item at the beginning of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n return deque._data[frontIndex];\\n }\\n\\n /**\\n * @dev Returns the item at the end of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n return deque._data[backIndex];\\n }\\n\\n /**\\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\\n * `length(deque) - 1`.\\n *\\n * Reverts with `OutOfBounds` if the index is out of bounds.\\n */\\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\\n // int256(deque._begin) is a safe upcast\\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\\n if (idx >= deque._end) revert OutOfBounds();\\n return deque._data[idx];\\n }\\n\\n /**\\n * @dev Resets the queue back to being empty.\\n *\\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\\n * out on potential gas refunds.\\n */\\n function clear(Bytes32Deque storage deque) internal {\\n deque._begin = 0;\\n deque._end = 0;\\n }\\n\\n /**\\n * @dev Returns the number of items in the queue.\\n */\\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\\n // We also assume there are at most int256.max items in the queue.\\n unchecked {\\n return uint256(int256(deque._end) - int256(deque._begin));\\n }\\n }\\n\\n /**\\n * @dev Returns true if the queue is empty.\\n */\\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\\n return deque._end <= deque._begin;\\n }\\n}\\n\",\"keccak256\":\"0x4859ffd6dd69382a1462930c00b6e394007da80e78e510f56930271034737bf2\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x61016060405260026007553480156200001757600080fd5b506040516200329a3803806200329a8339810160408190526200003a91620002ec565b6004816040518060400160405280601481526020017f56656c6f63696d6574657220476f7665726e6f7200000000000000000000000081525080620000846200015e60201b60201c565b815160208084019190912082518383012060e08290526101008190524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81880181905281830187905260608201869052608082019490945230818401528151808203909301835260c00190528051940193909320919290916080523060c05261012052505082516200012a925060009150602084019062000246565b50506001600160a01b031661014052620001448162000179565b5050600680546001600160a01b031916331790556200035a565b6040805180820190915260018152603160f81b602082015290565b6064811115620002015760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a40160405180910390fd5b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b82805462000254906200031e565b90600052602060002090601f016020900481019282620002785760008555620002c3565b82601f106200029357805160ff1916838001178555620002c3565b82800160010185558215620002c3579182015b82811115620002c3578251825591602001919060010190620002a6565b50620002d1929150620002d5565b5090565b5b80821115620002d15760008155600101620002d6565b600060208284031215620002ff57600080fd5b81516001600160a01b03811681146200031757600080fd5b9392505050565b600181811c908216806200033357607f821691505b6020821081036200035457634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e051610100516101205161014051612ed0620003ca600039600081816107df0152818161120f015281816113e40152611a0601526000611b2301526000611b7201526000611b4d01526000611aa601526000611ad001526000611afa0152612ed06000f3fe6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a26469706673582212203270a9fc50cfa0f139ef918071f19d9b00812268f9d1e713077fc9299cb1081d64736f6c634300080d0033", - "deployedBytecode": "0x6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a26469706673582212203270a9fc50cfa0f139ef918071f19d9b00812268f9d1e713077fc9299cb1081d64736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"_ve\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"Empty\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"proposer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"string[]\",\"name\":\"signatures\",\"type\":\"string[]\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"ProposalCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldQuorumNumerator\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"QuorumNumeratorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"VoteCast\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"VoteCastWithParams\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"COUNTING_MODE\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EXTENDED_BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_PROPOSAL_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROPOSAL_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"}],\"name\":\"castVote\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"castVoteWithReason\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"castVoteWithReasonAndParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteWithReasonAndParamsBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"execute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"getVotesWithParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasVoted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"hashProposal\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalDeadline\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalSnapshot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"againstVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"forVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"abstainVotes\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"propose\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"quorum\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumDenominator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"}],\"name\":\"setProposalNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTeam\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"state\",\"outputs\":[{\"internalType\":\"enum IGovernor.ProposalState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"updateQuorumNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"Empty()\":[{\"details\":\"An operation (e.g. {front}) couldn't be completed due to the queue being empty.\"}]},\"kind\":\"dev\",\"methods\":{\"COUNTING_MODE()\":{\"details\":\"See {IGovernor-COUNTING_MODE}.\"},\"castVote(uint256,uint8)\":{\"details\":\"See {IGovernor-castVote}.\"},\"castVoteBySig(uint256,uint8,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteBySig}.\"},\"castVoteWithReason(uint256,uint8,string)\":{\"details\":\"See {IGovernor-castVoteWithReason}.\"},\"castVoteWithReasonAndParams(uint256,uint8,string,bytes)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParams}.\"},\"castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParamsBySig}.\"},\"execute(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-execute}.\"},\"getVotes(address,uint256)\":{\"details\":\"See {IGovernor-getVotes}.\"},\"getVotesWithParams(address,uint256,bytes)\":{\"details\":\"See {IGovernor-getVotesWithParams}.\"},\"hasVoted(uint256,address)\":{\"details\":\"See {IGovernor-hasVoted}.\"},\"hashProposal(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-hashProposal}. The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in advance, before the proposal is submitted. Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the same proposal (with same operation and same description) will have the same id if submitted on multiple governors across multiple networks. This also means that in order to execute the same operation twice (on the same governor) the proposer will have to change the description in order to avoid proposal id conflicts.\"},\"name()\":{\"details\":\"See {IGovernor-name}.\"},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155BatchReceived}.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155Received}.\"},\"onERC721Received(address,address,uint256,bytes)\":{\"details\":\"See {IERC721Receiver-onERC721Received}.\"},\"proposalDeadline(uint256)\":{\"details\":\"See {IGovernor-proposalDeadline}.\"},\"proposalSnapshot(uint256)\":{\"details\":\"See {IGovernor-proposalSnapshot}.\"},\"proposalThreshold()\":{\"details\":\"Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\"},\"proposalVotes(uint256)\":{\"details\":\"Accessor to the internal vote counts.\"},\"propose(address[],uint256[],bytes[],string)\":{\"details\":\"See {IGovernor-propose}.\"},\"quorum(uint256)\":{\"details\":\"Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\"},\"quorumDenominator()\":{\"details\":\"Returns the quorum denominator. Defaults to 100, but may be overridden.\"},\"quorumNumerator()\":{\"details\":\"Returns the current quorum numerator. See {quorumDenominator}.\"},\"relay(address,uint256,bytes)\":{\"details\":\"Relays a transaction or function call to an arbitrary target. In cases where the governance executor is some contract other than the governor itself, like when using a timelock, this function can be invoked in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake. Note that if the executor is simply the governor itself, use of `relay` is redundant.\"},\"state(uint256)\":{\"details\":\"See {IGovernor-state}.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"updateQuorumNumerator(uint256)\":{\"details\":\"Changes the quorum numerator. Emits a {QuorumNumeratorUpdated} event. Requirements: - Must be called through a governance proposal. - New numerator must be smaller or equal to the denominator.\"},\"version()\":{\"details\":\"See {IGovernor-version}.\"},\"votingDelay()\":{\"details\":\"Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\"},\"votingPeriod()\":{\"details\":\"Delay, in number of blocks, between the vote start and vote ends. NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting duration compared to the voting delay.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"votingDelay()\":{\"notice\":\"module:user-config\"},\"votingPeriod()\":{\"notice\":\"module:user-config\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/FlowGovernor.sol\":\"FlowGovernor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/FlowGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IGovernor} from \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\nimport {L2GovernorCountingSimple} from \\\"contracts/governance/L2GovernorCountingSimple.sol\\\";\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\nimport {L2GovernorVotesQuorumFraction} from \\\"contracts/governance/L2GovernorVotesQuorumFraction.sol\\\";\\n\\ncontract FlowGovernor is\\n L2Governor,\\n L2GovernorCountingSimple,\\n L2GovernorVotes,\\n L2GovernorVotesQuorumFraction\\n{\\n address public team;\\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\\n uint256 public proposalNumerator = 2; // start at 0.02%\\n\\n constructor(IVotes _ve)\\n L2Governor(\\\"Velocimeter Governor\\\")\\n L2GovernorVotes(_ve)\\n L2GovernorVotesQuorumFraction(4) // 4%\\n {\\n team = msg.sender;\\n }\\n\\n function votingDelay() public pure override(IGovernor) returns (uint256) {\\n return 15 minutes; // 1 block\\n }\\n\\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\\n return 1 weeks;\\n }\\n\\n function setTeam(address newTeam) external {\\n require(msg.sender == team, \\\"not team\\\");\\n team = newTeam;\\n }\\n\\n function setProposalNumerator(uint256 numerator) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \\\"numerator too high\\\");\\n proposalNumerator = numerator;\\n }\\n\\n function proposalThreshold()\\n public\\n view\\n override(L2Governor)\\n returns (uint256)\\n {\\n return\\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\\n PROPOSAL_DENOMINATOR;\\n }\\n}\\n\",\"keccak256\":\"0xbf02f2fa1b0179b06bba2274ce6720c31ba3783f899502567cc25a093b27edb6\",\"license\":\"MIT\"},\"contracts/governance/L2Governor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Address.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Context.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\\n *\\n * @dev Core of the governance system, designed to be extended though various modules.\\n *\\n * This contract is abstract and requires several function to be implemented in various modules:\\n *\\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\\n * - A voting module must implement {_getVotes}\\n * - Additionanly, the {votingPeriod} must also be implemented\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\\n using SafeCast for uint256;\\n using Timers for Timers.Timestamp;\\n\\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\\\"Ballot(uint256 proposalId,uint8 support)\\\");\\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\\n keccak256(\\\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\\\");\\n\\n struct ProposalCore {\\n Timers.Timestamp voteStart;\\n Timers.Timestamp voteEnd;\\n bool executed;\\n bool canceled;\\n }\\n\\n string private _name;\\n\\n mapping(uint256 => ProposalCore) private _proposals;\\n\\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\\n\\n /**\\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\\n * parameter setters in {GovernorSettings} are protected using this modifier.\\n *\\n * The governance executing address may be different from the Governor's own address, for example it could be a\\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\\n * for example, additional timelock proposers are not able to change governance parameters without going through the\\n * governance protocol (since v4.6).\\n */\\n modifier onlyGovernance() {\\n require(_msgSender() == _executor(), \\\"Governor: onlyGovernance\\\");\\n if (_executor() != address(this)) {\\n bytes32 msgDataHash = keccak256(_msgData());\\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\\n while (_governanceCall.popFront() != msgDataHash) {}\\n }\\n _;\\n }\\n\\n /**\\n * @dev Sets the value for {name} and {version}\\n */\\n constructor(string memory name_) EIP712(name_, version()) {\\n _name = name_;\\n }\\n\\n /**\\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\\n */\\n receive() external payable virtual {\\n require(_executor() == address(this));\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\\n // include the castVoteWithReasonAndParams() function as standard\\n return\\n interfaceId ==\\n (type(IGovernor).interfaceId ^\\n this.castVoteWithReasonAndParams.selector ^\\n this.castVoteWithReasonAndParamsBySig.selector ^\\n this.getVotesWithParams.selector) ||\\n interfaceId == type(IGovernor).interfaceId ||\\n interfaceId == type(IERC1155Receiver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IGovernor-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IGovernor-version}.\\n */\\n function version() public view virtual override returns (string memory) {\\n return \\\"1\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hashProposal}.\\n *\\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\\n * advance, before the proposal is submitted.\\n *\\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual override returns (uint256) {\\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\\n }\\n\\n /**\\n * @dev See {IGovernor-state}.\\n */\\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n\\n if (proposal.executed) {\\n return ProposalState.Executed;\\n }\\n\\n if (proposal.canceled) {\\n return ProposalState.Canceled;\\n }\\n\\n uint256 start = proposalSnapshot(proposalId);\\n\\n if (start == 0) {\\n revert(\\\"Governor: unknown proposal id\\\");\\n }\\n\\n if (start >= block.timestamp) {\\n return ProposalState.Pending;\\n }\\n\\n uint256 deadline = proposalDeadline(proposalId);\\n\\n if (deadline >= block.timestamp) {\\n return ProposalState.Active;\\n }\\n\\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\\n return ProposalState.Succeeded;\\n } else {\\n return ProposalState.Defeated;\\n }\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalSnapshot}.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteStart.getDeadline();\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalDeadline}.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteEnd.getDeadline();\\n }\\n\\n /**\\n * @dev Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\\n */\\n function proposalThreshold() public view virtual returns (uint256) {\\n return 0;\\n }\\n\\n /**\\n * @dev Amount of votes already cast passes the threshold limit.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Is the proposal successful or not.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) internal view virtual returns (uint256);\\n\\n /**\\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\\n *\\n * Note: Support is generic and can represent various things depending on the voting system used.\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory params\\n ) internal virtual;\\n\\n /**\\n * @dev Default additional encoded parameters used by castVote methods that don't include them\\n *\\n * Note: Should be overridden by specific implementations to use an appropriate value, the\\n * meaning of the additional params, in the context of that implementation\\n */\\n function _defaultParams() internal view virtual returns (bytes memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-propose}.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual override returns (uint256) {\\n require(\\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\\n \\\"Governor: proposer votes below proposal threshold\\\"\\n );\\n\\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\\n\\n require(targets.length == values.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length == calldatas.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length > 0, \\\"Governor: empty proposal\\\");\\n\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(proposal.voteStart.isUnset(), \\\"Governor: proposal already exists\\\");\\n\\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\\n uint64 deadline = start + votingPeriod().toUint64();\\n\\n proposal.voteStart.setDeadline(start);\\n proposal.voteEnd.setDeadline(deadline);\\n\\n emit ProposalCreated(\\n proposalId,\\n _msgSender(),\\n targets,\\n values,\\n new string[](targets.length),\\n calldatas,\\n start,\\n deadline,\\n description\\n );\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-execute}.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual override returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n\\n ProposalState status = state(proposalId);\\n require(\\n status == ProposalState.Succeeded || status == ProposalState.Queued,\\n \\\"Governor: proposal not successful\\\"\\n );\\n _proposals[proposalId].executed = true;\\n\\n emit ProposalExecuted(proposalId);\\n\\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\\n _execute(proposalId, targets, values, calldatas, descriptionHash);\\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\\n */\\n function _execute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n string memory errorMessage = \\\"Governor: call reverted without message\\\";\\n for (uint256 i = 0; i < targets.length; ++i) {\\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\\n Address.verifyCallResult(success, returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Hook before execution is triggered.\\n */\\n function _beforeExecute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory, /* values */\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n for (uint256 i = 0; i < targets.length; ++i) {\\n if (targets[i] == address(this)) {\\n _governanceCall.pushBack(keccak256(calldatas[i]));\\n }\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook after execution is triggered.\\n */\\n function _afterExecute(\\n uint256, /* proposalId */\\n address[] memory, /* targets */\\n uint256[] memory, /* values */\\n bytes[] memory, /* calldatas */\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n if (!_governanceCall.empty()) {\\n _governanceCall.clear();\\n }\\n }\\n }\\n\\n /**\\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\\n * canceled to allow distinguishing it from executed proposals.\\n *\\n * Emits a {IGovernor-ProposalCanceled} event.\\n */\\n function _cancel(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) internal virtual returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n ProposalState status = state(proposalId);\\n\\n require(\\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\\n \\\"Governor: proposal not active\\\"\\n );\\n _proposals[proposalId].canceled = true;\\n\\n emit ProposalCanceled(proposalId);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotes}.\\n */\\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, _defaultParams());\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotesWithParams}.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVote}.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReason}.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteBySig}.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\\n v,\\n r,\\n s\\n );\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(\\n keccak256(\\n abi.encode(\\n EXTENDED_BALLOT_TYPEHASH,\\n proposalId,\\n support,\\n keccak256(bytes(reason)),\\n keccak256(params)\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason\\n ) internal virtual returns (uint256) {\\n return _castVote(proposalId, account, support, reason, _defaultParams());\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason,\\n bytes memory params\\n ) internal virtual returns (uint256) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(state(proposalId) == ProposalState.Active, \\\"Governor: vote not currently active\\\");\\n\\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\\n _countVote(proposalId, account, support, weight, params);\\n\\n if (params.length == 0) {\\n emit VoteCast(account, proposalId, support, weight, reason);\\n } else {\\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\\n }\\n\\n return weight;\\n }\\n\\n /**\\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\\n */\\n function relay(\\n address target,\\n uint256 value,\\n bytes calldata data\\n ) external virtual onlyGovernance {\\n Address.functionCallWithValue(target, data, value);\\n }\\n\\n /**\\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\\n * through another contract such as a timelock.\\n */\\n function _executor() internal view virtual returns (address) {\\n return address(this);\\n }\\n\\n /**\\n * @dev See {IERC721Receiver-onERC721Received}.\\n */\\n function onERC721Received(\\n address,\\n address,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155Received}.\\n */\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\\n */\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] memory,\\n uint256[] memory,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155BatchReceived.selector;\\n }\\n}\\n\",\"keccak256\":\"0xa2846313b89a871807cdebd0225b0bf8f23b17505ab8b3288549ec54a5a4a71b\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorCountingSimple.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\\n *\\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorCountingSimple is L2Governor {\\n /**\\n * @dev Supported vote types. Matches Governor Bravo ordering.\\n */\\n enum VoteType {\\n Against,\\n For,\\n Abstain\\n }\\n\\n struct ProposalVote {\\n uint256 againstVotes;\\n uint256 forVotes;\\n uint256 abstainVotes;\\n mapping(address => bool) hasVoted;\\n }\\n\\n mapping(uint256 => ProposalVote) private _proposalVotes;\\n\\n /**\\n * @dev See {IGovernor-COUNTING_MODE}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual override returns (string memory) {\\n return \\\"support=bravo&quorum=for,abstain\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hasVoted}.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\\n return _proposalVotes[proposalId].hasVoted[account];\\n }\\n\\n /**\\n * @dev Accessor to the internal vote counts.\\n */\\n function proposalVotes(uint256 proposalId)\\n public\\n view\\n virtual\\n returns (\\n uint256 againstVotes,\\n uint256 forVotes,\\n uint256 abstainVotes\\n )\\n {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\\n }\\n\\n /**\\n * @dev See {Governor-_quorumReached}.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return proposalvote.forVotes > proposalvote.againstVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory // params\\n ) internal virtual override {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n require(!proposalvote.hasVoted[account], \\\"GovernorVotingSimple: vote already cast\\\");\\n proposalvote.hasVoted[account] = true;\\n\\n if (support == uint8(VoteType.Against)) {\\n proposalvote.againstVotes += weight;\\n } else if (support == uint8(VoteType.For)) {\\n proposalvote.forVotes += weight;\\n } else if (support == uint8(VoteType.Abstain)) {\\n proposalvote.abstainVotes += weight;\\n } else {\\n revert(\\\"GovernorVotingSimple: invalid value for enum VoteType\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xdc37daa24118a6e6ba5208b4abefa1632af2ff340135ca6c6d7237f70102d5db\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotes is L2Governor {\\n IVotes public immutable token;\\n\\n constructor(IVotes tokenAddress) {\\n token = tokenAddress;\\n }\\n\\n /**\\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory /*params*/\\n ) internal view virtual override returns (uint256) {\\n return token.getPastVotes(account, blockTimestamp);\\n }\\n}\\n\",\"keccak256\":\"0x605a7de71228dda3cb8fd878cac313a86bc5841fd34d7344214346ba46e63af1\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotesQuorumFraction.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\\n * fraction of the total supply.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\\n uint256 private _quorumNumerator;\\n\\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\\n\\n /**\\n * @dev Initialize quorum as a fraction of the token's total supply.\\n *\\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\\n * customized by overriding {quorumDenominator}.\\n */\\n constructor(uint256 quorumNumeratorValue) {\\n _updateQuorumNumerator(quorumNumeratorValue);\\n }\\n\\n /**\\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\\n */\\n function quorumNumerator() public view virtual returns (uint256) {\\n return _quorumNumerator;\\n }\\n\\n /**\\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\\n */\\n function quorumDenominator() public view virtual returns (uint256) {\\n return 100;\\n }\\n\\n /**\\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\\n */\\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - Must be called through a governance proposal.\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\\n _updateQuorumNumerator(newQuorumNumerator);\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\\n require(\\n newQuorumNumerator <= quorumDenominator(),\\n \\\"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\\\"\\n );\\n\\n uint256 oldQuorumNumerator = _quorumNumerator;\\n _quorumNumerator = newQuorumNumerator;\\n\\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\\n }\\n}\\n\",\"keccak256\":\"0xe66d29c0ffd2274de933d80e11d68891f3acc3f078be4560a2b493b7d88dcb7f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Interface of the {Governor} core.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract IGovernor is IERC165 {\\n enum ProposalState {\\n Pending,\\n Active,\\n Canceled,\\n Defeated,\\n Succeeded,\\n Queued,\\n Expired,\\n Executed\\n }\\n\\n /**\\n * @dev Emitted when a proposal is created.\\n */\\n event ProposalCreated(\\n uint256 proposalId,\\n address proposer,\\n address[] targets,\\n uint256[] values,\\n string[] signatures,\\n bytes[] calldatas,\\n uint256 startBlock,\\n uint256 endBlock,\\n string description\\n );\\n\\n /**\\n * @dev Emitted when a proposal is canceled.\\n */\\n event ProposalCanceled(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a proposal is executed.\\n */\\n event ProposalExecuted(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a vote is cast without params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n */\\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\\n\\n /**\\n * @dev Emitted when a vote is cast with params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\\n */\\n event VoteCastWithParams(\\n address indexed voter,\\n uint256 proposalId,\\n uint8 support,\\n uint256 weight,\\n string reason,\\n bytes params\\n );\\n\\n /**\\n * @notice module:core\\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\\n */\\n function name() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \\\"1\\\"\\n */\\n function version() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:voting\\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\\n *\\n * There are 2 standard keys: `support` and `quorum`.\\n *\\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\\n * - `quorum=bravo` means that only For votes are counted towards quorum.\\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\\n *\\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\\n * name that describes the behavior. For example:\\n *\\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\\n *\\n * NOTE: The string can be decoded by the standard\\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\\n * JavaScript class.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Current state of a proposal, following Compound's convention\\n */\\n function state(uint256 proposalId) public view virtual returns (ProposalState);\\n\\n /**\\n * @notice module:core\\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\\n * beginning of the following block.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\\n * during this block.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\\n */\\n function votingDelay() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of blocks, between the vote start and vote ends.\\n *\\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\\n * duration compared to the voting delay.\\n */\\n function votingPeriod() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Minimum number of cast voted required for a proposal to be successful.\\n *\\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\\n */\\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber`.\\n *\\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\\n * multiple), {ERC20Votes} tokens.\\n */\\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockNumber,\\n bytes memory params\\n ) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:voting\\n * @dev Returns whether `account` has cast a vote on `proposalId`.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\\n\\n /**\\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\\n * {IGovernor-votingPeriod} blocks after the voting starts.\\n *\\n * Emits a {ProposalCreated} event.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\\n * deadline to be reached.\\n *\\n * Emits a {ProposalExecuted} event.\\n *\\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Cast a vote\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xa52d593ff06a2353f78fa149da31f2ca94f03d1eff99bde41977fa2fe985a92f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2e53602b96c1bf97c731ed3e2a981b4f85e23a9410a5ebd36e549a4cc93340dc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x2626d8ab3dfdad0fad630c212ad146d59473d0f48b771784c61a7c1dbbea1f3f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Tooling for timepoints, timers and delays\\n */\\nlibrary Timers {\\n struct Timestamp {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(Timestamp storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(Timestamp memory timer) internal view returns (bool) {\\n return timer._deadline > block.timestamp;\\n }\\n\\n function isExpired(Timestamp memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.timestamp;\\n }\\n\\n struct BlockNumber {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(BlockNumber storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(BlockNumber memory timer) internal view returns (bool) {\\n return timer._deadline > block.number;\\n }\\n\\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.number;\\n }\\n}\\n\",\"keccak256\":\"0x29791a62950a7983e02a673639c1a781d1e448691800456c2ce4b99715391b14\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS,\\n InvalidSignatureV // Deprecated in v4.8\\n }\\n\\n function _throwError(RecoverError error) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert(\\\"ECDSA: invalid signature\\\");\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert(\\\"ECDSA: invalid signature 's' value\\\");\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature` or error string. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\\n if (signature.length == 65) {\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n /// @solidity memory-safe-assembly\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n return tryRecover(hash, v, r, s);\\n } else {\\n return (address(0), RecoverError.InvalidSignatureLength);\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, signature);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n *\\n * _Available since v4.2._\\n */\\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature);\\n }\\n\\n return (signer, RecoverError.NoError);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from `s`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", Strings.toString(s.length), s));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Typed Data, created from a\\n * `domainSeparator` and a `structHash`. This produces hash corresponding\\n * to the one signed with the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\\n * JSON-RPC method as part of EIP-712.\\n *\\n * See {recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n }\\n}\\n\",\"keccak256\":\"0x54ee424bfc83ce63b2a918b9a1efb5090a0fb68dbd1de3b10bc667776885dd4f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ECDSA.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n /* solhint-disable var-name-mixedcase */\\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n // invalidate the cached domain separator if the chain id changes.\\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n uint256 private immutable _CACHED_CHAIN_ID;\\n address private immutable _CACHED_THIS;\\n\\n bytes32 private immutable _HASHED_NAME;\\n bytes32 private immutable _HASHED_VERSION;\\n bytes32 private immutable _TYPE_HASH;\\n\\n /* solhint-enable var-name-mixedcase */\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n constructor(string memory name, string memory version) {\\n bytes32 hashedName = keccak256(bytes(name));\\n bytes32 hashedVersion = keccak256(bytes(version));\\n bytes32 typeHash = keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n );\\n _HASHED_NAME = hashedName;\\n _HASHED_VERSION = hashedVersion;\\n _CACHED_CHAIN_ID = block.chainid;\\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n _CACHED_THIS = address(this);\\n _TYPE_HASH = typeHash;\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\\n return _CACHED_DOMAIN_SEPARATOR;\\n } else {\\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n }\\n }\\n\\n function _buildDomainSeparator(\\n bytes32 typeHash,\\n bytes32 nameHash,\\n bytes32 versionHash\\n ) private view returns (bytes32) {\\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\\n }\\n}\\n\",\"keccak256\":\"0x948d8b2d18f38141ec78c5229d770d950ebc781ed3f44cc9e3ccbb9fded5846a\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\\n\\nimport \\\"./EIP712.sol\\\";\\n\",\"keccak256\":\"0xea30c402170bc240354b74e6c6f6a8e5bdb1935d90d168cc58c0654461c6a72b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3546b156d97633f7f8cad536d5454c81d1d604687c02b2eb105fdc33cb962b41\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\\npragma solidity ^0.8.4;\\n\\nimport \\\"../math/SafeCast.sol\\\";\\n\\n/**\\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\\n * the existing queue contents are left in storage.\\n *\\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\\n * used in storage, and not in memory.\\n * ```\\n * DoubleEndedQueue.Bytes32Deque queue;\\n * ```\\n *\\n * _Available since v4.6._\\n */\\nlibrary DoubleEndedQueue {\\n /**\\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\\n */\\n error Empty();\\n\\n /**\\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\\n */\\n error OutOfBounds();\\n\\n /**\\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\\n *\\n * Struct members have an underscore prefix indicating that they are \\\"private\\\" and should not be read or written to\\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\\n * lead to unexpected behavior.\\n *\\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\\n * data[end - 1].\\n */\\n struct Bytes32Deque {\\n int128 _begin;\\n int128 _end;\\n mapping(int128 => bytes32) _data;\\n }\\n\\n /**\\n * @dev Inserts an item at the end of the queue.\\n */\\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 backIndex = deque._end;\\n deque._data[backIndex] = value;\\n unchecked {\\n deque._end = backIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Removes the item at the end of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n value = deque._data[backIndex];\\n delete deque._data[backIndex];\\n deque._end = backIndex;\\n }\\n\\n /**\\n * @dev Inserts an item at the beginning of the queue.\\n */\\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 frontIndex;\\n unchecked {\\n frontIndex = deque._begin - 1;\\n }\\n deque._data[frontIndex] = value;\\n deque._begin = frontIndex;\\n }\\n\\n /**\\n * @dev Removes the item at the beginning of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n value = deque._data[frontIndex];\\n delete deque._data[frontIndex];\\n unchecked {\\n deque._begin = frontIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Returns the item at the beginning of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n return deque._data[frontIndex];\\n }\\n\\n /**\\n * @dev Returns the item at the end of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n return deque._data[backIndex];\\n }\\n\\n /**\\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\\n * `length(deque) - 1`.\\n *\\n * Reverts with `OutOfBounds` if the index is out of bounds.\\n */\\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\\n // int256(deque._begin) is a safe upcast\\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\\n if (idx >= deque._end) revert OutOfBounds();\\n return deque._data[idx];\\n }\\n\\n /**\\n * @dev Resets the queue back to being empty.\\n *\\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\\n * out on potential gas refunds.\\n */\\n function clear(Bytes32Deque storage deque) internal {\\n deque._begin = 0;\\n deque._end = 0;\\n }\\n\\n /**\\n * @dev Returns the number of items in the queue.\\n */\\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\\n // We also assume there are at most int256.max items in the queue.\\n unchecked {\\n return uint256(int256(deque._end) - int256(deque._begin));\\n }\\n }\\n\\n /**\\n * @dev Returns true if the queue is empty.\\n */\\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\\n return deque._end <= deque._begin;\\n }\\n}\\n\",\"keccak256\":\"0x4859ffd6dd69382a1462930c00b6e394007da80e78e510f56930271034737bf2\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x61016060405260026007553480156200001757600080fd5b506040516200329a3803806200329a8339810160408190526200003a91620002ec565b6004816040518060400160405280601481526020017f56656c6f63696d6574657220476f7665726e6f7200000000000000000000000081525080620000846200015e60201b60201c565b815160208084019190912082518383012060e08290526101008190524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81880181905281830187905260608201869052608082019490945230818401528151808203909301835260c00190528051940193909320919290916080523060c05261012052505082516200012a925060009150602084019062000246565b50506001600160a01b031661014052620001448162000179565b5050600680546001600160a01b031916331790556200035a565b6040805180820190915260018152603160f81b602082015290565b6064811115620002015760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a40160405180910390fd5b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b82805462000254906200031e565b90600052602060002090601f016020900481019282620002785760008555620002c3565b82601f106200029357805160ff1916838001178555620002c3565b82800160010185558215620002c3579182015b82811115620002c3578251825591602001919060010190620002a6565b50620002d1929150620002d5565b5090565b5b80821115620002d15760008155600101620002d6565b600060208284031215620002ff57600080fd5b81516001600160a01b03811681146200031757600080fd5b9392505050565b600181811c908216806200033357607f821691505b6020821081036200035457634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e051610100516101205161014051612ed0620003ca600039600081816107df0152818161120f015281816113e40152611a0601526000611b2301526000611b7201526000611b4d01526000611aa601526000611ad001526000611afa0152612ed06000f3fe6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220f1c9f7302b3d88ded5042644bb73ef24c2cd7fc463479870f81e5dbfe2cbed0b64736f6c634300080d0033", + "deployedBytecode": "0x6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220f1c9f7302b3d88ded5042644bb73ef24c2cd7fc463479870f81e5dbfe2cbed0b64736f6c634300080d0033", "devdoc": { "errors": { "Empty()": [ diff --git a/deployments/arbitrumGoerli/GaugeFactory.json b/deployments/arbitrumGoerli/GaugeFactory.json index 9fbf8194..455c1568 100644 --- a/deployments/arbitrumGoerli/GaugeFactory.json +++ b/deployments/arbitrumGoerli/GaugeFactory.json @@ -1,5 +1,5 @@ { - "address": "0x18B8e4fEf12a17BFe35f0A1a4ca3cA7208F30123", + "address": "0x596CAFB654c2281838b570F3801a8288b7B7bE8a", "abi": [ { "inputs": [ @@ -59,28 +59,28 @@ "type": "function" } ], - "transactionHash": "0xb6453d5b0001f1377c6a90bdeb63e578a2637846a3bdf6fb5a1f5bfb4629abd7", + "transactionHash": "0x0ef11d8a4fe5d29db766f0b627fa7070269253ffd23b330f06a7a91a33aa33c5", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x18B8e4fEf12a17BFe35f0A1a4ca3cA7208F30123", + "contractAddress": "0x596CAFB654c2281838b570F3801a8288b7B7bE8a", "transactionIndex": 1, "gasUsed": "3308285", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xeb412148cd5f01ceae88fae38c726bba49346e9b772e4301c2b15300a8a1e105", - "transactionHash": "0xb6453d5b0001f1377c6a90bdeb63e578a2637846a3bdf6fb5a1f5bfb4629abd7", + "blockHash": "0xa8f22b723725bc8dfd117d9cb5e7c686e4f60abb6a7e604fb65cefd7db47795b", + "transactionHash": "0x0ef11d8a4fe5d29db766f0b627fa7070269253ffd23b330f06a7a91a33aa33c5", "logs": [], - "blockNumber": 5814394, + "blockNumber": 5849128, "cumulativeGasUsed": "3308285", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 5, - "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_internal_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_external_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_ve\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isPair\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_gauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/GaugeFactory.sol\":\"GaugeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Gauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\\ncontract Gauge is IGauge {\\n address public immutable stake; // the LP token that needs to be staked for rewards\\n address public immutable _ve; // the ve token used for gauges\\n address public immutable internal_bribe;\\n address public immutable external_bribe;\\n address public immutable voter;\\n\\n uint256 public derivedSupply;\\n mapping(address => uint256) public derivedBalances;\\n\\n bool public isForPair;\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 internal constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(address => uint256)) public lastEarn;\\n mapping(address => mapping(address => uint256))\\n public userRewardPerTokenStored;\\n\\n mapping(address => uint256) public tokenIds;\\n\\n uint256 public totalSupply;\\n mapping(address => uint256) public balanceOf;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n uint256 public fees0;\\n uint256 public fees1;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(\\n address _stake,\\n address _internal_bribe,\\n address _external_bribe,\\n address __ve,\\n address _voter,\\n bool _forPair,\\n address[] memory _allowedRewardTokens\\n ) {\\n stake = _stake;\\n internal_bribe = _internal_bribe;\\n external_bribe = _external_bribe;\\n _ve = __ve;\\n voter = _voter;\\n isForPair = _forPair;\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function claimFees()\\n external\\n lock\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n return _claimFees();\\n }\\n\\n function _claimFees()\\n internal\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n if (!isForPair) {\\n return (0, 0);\\n }\\n (claimed0, claimed1) = IPair(stake).claimFees();\\n if (claimed0 > 0 || claimed1 > 0) {\\n uint256 _fees0 = fees0 + claimed0;\\n uint256 _fees1 = fees1 + claimed1;\\n (address _token0, address _token1) = IPair(stake).tokens();\\n if (\\n _fees0 > IBribe(internal_bribe).left(_token0) &&\\n _fees0 / DURATION > 0\\n ) {\\n fees0 = 0;\\n _safeApprove(_token0, internal_bribe, _fees0);\\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\\n } else {\\n fees0 = _fees0;\\n }\\n if (\\n _fees1 > IBribe(internal_bribe).left(_token1) &&\\n _fees1 / DURATION > 0\\n ) {\\n fees1 = 0;\\n _safeApprove(_token1, internal_bribe, _fees1);\\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\\n } else {\\n fees1 = _fees1;\\n }\\n\\n emit ClaimFees(msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(address account, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(address account, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[account][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[account] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n derivedSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n function getReward(address account, address[] memory tokens) external lock {\\n require(msg.sender == account || msg.sender == voter);\\n _unlocked = 1;\\n IVoter(voter).distribute(address(this));\\n _unlocked = 2;\\n\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], account);\\n lastEarn[tokens[i]][account] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n\\n uint256 _derivedBalance = derivedBalances[account];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(account);\\n derivedBalances[account] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(account, derivedBalances[account]);\\n _writeSupplyCheckpoint();\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (derivedSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / derivedSupply);\\n }\\n\\n function derivedBalance(address account) public view returns (uint256) {\\n return balanceOf[account];\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\\n function earned(address token, address account)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][account],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[account] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[account] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[account][i];\\n Checkpoint memory cp1 = checkpoints[account][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[account][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][account]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n function depositAll(uint256 tokenId) external {\\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\\n }\\n\\n function deposit(uint256 amount, uint256 tokenId) public lock {\\n require(amount > 0);\\n _updateRewardForAllTokens();\\n\\n _safeTransferFrom(stake, msg.sender, address(this), amount);\\n totalSupply += amount;\\n balanceOf[msg.sender] += amount;\\n\\n if (tokenId > 0) {\\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\\n if (tokenIds[msg.sender] == 0) {\\n tokenIds[msg.sender] = tokenId;\\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\\n }\\n require(tokenIds[msg.sender] == tokenId);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, _derivedBalance);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function withdrawAll() external {\\n withdraw(balanceOf[msg.sender]);\\n }\\n\\n function withdraw(uint256 amount) public {\\n uint256 tokenId = 0;\\n if (amount == balanceOf[msg.sender]) {\\n tokenId = tokenIds[msg.sender];\\n }\\n withdrawToken(amount, tokenId);\\n }\\n\\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[msg.sender] -= amount;\\n _safeTransfer(stake, msg.sender, amount);\\n\\n if (tokenId > 0) {\\n require(tokenId == tokenIds[msg.sender]);\\n tokenIds[msg.sender] = 0;\\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(token != stake);\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"rewards tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n _claimFees();\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeApprove(\\n address token,\\n address spender,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x38cc0284dd60d8a1418d9c34e6be84911ca4a1b479dc129f19b9027e4c670e1f\",\"license\":\"MIT\"},\"contracts/factories/GaugeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/Gauge.sol';\\n\\ncontract GaugeFactory is IGaugeFactory {\\n address public last_gauge;\\n\\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\\n return last_gauge;\\n }\\n}\\n\",\"keccak256\":\"0x34f6ac4bdace9ef01d8cffda9b45842efae88b519230c67759b9936aee6acc9b\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50613b19806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea2646970667358221220c9c7170e6533f9335bb092247861296b17f43f3dd5553246381036dde06e43f364736f6c634300080d0033a2646970667358221220036a8a62293c9b1a5f9ccfeaf493ee8d2c511917db3b1f888e333523d7fb117264736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea2646970667358221220c9c7170e6533f9335bb092247861296b17f43f3dd5553246381036dde06e43f364736f6c634300080d0033a2646970667358221220036a8a62293c9b1a5f9ccfeaf493ee8d2c511917db3b1f888e333523d7fb117264736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_internal_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_external_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_ve\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isPair\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_gauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/GaugeFactory.sol\":\"GaugeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Gauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\\ncontract Gauge is IGauge {\\n address public immutable stake; // the LP token that needs to be staked for rewards\\n address public immutable _ve; // the ve token used for gauges\\n address public immutable internal_bribe;\\n address public immutable external_bribe;\\n address public immutable voter;\\n\\n uint256 public derivedSupply;\\n mapping(address => uint256) public derivedBalances;\\n\\n bool public isForPair;\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 internal constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(address => uint256)) public lastEarn;\\n mapping(address => mapping(address => uint256))\\n public userRewardPerTokenStored;\\n\\n mapping(address => uint256) public tokenIds;\\n\\n uint256 public totalSupply;\\n mapping(address => uint256) public balanceOf;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n uint256 public fees0;\\n uint256 public fees1;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(\\n address _stake,\\n address _internal_bribe,\\n address _external_bribe,\\n address __ve,\\n address _voter,\\n bool _forPair,\\n address[] memory _allowedRewardTokens\\n ) {\\n stake = _stake;\\n internal_bribe = _internal_bribe;\\n external_bribe = _external_bribe;\\n _ve = __ve;\\n voter = _voter;\\n isForPair = _forPair;\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function claimFees()\\n external\\n lock\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n return _claimFees();\\n }\\n\\n function _claimFees()\\n internal\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n if (!isForPair) {\\n return (0, 0);\\n }\\n (claimed0, claimed1) = IPair(stake).claimFees();\\n if (claimed0 > 0 || claimed1 > 0) {\\n uint256 _fees0 = fees0 + claimed0;\\n uint256 _fees1 = fees1 + claimed1;\\n (address _token0, address _token1) = IPair(stake).tokens();\\n if (\\n _fees0 > IBribe(internal_bribe).left(_token0) &&\\n _fees0 / DURATION > 0\\n ) {\\n fees0 = 0;\\n _safeApprove(_token0, internal_bribe, _fees0);\\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\\n } else {\\n fees0 = _fees0;\\n }\\n if (\\n _fees1 > IBribe(internal_bribe).left(_token1) &&\\n _fees1 / DURATION > 0\\n ) {\\n fees1 = 0;\\n _safeApprove(_token1, internal_bribe, _fees1);\\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\\n } else {\\n fees1 = _fees1;\\n }\\n\\n emit ClaimFees(msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(address account, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(address account, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[account][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[account] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n derivedSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n function getReward(address account, address[] memory tokens) external lock {\\n require(msg.sender == account || msg.sender == voter);\\n _unlocked = 1;\\n IVoter(voter).distribute(address(this));\\n _unlocked = 2;\\n\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], account);\\n lastEarn[tokens[i]][account] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n\\n uint256 _derivedBalance = derivedBalances[account];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(account);\\n derivedBalances[account] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(account, derivedBalances[account]);\\n _writeSupplyCheckpoint();\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (derivedSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / derivedSupply);\\n }\\n\\n function derivedBalance(address account) public view returns (uint256) {\\n return balanceOf[account];\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\\n function earned(address token, address account)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][account],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[account] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[account] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[account][i];\\n Checkpoint memory cp1 = checkpoints[account][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[account][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][account]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n function depositAll(uint256 tokenId) external {\\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\\n }\\n\\n function deposit(uint256 amount, uint256 tokenId) public lock {\\n require(amount > 0);\\n _updateRewardForAllTokens();\\n\\n _safeTransferFrom(stake, msg.sender, address(this), amount);\\n totalSupply += amount;\\n balanceOf[msg.sender] += amount;\\n\\n if (tokenId > 0) {\\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\\n if (tokenIds[msg.sender] == 0) {\\n tokenIds[msg.sender] = tokenId;\\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\\n }\\n require(tokenIds[msg.sender] == tokenId);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, _derivedBalance);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function withdrawAll() external {\\n withdraw(balanceOf[msg.sender]);\\n }\\n\\n function withdraw(uint256 amount) public {\\n uint256 tokenId = 0;\\n if (amount == balanceOf[msg.sender]) {\\n tokenId = tokenIds[msg.sender];\\n }\\n withdrawToken(amount, tokenId);\\n }\\n\\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[msg.sender] -= amount;\\n _safeTransfer(stake, msg.sender, amount);\\n\\n if (tokenId > 0) {\\n require(tokenId == tokenIds[msg.sender]);\\n tokenIds[msg.sender] = 0;\\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(token != stake);\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"rewards tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n _claimFees();\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeApprove(\\n address token,\\n address spender,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x38cc0284dd60d8a1418d9c34e6be84911ca4a1b479dc129f19b9027e4c670e1f\",\"license\":\"MIT\"},\"contracts/factories/GaugeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/Gauge.sol';\\n\\ncontract GaugeFactory is IGaugeFactory {\\n address public last_gauge;\\n\\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\\n return last_gauge;\\n }\\n}\\n\",\"keccak256\":\"0x34f6ac4bdace9ef01d8cffda9b45842efae88b519230c67759b9936aee6acc9b\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50613b19806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea2646970667358221220929baeb85b1bc48821b4e95a725f54f20ab2e3f0c1a3816544d164232d22aa3064736f6c634300080d0033a26469706673582212203721086bab0d5375338b81f026a2a24a718fd4b50955e5f51d88550583d6e94264736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea2646970667358221220929baeb85b1bc48821b4e95a725f54f20ab2e3f0c1a3816544d164232d22aa3064736f6c634300080d0033a26469706673582212203721086bab0d5375338b81f026a2a24a718fd4b50955e5f51d88550583d6e94264736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/MerkleClaim.json b/deployments/arbitrumGoerli/MerkleClaim.json index 0b2d815b..90e70784 100644 --- a/deployments/arbitrumGoerli/MerkleClaim.json +++ b/deployments/arbitrumGoerli/MerkleClaim.json @@ -1,5 +1,5 @@ { - "address": "0x0BDAc938ec4f1af0f6C204e02C0BbdFC9ebd0f7c", + "address": "0x1A0F539D3A6096e5C6928b95A651170B339c5FBf", "abi": [ { "inputs": [ @@ -105,31 +105,31 @@ "type": "function" } ], - "transactionHash": "0xcc8c8ccc2638458967c3317621c92db366e7c03f40fa24a0643454c4f0f75d0a", + "transactionHash": "0x289e0c6e8a39e9b3ac929aa2c0b9aa9b313430065d7ec57f21aadd95fdb1ec25", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x0BDAc938ec4f1af0f6C204e02C0BbdFC9ebd0f7c", - "transactionIndex": 2, + "contractAddress": "0x1A0F539D3A6096e5C6928b95A651170B339c5FBf", + "transactionIndex": 1, "gasUsed": "356966", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc6812df80d99d1860e7e02f59b24352e93cee25bc38196eba4c1b4a9c36ae3ee", - "transactionHash": "0xcc8c8ccc2638458967c3317621c92db366e7c03f40fa24a0643454c4f0f75d0a", + "blockHash": "0xe8918a50edda4178b26d2c1881955b3ce0ec4b49d11d04747b7599d4701d542a", + "transactionHash": "0x289e0c6e8a39e9b3ac929aa2c0b9aa9b313430065d7ec57f21aadd95fdb1ec25", "logs": [], - "blockNumber": 5814457, - "cumulativeGasUsed": "841938", + "blockNumber": 5849272, + "cumulativeGasUsed": "356966", "status": 1, "byzantium": true }, "args": [ - "0x8c35578054126d4DD063CFaBA40B7F9B63A13981", + "0x0432f39386A9B1d0339c8Ba0af617b16C86ADA05", "0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f" ], - "numDeployments": 5, - "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_flow\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"_merkleRoot\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Claim\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FLOW\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"hasClaimed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\",\"events\":{\"Claim(address,uint256)\":{\"params\":{\"amount\":\"of tokens claimed\",\"to\":\"recipient of claim\"}}},\"kind\":\"dev\",\"methods\":{\"claim(address,uint256,bytes32[])\":{\"params\":{\"amount\":\"of tokens owed to claimee\",\"proof\":\"merkle proof to prove address and amount are in tree\",\"to\":\"address of claimee\"}},\"constructor\":{\"params\":{\"_flow\":\"address\",\"_merkleRoot\":\"of claimees\"}}},\"title\":\"MerkleClaim\",\"version\":1},\"userdoc\":{\"events\":{\"Claim(address,uint256)\":{\"notice\":\"Emitted after a successful token claim\"}},\"kind\":\"user\",\"methods\":{\"FLOW()\":{\"notice\":\"FLOW token to claim\"},\"claim(address,uint256,bytes32[])\":{\"notice\":\"Allows claiming tokens if address is part of merkle tree\"},\"constructor\":{\"notice\":\"Creates a new MerkleClaim contract\"},\"hasClaimed(address)\":{\"notice\":\"Mapping of addresses who have claimed tokens\"},\"merkleRoot()\":{\"notice\":\"ERC20-claimee inclusion root\"}},\"notice\":\"Claims FLOW for members of a merkle tree\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/MerkleClaim.sol\":\"MerkleClaim\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/redeem/MerkleClaim.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity 0.8.13;\\n\\n/// ============ Imports ============\\n\\nimport {IFlow} from \\\"contracts/interfaces/IFlow.sol\\\";\\nimport {MerkleProof} from \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\\\"; // OZ: MerkleProof\\n\\n/// @title MerkleClaim\\n/// @notice Claims FLOW for members of a merkle tree\\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\\ncontract MerkleClaim {\\n /// ============ Immutable storage ============\\n\\n /// @notice FLOW token to claim\\n IFlow public immutable FLOW;\\n /// @notice ERC20-claimee inclusion root\\n bytes32 public immutable merkleRoot;\\n\\n /// ============ Mutable storage ============\\n\\n /// @notice Mapping of addresses who have claimed tokens\\n mapping(address => bool) public hasClaimed;\\n\\n /// ============ Constructor ============\\n\\n /// @notice Creates a new MerkleClaim contract\\n /// @param _flow address\\n /// @param _merkleRoot of claimees\\n constructor(address _flow, bytes32 _merkleRoot) {\\n FLOW = IFlow(_flow);\\n merkleRoot = _merkleRoot;\\n }\\n\\n /// ============ Events ============\\n\\n /// @notice Emitted after a successful token claim\\n /// @param to recipient of claim\\n /// @param amount of tokens claimed\\n event Claim(address indexed to, uint256 amount);\\n\\n /// ============ Functions ============\\n\\n /// @notice Allows claiming tokens if address is part of merkle tree\\n /// @param to address of claimee\\n /// @param amount of tokens owed to claimee\\n /// @param proof merkle proof to prove address and amount are in tree\\n function claim(\\n address to,\\n uint256 amount,\\n bytes32[] calldata proof\\n ) external {\\n // Throw if address has already claimed tokens\\n require(!hasClaimed[to], \\\"ALREADY_CLAIMED\\\");\\n\\n // Verify merkle proof, or revert if not in tree\\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\\n require(isValidLeaf, \\\"NOT_IN_MERKLE\\\");\\n\\n // Set address to claimed\\n hasClaimed[to] = true;\\n\\n // Claim tokens for address\\n require(FLOW.claim(to, amount), \\\"CLAIM_FAILED\\\");\\n\\n // Emit claim event\\n emit Claim(to, amount);\\n }\\n}\\n\",\"keccak256\":\"0xf169ba9559c5c39dc79b2281410b09fd92f200a3b0489b32e28ce08a00a98826\",\"license\":\"AGPL-3.0-only\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev These functions deal with verification of Merkle Tree proofs.\\n *\\n * The tree and the proofs can be generated using our\\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\\n * You will find a quickstart guide in the readme.\\n *\\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\\n * hashing, or use a hash function other than keccak256 for hashing leaves.\\n * This is because the concatenation of a sorted pair of internal nodes in\\n * the merkle tree could be reinterpreted as a leaf value.\\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\\n * against this attack out of the box.\\n */\\nlibrary MerkleProof {\\n /**\\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\\n * defined by `root`. For this, a `proof` must be provided, containing\\n * sibling hashes on the branch from the leaf to the root of the tree. Each\\n * pair of leaves and each pair of pre-images are assumed to be sorted.\\n */\\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProof(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {verify}\\n *\\n * _Available since v4.7._\\n */\\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProofCalldata(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\\n * hash matches the root of the tree. When processing the proof, the pairs\\n * of leafs & pre-images are assumed to be sorted.\\n *\\n * _Available since v4.4._\\n */\\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Calldata version of {processProof}\\n *\\n * _Available since v4.7._\\n */\\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerify(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProof(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {multiProofVerify}\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerifyCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\\n * respectively.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProof(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n /**\\n * @dev Calldata version of {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProofCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\\n }\\n\\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x00, a)\\n mstore(0x20, b)\\n value := keccak256(0x00, 0x40)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcc76dbe53154a5bbd12fdd1613a73f73f3dc7c63d813be36f7ee606f52d6a7b3\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60c060405234801561001057600080fd5b5060405161062638038061062683398101604081905261002f91610045565b6001600160a01b0390911660805260a05261007f565b6000806040838503121561005857600080fd5b82516001600160a01b038116811461006f57600080fd5b6020939093015192949293505050565b60805160a0516105766100b060003960008181605601526101ea0152600081816090015261029601526105766000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633189097b1461008b5780633d13f874146100ca57806373b2e80e146100df575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6100b27f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6100dd6100d836600461043c565b610112565b005b6101026100ed3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220a1b07a4e977287c43c42e0b0a2edb40fce264268ea2158cb90b7041e8a3aa19464736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633189097b1461008b5780633d13f874146100ca57806373b2e80e146100df575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6100b27f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6100dd6100d836600461043c565b610112565b005b6101026100ed3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220a1b07a4e977287c43c42e0b0a2edb40fce264268ea2158cb90b7041e8a3aa19464736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_flow\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"_merkleRoot\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Claim\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FLOW\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"hasClaimed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\",\"events\":{\"Claim(address,uint256)\":{\"params\":{\"amount\":\"of tokens claimed\",\"to\":\"recipient of claim\"}}},\"kind\":\"dev\",\"methods\":{\"claim(address,uint256,bytes32[])\":{\"params\":{\"amount\":\"of tokens owed to claimee\",\"proof\":\"merkle proof to prove address and amount are in tree\",\"to\":\"address of claimee\"}},\"constructor\":{\"params\":{\"_flow\":\"address\",\"_merkleRoot\":\"of claimees\"}}},\"title\":\"MerkleClaim\",\"version\":1},\"userdoc\":{\"events\":{\"Claim(address,uint256)\":{\"notice\":\"Emitted after a successful token claim\"}},\"kind\":\"user\",\"methods\":{\"FLOW()\":{\"notice\":\"FLOW token to claim\"},\"claim(address,uint256,bytes32[])\":{\"notice\":\"Allows claiming tokens if address is part of merkle tree\"},\"constructor\":{\"notice\":\"Creates a new MerkleClaim contract\"},\"hasClaimed(address)\":{\"notice\":\"Mapping of addresses who have claimed tokens\"},\"merkleRoot()\":{\"notice\":\"ERC20-claimee inclusion root\"}},\"notice\":\"Claims FLOW for members of a merkle tree\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/MerkleClaim.sol\":\"MerkleClaim\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/redeem/MerkleClaim.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity 0.8.13;\\n\\n/// ============ Imports ============\\n\\nimport {IFlow} from \\\"contracts/interfaces/IFlow.sol\\\";\\nimport {MerkleProof} from \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\\\"; // OZ: MerkleProof\\n\\n/// @title MerkleClaim\\n/// @notice Claims FLOW for members of a merkle tree\\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\\ncontract MerkleClaim {\\n /// ============ Immutable storage ============\\n\\n /// @notice FLOW token to claim\\n IFlow public immutable FLOW;\\n /// @notice ERC20-claimee inclusion root\\n bytes32 public immutable merkleRoot;\\n\\n /// ============ Mutable storage ============\\n\\n /// @notice Mapping of addresses who have claimed tokens\\n mapping(address => bool) public hasClaimed;\\n\\n /// ============ Constructor ============\\n\\n /// @notice Creates a new MerkleClaim contract\\n /// @param _flow address\\n /// @param _merkleRoot of claimees\\n constructor(address _flow, bytes32 _merkleRoot) {\\n FLOW = IFlow(_flow);\\n merkleRoot = _merkleRoot;\\n }\\n\\n /// ============ Events ============\\n\\n /// @notice Emitted after a successful token claim\\n /// @param to recipient of claim\\n /// @param amount of tokens claimed\\n event Claim(address indexed to, uint256 amount);\\n\\n /// ============ Functions ============\\n\\n /// @notice Allows claiming tokens if address is part of merkle tree\\n /// @param to address of claimee\\n /// @param amount of tokens owed to claimee\\n /// @param proof merkle proof to prove address and amount are in tree\\n function claim(\\n address to,\\n uint256 amount,\\n bytes32[] calldata proof\\n ) external {\\n // Throw if address has already claimed tokens\\n require(!hasClaimed[to], \\\"ALREADY_CLAIMED\\\");\\n\\n // Verify merkle proof, or revert if not in tree\\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\\n require(isValidLeaf, \\\"NOT_IN_MERKLE\\\");\\n\\n // Set address to claimed\\n hasClaimed[to] = true;\\n\\n // Claim tokens for address\\n require(FLOW.claim(to, amount), \\\"CLAIM_FAILED\\\");\\n\\n // Emit claim event\\n emit Claim(to, amount);\\n }\\n}\\n\",\"keccak256\":\"0xf169ba9559c5c39dc79b2281410b09fd92f200a3b0489b32e28ce08a00a98826\",\"license\":\"AGPL-3.0-only\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev These functions deal with verification of Merkle Tree proofs.\\n *\\n * The tree and the proofs can be generated using our\\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\\n * You will find a quickstart guide in the readme.\\n *\\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\\n * hashing, or use a hash function other than keccak256 for hashing leaves.\\n * This is because the concatenation of a sorted pair of internal nodes in\\n * the merkle tree could be reinterpreted as a leaf value.\\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\\n * against this attack out of the box.\\n */\\nlibrary MerkleProof {\\n /**\\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\\n * defined by `root`. For this, a `proof` must be provided, containing\\n * sibling hashes on the branch from the leaf to the root of the tree. Each\\n * pair of leaves and each pair of pre-images are assumed to be sorted.\\n */\\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProof(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {verify}\\n *\\n * _Available since v4.7._\\n */\\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProofCalldata(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\\n * hash matches the root of the tree. When processing the proof, the pairs\\n * of leafs & pre-images are assumed to be sorted.\\n *\\n * _Available since v4.4._\\n */\\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Calldata version of {processProof}\\n *\\n * _Available since v4.7._\\n */\\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerify(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProof(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {multiProofVerify}\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerifyCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\\n * respectively.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProof(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n /**\\n * @dev Calldata version of {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProofCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\\n }\\n\\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x00, a)\\n mstore(0x20, b)\\n value := keccak256(0x00, 0x40)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcc76dbe53154a5bbd12fdd1613a73f73f3dc7c63d813be36f7ee606f52d6a7b3\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c060405234801561001057600080fd5b5060405161062638038061062683398101604081905261002f91610045565b6001600160a01b0390911660805260a05261007f565b6000806040838503121561005857600080fd5b82516001600160a01b038116811461006f57600080fd5b6020939093015192949293505050565b60805160a0516105766100b060003960008181605601526101ea0152600081816090015261029601526105766000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633189097b1461008b5780633d13f874146100ca57806373b2e80e146100df575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6100b27f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6100dd6100d836600461043c565b610112565b005b6101026100ed3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea26469706673582212207985f8a8caed236605c9814107a30108b41352a1b3fe5cb8dbfa1e351035101d64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633189097b1461008b5780633d13f874146100ca57806373b2e80e146100df575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6100b27f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6100dd6100d836600461043c565b610112565b005b6101026100ed3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea26469706673582212207985f8a8caed236605c9814107a30108b41352a1b3fe5cb8dbfa1e351035101d64736f6c634300080d0033", "devdoc": { "author": "Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)", "events": { diff --git a/deployments/arbitrumGoerli/Minter.json b/deployments/arbitrumGoerli/Minter.json index c3faba2e..921a3438 100644 --- a/deployments/arbitrumGoerli/Minter.json +++ b/deployments/arbitrumGoerli/Minter.json @@ -1,5 +1,5 @@ { - "address": "0x07430f617D301343db890E42f3Fd7d61AA435a1A", + "address": "0x83886D8982819B9f1E36e8F134ED3d1AE3eaF9bd", "abi": [ { "inputs": [ @@ -324,32 +324,32 @@ "type": "function" } ], - "transactionHash": "0xb0588b210ecf7e3a0b144eac270b11bd57813f69fba45512ad7c2caf577ccb86", + "transactionHash": "0x4354bf457db79ca255447093921e0120a9129a063f8c5d5604c676db1f7db200", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x07430f617D301343db890E42f3Fd7d61AA435a1A", + "contractAddress": "0x83886D8982819B9f1E36e8F134ED3d1AE3eaF9bd", "transactionIndex": 1, "gasUsed": "1199219", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xe7a558c4aa52fae6851c8e72d692d25e80572c4e412851e9343330d846f5d5f6", - "transactionHash": "0xb0588b210ecf7e3a0b144eac270b11bd57813f69fba45512ad7c2caf577ccb86", + "blockHash": "0xff230fc39d91af4258c4a6843926acf7f74e80f8836eb49f6a70d6cab73bb9d6", + "transactionHash": "0x4354bf457db79ca255447093921e0120a9129a063f8c5d5604c676db1f7db200", "logs": [], - "blockNumber": 5814441, + "blockNumber": 5849239, "cumulativeGasUsed": "1199219", "status": 1, "byzantium": true }, "args": [ - "0xfD6108E8FDD2e6D125f71E68C7B8eD48f997c2Ad", - "0xad0F425b3edB0FC3a06096092B5736A280C90C40", - "0x85e7505be0F725AED67379Eb7F78d8561101caAE" + "0xe08A284C791c72E59C9020303b9B70E67bCf1d6C", + "0xF003091B78974ee3F99ec70fC5F42fc9810664EC", + "0xd06A463fD49720629A285E3C8De4310bc103df0a" ], - "numDeployments": 5, - "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__voter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__rewards_distributor\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weekly\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_supply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_emission\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_TEAM_RATE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_flow\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_rewards_distributor\",\"outputs\":[{\"internalType\":\"contract IRewardsDistributor\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"contract IVotingEscrow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_voter\",\"outputs\":[{\"internalType\":\"contract IVoter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"active_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"calculate_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minted\",\"type\":\"uint256\"}],\"name\":\"calculate_growth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"claimants\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingTeam\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_teamRate\",\"type\":\"uint256\"}],\"name\":\"setTeamRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"teamRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"update_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Minter.sol\":\"Minter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Minter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IMinter.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\\n\\ncontract Minter is IMinter {\\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\\n uint256 internal constant EMISSION = 990;\\n uint256 internal constant TAIL_EMISSION = 2;\\n uint256 internal constant PRECISION = 1000;\\n IFlow public immutable _flow;\\n IVoter public immutable _voter;\\n IVotingEscrow public immutable _ve;\\n IRewardsDistributor public immutable _rewards_distributor;\\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M FLOW (FLOW has 18 decimals)\\n uint256 public active_period;\\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\\n\\n address internal initializer;\\n address public team;\\n address public pendingTeam;\\n uint256 public teamRate;\\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\\n\\n event Mint(\\n address indexed sender,\\n uint256 weekly,\\n uint256 circulating_supply,\\n uint256 circulating_emission\\n );\\n\\n constructor(\\n address __voter, // the voting & distribution system\\n address __ve, // the ve(3,3) system that will be locked into\\n address __rewards_distributor // the distribution system that ensures users aren't diluted\\n ) {\\n initializer = msg.sender;\\n team = msg.sender;\\n teamRate = 30; // 30 bps = 0.03%\\n _flow = IFlow(IVotingEscrow(__ve).token());\\n _voter = IVoter(__voter);\\n _ve = IVotingEscrow(__ve);\\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\\n }\\n\\n function initialize(\\n address[] memory claimants,\\n uint256[] memory amounts,\\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\\n ) external {\\n require(initializer == msg.sender);\\n _flow.mint(address(this), max);\\n _flow.approve(address(_ve), type(uint256).max);\\n for (uint256 i = 0; i < claimants.length; i++) {\\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\\n }\\n initializer = address(0);\\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\\n }\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team, \\\"not team\\\");\\n pendingTeam = _team;\\n }\\n\\n function acceptTeam() external {\\n require(msg.sender == pendingTeam, \\\"not pending team\\\");\\n team = pendingTeam;\\n }\\n\\n function setTeamRate(uint256 _teamRate) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(_teamRate <= MAX_TEAM_RATE, \\\"rate too high\\\");\\n teamRate = _teamRate;\\n }\\n\\n // calculate circulating supply as total token supply - locked supply\\n function circulating_supply() public view returns (uint256) {\\n return _flow.totalSupply() - _ve.totalSupply();\\n }\\n\\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\\n function calculate_emission() public view returns (uint256) {\\n return (weekly * EMISSION) / PRECISION;\\n }\\n\\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\\n function weekly_emission() public view returns (uint256) {\\n return MathDunks.max(calculate_emission(), circulating_emission());\\n }\\n\\n // calculates tail end (infinity) emissions as 0.2% of total supply\\n function circulating_emission() public view returns (uint256) {\\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\\n }\\n\\n // calculate inflation and adjust ve balances accordingly\\n function calculate_growth(uint256 _minted) public view returns (uint256) {\\n uint256 _veTotal = _ve.totalSupply();\\n uint256 _flowTotal = _flow.totalSupply();\\n return\\n (((((_minted * _veTotal) / _flowTotal) * _veTotal) / _flowTotal) *\\n _veTotal) /\\n _flowTotal /\\n 2;\\n }\\n\\n // update period can only be called once per cycle (1 week)\\n function update_period() external returns (uint256) {\\n uint256 _period = active_period;\\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\\n // only trigger if new week\\n _period = (block.timestamp / WEEK) * WEEK;\\n active_period = _period;\\n weekly = weekly_emission();\\n\\n uint256 _growth = calculate_growth(weekly);\\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\\n (PRECISION - teamRate);\\n uint256 _required = _growth + weekly + _teamEmissions;\\n uint256 _balanceOf = _flow.balanceOf(address(this));\\n if (_balanceOf < _required) {\\n _flow.mint(address(this), _required - _balanceOf);\\n }\\n\\n require(_flow.transfer(team, _teamEmissions));\\n require(_flow.transfer(address(_rewards_distributor), _growth));\\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\\n\\n _flow.approve(address(_voter), weekly);\\n _voter.notifyRewardAmount(weekly);\\n\\n emit Mint(\\n msg.sender,\\n weekly,\\n circulating_supply(),\\n circulating_emission()\\n );\\n }\\n return _period;\\n }\\n}\\n\",\"keccak256\":\"0xc661046dd2b90d93e4f057d2497b137703b4f0c3caccfe846f1a81906a2e1961\",\"license\":\"MIT\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x6101006040526a0c685fa11e01ec6f0000006000553480156200002157600080fd5b506040516200158938038062001589833981016040819052620000449162000156565b60028054336001600160a01b03199182168117909255600380549091169091179055601e60055560408051637e062a3560e11b815290516001600160a01b0384169163fc0c546a9160048083019260209291908290030181865afa158015620000b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d79190620001a0565b6001600160a01b0390811660805283811660a05282811660c052811660e05262093a808062000108816002620001db565b620001149042620001fd565b62000120919062000218565b6200012c9190620001db565b600155506200023b915050565b80516001600160a01b03811681146200015157600080fd5b919050565b6000806000606084860312156200016c57600080fd5b620001778462000139565b9250620001876020850162000139565b9150620001976040850162000139565b90509250925092565b600060208284031215620001b357600080fd5b620001be8262000139565b9392505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620001f857620001f8620001c5565b500290565b60008219821115620002135762000213620001c5565b500190565b6000826200023657634e487b7160e01b600052601260045260246000fd5b500490565b60805160a05160c05160e051611296620002f3600039600081816101d101528181610c3701528181610cde0152610d5101526000818161023a015281816104b30152818161055f01528181610689015261087501526000818161019201528181610e090152610ea301526000818161029d01528181610426015281816104e30152818161070f015281816108f701528181610a5f01528181610ade01528181610ba801528181610c660152610dda01526112966000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c806385170813116100ad578063cfc6c8ff11610071578063cfc6c8ff14610277578063d13996081461027f578063e038c75a14610288578063ed29fc1114610290578063fe75cac51461029857600080fd5b8063851708131461020f57806385f2aef2146102225780638dd598fb146102355780638e01fbfa1461025c578063b5cc143a1461026f57600080fd5b806336d96faf116100f457806336d96faf146101855780633db9b42a1461018d5780634b1cd5da146101cc57806359d46ffc146101f357806378ef7f021461020657600080fd5b806301c8e6fd14610131578063095cf5c61461014c5780631eebae801461016157806326cfc17b146101695780632e8f7b1f14610172575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b61015f61015a366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61015f610180366004610fb8565b610353565b6101396103de565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6004546101b4906001600160a01b031681565b61013960055481565b61015f61021d3660046110a7565b6103f3565b6003546101b4906001600160a01b031681565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b61013961026a366004610fb8565b610684565b61015f6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea2646970667358221220611c27f9ec43450f21c5035bcf854d588812e7b814d381a4e6f1f4d748cde01c64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c806385170813116100ad578063cfc6c8ff11610071578063cfc6c8ff14610277578063d13996081461027f578063e038c75a14610288578063ed29fc1114610290578063fe75cac51461029857600080fd5b8063851708131461020f57806385f2aef2146102225780638dd598fb146102355780638e01fbfa1461025c578063b5cc143a1461026f57600080fd5b806336d96faf116100f457806336d96faf146101855780633db9b42a1461018d5780634b1cd5da146101cc57806359d46ffc146101f357806378ef7f021461020657600080fd5b806301c8e6fd14610131578063095cf5c61461014c5780631eebae801461016157806326cfc17b146101695780632e8f7b1f14610172575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b61015f61015a366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61015f610180366004610fb8565b610353565b6101396103de565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6004546101b4906001600160a01b031681565b61013960055481565b61015f61021d3660046110a7565b6103f3565b6003546101b4906001600160a01b031681565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b61013961026a366004610fb8565b610684565b61015f6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea2646970667358221220611c27f9ec43450f21c5035bcf854d588812e7b814d381a4e6f1f4d748cde01c64736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__voter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__rewards_distributor\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weekly\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_supply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_emission\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_TEAM_RATE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_flow\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_rewards_distributor\",\"outputs\":[{\"internalType\":\"contract IRewardsDistributor\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"contract IVotingEscrow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_voter\",\"outputs\":[{\"internalType\":\"contract IVoter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"active_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"calculate_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minted\",\"type\":\"uint256\"}],\"name\":\"calculate_growth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"claimants\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingTeam\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_teamRate\",\"type\":\"uint256\"}],\"name\":\"setTeamRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"teamRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"update_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Minter.sol\":\"Minter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Minter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IMinter.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\\n\\ncontract Minter is IMinter {\\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\\n uint256 internal constant EMISSION = 990;\\n uint256 internal constant TAIL_EMISSION = 2;\\n uint256 internal constant PRECISION = 1000;\\n IFlow public immutable _flow;\\n IVoter public immutable _voter;\\n IVotingEscrow public immutable _ve;\\n IRewardsDistributor public immutable _rewards_distributor;\\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M FLOW (FLOW has 18 decimals)\\n uint256 public active_period;\\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\\n\\n address internal initializer;\\n address public team;\\n address public pendingTeam;\\n uint256 public teamRate;\\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\\n\\n event Mint(\\n address indexed sender,\\n uint256 weekly,\\n uint256 circulating_supply,\\n uint256 circulating_emission\\n );\\n\\n constructor(\\n address __voter, // the voting & distribution system\\n address __ve, // the ve(3,3) system that will be locked into\\n address __rewards_distributor // the distribution system that ensures users aren't diluted\\n ) {\\n initializer = msg.sender;\\n team = msg.sender;\\n teamRate = 30; // 30 bps = 0.03%\\n _flow = IFlow(IVotingEscrow(__ve).token());\\n _voter = IVoter(__voter);\\n _ve = IVotingEscrow(__ve);\\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\\n }\\n\\n function initialize(\\n address[] memory claimants,\\n uint256[] memory amounts,\\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\\n ) external {\\n require(initializer == msg.sender);\\n _flow.mint(address(this), max);\\n _flow.approve(address(_ve), type(uint256).max);\\n for (uint256 i = 0; i < claimants.length; i++) {\\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\\n }\\n initializer = address(0);\\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\\n }\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team, \\\"not team\\\");\\n pendingTeam = _team;\\n }\\n\\n function acceptTeam() external {\\n require(msg.sender == pendingTeam, \\\"not pending team\\\");\\n team = pendingTeam;\\n }\\n\\n function setTeamRate(uint256 _teamRate) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(_teamRate <= MAX_TEAM_RATE, \\\"rate too high\\\");\\n teamRate = _teamRate;\\n }\\n\\n // calculate circulating supply as total token supply - locked supply\\n function circulating_supply() public view returns (uint256) {\\n return _flow.totalSupply() - _ve.totalSupply();\\n }\\n\\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\\n function calculate_emission() public view returns (uint256) {\\n return (weekly * EMISSION) / PRECISION;\\n }\\n\\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\\n function weekly_emission() public view returns (uint256) {\\n return MathDunks.max(calculate_emission(), circulating_emission());\\n }\\n\\n // calculates tail end (infinity) emissions as 0.2% of total supply\\n function circulating_emission() public view returns (uint256) {\\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\\n }\\n\\n // calculate inflation and adjust ve balances accordingly\\n function calculate_growth(uint256 _minted) public view returns (uint256) {\\n uint256 _veTotal = _ve.totalSupply();\\n uint256 _flowTotal = _flow.totalSupply();\\n return\\n (((((_minted * _veTotal) / _flowTotal) * _veTotal) / _flowTotal) *\\n _veTotal) /\\n _flowTotal /\\n 2;\\n }\\n\\n // update period can only be called once per cycle (1 week)\\n function update_period() external returns (uint256) {\\n uint256 _period = active_period;\\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\\n // only trigger if new week\\n _period = (block.timestamp / WEEK) * WEEK;\\n active_period = _period;\\n weekly = weekly_emission();\\n\\n uint256 _growth = calculate_growth(weekly);\\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\\n (PRECISION - teamRate);\\n uint256 _required = _growth + weekly + _teamEmissions;\\n uint256 _balanceOf = _flow.balanceOf(address(this));\\n if (_balanceOf < _required) {\\n _flow.mint(address(this), _required - _balanceOf);\\n }\\n\\n require(_flow.transfer(team, _teamEmissions));\\n require(_flow.transfer(address(_rewards_distributor), _growth));\\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\\n\\n _flow.approve(address(_voter), weekly);\\n _voter.notifyRewardAmount(weekly);\\n\\n emit Mint(\\n msg.sender,\\n weekly,\\n circulating_supply(),\\n circulating_emission()\\n );\\n }\\n return _period;\\n }\\n}\\n\",\"keccak256\":\"0xc661046dd2b90d93e4f057d2497b137703b4f0c3caccfe846f1a81906a2e1961\",\"license\":\"MIT\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x6101006040526a0c685fa11e01ec6f0000006000553480156200002157600080fd5b506040516200158938038062001589833981016040819052620000449162000156565b60028054336001600160a01b03199182168117909255600380549091169091179055601e60055560408051637e062a3560e11b815290516001600160a01b0384169163fc0c546a9160048083019260209291908290030181865afa158015620000b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d79190620001a0565b6001600160a01b0390811660805283811660a05282811660c052811660e05262093a808062000108816002620001db565b620001149042620001fd565b62000120919062000218565b6200012c9190620001db565b600155506200023b915050565b80516001600160a01b03811681146200015157600080fd5b919050565b6000806000606084860312156200016c57600080fd5b620001778462000139565b9250620001876020850162000139565b9150620001976040850162000139565b90509250925092565b600060208284031215620001b357600080fd5b620001be8262000139565b9392505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620001f857620001f8620001c5565b500290565b60008219821115620002135762000213620001c5565b500190565b6000826200023657634e487b7160e01b600052601260045260246000fd5b500490565b60805160a05160c05160e051611296620002f3600039600081816101d101528181610c3701528181610cde0152610d5101526000818161023a015281816104b30152818161055f01528181610689015261087501526000818161019201528181610e090152610ea301526000818161029d01528181610426015281816104e30152818161070f015281816108f701528181610a5f01528181610ade01528181610ba801528181610c660152610dda01526112966000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c806385170813116100ad578063cfc6c8ff11610071578063cfc6c8ff14610277578063d13996081461027f578063e038c75a14610288578063ed29fc1114610290578063fe75cac51461029857600080fd5b8063851708131461020f57806385f2aef2146102225780638dd598fb146102355780638e01fbfa1461025c578063b5cc143a1461026f57600080fd5b806336d96faf116100f457806336d96faf146101855780633db9b42a1461018d5780634b1cd5da146101cc57806359d46ffc146101f357806378ef7f021461020657600080fd5b806301c8e6fd14610131578063095cf5c61461014c5780631eebae801461016157806326cfc17b146101695780632e8f7b1f14610172575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b61015f61015a366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61015f610180366004610fb8565b610353565b6101396103de565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6004546101b4906001600160a01b031681565b61013960055481565b61015f61021d3660046110a7565b6103f3565b6003546101b4906001600160a01b031681565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b61013961026a366004610fb8565b610684565b61015f6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea2646970667358221220b5102dde2ecb2debf164c245d3462a1f37c037e8bd5c4cbfdac3bfe5a8282da664736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c806385170813116100ad578063cfc6c8ff11610071578063cfc6c8ff14610277578063d13996081461027f578063e038c75a14610288578063ed29fc1114610290578063fe75cac51461029857600080fd5b8063851708131461020f57806385f2aef2146102225780638dd598fb146102355780638e01fbfa1461025c578063b5cc143a1461026f57600080fd5b806336d96faf116100f457806336d96faf146101855780633db9b42a1461018d5780634b1cd5da146101cc57806359d46ffc146101f357806378ef7f021461020657600080fd5b806301c8e6fd14610131578063095cf5c61461014c5780631eebae801461016157806326cfc17b146101695780632e8f7b1f14610172575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b61015f61015a366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61015f610180366004610fb8565b610353565b6101396103de565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6004546101b4906001600160a01b031681565b61013960055481565b61015f61021d3660046110a7565b6103f3565b6003546101b4906001600160a01b031681565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b61013961026a366004610fb8565b610684565b61015f6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea2646970667358221220b5102dde2ecb2debf164c245d3462a1f37c037e8bd5c4cbfdac3bfe5a8282da664736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/PairFactory.json b/deployments/arbitrumGoerli/PairFactory.json index 4ff7bc2e..4da0cf42 100644 --- a/deployments/arbitrumGoerli/PairFactory.json +++ b/deployments/arbitrumGoerli/PairFactory.json @@ -1,5 +1,5 @@ { - "address": "0xE4a96d05579a4306e19E1C36F8e6A1567c982750", + "address": "0x32bB8e83F877948Db847BDB6A8DB51d441324c1F", "abi": [ { "inputs": [], @@ -383,28 +383,28 @@ "type": "function" } ], - "transactionHash": "0x7d6ecce94e4b0fdfbb6517e5f12b8144a2c462bae3c930bb89b27a2c3d76743a", + "transactionHash": "0x9c0defb75d082c1c291c4433fe0a4a9fe8c99f66f15355118be6ec20ed56d61d", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xE4a96d05579a4306e19E1C36F8e6A1567c982750", - "transactionIndex": 1, - "gasUsed": "4628142", + "contractAddress": "0x32bB8e83F877948Db847BDB6A8DB51d441324c1F", + "transactionIndex": 4, + "gasUsed": "4628154", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x5d2cb85b06cb5c4425a24994bfb67c1dc2da92fab91ba21f76c9ad32b3c19e97", - "transactionHash": "0x7d6ecce94e4b0fdfbb6517e5f12b8144a2c462bae3c930bb89b27a2c3d76743a", + "blockHash": "0x0f7dfa6d40eef900eb285abcc2802de04aa63b6f95a04ea5aad476325268ac66", + "transactionHash": "0x9c0defb75d082c1c291c4433fe0a4a9fe8c99f66f15355118be6ec20ed56d61d", "logs": [], - "blockNumber": 5814405, - "cumulativeGasUsed": "4628142", + "blockNumber": 5849166, + "cumulativeGasUsed": "5463539", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 5, - "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"PairCreated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_FEE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allPairs\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"allPairsLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"createPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getInitializable\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"name\":\"getPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pairCodeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingFeeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingPauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_feeManager\",\"type\":\"address\"}],\"name\":\"setFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_state\",\"type\":\"bool\"}],\"name\":\"setPause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pauser\",\"type\":\"address\"}],\"name\":\"setPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stableFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"volatileFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/PairFactory.sol\":\"PairFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Pair.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairCallee.sol\\\";\\nimport \\\"contracts/factories/PairFactory.sol\\\";\\nimport \\\"contracts/PairFees.sol\\\";\\n\\n// The base pair of pools, either stable or volatile\\ncontract Pair is IPair {\\n string public name;\\n string public symbol;\\n uint8 public constant decimals = 18;\\n\\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\\n bool public immutable stable;\\n\\n uint256 public totalSupply = 0;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n mapping(address => uint256) public balanceOf;\\n\\n bytes32 internal DOMAIN_SEPARATOR;\\n // keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 internal constant PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n mapping(address => uint256) public nonces;\\n\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n\\n address public immutable token0;\\n address public immutable token1;\\n address public immutable fees;\\n address immutable factory;\\n\\n // Structure to capture time period obervations every 30 minutes, used for local oracles\\n struct Observation {\\n uint256 timestamp;\\n uint256 reserve0Cumulative;\\n uint256 reserve1Cumulative;\\n }\\n\\n // Capture oracle reading every 30 minutes\\n uint256 constant periodSize = 1800;\\n\\n Observation[] public observations;\\n\\n uint256 internal immutable decimals0;\\n uint256 internal immutable decimals1;\\n\\n uint256 public reserve0;\\n uint256 public reserve1;\\n uint256 public blockTimestampLast;\\n\\n uint256 public reserve0CumulativeLast;\\n uint256 public reserve1CumulativeLast;\\n\\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \\\"clean\\\"\\n // this further allows LP holders to easily claim fees for tokens they have/staked\\n uint256 public index0 = 0;\\n uint256 public index1 = 0;\\n\\n // position assigned to each LP to track their current index0 & index1 vs the global position\\n mapping(address => uint256) public supplyIndex0;\\n mapping(address => uint256) public supplyIndex1;\\n\\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\\n mapping(address => uint256) public claimable0;\\n mapping(address => uint256) public claimable1;\\n\\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\\n event Burn(\\n address indexed sender,\\n uint256 amount0,\\n uint256 amount1,\\n address indexed to\\n );\\n event Swap(\\n address indexed sender,\\n uint256 amount0In,\\n uint256 amount1In,\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address indexed to\\n );\\n event Sync(uint256 reserve0, uint256 reserve1);\\n event Claim(\\n address indexed sender,\\n address indexed recipient,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 amount\\n );\\n\\n constructor() {\\n factory = msg.sender;\\n (address _token0, address _token1, bool _stable) = PairFactory(\\n msg.sender\\n ).getInitializable();\\n (token0, token1, stable) = (_token0, _token1, _stable);\\n fees = address(new PairFees(_token0, _token1));\\n if (_stable) {\\n name = string(\\n abi.encodePacked(\\n \\\"StableV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"sAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n } else {\\n name = string(\\n abi.encodePacked(\\n \\\"VolatileV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"vAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n }\\n\\n decimals0 = 10**IERC20(_token0).decimals();\\n decimals1 = 10**IERC20(_token1).decimals();\\n\\n observations.push(Observation(block.timestamp, 0, 0));\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function observationLength() external view returns (uint256) {\\n return observations.length;\\n }\\n\\n function lastObservation() public view returns (Observation memory) {\\n return observations[observations.length - 1];\\n }\\n\\n function metadata()\\n external\\n view\\n returns (\\n uint256 dec0,\\n uint256 dec1,\\n uint256 r0,\\n uint256 r1,\\n bool st,\\n address t0,\\n address t1\\n )\\n {\\n return (\\n decimals0,\\n decimals1,\\n reserve0,\\n reserve1,\\n stable,\\n token0,\\n token1\\n );\\n }\\n\\n function tokens() external view returns (address, address) {\\n return (token0, token1);\\n }\\n\\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\\n _updateFor(msg.sender);\\n\\n claimed0 = claimable0[msg.sender];\\n claimed1 = claimable1[msg.sender];\\n\\n if (claimed0 > 0 || claimed1 > 0) {\\n claimable0[msg.sender] = 0;\\n claimable1[msg.sender] = 0;\\n\\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\\n\\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n // Accrue fees on token0\\n function _update0(uint256 amount) internal {\\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index0 += _ratio;\\n }\\n emit Fees(msg.sender, amount, 0);\\n }\\n\\n // Accrue fees on token1\\n function _update1(uint256 amount) internal {\\n _safeTransfer(token1, fees, amount);\\n uint256 _ratio = (amount * 1e18) / totalSupply;\\n if (_ratio > 0) {\\n index1 += _ratio;\\n }\\n emit Fees(msg.sender, 0, amount);\\n }\\n\\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\\n // Fees are segregated from core funds, so fees can never put liquidity at risk\\n function _updateFor(address recipient) internal {\\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\\n if (_supplied > 0) {\\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\\n uint256 _supplyIndex1 = supplyIndex1[recipient];\\n uint256 _index0 = index0; // get global index0 for accumulated fees\\n uint256 _index1 = index1;\\n supplyIndex0[recipient] = _index0; // update user current position to global position\\n supplyIndex1[recipient] = _index1;\\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\\n uint256 _delta1 = _index1 - _supplyIndex1;\\n if (_delta0 > 0) {\\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\\n claimable0[recipient] += _share;\\n }\\n if (_delta1 > 0) {\\n uint256 _share = (_supplied * _delta1) / 1e18;\\n claimable1[recipient] += _share;\\n }\\n } else {\\n supplyIndex0[recipient] = index0; // new users are set to the default global state\\n supplyIndex1[recipient] = index1;\\n }\\n }\\n\\n function getReserves()\\n public\\n view\\n returns (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n )\\n {\\n _reserve0 = reserve0;\\n _reserve1 = reserve1;\\n _blockTimestampLast = blockTimestampLast;\\n }\\n\\n // update reserves and, on the first call per block, price accumulators\\n function _update(\\n uint256 balance0,\\n uint256 balance1,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal {\\n uint256 blockTimestamp = block.timestamp;\\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\\n reserve0CumulativeLast += _reserve0 * timeElapsed;\\n reserve1CumulativeLast += _reserve1 * timeElapsed;\\n }\\n\\n Observation memory _point = lastObservation();\\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\\n if (timeElapsed > periodSize) {\\n observations.push(\\n Observation(\\n blockTimestamp,\\n reserve0CumulativeLast,\\n reserve1CumulativeLast\\n )\\n );\\n }\\n reserve0 = balance0;\\n reserve1 = balance1;\\n blockTimestampLast = blockTimestamp;\\n emit Sync(reserve0, reserve1);\\n }\\n\\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\\n function currentCumulativePrices()\\n public\\n view\\n returns (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n uint256 blockTimestamp\\n )\\n {\\n blockTimestamp = block.timestamp;\\n reserve0Cumulative = reserve0CumulativeLast;\\n reserve1Cumulative = reserve1CumulativeLast;\\n\\n // if time has elapsed since the last update on the pair, mock the accumulated price values\\n (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n ) = getReserves();\\n if (_blockTimestampLast != blockTimestamp) {\\n // subtraction overflow is desired\\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\\n reserve0Cumulative += _reserve0 * timeElapsed;\\n reserve1Cumulative += _reserve1 * timeElapsed;\\n }\\n }\\n\\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\\n function current(address tokenIn, uint256 amountIn)\\n external\\n view\\n returns (uint256 amountOut)\\n {\\n Observation memory _observation = lastObservation();\\n (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n\\n ) = currentCumulativePrices();\\n if (block.timestamp == _observation.timestamp) {\\n _observation = observations[observations.length - 2];\\n }\\n\\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\\n uint256 _reserve0 = (reserve0Cumulative -\\n _observation.reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (reserve1Cumulative -\\n _observation.reserve1Cumulative) / timeElapsed;\\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n // as per `current`, however allows user configured granularity, up to the full window size\\n function quote(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 granularity\\n ) external view returns (uint256 amountOut) {\\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\\n uint256 priceAverageCumulative;\\n for (uint256 i = 0; i < _prices.length; i++) {\\n priceAverageCumulative += _prices[i];\\n }\\n return priceAverageCumulative / granularity;\\n }\\n\\n // returns a memory set of twap prices\\n function prices(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points\\n ) external view returns (uint256[] memory) {\\n return sample(tokenIn, amountIn, points, 1);\\n }\\n\\n function sample(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points,\\n uint256 window\\n ) public view returns (uint256[] memory) {\\n uint256[] memory _prices = new uint256[](points);\\n\\n uint256 length = observations.length - 1;\\n uint256 i = length - (points * window);\\n uint256 nextIndex = 0;\\n uint256 index = 0;\\n\\n for (; i < length; i += window) {\\n nextIndex = i + window;\\n uint256 timeElapsed = observations[nextIndex].timestamp -\\n observations[i].timestamp;\\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\\n observations[i].reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\\n observations[i].reserve1Cumulative) / timeElapsed;\\n _prices[index] = _getAmountOut(\\n amountIn,\\n tokenIn,\\n _reserve0,\\n _reserve1\\n );\\n // index < length; length cannot overflow\\n unchecked {\\n index = index + 1;\\n }\\n }\\n return _prices;\\n }\\n\\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\\n // standard uniswap v2 implementation\\n function mint(address to) external lock returns (uint256 liquidity) {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\\n uint256 _amount0 = _balance0 - _reserve0;\\n uint256 _amount1 = _balance1 - _reserve1;\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n if (_totalSupply == 0) {\\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\\n } else {\\n liquidity = MathDunks.min(\\n (_amount0 * _totalSupply) / _reserve0,\\n (_amount1 * _totalSupply) / _reserve1\\n );\\n }\\n require(liquidity > 0, \\\"ILM\\\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\\n _mint(to, liquidity);\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Mint(msg.sender, _amount0, _amount1);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n // standard uniswap v2 implementation\\n function burn(address to)\\n external\\n lock\\n returns (uint256 amount0, uint256 amount1)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n (address _token0, address _token1) = (token0, token1);\\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\\n uint256 _liquidity = balanceOf[address(this)];\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\\n require(amount0 > 0 && amount1 > 0, \\\"ILB\\\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\\n _burn(address(this), _liquidity);\\n _safeTransfer(_token0, to, amount0);\\n _safeTransfer(_token1, to, amount1);\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Burn(msg.sender, amount0, amount1, to);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n function swap(\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address to,\\n bytes calldata data\\n ) external lock {\\n require(!PairFactory(factory).isPaused());\\n require(amount0Out > 0 || amount1Out > 0, \\\"IOA\\\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \\\"IL\\\"); // Pair: INSUFFICIENT_LIQUIDITY\\n\\n uint256 _balance0;\\n uint256 _balance1;\\n {\\n // scope for _token{0,1}, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n require(to != _token0 && to != _token1, \\\"IT\\\"); // Pair: INVALID_TO\\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\\n if (data.length > 0)\\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n }\\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\\n ? _balance0 - (_reserve0 - amount0Out)\\n : 0;\\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\\n ? _balance1 - (_reserve1 - amount1Out)\\n : 0;\\n require(amount0In > 0 || amount1In > 0, \\\"IIA\\\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\\n {\\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n if (amount0In > 0)\\n _update0(\\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token0 and move them out of pool\\n if (amount1In > 0)\\n _update1(\\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token1 and move them out of pool\\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \\\"K\\\"); // Pair: K\\n }\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\\n }\\n\\n // force balances to match reserves\\n function skim(address to) external lock {\\n (address _token0, address _token1) = (token0, token1);\\n _safeTransfer(\\n _token0,\\n to,\\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\\n );\\n _safeTransfer(\\n _token1,\\n to,\\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\\n );\\n }\\n\\n // force reserves to match balances\\n function sync() external lock {\\n _update(\\n IERC20(token0).balanceOf(address(this)),\\n IERC20(token1).balanceOf(address(this)),\\n reserve0,\\n reserve1\\n );\\n }\\n\\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\\n 1e18 +\\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\\n 1e18;\\n }\\n\\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (3 * x0 * ((y * y) / 1e18)) /\\n 1e18 +\\n ((((x0 * x0) / 1e18) * x0) / 1e18);\\n }\\n\\n function _get_y(\\n uint256 x0,\\n uint256 xy,\\n uint256 y\\n ) internal pure returns (uint256) {\\n for (uint256 i = 0; i < 255; i++) {\\n uint256 y_prev = y;\\n uint256 k = _f(x0, y);\\n if (k < xy) {\\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\\n y = y + dy;\\n } else {\\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getAmountOut(uint256 amountIn, address tokenIn)\\n external\\n view\\n returns (uint256)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n function _getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal view returns (uint256) {\\n if (stable) {\\n uint256 xy = _k(_reserve0, _reserve1);\\n _reserve0 = (_reserve0 * 1e18) / decimals0;\\n _reserve1 = (_reserve1 * 1e18) / decimals1;\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0\\n ? (amountIn * 1e18) / decimals0\\n : (amountIn * 1e18) / decimals1;\\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\\n } else {\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n return (amountIn * reserveB) / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\\n if (stable) {\\n uint256 _x = (x * 1e18) / decimals0;\\n uint256 _y = (y * 1e18) / decimals1;\\n uint256 _a = (_x * _y) / 1e18;\\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return (_a * _b) / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n\\n function _mint(address dst, uint256 amount) internal {\\n _updateFor(dst); // balances must be updated on mint/burn/transfer\\n totalSupply += amount;\\n balanceOf[dst] += amount;\\n emit Transfer(address(0), dst, amount);\\n }\\n\\n function _burn(address dst, uint256 amount) internal {\\n _updateFor(dst);\\n totalSupply -= amount;\\n balanceOf[dst] -= amount;\\n emit Transfer(dst, address(0), amount);\\n }\\n\\n function approve(address spender, uint256 amount) external returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external {\\n require(deadline >= block.timestamp, \\\"Pair: EXPIRED\\\");\\n DOMAIN_SEPARATOR = keccak256(\\n abi.encode(\\n keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n ),\\n keccak256(bytes(name)),\\n keccak256(bytes(\\\"1\\\")),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR,\\n keccak256(\\n abi.encode(\\n PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n );\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n require(\\n recoveredAddress != address(0) && recoveredAddress == owner,\\n \\\"Pair: INVALID_SIGNATURE\\\"\\n );\\n allowance[owner][spender] = value;\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function transfer(address dst, uint256 amount) external returns (bool) {\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 amount\\n ) external returns (bool) {\\n address spender = msg.sender;\\n uint256 spenderAllowance = allowance[src][spender];\\n\\n if (spender != src && spenderAllowance != type(uint256).max) {\\n uint256 newAllowance = spenderAllowance - amount;\\n allowance[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n function _transferTokens(\\n address src,\\n address dst,\\n uint256 amount\\n ) internal {\\n _updateFor(src); // update fee position for src\\n _updateFor(dst); // update fee position for dst\\n\\n balanceOf[src] -= amount;\\n balanceOf[dst] += amount;\\n\\n emit Transfer(src, dst, amount);\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x4f508747645f4480e0b0f23d952fa9b82af1d9bc60b15b8cd1f542ee136043d1\",\"license\":\"MIT\"},\"contracts/PairFees.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IERC20.sol';\\n\\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\\ncontract PairFees {\\n\\n address internal immutable pair; // The pair it is bonded to\\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\\n\\n constructor(address _token0, address _token1) {\\n pair = msg.sender;\\n token0 = _token0;\\n token1 = _token1;\\n }\\n\\n function _safeTransfer(address token,address to,uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n // Allow the pair to transfer fees to users\\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\\n require(msg.sender == pair);\\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\\n }\\n\\n}\\n\",\"keccak256\":\"0xb772e192bab353f8642e89a95ef4ef0255d1caef08444101d7fe34469c1000ca\",\"license\":\"MIT\"},\"contracts/factories/PairFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/Pair.sol';\\n\\ncontract PairFactory is IPairFactory {\\n\\n bool public isPaused;\\n address public pauser;\\n address public pendingPauser;\\n\\n uint256 public stableFee;\\n uint256 public volatileFee;\\n uint256 public constant MAX_FEE = 5; // 0.05%\\n address public feeManager;\\n address public pendingFeeManager;\\n\\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\\n address[] public allPairs;\\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\\n\\n address internal _temp0;\\n address internal _temp1;\\n bool internal _temp;\\n\\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\\n\\n constructor() {\\n pauser = msg.sender;\\n isPaused = false;\\n feeManager = msg.sender;\\n stableFee = 2; // 0.02%\\n volatileFee = 2;\\n }\\n\\n function allPairsLength() external view returns (uint) {\\n return allPairs.length;\\n }\\n\\n function setPauser(address _pauser) external {\\n require(msg.sender == pauser);\\n pendingPauser = _pauser;\\n }\\n\\n function acceptPauser() external {\\n require(msg.sender == pendingPauser);\\n pauser = pendingPauser;\\n }\\n\\n function setPause(bool _state) external {\\n require(msg.sender == pauser);\\n isPaused = _state;\\n }\\n\\n function setFeeManager(address _feeManager) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n pendingFeeManager = _feeManager;\\n }\\n\\n function acceptFeeManager() external {\\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\\n feeManager = pendingFeeManager;\\n }\\n\\n function setFee(bool _stable, uint256 _fee) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n require(_fee <= MAX_FEE, 'fee too high');\\n require(_fee != 0, 'fee must be nonzero');\\n if (_stable) {\\n stableFee = _fee;\\n } else {\\n volatileFee = _fee;\\n }\\n }\\n\\n function getFee(bool _stable) public view returns(uint256) {\\n return _stable ? stableFee : volatileFee;\\n }\\n\\n function pairCodeHash() external pure returns (bytes32) {\\n return keccak256(type(Pair).creationCode);\\n }\\n\\n function getInitializable() external view returns (address, address, bool) {\\n return (_temp0, _temp1, _temp);\\n }\\n\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\\n (_temp0, _temp1, _temp) = (token0, token1, stable);\\n pair = address(new Pair{salt:salt}());\\n getPair[token0][token1][stable] = pair;\\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\\n allPairs.push(pair);\\n isPair[pair] = true;\\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\\n }\\n}\\n\",\"keccak256\":\"0x9b7984117a5a32188aa9ddf42b6cff024240579ab30f3776f7a201285d813e4f\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairCallee.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairCallee {\\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x3ac2de2c7a08bf59fd1006e4d108b247916369de15fbd048b72ca2b7814023ca\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50600080546001600160a81b03191633610100810260ff1916919091178255600480546001600160a01b0319169091179055600280805560035561519190819061005a90396000f3fe60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea2646970667358221220ff1d4003304bd460d210311318fdfcf0424b931f7affbe2b2f368518adf993e564736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea2646970667358221220897f96d22d617a86c8245dcbfac365296ab66900e6de019e62f6b31bc214be2c64736f6c634300080d0033a26469706673582212204645a8cdd9943867307d2264d375485cfdbe388ee5ca8c7335f9e2fc9f900ec764736f6c634300080d0033", - "deployedBytecode": "0x60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea2646970667358221220ff1d4003304bd460d210311318fdfcf0424b931f7affbe2b2f368518adf993e564736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea2646970667358221220897f96d22d617a86c8245dcbfac365296ab66900e6de019e62f6b31bc214be2c64736f6c634300080d0033a26469706673582212204645a8cdd9943867307d2264d375485cfdbe388ee5ca8c7335f9e2fc9f900ec764736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"PairCreated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_FEE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allPairs\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"allPairsLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"createPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getInitializable\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"name\":\"getPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pairCodeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingFeeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingPauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_feeManager\",\"type\":\"address\"}],\"name\":\"setFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_state\",\"type\":\"bool\"}],\"name\":\"setPause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pauser\",\"type\":\"address\"}],\"name\":\"setPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stableFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"volatileFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/PairFactory.sol\":\"PairFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Pair.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairCallee.sol\\\";\\nimport \\\"contracts/factories/PairFactory.sol\\\";\\nimport \\\"contracts/PairFees.sol\\\";\\n\\n// The base pair of pools, either stable or volatile\\ncontract Pair is IPair {\\n string public name;\\n string public symbol;\\n uint8 public constant decimals = 18;\\n\\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\\n bool public immutable stable;\\n\\n uint256 public totalSupply = 0;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n mapping(address => uint256) public balanceOf;\\n\\n bytes32 internal DOMAIN_SEPARATOR;\\n // keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 internal constant PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n mapping(address => uint256) public nonces;\\n\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n\\n address public immutable token0;\\n address public immutable token1;\\n address public immutable fees;\\n address immutable factory;\\n\\n // Structure to capture time period obervations every 30 minutes, used for local oracles\\n struct Observation {\\n uint256 timestamp;\\n uint256 reserve0Cumulative;\\n uint256 reserve1Cumulative;\\n }\\n\\n // Capture oracle reading every 30 minutes\\n uint256 constant periodSize = 1800;\\n\\n Observation[] public observations;\\n\\n uint256 internal immutable decimals0;\\n uint256 internal immutable decimals1;\\n\\n uint256 public reserve0;\\n uint256 public reserve1;\\n uint256 public blockTimestampLast;\\n\\n uint256 public reserve0CumulativeLast;\\n uint256 public reserve1CumulativeLast;\\n\\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \\\"clean\\\"\\n // this further allows LP holders to easily claim fees for tokens they have/staked\\n uint256 public index0 = 0;\\n uint256 public index1 = 0;\\n\\n // position assigned to each LP to track their current index0 & index1 vs the global position\\n mapping(address => uint256) public supplyIndex0;\\n mapping(address => uint256) public supplyIndex1;\\n\\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\\n mapping(address => uint256) public claimable0;\\n mapping(address => uint256) public claimable1;\\n\\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\\n event Burn(\\n address indexed sender,\\n uint256 amount0,\\n uint256 amount1,\\n address indexed to\\n );\\n event Swap(\\n address indexed sender,\\n uint256 amount0In,\\n uint256 amount1In,\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address indexed to\\n );\\n event Sync(uint256 reserve0, uint256 reserve1);\\n event Claim(\\n address indexed sender,\\n address indexed recipient,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 amount\\n );\\n\\n constructor() {\\n factory = msg.sender;\\n (address _token0, address _token1, bool _stable) = PairFactory(\\n msg.sender\\n ).getInitializable();\\n (token0, token1, stable) = (_token0, _token1, _stable);\\n fees = address(new PairFees(_token0, _token1));\\n if (_stable) {\\n name = string(\\n abi.encodePacked(\\n \\\"StableV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"sAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n } else {\\n name = string(\\n abi.encodePacked(\\n \\\"VolatileV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"vAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n }\\n\\n decimals0 = 10**IERC20(_token0).decimals();\\n decimals1 = 10**IERC20(_token1).decimals();\\n\\n observations.push(Observation(block.timestamp, 0, 0));\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function observationLength() external view returns (uint256) {\\n return observations.length;\\n }\\n\\n function lastObservation() public view returns (Observation memory) {\\n return observations[observations.length - 1];\\n }\\n\\n function metadata()\\n external\\n view\\n returns (\\n uint256 dec0,\\n uint256 dec1,\\n uint256 r0,\\n uint256 r1,\\n bool st,\\n address t0,\\n address t1\\n )\\n {\\n return (\\n decimals0,\\n decimals1,\\n reserve0,\\n reserve1,\\n stable,\\n token0,\\n token1\\n );\\n }\\n\\n function tokens() external view returns (address, address) {\\n return (token0, token1);\\n }\\n\\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\\n _updateFor(msg.sender);\\n\\n claimed0 = claimable0[msg.sender];\\n claimed1 = claimable1[msg.sender];\\n\\n if (claimed0 > 0 || claimed1 > 0) {\\n claimable0[msg.sender] = 0;\\n claimable1[msg.sender] = 0;\\n\\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\\n\\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n // Accrue fees on token0\\n function _update0(uint256 amount) internal {\\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index0 += _ratio;\\n }\\n emit Fees(msg.sender, amount, 0);\\n }\\n\\n // Accrue fees on token1\\n function _update1(uint256 amount) internal {\\n _safeTransfer(token1, fees, amount);\\n uint256 _ratio = (amount * 1e18) / totalSupply;\\n if (_ratio > 0) {\\n index1 += _ratio;\\n }\\n emit Fees(msg.sender, 0, amount);\\n }\\n\\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\\n // Fees are segregated from core funds, so fees can never put liquidity at risk\\n function _updateFor(address recipient) internal {\\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\\n if (_supplied > 0) {\\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\\n uint256 _supplyIndex1 = supplyIndex1[recipient];\\n uint256 _index0 = index0; // get global index0 for accumulated fees\\n uint256 _index1 = index1;\\n supplyIndex0[recipient] = _index0; // update user current position to global position\\n supplyIndex1[recipient] = _index1;\\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\\n uint256 _delta1 = _index1 - _supplyIndex1;\\n if (_delta0 > 0) {\\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\\n claimable0[recipient] += _share;\\n }\\n if (_delta1 > 0) {\\n uint256 _share = (_supplied * _delta1) / 1e18;\\n claimable1[recipient] += _share;\\n }\\n } else {\\n supplyIndex0[recipient] = index0; // new users are set to the default global state\\n supplyIndex1[recipient] = index1;\\n }\\n }\\n\\n function getReserves()\\n public\\n view\\n returns (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n )\\n {\\n _reserve0 = reserve0;\\n _reserve1 = reserve1;\\n _blockTimestampLast = blockTimestampLast;\\n }\\n\\n // update reserves and, on the first call per block, price accumulators\\n function _update(\\n uint256 balance0,\\n uint256 balance1,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal {\\n uint256 blockTimestamp = block.timestamp;\\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\\n reserve0CumulativeLast += _reserve0 * timeElapsed;\\n reserve1CumulativeLast += _reserve1 * timeElapsed;\\n }\\n\\n Observation memory _point = lastObservation();\\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\\n if (timeElapsed > periodSize) {\\n observations.push(\\n Observation(\\n blockTimestamp,\\n reserve0CumulativeLast,\\n reserve1CumulativeLast\\n )\\n );\\n }\\n reserve0 = balance0;\\n reserve1 = balance1;\\n blockTimestampLast = blockTimestamp;\\n emit Sync(reserve0, reserve1);\\n }\\n\\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\\n function currentCumulativePrices()\\n public\\n view\\n returns (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n uint256 blockTimestamp\\n )\\n {\\n blockTimestamp = block.timestamp;\\n reserve0Cumulative = reserve0CumulativeLast;\\n reserve1Cumulative = reserve1CumulativeLast;\\n\\n // if time has elapsed since the last update on the pair, mock the accumulated price values\\n (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n ) = getReserves();\\n if (_blockTimestampLast != blockTimestamp) {\\n // subtraction overflow is desired\\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\\n reserve0Cumulative += _reserve0 * timeElapsed;\\n reserve1Cumulative += _reserve1 * timeElapsed;\\n }\\n }\\n\\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\\n function current(address tokenIn, uint256 amountIn)\\n external\\n view\\n returns (uint256 amountOut)\\n {\\n Observation memory _observation = lastObservation();\\n (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n\\n ) = currentCumulativePrices();\\n if (block.timestamp == _observation.timestamp) {\\n _observation = observations[observations.length - 2];\\n }\\n\\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\\n uint256 _reserve0 = (reserve0Cumulative -\\n _observation.reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (reserve1Cumulative -\\n _observation.reserve1Cumulative) / timeElapsed;\\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n // as per `current`, however allows user configured granularity, up to the full window size\\n function quote(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 granularity\\n ) external view returns (uint256 amountOut) {\\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\\n uint256 priceAverageCumulative;\\n for (uint256 i = 0; i < _prices.length; i++) {\\n priceAverageCumulative += _prices[i];\\n }\\n return priceAverageCumulative / granularity;\\n }\\n\\n // returns a memory set of twap prices\\n function prices(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points\\n ) external view returns (uint256[] memory) {\\n return sample(tokenIn, amountIn, points, 1);\\n }\\n\\n function sample(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points,\\n uint256 window\\n ) public view returns (uint256[] memory) {\\n uint256[] memory _prices = new uint256[](points);\\n\\n uint256 length = observations.length - 1;\\n uint256 i = length - (points * window);\\n uint256 nextIndex = 0;\\n uint256 index = 0;\\n\\n for (; i < length; i += window) {\\n nextIndex = i + window;\\n uint256 timeElapsed = observations[nextIndex].timestamp -\\n observations[i].timestamp;\\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\\n observations[i].reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\\n observations[i].reserve1Cumulative) / timeElapsed;\\n _prices[index] = _getAmountOut(\\n amountIn,\\n tokenIn,\\n _reserve0,\\n _reserve1\\n );\\n // index < length; length cannot overflow\\n unchecked {\\n index = index + 1;\\n }\\n }\\n return _prices;\\n }\\n\\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\\n // standard uniswap v2 implementation\\n function mint(address to) external lock returns (uint256 liquidity) {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\\n uint256 _amount0 = _balance0 - _reserve0;\\n uint256 _amount1 = _balance1 - _reserve1;\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n if (_totalSupply == 0) {\\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\\n } else {\\n liquidity = MathDunks.min(\\n (_amount0 * _totalSupply) / _reserve0,\\n (_amount1 * _totalSupply) / _reserve1\\n );\\n }\\n require(liquidity > 0, \\\"ILM\\\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\\n _mint(to, liquidity);\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Mint(msg.sender, _amount0, _amount1);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n // standard uniswap v2 implementation\\n function burn(address to)\\n external\\n lock\\n returns (uint256 amount0, uint256 amount1)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n (address _token0, address _token1) = (token0, token1);\\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\\n uint256 _liquidity = balanceOf[address(this)];\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\\n require(amount0 > 0 && amount1 > 0, \\\"ILB\\\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\\n _burn(address(this), _liquidity);\\n _safeTransfer(_token0, to, amount0);\\n _safeTransfer(_token1, to, amount1);\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Burn(msg.sender, amount0, amount1, to);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n function swap(\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address to,\\n bytes calldata data\\n ) external lock {\\n require(!PairFactory(factory).isPaused());\\n require(amount0Out > 0 || amount1Out > 0, \\\"IOA\\\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \\\"IL\\\"); // Pair: INSUFFICIENT_LIQUIDITY\\n\\n uint256 _balance0;\\n uint256 _balance1;\\n {\\n // scope for _token{0,1}, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n require(to != _token0 && to != _token1, \\\"IT\\\"); // Pair: INVALID_TO\\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\\n if (data.length > 0)\\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n }\\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\\n ? _balance0 - (_reserve0 - amount0Out)\\n : 0;\\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\\n ? _balance1 - (_reserve1 - amount1Out)\\n : 0;\\n require(amount0In > 0 || amount1In > 0, \\\"IIA\\\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\\n {\\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n if (amount0In > 0)\\n _update0(\\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token0 and move them out of pool\\n if (amount1In > 0)\\n _update1(\\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token1 and move them out of pool\\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \\\"K\\\"); // Pair: K\\n }\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\\n }\\n\\n // force balances to match reserves\\n function skim(address to) external lock {\\n (address _token0, address _token1) = (token0, token1);\\n _safeTransfer(\\n _token0,\\n to,\\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\\n );\\n _safeTransfer(\\n _token1,\\n to,\\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\\n );\\n }\\n\\n // force reserves to match balances\\n function sync() external lock {\\n _update(\\n IERC20(token0).balanceOf(address(this)),\\n IERC20(token1).balanceOf(address(this)),\\n reserve0,\\n reserve1\\n );\\n }\\n\\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\\n 1e18 +\\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\\n 1e18;\\n }\\n\\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (3 * x0 * ((y * y) / 1e18)) /\\n 1e18 +\\n ((((x0 * x0) / 1e18) * x0) / 1e18);\\n }\\n\\n function _get_y(\\n uint256 x0,\\n uint256 xy,\\n uint256 y\\n ) internal pure returns (uint256) {\\n for (uint256 i = 0; i < 255; i++) {\\n uint256 y_prev = y;\\n uint256 k = _f(x0, y);\\n if (k < xy) {\\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\\n y = y + dy;\\n } else {\\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getAmountOut(uint256 amountIn, address tokenIn)\\n external\\n view\\n returns (uint256)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n function _getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal view returns (uint256) {\\n if (stable) {\\n uint256 xy = _k(_reserve0, _reserve1);\\n _reserve0 = (_reserve0 * 1e18) / decimals0;\\n _reserve1 = (_reserve1 * 1e18) / decimals1;\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0\\n ? (amountIn * 1e18) / decimals0\\n : (amountIn * 1e18) / decimals1;\\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\\n } else {\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n return (amountIn * reserveB) / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\\n if (stable) {\\n uint256 _x = (x * 1e18) / decimals0;\\n uint256 _y = (y * 1e18) / decimals1;\\n uint256 _a = (_x * _y) / 1e18;\\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return (_a * _b) / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n\\n function _mint(address dst, uint256 amount) internal {\\n _updateFor(dst); // balances must be updated on mint/burn/transfer\\n totalSupply += amount;\\n balanceOf[dst] += amount;\\n emit Transfer(address(0), dst, amount);\\n }\\n\\n function _burn(address dst, uint256 amount) internal {\\n _updateFor(dst);\\n totalSupply -= amount;\\n balanceOf[dst] -= amount;\\n emit Transfer(dst, address(0), amount);\\n }\\n\\n function approve(address spender, uint256 amount) external returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external {\\n require(deadline >= block.timestamp, \\\"Pair: EXPIRED\\\");\\n DOMAIN_SEPARATOR = keccak256(\\n abi.encode(\\n keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n ),\\n keccak256(bytes(name)),\\n keccak256(bytes(\\\"1\\\")),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR,\\n keccak256(\\n abi.encode(\\n PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n );\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n require(\\n recoveredAddress != address(0) && recoveredAddress == owner,\\n \\\"Pair: INVALID_SIGNATURE\\\"\\n );\\n allowance[owner][spender] = value;\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function transfer(address dst, uint256 amount) external returns (bool) {\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 amount\\n ) external returns (bool) {\\n address spender = msg.sender;\\n uint256 spenderAllowance = allowance[src][spender];\\n\\n if (spender != src && spenderAllowance != type(uint256).max) {\\n uint256 newAllowance = spenderAllowance - amount;\\n allowance[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n function _transferTokens(\\n address src,\\n address dst,\\n uint256 amount\\n ) internal {\\n _updateFor(src); // update fee position for src\\n _updateFor(dst); // update fee position for dst\\n\\n balanceOf[src] -= amount;\\n balanceOf[dst] += amount;\\n\\n emit Transfer(src, dst, amount);\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x4f508747645f4480e0b0f23d952fa9b82af1d9bc60b15b8cd1f542ee136043d1\",\"license\":\"MIT\"},\"contracts/PairFees.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IERC20.sol';\\n\\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\\ncontract PairFees {\\n\\n address internal immutable pair; // The pair it is bonded to\\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\\n\\n constructor(address _token0, address _token1) {\\n pair = msg.sender;\\n token0 = _token0;\\n token1 = _token1;\\n }\\n\\n function _safeTransfer(address token,address to,uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n // Allow the pair to transfer fees to users\\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\\n require(msg.sender == pair);\\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\\n }\\n\\n}\\n\",\"keccak256\":\"0xb772e192bab353f8642e89a95ef4ef0255d1caef08444101d7fe34469c1000ca\",\"license\":\"MIT\"},\"contracts/factories/PairFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/Pair.sol';\\n\\ncontract PairFactory is IPairFactory {\\n\\n bool public isPaused;\\n address public pauser;\\n address public pendingPauser;\\n\\n uint256 public stableFee;\\n uint256 public volatileFee;\\n uint256 public constant MAX_FEE = 5; // 0.05%\\n address public feeManager;\\n address public pendingFeeManager;\\n\\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\\n address[] public allPairs;\\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\\n\\n address internal _temp0;\\n address internal _temp1;\\n bool internal _temp;\\n\\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\\n\\n constructor() {\\n pauser = msg.sender;\\n isPaused = false;\\n feeManager = msg.sender;\\n stableFee = 2; // 0.02%\\n volatileFee = 2;\\n }\\n\\n function allPairsLength() external view returns (uint) {\\n return allPairs.length;\\n }\\n\\n function setPauser(address _pauser) external {\\n require(msg.sender == pauser);\\n pendingPauser = _pauser;\\n }\\n\\n function acceptPauser() external {\\n require(msg.sender == pendingPauser);\\n pauser = pendingPauser;\\n }\\n\\n function setPause(bool _state) external {\\n require(msg.sender == pauser);\\n isPaused = _state;\\n }\\n\\n function setFeeManager(address _feeManager) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n pendingFeeManager = _feeManager;\\n }\\n\\n function acceptFeeManager() external {\\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\\n feeManager = pendingFeeManager;\\n }\\n\\n function setFee(bool _stable, uint256 _fee) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n require(_fee <= MAX_FEE, 'fee too high');\\n require(_fee != 0, 'fee must be nonzero');\\n if (_stable) {\\n stableFee = _fee;\\n } else {\\n volatileFee = _fee;\\n }\\n }\\n\\n function getFee(bool _stable) public view returns(uint256) {\\n return _stable ? stableFee : volatileFee;\\n }\\n\\n function pairCodeHash() external pure returns (bytes32) {\\n return keccak256(type(Pair).creationCode);\\n }\\n\\n function getInitializable() external view returns (address, address, bool) {\\n return (_temp0, _temp1, _temp);\\n }\\n\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\\n (_temp0, _temp1, _temp) = (token0, token1, stable);\\n pair = address(new Pair{salt:salt}());\\n getPair[token0][token1][stable] = pair;\\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\\n allPairs.push(pair);\\n isPair[pair] = true;\\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\\n }\\n}\\n\",\"keccak256\":\"0x9b7984117a5a32188aa9ddf42b6cff024240579ab30f3776f7a201285d813e4f\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairCallee.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairCallee {\\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x3ac2de2c7a08bf59fd1006e4d108b247916369de15fbd048b72ca2b7814023ca\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50600080546001600160a81b03191633610100810260ff1916919091178255600480546001600160a01b0319169091179055600280805560035561519190819061005a90396000f3fe60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea2646970667358221220ce154b3635cf14657eefb7534908f2ecf29803c977257640f38a3f975ef8e6f064736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea2646970667358221220ac6681731d4115b51788d75ee3ed8f52d572455bd0bdc1c79a8f79eb1e44459964736f6c634300080d0033a2646970667358221220316924ccc9676e4b6e71a5db0daf7f5c2096ee7d53ebe473a356330c9381716264736f6c634300080d0033", + "deployedBytecode": "0x60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea2646970667358221220ce154b3635cf14657eefb7534908f2ecf29803c977257640f38a3f975ef8e6f064736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea2646970667358221220ac6681731d4115b51788d75ee3ed8f52d572455bd0bdc1c79a8f79eb1e44459964736f6c634300080d0033a2646970667358221220316924ccc9676e4b6e71a5db0daf7f5c2096ee7d53ebe473a356330c9381716264736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/RedemptionReceiver.json b/deployments/arbitrumGoerli/RedemptionReceiver.json index 0cfe5f33..2da9fbbd 100644 --- a/deployments/arbitrumGoerli/RedemptionReceiver.json +++ b/deployments/arbitrumGoerli/RedemptionReceiver.json @@ -1,5 +1,5 @@ { - "address": "0xCe4d8bccE6d2D9B48565d660c45a397D3Fb4a497", + "address": "0x86E0Da889381Fb86d40D7E870d247C4aFD992cc0", "abi": [ { "inputs": [ @@ -323,33 +323,33 @@ "type": "function" } ], - "transactionHash": "0x299e902c0e7a5f362b791877aa19a16d7869bc3149bec56ce64be85f8957c904", + "transactionHash": "0xb6342afd08f27f8a374dabba92721ac4f3eb834d991a5a7969c4f0d86cec9971", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xCe4d8bccE6d2D9B48565d660c45a397D3Fb4a497", + "contractAddress": "0x86E0Da889381Fb86d40D7E870d247C4aFD992cc0", "transactionIndex": 1, "gasUsed": "841985", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc8fcd776d23ee2cb7efd3795d529b15a6769f03ae3e23c810a625ff04d9aeb5b", - "transactionHash": "0x299e902c0e7a5f362b791877aa19a16d7869bc3149bec56ce64be85f8957c904", + "blockHash": "0xd107dacdd5f5bf803ef35e882ef00c8c256aca1f1c0b5b68f9a65a3002e072b4", + "transactionHash": "0xb6342afd08f27f8a374dabba92721ac4f3eb834d991a5a7969c4f0d86cec9971", "logs": [], - "blockNumber": 5814450, + "blockNumber": 5849258, "cumulativeGasUsed": "841985", "status": 1, "byzantium": true }, "args": [ "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8", - "0x8c35578054126d4DD063CFaBA40B7F9B63A13981", + "0x0432f39386A9B1d0339c8Ba0af617b16C86ADA05", 10012, "0x3c2269811836af69497E5F486A85D7316753cf62" ], - "numDeployments": 5, - "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_usdc\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_flow\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"_fantomChainId\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"_endpoint\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fantomSender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableUSDC\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableFLOW\",\"type\":\"uint256\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ELIGIBLE_WEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FLOW\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"USDC\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"toAddressBytes\",\"type\":\"bytes\"}],\"name\":\"addressFromPackedBytes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimLeftovers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endpoint\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomChainId\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_fantomSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableFLOW\",\"type\":\"uint256\"}],\"name\":\"initializeReceiverWith\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"leftoverFLOW\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"srcChainId\",\"type\":\"uint16\"},{\"internalType\":\"bytes\",\"name\":\"srcAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"lzReceive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountWEVE\",\"type\":\"uint256\"}],\"name\":\"previewRedeem\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"shareOfUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shareOfFLOW\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableFLOW\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableUSDC\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemedWEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process This contract is responsible for receiving the LZ message and distributing USDC + FLOW\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/RedemptionReceiver.sol\":\"RedemptionReceiver\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/redeem/RedemptionReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\\\";\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\n\\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\\n/// This contract is responsible for receiving the LZ message and distributing USDC + FLOW\\ncontract RedemptionReceiver is ILayerZeroReceiver {\\n IERC20 public immutable USDC;\\n IFlow public immutable FLOW;\\n\\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\\n address public immutable endpoint;\\n\\n address public team;\\n uint256 public immutable deployed;\\n\\n address public fantomSender;\\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\\n uint256 public redeemedWEVE;\\n uint256 public redeemableUSDC;\\n uint256 public redeemableFLOW;\\n uint256 public leftoverFLOW;\\n\\n constructor(\\n address _usdc,\\n address _flow,\\n uint16 _fantomChainId,\\n address _endpoint\\n ) {\\n require(_fantomChainId == 12 || _fantomChainId == 10012, \\\"CHAIN_ID_NOT_FTM\\\");\\n\\n USDC = IERC20(_usdc);\\n FLOW = IFlow(_flow);\\n\\n fantomChainId = _fantomChainId;\\n endpoint = _endpoint;\\n\\n team = msg.sender;\\n deployed = block.timestamp;\\n }\\n\\n modifier onlyTeam() {\\n require(msg.sender == team, \\\"ONLY_TEAM\\\");\\n _;\\n }\\n\\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableFLOW);\\n\\n function initializeReceiverWith(\\n address _fantomSender,\\n uint256 _redeemableUSDC,\\n uint256 _redeemableFLOW\\n ) external onlyTeam {\\n require(fantomSender == address(0), \\\"ALREADY_INITIALIZED\\\");\\n require(\\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n fantomSender = _fantomSender;\\n redeemableUSDC = _redeemableUSDC;\\n redeemableFLOW = _redeemableFLOW;\\n leftoverFLOW = _redeemableFLOW;\\n\\n emit Initialized(fantomSender, redeemableUSDC, redeemableFLOW);\\n }\\n\\n function setTeam(address _team) external onlyTeam {\\n team = _team;\\n }\\n\\n function previewRedeem(uint256 amountWEVE)\\n public\\n view\\n returns (uint256 shareOfUSDC, uint256 shareOfFLOW)\\n {\\n // pro rata USDC\\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\\n // pro rata FLOW\\n shareOfFLOW = (amountWEVE * redeemableFLOW) / ELIGIBLE_WEVE;\\n }\\n\\n function lzReceive(\\n uint16 srcChainId,\\n bytes memory srcAddress,\\n uint64,\\n bytes memory payload\\n ) external override {\\n require(fantomSender != address(0), \\\"NOT_INITIALIZED\\\");\\n require(\\n msg.sender == endpoint &&\\n srcChainId == fantomChainId &&\\n addressFromPackedBytes(srcAddress) == fantomSender,\\n \\\"UNAUTHORIZED_CALLER\\\"\\n );\\n\\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\\n payload,\\n (address, uint256)\\n );\\n\\n require(\\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\\n \\\"cannot redeem more than eligible\\\"\\n );\\n (uint256 shareOfUSDC, uint256 shareOfFLOW) = previewRedeem(amountWEVE);\\n\\n require(\\n USDC.transfer(redemptionAddress, shareOfUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n leftoverFLOW -= shareOfFLOW; // this will revert if underflows\\n require(\\n FLOW.claim(redemptionAddress, shareOfFLOW),\\n \\\"CLAIM_FAILED\\\"\\n );\\n }\\n\\n function addressFromPackedBytes(bytes memory toAddressBytes)\\n public\\n pure\\n returns (address toAddress)\\n {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n toAddress := mload(add(toAddressBytes, 20))\\n }\\n }\\n\\n function claimLeftovers() external onlyTeam {\\n require(block.timestamp >= deployed + 30 days, \\\"LEFTOVERS_NOT_CLAIMABLE\\\");\\n require(\\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n }\\n}\\n\",\"keccak256\":\"0x582d45a8db937fe4a965056bcbe7d1427f71be66e8071bb1cae76d5f36c6c314\",\"license\":\"MIT\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\nimport \\\"./ILayerZeroUserApplicationConfig.sol\\\";\\n\\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\\n // @param _dstChainId - the destination chain identifier\\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\\n // @param _payload - a custom bytes payload to send to the destination contract\\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\\n\\n // @notice used by the messaging library to publish verified payload\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source contract (as bytes) at the source chain\\n // @param _dstAddress - the address on destination chain\\n // @param _nonce - the unbound message ordering nonce\\n // @param _gasLimit - the gas limit for external contract execution\\n // @param _payload - verified payload to send to the destination contract\\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\\n\\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\\n\\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\\n // @param _srcAddress - the source chain contract address\\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\\n\\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\\n // @param _dstChainId - the destination chain identifier\\n // @param _userApplication - the user app address on this EVM chain\\n // @param _payload - the custom message to send over LayerZero\\n // @param _payInZRO - if false, user app pays the protocol fee in native token\\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\\n\\n // @notice get this Endpoint's immutable source identifier\\n function getChainId() external view returns (uint16);\\n\\n // @notice the interface to retry failed message on this Endpoint destination\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n // @param _payload - the payload to be retried\\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\\n\\n // @notice query if any STORED payload (message blocking) at the endpoint.\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\\n\\n // @notice query if the _libraryAddress is valid for sending msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getSendLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the _libraryAddress is valid for receiving msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the non-reentrancy guard for send() is on\\n // @return true if the guard is on. false otherwise\\n function isSendingPayload() external view returns (bool);\\n\\n // @notice query if the non-reentrancy guard for receive() is on\\n // @return true if the guard is on. false otherwise\\n function isReceivingPayload() external view returns (bool);\\n\\n // @notice get the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _userApplication - the contract address of the user application\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\\n\\n // @notice get the send() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getSendVersion(address _userApplication) external view returns (uint16);\\n\\n // @notice get the lzReceive() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getReceiveVersion(address _userApplication) external view returns (uint16);\\n}\\n\",\"keccak256\":\"0xbc2e0022d4d53d136830aa90037be2ed7a0966f5fd1b409bf5986185984c495f\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroReceiver {\\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\\n // @param _srcChainId - the source endpoint identifier\\n // @param _srcAddress - the source sending contract address from the source chain\\n // @param _nonce - the ordered message nonce\\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\\n}\\n\",\"keccak256\":\"0xd1617e455d90d41556bba636bc440627d301ec481de16ff04fbd520333c3c6f3\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroUserApplicationConfig {\\n // @notice set the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n // @param _config - configuration in the bytes. can encode arbitrary content.\\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\\n\\n // @notice set the send() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setSendVersion(uint16 _version) external;\\n\\n // @notice set the lzReceive() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setReceiveVersion(uint16 _version) external;\\n\\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\\n // @param _srcChainId - the chainId of the source chain\\n // @param _srcAddress - the contract address of the source contract at the source chain\\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\\n}\\n\",\"keccak256\":\"0xdc7e072cf3064081a8edf4a286ca43ddecc24330f2923d96f416f9d3f6538447\",\"license\":\"BUSL-1.1\"}},\"version\":1}", - "bytecode": "0x61012060405234801561001157600080fd5b50604051610f81380380610f81833981016040819052610030916100e2565b8161ffff16600c148061004857508161ffff1661271c145b61008b5760405162461bcd60e51b815260206004820152601060248201526f434841494e5f49445f4e4f545f46544d60801b604482015260640160405180910390fd5b6001600160a01b0393841660805291831660a05261ffff1660c0521660e052600080546001600160a01b03191633179055426101005261013f565b80516001600160a01b03811681146100dd57600080fd5b919050565b600080600080608085870312156100f857600080fd5b610101856100c6565b935061010f602086016100c6565b9250604085015161ffff8116811461012657600080fd5b9150610134606086016100c6565b905092959194509250565b60805160a05160c05160e05161010051610dcd6101b4600039600081816102d601526108c00152600081816101d30152610352015260008181610263015261037c015260008181610163015261059f01526000818161023c015281816104d70152818161078e015261094c0152610dcd6000f3fe608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a408bb4c11610071578063a408bb4c14610298578063aaa8f2ef146102a0578063b8ea6281146102b3578063caccb667146102c8578063f905c15a146102d157600080fd5b80636bfd23a71461021b57806385f2aef21461022457806389a3027114610237578063997a03b71461025e57600080fd5b806347db1a6a116100e957806347db1a6a1461019d5780634cdad506146101a65780635e280f11146101ce57806363b4eb8d146101f557806368ecc6bc1461020857600080fd5b80621d35671461011a578063095cf5c61461012f5780631308db08146101425780633189097b1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60055481565b6040519081526020015b60405180910390f35b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b61014b60035481565b6101b96101b4366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b600154610185906001600160a01b031681565b61012d610216366004610be5565b6106f3565b61014b60025481565b600054610185906001600160a01b031681565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6102857f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101856102c1366004610c1a565b6014015190565b61014b60045481565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea2646970667358221220fa48dc36406d08ebc3152e620c13d8b9f478aff977b39deae155b9b3bcb0feaa64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a408bb4c11610071578063a408bb4c14610298578063aaa8f2ef146102a0578063b8ea6281146102b3578063caccb667146102c8578063f905c15a146102d157600080fd5b80636bfd23a71461021b57806385f2aef21461022457806389a3027114610237578063997a03b71461025e57600080fd5b806347db1a6a116100e957806347db1a6a1461019d5780634cdad506146101a65780635e280f11146101ce57806363b4eb8d146101f557806368ecc6bc1461020857600080fd5b80621d35671461011a578063095cf5c61461012f5780631308db08146101425780633189097b1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60055481565b6040519081526020015b60405180910390f35b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b61014b60035481565b6101b96101b4366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b600154610185906001600160a01b031681565b61012d610216366004610be5565b6106f3565b61014b60025481565b600054610185906001600160a01b031681565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6102857f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101856102c1366004610c1a565b6014015190565b61014b60045481565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea2646970667358221220fa48dc36406d08ebc3152e620c13d8b9f478aff977b39deae155b9b3bcb0feaa64736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_usdc\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_flow\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"_fantomChainId\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"_endpoint\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fantomSender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableUSDC\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableFLOW\",\"type\":\"uint256\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ELIGIBLE_WEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FLOW\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"USDC\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"toAddressBytes\",\"type\":\"bytes\"}],\"name\":\"addressFromPackedBytes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimLeftovers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endpoint\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomChainId\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_fantomSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableFLOW\",\"type\":\"uint256\"}],\"name\":\"initializeReceiverWith\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"leftoverFLOW\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"srcChainId\",\"type\":\"uint16\"},{\"internalType\":\"bytes\",\"name\":\"srcAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"lzReceive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountWEVE\",\"type\":\"uint256\"}],\"name\":\"previewRedeem\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"shareOfUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shareOfFLOW\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableFLOW\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableUSDC\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemedWEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process This contract is responsible for receiving the LZ message and distributing USDC + FLOW\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/RedemptionReceiver.sol\":\"RedemptionReceiver\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/redeem/RedemptionReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\\\";\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\n\\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\\n/// This contract is responsible for receiving the LZ message and distributing USDC + FLOW\\ncontract RedemptionReceiver is ILayerZeroReceiver {\\n IERC20 public immutable USDC;\\n IFlow public immutable FLOW;\\n\\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\\n address public immutable endpoint;\\n\\n address public team;\\n uint256 public immutable deployed;\\n\\n address public fantomSender;\\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\\n uint256 public redeemedWEVE;\\n uint256 public redeemableUSDC;\\n uint256 public redeemableFLOW;\\n uint256 public leftoverFLOW;\\n\\n constructor(\\n address _usdc,\\n address _flow,\\n uint16 _fantomChainId,\\n address _endpoint\\n ) {\\n require(_fantomChainId == 12 || _fantomChainId == 10012, \\\"CHAIN_ID_NOT_FTM\\\");\\n\\n USDC = IERC20(_usdc);\\n FLOW = IFlow(_flow);\\n\\n fantomChainId = _fantomChainId;\\n endpoint = _endpoint;\\n\\n team = msg.sender;\\n deployed = block.timestamp;\\n }\\n\\n modifier onlyTeam() {\\n require(msg.sender == team, \\\"ONLY_TEAM\\\");\\n _;\\n }\\n\\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableFLOW);\\n\\n function initializeReceiverWith(\\n address _fantomSender,\\n uint256 _redeemableUSDC,\\n uint256 _redeemableFLOW\\n ) external onlyTeam {\\n require(fantomSender == address(0), \\\"ALREADY_INITIALIZED\\\");\\n require(\\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n fantomSender = _fantomSender;\\n redeemableUSDC = _redeemableUSDC;\\n redeemableFLOW = _redeemableFLOW;\\n leftoverFLOW = _redeemableFLOW;\\n\\n emit Initialized(fantomSender, redeemableUSDC, redeemableFLOW);\\n }\\n\\n function setTeam(address _team) external onlyTeam {\\n team = _team;\\n }\\n\\n function previewRedeem(uint256 amountWEVE)\\n public\\n view\\n returns (uint256 shareOfUSDC, uint256 shareOfFLOW)\\n {\\n // pro rata USDC\\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\\n // pro rata FLOW\\n shareOfFLOW = (amountWEVE * redeemableFLOW) / ELIGIBLE_WEVE;\\n }\\n\\n function lzReceive(\\n uint16 srcChainId,\\n bytes memory srcAddress,\\n uint64,\\n bytes memory payload\\n ) external override {\\n require(fantomSender != address(0), \\\"NOT_INITIALIZED\\\");\\n require(\\n msg.sender == endpoint &&\\n srcChainId == fantomChainId &&\\n addressFromPackedBytes(srcAddress) == fantomSender,\\n \\\"UNAUTHORIZED_CALLER\\\"\\n );\\n\\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\\n payload,\\n (address, uint256)\\n );\\n\\n require(\\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\\n \\\"cannot redeem more than eligible\\\"\\n );\\n (uint256 shareOfUSDC, uint256 shareOfFLOW) = previewRedeem(amountWEVE);\\n\\n require(\\n USDC.transfer(redemptionAddress, shareOfUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n leftoverFLOW -= shareOfFLOW; // this will revert if underflows\\n require(\\n FLOW.claim(redemptionAddress, shareOfFLOW),\\n \\\"CLAIM_FAILED\\\"\\n );\\n }\\n\\n function addressFromPackedBytes(bytes memory toAddressBytes)\\n public\\n pure\\n returns (address toAddress)\\n {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n toAddress := mload(add(toAddressBytes, 20))\\n }\\n }\\n\\n function claimLeftovers() external onlyTeam {\\n require(block.timestamp >= deployed + 30 days, \\\"LEFTOVERS_NOT_CLAIMABLE\\\");\\n require(\\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n }\\n}\\n\",\"keccak256\":\"0x582d45a8db937fe4a965056bcbe7d1427f71be66e8071bb1cae76d5f36c6c314\",\"license\":\"MIT\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\nimport \\\"./ILayerZeroUserApplicationConfig.sol\\\";\\n\\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\\n // @param _dstChainId - the destination chain identifier\\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\\n // @param _payload - a custom bytes payload to send to the destination contract\\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\\n\\n // @notice used by the messaging library to publish verified payload\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source contract (as bytes) at the source chain\\n // @param _dstAddress - the address on destination chain\\n // @param _nonce - the unbound message ordering nonce\\n // @param _gasLimit - the gas limit for external contract execution\\n // @param _payload - verified payload to send to the destination contract\\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\\n\\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\\n\\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\\n // @param _srcAddress - the source chain contract address\\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\\n\\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\\n // @param _dstChainId - the destination chain identifier\\n // @param _userApplication - the user app address on this EVM chain\\n // @param _payload - the custom message to send over LayerZero\\n // @param _payInZRO - if false, user app pays the protocol fee in native token\\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\\n\\n // @notice get this Endpoint's immutable source identifier\\n function getChainId() external view returns (uint16);\\n\\n // @notice the interface to retry failed message on this Endpoint destination\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n // @param _payload - the payload to be retried\\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\\n\\n // @notice query if any STORED payload (message blocking) at the endpoint.\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\\n\\n // @notice query if the _libraryAddress is valid for sending msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getSendLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the _libraryAddress is valid for receiving msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the non-reentrancy guard for send() is on\\n // @return true if the guard is on. false otherwise\\n function isSendingPayload() external view returns (bool);\\n\\n // @notice query if the non-reentrancy guard for receive() is on\\n // @return true if the guard is on. false otherwise\\n function isReceivingPayload() external view returns (bool);\\n\\n // @notice get the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _userApplication - the contract address of the user application\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\\n\\n // @notice get the send() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getSendVersion(address _userApplication) external view returns (uint16);\\n\\n // @notice get the lzReceive() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getReceiveVersion(address _userApplication) external view returns (uint16);\\n}\\n\",\"keccak256\":\"0xbc2e0022d4d53d136830aa90037be2ed7a0966f5fd1b409bf5986185984c495f\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroReceiver {\\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\\n // @param _srcChainId - the source endpoint identifier\\n // @param _srcAddress - the source sending contract address from the source chain\\n // @param _nonce - the ordered message nonce\\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\\n}\\n\",\"keccak256\":\"0xd1617e455d90d41556bba636bc440627d301ec481de16ff04fbd520333c3c6f3\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroUserApplicationConfig {\\n // @notice set the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n // @param _config - configuration in the bytes. can encode arbitrary content.\\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\\n\\n // @notice set the send() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setSendVersion(uint16 _version) external;\\n\\n // @notice set the lzReceive() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setReceiveVersion(uint16 _version) external;\\n\\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\\n // @param _srcChainId - the chainId of the source chain\\n // @param _srcAddress - the contract address of the source contract at the source chain\\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\\n}\\n\",\"keccak256\":\"0xdc7e072cf3064081a8edf4a286ca43ddecc24330f2923d96f416f9d3f6538447\",\"license\":\"BUSL-1.1\"}},\"version\":1}", + "bytecode": "0x61012060405234801561001157600080fd5b50604051610f81380380610f81833981016040819052610030916100e2565b8161ffff16600c148061004857508161ffff1661271c145b61008b5760405162461bcd60e51b815260206004820152601060248201526f434841494e5f49445f4e4f545f46544d60801b604482015260640160405180910390fd5b6001600160a01b0393841660805291831660a05261ffff1660c0521660e052600080546001600160a01b03191633179055426101005261013f565b80516001600160a01b03811681146100dd57600080fd5b919050565b600080600080608085870312156100f857600080fd5b610101856100c6565b935061010f602086016100c6565b9250604085015161ffff8116811461012657600080fd5b9150610134606086016100c6565b905092959194509250565b60805160a05160c05160e05161010051610dcd6101b4600039600081816102d601526108c00152600081816101d30152610352015260008181610263015261037c015260008181610163015261059f01526000818161023c015281816104d70152818161078e015261094c0152610dcd6000f3fe608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a408bb4c11610071578063a408bb4c14610298578063aaa8f2ef146102a0578063b8ea6281146102b3578063caccb667146102c8578063f905c15a146102d157600080fd5b80636bfd23a71461021b57806385f2aef21461022457806389a3027114610237578063997a03b71461025e57600080fd5b806347db1a6a116100e957806347db1a6a1461019d5780634cdad506146101a65780635e280f11146101ce57806363b4eb8d146101f557806368ecc6bc1461020857600080fd5b80621d35671461011a578063095cf5c61461012f5780631308db08146101425780633189097b1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60055481565b6040519081526020015b60405180910390f35b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b61014b60035481565b6101b96101b4366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b600154610185906001600160a01b031681565b61012d610216366004610be5565b6106f3565b61014b60025481565b600054610185906001600160a01b031681565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6102857f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101856102c1366004610c1a565b6014015190565b61014b60045481565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea26469706673582212207b71c24b86331eb328782c3cff47b5a9ace7bd87e1419a0421a4319761d8270c64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a408bb4c11610071578063a408bb4c14610298578063aaa8f2ef146102a0578063b8ea6281146102b3578063caccb667146102c8578063f905c15a146102d157600080fd5b80636bfd23a71461021b57806385f2aef21461022457806389a3027114610237578063997a03b71461025e57600080fd5b806347db1a6a116100e957806347db1a6a1461019d5780634cdad506146101a65780635e280f11146101ce57806363b4eb8d146101f557806368ecc6bc1461020857600080fd5b80621d35671461011a578063095cf5c61461012f5780631308db08146101425780633189097b1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60055481565b6040519081526020015b60405180910390f35b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b61014b60035481565b6101b96101b4366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b600154610185906001600160a01b031681565b61012d610216366004610be5565b6106f3565b61014b60025481565b600054610185906001600160a01b031681565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6102857f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101856102c1366004610c1a565b6014015190565b61014b60045481565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea26469706673582212207b71c24b86331eb328782c3cff47b5a9ace7bd87e1419a0421a4319761d8270c64736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/RewardsDistributor.json b/deployments/arbitrumGoerli/RewardsDistributor.json index 4e6be817..c929eecf 100644 --- a/deployments/arbitrumGoerli/RewardsDistributor.json +++ b/deployments/arbitrumGoerli/RewardsDistributor.json @@ -1,5 +1,5 @@ { - "address": "0x85e7505be0F725AED67379Eb7F78d8561101caAE", + "address": "0xd06A463fD49720629A285E3C8De4310bc103df0a", "abi": [ { "inputs": [ @@ -351,45 +351,45 @@ "type": "function" } ], - "transactionHash": "0xbcdd4fe808f20d21c52d94ef1d4819b0ffa6e595bce37b1fe7b4303974eee346", + "transactionHash": "0x27c5e1e464a8506a9d266b0632cf37d05f43b0f3a1ebe2adc653e8e0051168bf", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x85e7505be0F725AED67379Eb7F78d8561101caAE", + "contractAddress": "0xd06A463fD49720629A285E3C8De4310bc103df0a", "transactionIndex": 1, "gasUsed": "1623336", - "logsBloom": "0x00000000000000000000000000000000000004000000400000000000000000000000000000000000000000200010000000000000000000000004000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000800000000000000020000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xf63a14d84d9124cfc028f0ee04331c15005c46436bc1b521d09512e115713525", - "transactionHash": "0xbcdd4fe808f20d21c52d94ef1d4819b0ffa6e595bce37b1fe7b4303974eee346", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000080000000020000000000000000000000000000000000000000000000040200000000000002000000000000000000000000000000000000000000020000000000000000000000000000008000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000010000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x524168c7b377927743d8fe0de27e415ee684f569cbe9134c6c42828e382244f4", + "transactionHash": "0x27c5e1e464a8506a9d266b0632cf37d05f43b0f3a1ebe2adc653e8e0051168bf", "logs": [ { "transactionIndex": 1, - "blockNumber": 5814435, - "transactionHash": "0xbcdd4fe808f20d21c52d94ef1d4819b0ffa6e595bce37b1fe7b4303974eee346", - "address": "0x8c35578054126d4DD063CFaBA40B7F9B63A13981", + "blockNumber": 5849223, + "transactionHash": "0x27c5e1e464a8506a9d266b0632cf37d05f43b0f3a1ebe2adc653e8e0051168bf", + "address": "0x0432f39386A9B1d0339c8Ba0af617b16C86ADA05", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x00000000000000000000000085e7505be0f725aed67379eb7f78d8561101caae", - "0x000000000000000000000000ad0f425b3edb0fc3a06096092b5736a280c90c40" + "0x000000000000000000000000d06a463fd49720629a285e3c8de4310bc103df0a", + "0x000000000000000000000000f003091b78974ee3f99ec70fc5f42fc9810664ec" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "logIndex": 0, - "blockHash": "0xf63a14d84d9124cfc028f0ee04331c15005c46436bc1b521d09512e115713525" + "blockHash": "0x524168c7b377927743d8fe0de27e415ee684f569cbe9134c6c42828e382244f4" } ], - "blockNumber": 5814435, + "blockNumber": 5849223, "cumulativeGasUsed": "1623336", "status": 1, "byzantium": true }, "args": [ - "0xad0F425b3edB0FC3a06096092B5736A280C90C40" + "0xF003091B78974ee3F99ec70fC5F42fc9810664EC" ], - "numDeployments": 5, - "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voting_escrow\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"time\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"CheckpointToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"claim_epoch\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"max_epoch\",\"type\":\"uint256\"}],\"name\":\"Claimed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"checkpoint_token\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint_total_supply\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"_tokenIds\",\"type\":\"uint256[]\"}],\"name\":\"claim_many\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_token_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"}],\"name\":\"setDepositor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"start_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"time_cursor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"time_cursor_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token_last_balance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"tokens_per_week\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_epoch_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"ve_for_at\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ve_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voting_escrow\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RewardsDistributor.sol\":\"RewardsDistributor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/*\\n\\n@title Curve Fee Distribution modified for ve(3,3) emissions\\n@author Curve Finance, andrecronje\\n@license MIT\\n\\n*/\\n\\ncontract RewardsDistributor is IRewardsDistributor {\\n event CheckpointToken(uint256 time, uint256 tokens);\\n\\n event Claimed(\\n uint256 tokenId,\\n uint256 amount,\\n uint256 claim_epoch,\\n uint256 max_epoch\\n );\\n\\n uint256 constant WEEK = 7 * 86400;\\n\\n uint256 public start_time;\\n uint256 public time_cursor;\\n mapping(uint256 => uint256) public time_cursor_of;\\n mapping(uint256 => uint256) public user_epoch_of;\\n\\n uint256 public last_token_time;\\n uint256[1000000000000000] public tokens_per_week;\\n\\n address public voting_escrow;\\n address public token;\\n uint256 public token_last_balance;\\n\\n uint256[1000000000000000] public ve_supply;\\n\\n address public depositor;\\n\\n constructor(address _voting_escrow) {\\n uint256 _t = (block.timestamp / WEEK) * WEEK;\\n start_time = _t;\\n last_token_time = _t;\\n time_cursor = _t;\\n address _token = IVotingEscrow(_voting_escrow).token();\\n token = _token;\\n voting_escrow = _voting_escrow;\\n depositor = msg.sender;\\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\\n }\\n\\n function timestamp() external view returns (uint256) {\\n return (block.timestamp / WEEK) * WEEK;\\n }\\n\\n function _checkpoint_token() internal {\\n uint256 token_balance = IERC20(token).balanceOf(address(this));\\n uint256 to_distribute = token_balance - token_last_balance;\\n token_last_balance = token_balance;\\n\\n uint256 t = last_token_time;\\n uint256 since_last = block.timestamp - t;\\n last_token_time = block.timestamp;\\n uint256 this_week = (t / WEEK) * WEEK;\\n uint256 next_week = 0;\\n\\n for (uint256 i = 0; i < 20; i++) {\\n next_week = this_week + WEEK;\\n if (block.timestamp < next_week) {\\n if (since_last == 0 && block.timestamp == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (block.timestamp - t)) /\\n since_last;\\n }\\n break;\\n } else {\\n if (since_last == 0 && next_week == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (next_week - t)) /\\n since_last;\\n }\\n }\\n t = next_week;\\n this_week = next_week;\\n }\\n emit CheckpointToken(block.timestamp, to_distribute);\\n }\\n\\n function checkpoint_token() external {\\n assert(msg.sender == depositor);\\n _checkpoint_token();\\n }\\n\\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\\n internal\\n view\\n returns (uint256)\\n {\\n uint256 _min = 0;\\n uint256 _max = IVotingEscrow(ve).epoch();\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n _mid\\n );\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function _find_timestamp_user_epoch(\\n address ve,\\n uint256 tokenId,\\n uint256 _timestamp,\\n uint256 max_user_epoch\\n ) internal view returns (uint256) {\\n uint256 _min = 0;\\n uint256 _max = max_user_epoch;\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\\n .user_point_history(tokenId, _mid);\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\\n external\\n view\\n returns (uint256)\\n {\\n address ve = voting_escrow;\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _timestamp,\\n max_user_epoch\\n );\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n epoch\\n );\\n return\\n MathDunks.max(\\n uint256(\\n int256(\\n pt.bias -\\n pt.slope *\\n (int128(int256(_timestamp - pt.ts)))\\n )\\n ),\\n 0\\n );\\n }\\n\\n function _checkpoint_total_supply() internal {\\n address ve = voting_escrow;\\n uint256 t = time_cursor;\\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\\n IVotingEscrow(ve).checkpoint();\\n\\n for (uint256 i = 0; i < 20; i++) {\\n if (t > rounded_timestamp) {\\n break;\\n } else {\\n uint256 epoch = _find_timestamp_epoch(ve, t);\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n epoch\\n );\\n int128 dt = 0;\\n if (t > pt.ts) {\\n dt = int128(int256(t - pt.ts));\\n }\\n ve_supply[t] = MathDunks.max(\\n uint256(int256(pt.bias - pt.slope * dt)),\\n 0\\n );\\n }\\n t += WEEK;\\n }\\n time_cursor = t;\\n }\\n\\n function checkpoint_total_supply() external {\\n _checkpoint_total_supply();\\n }\\n\\n function _claim(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\\n user_epoch_of[_tokenId] = user_epoch;\\n time_cursor_of[_tokenId] = week_cursor;\\n\\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\\n\\n return to_distribute;\\n }\\n\\n function _claimable(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal view returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n return to_distribute;\\n }\\n\\n function claimable(uint256 _tokenId) external view returns (uint256) {\\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\\n return _claimable(_tokenId, voting_escrow, _last_token_time);\\n }\\n\\n function claim(uint256 _tokenId) external returns (uint256) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\\n token_last_balance -= amount;\\n }\\n return amount;\\n }\\n\\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n address _voting_escrow = voting_escrow;\\n uint256 total = 0;\\n\\n for (uint256 i = 0; i < _tokenIds.length; i++) {\\n uint256 _tokenId = _tokenIds[i];\\n if (_tokenId == 0) break;\\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\\n total += amount;\\n }\\n }\\n if (total != 0) {\\n token_last_balance -= total;\\n }\\n\\n return true;\\n }\\n\\n // Once off event on contract initialize\\n function setDepositor(address _depositor) external {\\n require(msg.sender == depositor);\\n depositor = _depositor;\\n }\\n}\\n\",\"keccak256\":\"0xc3e7c3c7944974ce250313d2794fbfa3a98786e2040c685dc250c71ff9002829\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b5060405162001b9f38038062001b9f83398101604081905262000034916200019f565b600062093a80620000468142620001d1565b620000529190620001f4565b90508060008190555080600481905550806001819055506000826001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000aa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d091906200019f565b66038d7ea4c6800680546001600160a01b038381166001600160a01b0319928316811790935566038d7ea4c6800580549188169183168217905566071afd498d00088054909216331790915560405163095ea7b360e01b8152600481019190915260001960248201529192509063095ea7b3906044016020604051808303816000875af115801562000166573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200018c919062000222565b6200019657600080fd5b50505062000246565b600060208284031215620001b257600080fd5b81516001600160a01b0381168114620001ca57600080fd5b9392505050565b600082620001ef57634e487b7160e01b600052601260045260246000fd5b500490565b60008160001904831182151516156200021d57634e487b7160e01b600052601160045260246000fd5b500290565b6000602082840312156200023557600080fd5b81518015158114620001ca57600080fd5b61194980620002566000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea264697066735822122010fa9684b9cfb008f9cdfd287eddb3ae9817c769f858f828efc2818acbe56f8564736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea264697066735822122010fa9684b9cfb008f9cdfd287eddb3ae9817c769f858f828efc2818acbe56f8564736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voting_escrow\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"time\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"CheckpointToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"claim_epoch\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"max_epoch\",\"type\":\"uint256\"}],\"name\":\"Claimed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"checkpoint_token\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint_total_supply\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"_tokenIds\",\"type\":\"uint256[]\"}],\"name\":\"claim_many\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_token_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"}],\"name\":\"setDepositor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"start_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"time_cursor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"time_cursor_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token_last_balance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"tokens_per_week\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_epoch_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"ve_for_at\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ve_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voting_escrow\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RewardsDistributor.sol\":\"RewardsDistributor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/*\\n\\n@title Curve Fee Distribution modified for ve(3,3) emissions\\n@author Curve Finance, andrecronje\\n@license MIT\\n\\n*/\\n\\ncontract RewardsDistributor is IRewardsDistributor {\\n event CheckpointToken(uint256 time, uint256 tokens);\\n\\n event Claimed(\\n uint256 tokenId,\\n uint256 amount,\\n uint256 claim_epoch,\\n uint256 max_epoch\\n );\\n\\n uint256 constant WEEK = 7 * 86400;\\n\\n uint256 public start_time;\\n uint256 public time_cursor;\\n mapping(uint256 => uint256) public time_cursor_of;\\n mapping(uint256 => uint256) public user_epoch_of;\\n\\n uint256 public last_token_time;\\n uint256[1000000000000000] public tokens_per_week;\\n\\n address public voting_escrow;\\n address public token;\\n uint256 public token_last_balance;\\n\\n uint256[1000000000000000] public ve_supply;\\n\\n address public depositor;\\n\\n constructor(address _voting_escrow) {\\n uint256 _t = (block.timestamp / WEEK) * WEEK;\\n start_time = _t;\\n last_token_time = _t;\\n time_cursor = _t;\\n address _token = IVotingEscrow(_voting_escrow).token();\\n token = _token;\\n voting_escrow = _voting_escrow;\\n depositor = msg.sender;\\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\\n }\\n\\n function timestamp() external view returns (uint256) {\\n return (block.timestamp / WEEK) * WEEK;\\n }\\n\\n function _checkpoint_token() internal {\\n uint256 token_balance = IERC20(token).balanceOf(address(this));\\n uint256 to_distribute = token_balance - token_last_balance;\\n token_last_balance = token_balance;\\n\\n uint256 t = last_token_time;\\n uint256 since_last = block.timestamp - t;\\n last_token_time = block.timestamp;\\n uint256 this_week = (t / WEEK) * WEEK;\\n uint256 next_week = 0;\\n\\n for (uint256 i = 0; i < 20; i++) {\\n next_week = this_week + WEEK;\\n if (block.timestamp < next_week) {\\n if (since_last == 0 && block.timestamp == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (block.timestamp - t)) /\\n since_last;\\n }\\n break;\\n } else {\\n if (since_last == 0 && next_week == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (next_week - t)) /\\n since_last;\\n }\\n }\\n t = next_week;\\n this_week = next_week;\\n }\\n emit CheckpointToken(block.timestamp, to_distribute);\\n }\\n\\n function checkpoint_token() external {\\n assert(msg.sender == depositor);\\n _checkpoint_token();\\n }\\n\\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\\n internal\\n view\\n returns (uint256)\\n {\\n uint256 _min = 0;\\n uint256 _max = IVotingEscrow(ve).epoch();\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n _mid\\n );\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function _find_timestamp_user_epoch(\\n address ve,\\n uint256 tokenId,\\n uint256 _timestamp,\\n uint256 max_user_epoch\\n ) internal view returns (uint256) {\\n uint256 _min = 0;\\n uint256 _max = max_user_epoch;\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\\n .user_point_history(tokenId, _mid);\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\\n external\\n view\\n returns (uint256)\\n {\\n address ve = voting_escrow;\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _timestamp,\\n max_user_epoch\\n );\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n epoch\\n );\\n return\\n MathDunks.max(\\n uint256(\\n int256(\\n pt.bias -\\n pt.slope *\\n (int128(int256(_timestamp - pt.ts)))\\n )\\n ),\\n 0\\n );\\n }\\n\\n function _checkpoint_total_supply() internal {\\n address ve = voting_escrow;\\n uint256 t = time_cursor;\\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\\n IVotingEscrow(ve).checkpoint();\\n\\n for (uint256 i = 0; i < 20; i++) {\\n if (t > rounded_timestamp) {\\n break;\\n } else {\\n uint256 epoch = _find_timestamp_epoch(ve, t);\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n epoch\\n );\\n int128 dt = 0;\\n if (t > pt.ts) {\\n dt = int128(int256(t - pt.ts));\\n }\\n ve_supply[t] = MathDunks.max(\\n uint256(int256(pt.bias - pt.slope * dt)),\\n 0\\n );\\n }\\n t += WEEK;\\n }\\n time_cursor = t;\\n }\\n\\n function checkpoint_total_supply() external {\\n _checkpoint_total_supply();\\n }\\n\\n function _claim(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\\n user_epoch_of[_tokenId] = user_epoch;\\n time_cursor_of[_tokenId] = week_cursor;\\n\\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\\n\\n return to_distribute;\\n }\\n\\n function _claimable(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal view returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n return to_distribute;\\n }\\n\\n function claimable(uint256 _tokenId) external view returns (uint256) {\\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\\n return _claimable(_tokenId, voting_escrow, _last_token_time);\\n }\\n\\n function claim(uint256 _tokenId) external returns (uint256) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\\n token_last_balance -= amount;\\n }\\n return amount;\\n }\\n\\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n address _voting_escrow = voting_escrow;\\n uint256 total = 0;\\n\\n for (uint256 i = 0; i < _tokenIds.length; i++) {\\n uint256 _tokenId = _tokenIds[i];\\n if (_tokenId == 0) break;\\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\\n total += amount;\\n }\\n }\\n if (total != 0) {\\n token_last_balance -= total;\\n }\\n\\n return true;\\n }\\n\\n // Once off event on contract initialize\\n function setDepositor(address _depositor) external {\\n require(msg.sender == depositor);\\n depositor = _depositor;\\n }\\n}\\n\",\"keccak256\":\"0xc3e7c3c7944974ce250313d2794fbfa3a98786e2040c685dc250c71ff9002829\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b5060405162001b9f38038062001b9f83398101604081905262000034916200019f565b600062093a80620000468142620001d1565b620000529190620001f4565b90508060008190555080600481905550806001819055506000826001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000aa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d091906200019f565b66038d7ea4c6800680546001600160a01b038381166001600160a01b0319928316811790935566038d7ea4c6800580549188169183168217905566071afd498d00088054909216331790915560405163095ea7b360e01b8152600481019190915260001960248201529192509063095ea7b3906044016020604051808303816000875af115801562000166573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200018c919062000222565b6200019657600080fd5b50505062000246565b600060208284031215620001b257600080fd5b81516001600160a01b0381168114620001ca57600080fd5b9392505050565b600082620001ef57634e487b7160e01b600052601260045260246000fd5b500490565b60008160001904831182151516156200021d57634e487b7160e01b600052601160045260246000fd5b500290565b6000602082840312156200023557600080fd5b81518015158114620001ca57600080fd5b61194980620002566000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea2646970667358221220877c3a13c3ebfa895eaa531d7321700f88e3027df204bd9c0bbc82338f0c4de964736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea2646970667358221220877c3a13c3ebfa895eaa531d7321700f88e3027df204bd9c0bbc82338f0c4de964736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/Router.json b/deployments/arbitrumGoerli/Router.json index 067b963f..ff838567 100644 --- a/deployments/arbitrumGoerli/Router.json +++ b/deployments/arbitrumGoerli/Router.json @@ -1,5 +1,5 @@ { - "address": "0xD2D41340706472DEf3b8A1d6143743D03Da38fed", + "address": "0x7620a00A75f7fAE135A7236E79982A98Cfd120e1", "abi": [ { "inputs": [ @@ -979,31 +979,31 @@ "type": "receive" } ], - "transactionHash": "0x7c4a24e69aaf4df164731cb3473791991b6801f813e6f574159e65ffc4f89d4f", + "transactionHash": "0x6a363131580509010713673da815190937e2a41dd72858f82ae4b0ed6a27e9c6", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xD2D41340706472DEf3b8A1d6143743D03Da38fed", + "contractAddress": "0x7620a00A75f7fAE135A7236E79982A98Cfd120e1", "transactionIndex": 1, "gasUsed": "3145971", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xd758637a25eeb7e41b28a5084badd5aa60779ea0a9aaff0c4ab4828c0125f7b7", - "transactionHash": "0x7c4a24e69aaf4df164731cb3473791991b6801f813e6f574159e65ffc4f89d4f", + "blockHash": "0x4ec5b790e5f67b0ad9c5f3bceb28bd1662399b685b9df03758668f55a983bcd2", + "transactionHash": "0x6a363131580509010713673da815190937e2a41dd72858f82ae4b0ed6a27e9c6", "logs": [], - "blockNumber": 5814411, + "blockNumber": 5849176, "cumulativeGasUsed": "3145971", "status": 1, "byzantium": true }, "args": [ - "0xE4a96d05579a4306e19E1C36F8e6A1567c982750", - "0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83" + "0x32bB8e83F877948Db847BDB6A8DB51d441324c1F", + "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1" ], - "numDeployments": 5, - "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_weth\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"UNSAFE_swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"}],\"name\":\"getAmountsOut\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reserveA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"pairFor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"}],\"name\":\"quoteAddLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"name\":\"quoteRemoveLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityETHWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"}],\"name\":\"sortTokens\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactETHForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForETH\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenFrom\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenTo\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokensSimple\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weth\",\"outputs\":[{\"internalType\":\"contract IWETH\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Router.sol\":\"Router\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Router.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairFactory.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\nimport \\\"contracts/interfaces/IWETH.sol\\\";\\n\\ncontract Router is IRouter {\\n struct route {\\n address from;\\n address to;\\n bool stable;\\n }\\n\\n address public immutable factory;\\n IWETH public immutable weth;\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n bytes32 immutable pairCodeHash;\\n\\n modifier ensure(uint256 deadline) {\\n require(deadline >= block.timestamp, \\\"Router: EXPIRED\\\");\\n _;\\n }\\n\\n constructor(address _factory, address _weth) {\\n factory = _factory;\\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\\n weth = IWETH(_weth);\\n }\\n\\n receive() external payable {\\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\\n }\\n\\n function sortTokens(address tokenA, address tokenB)\\n public\\n pure\\n returns (address token0, address token1)\\n {\\n require(tokenA != tokenB, \\\"Router: IDENTICAL_ADDRESSES\\\");\\n (token0, token1) = tokenA < tokenB\\n ? (tokenA, tokenB)\\n : (tokenB, tokenA);\\n require(token0 != address(0), \\\"Router: ZERO_ADDRESS\\\");\\n }\\n\\n // calculates the CREATE2 address for a pair without making any external calls\\n function pairFor(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (address pair) {\\n (address token0, address token1) = sortTokens(tokenA, tokenB);\\n pair = address(\\n uint160(\\n uint256(\\n keccak256(\\n abi.encodePacked(\\n hex\\\"ff\\\",\\n factory,\\n keccak256(abi.encodePacked(token0, token1, stable)),\\n pairCodeHash // init code hash\\n )\\n )\\n )\\n )\\n );\\n }\\n\\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\\n function quoteLiquidity(\\n uint256 amountA,\\n uint256 reserveA,\\n uint256 reserveB\\n ) internal pure returns (uint256 amountB) {\\n require(amountA > 0, \\\"Router: INSUFFICIENT_AMOUNT\\\");\\n require(reserveA > 0 && reserveB > 0, \\\"Router: INSUFFICIENT_LIQUIDITY\\\");\\n amountB = (amountA * reserveB) / reserveA;\\n }\\n\\n // fetches and sorts the reserves for a pair\\n function getReserves(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (uint256 reserveA, uint256 reserveB) {\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (uint256 reserve0, uint256 reserve1, ) = IPair(\\n pairFor(tokenA, tokenB, stable)\\n ).getReserves();\\n (reserveA, reserveB) = tokenA == token0\\n ? (reserve0, reserve1)\\n : (reserve1, reserve0);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n address tokenOut\\n ) external view returns (uint256 amount, bool stable) {\\n address pair = pairFor(tokenIn, tokenOut, true);\\n uint256 amountStable;\\n uint256 amountVolatile;\\n if (IPairFactory(factory).isPair(pair)) {\\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n pair = pairFor(tokenIn, tokenOut, false);\\n if (IPairFactory(factory).isPair(pair)) {\\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n return\\n amountStable > amountVolatile\\n ? (amountStable, true)\\n : (amountVolatile, false);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountsOut(uint256 amountIn, route[] memory routes)\\n public\\n view\\n returns (uint256[] memory amounts)\\n {\\n require(routes.length >= 1, \\\"Router: INVALID_PATH\\\");\\n amounts = new uint256[](routes.length + 1);\\n amounts[0] = amountIn;\\n for (uint256 i = 0; i < routes.length; i++) {\\n address pair = pairFor(\\n routes[i].from,\\n routes[i].to,\\n routes[i].stable\\n );\\n if (IPairFactory(factory).isPair(pair)) {\\n amounts[i + 1] = IPair(pair).getAmountOut(\\n amounts[i],\\n routes[i].from\\n );\\n }\\n }\\n }\\n\\n function isPair(address pair) external view returns (bool) {\\n return IPairFactory(factory).isPair(pair);\\n }\\n\\n function quoteAddLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired\\n )\\n external\\n view\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n (uint256 reserveA, uint256 reserveB) = (0, 0);\\n uint256 _totalSupply = 0;\\n if (_pair != address(0)) {\\n _totalSupply = IERC20(_pair).totalSupply();\\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\\n }\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n }\\n }\\n }\\n\\n function quoteRemoveLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity\\n ) external view returns (uint256 amountA, uint256 amountB) {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n\\n if (_pair == address(0)) {\\n return (0, 0);\\n }\\n\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n uint256 _totalSupply = IERC20(_pair).totalSupply();\\n\\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\\n }\\n\\n function _addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin\\n ) internal returns (uint256 amountA, uint256 amountB) {\\n require(amountADesired >= amountAMin);\\n require(amountBDesired >= amountBMin);\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n if (_pair == address(0)) {\\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\\n }\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n require(\\n amountBOptimal >= amountBMin,\\n \\\"Router: INSUFFICIENT_B_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n assert(amountAOptimal <= amountADesired);\\n require(\\n amountAOptimal >= amountAMin,\\n \\\"Router: INSUFFICIENT_A_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n }\\n }\\n }\\n\\n function addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n ensure(deadline)\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n (amountA, amountB) = _addLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n amountADesired,\\n amountBDesired,\\n amountAMin,\\n amountBMin\\n );\\n address pair = pairFor(tokenA, tokenB, stable);\\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\\n liquidity = IPair(pair).mint(to);\\n }\\n\\n function addLiquidityETH(\\n address token,\\n bool stable,\\n uint256 amountTokenDesired,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n payable\\n ensure(deadline)\\n returns (\\n uint256 amountToken,\\n uint256 amountETH,\\n uint256 liquidity\\n )\\n {\\n (amountToken, amountETH) = _addLiquidity(\\n token,\\n address(weth),\\n stable,\\n amountTokenDesired,\\n msg.value,\\n amountTokenMin,\\n amountETHMin\\n );\\n address pair = pairFor(token, address(weth), stable);\\n _safeTransferFrom(token, msg.sender, pair, amountToken);\\n weth.deposit{value: amountETH}();\\n assert(weth.transfer(pair, amountETH));\\n liquidity = IPair(pair).mint(to);\\n // refund dust eth, if any\\n if (msg.value > amountETH)\\n _safeTransferETH(msg.sender, msg.value - amountETH);\\n }\\n\\n // **** REMOVE LIQUIDITY ****\\n function removeLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (amountA, amountB) = tokenA == token0\\n ? (amount0, amount1)\\n : (amount1, amount0);\\n require(amountA >= amountAMin, \\\"Router: INSUFFICIENT_A_AMOUNT\\\");\\n require(amountB >= amountBMin, \\\"Router: INSUFFICIENT_B_AMOUNT\\\");\\n }\\n\\n function removeLiquidityETH(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\\n (amountToken, amountETH) = removeLiquidity(\\n token,\\n address(weth),\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n address(this),\\n deadline\\n );\\n _safeTransfer(token, to, amountToken);\\n weth.withdraw(amountETH);\\n _safeTransferETH(to, amountETH);\\n }\\n\\n function removeLiquidityWithPermit(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n {\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(\\n msg.sender,\\n address(this),\\n value,\\n deadline,\\n v,\\n r,\\n s\\n );\\n }\\n\\n (amountA, amountB) = removeLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n liquidity,\\n amountAMin,\\n amountBMin,\\n to,\\n deadline\\n );\\n }\\n\\n function removeLiquidityETHWithPermit(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountToken, uint256 amountETH) {\\n address pair = pairFor(token, address(weth), stable);\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\\n (amountToken, amountETH) = removeLiquidityETH(\\n token,\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n to,\\n deadline\\n );\\n }\\n\\n // **** SWAP ****\\n // requires the initial amount to have already been sent to the first pair\\n function _swap(\\n uint256[] memory amounts,\\n route[] memory routes,\\n address _to\\n ) internal virtual {\\n for (uint256 i = 0; i < routes.length; i++) {\\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\\n uint256 amountOut = amounts[i + 1];\\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\\n ? (uint256(0), amountOut)\\n : (amountOut, uint256(0));\\n address to = i < routes.length - 1\\n ? pairFor(\\n routes[i + 1].from,\\n routes[i + 1].to,\\n routes[i + 1].stable\\n )\\n : _to;\\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\\n amount0Out,\\n amount1Out,\\n to,\\n new bytes(0)\\n );\\n }\\n }\\n\\n function swapExactTokensForTokensSimple(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n address tokenFrom,\\n address tokenTo,\\n bool stable,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n route[] memory routes = new route[](1);\\n routes[0].from = tokenFrom;\\n routes[0].to = tokenTo;\\n routes[0].stable = stable;\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForTokens(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactETHForTokens(\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\\n require(routes[0].from == address(weth), \\\"Router: INVALID_PATH\\\");\\n amounts = getAmountsOut(msg.value, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n weth.deposit{value: amounts[0]}();\\n assert(\\n weth.transfer(\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n )\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForETH(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n require(\\n routes[routes.length - 1].to == address(weth),\\n \\\"Router: INVALID_PATH\\\"\\n );\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, address(this));\\n weth.withdraw(amounts[amounts.length - 1]);\\n _safeTransferETH(to, amounts[amounts.length - 1]);\\n }\\n\\n function UNSAFE_swapExactTokensForTokens(\\n uint256[] memory amounts,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory) {\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n return amounts;\\n }\\n\\n function _safeTransferETH(address to, uint256 value) internal {\\n (bool success, ) = to.call{value: value}(new bytes(0));\\n require(success, \\\"TransferHelper: ETH_TRANSFER_FAILED\\\");\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x3d84c846129d645eec66c37a493bb7fb401a2524497f450eaced155088305ead\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"},\"contracts/interfaces/IWETH.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n function transfer(address to, uint256 value) external returns (bool);\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0x20ad0b3a319a36e3430f0d8512ee3755de8f85a80effe78d06f333f5326ee3d7\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x60e06040523480156200001157600080fd5b50604051620039bc380380620039bc8339810160408190526200003491620000d8565b6001600160a01b038216608081905260408051631355724960e31b81529051639aab9248916004808201926020929091908290030181865afa1580156200007f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000a5919062000110565b60c0526001600160a01b031660a052506200012a565b80516001600160a01b0381168114620000d357600080fd5b919050565b60008060408385031215620000ec57600080fd5b620000f783620000bb565b91506200010760208401620000bb565b90509250929050565b6000602082840312156200012357600080fd5b5051919050565b60805160a05160c0516137c8620001f46000396000610ef901526000818161013e0152818161020b0152818161091901528181610b5801528181610da901528181611470015281816115830152818161161101528181611de901528181611e1f01528181611e5401528181611ee901528181612028015261207801526000818161042d01528181610c3e01528181610ebe015281816111770152818161128b0152818161199601528181611b0a01528181612115015281816126ff01526127a001526137c86000f3fe60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea2646970667358221220409357aa500e4ad5c5df258cdff4526c8b9ff8fedf890227a8ca1c5c4c6ea9d964736f6c634300080d0033", - "deployedBytecode": "0x60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea2646970667358221220409357aa500e4ad5c5df258cdff4526c8b9ff8fedf890227a8ca1c5c4c6ea9d964736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_weth\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"UNSAFE_swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"}],\"name\":\"getAmountsOut\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reserveA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"pairFor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"}],\"name\":\"quoteAddLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"name\":\"quoteRemoveLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityETHWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"}],\"name\":\"sortTokens\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactETHForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForETH\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenFrom\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenTo\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokensSimple\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weth\",\"outputs\":[{\"internalType\":\"contract IWETH\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Router.sol\":\"Router\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Router.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairFactory.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\nimport \\\"contracts/interfaces/IWETH.sol\\\";\\n\\ncontract Router is IRouter {\\n struct route {\\n address from;\\n address to;\\n bool stable;\\n }\\n\\n address public immutable factory;\\n IWETH public immutable weth;\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n bytes32 immutable pairCodeHash;\\n\\n modifier ensure(uint256 deadline) {\\n require(deadline >= block.timestamp, \\\"Router: EXPIRED\\\");\\n _;\\n }\\n\\n constructor(address _factory, address _weth) {\\n factory = _factory;\\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\\n weth = IWETH(_weth);\\n }\\n\\n receive() external payable {\\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\\n }\\n\\n function sortTokens(address tokenA, address tokenB)\\n public\\n pure\\n returns (address token0, address token1)\\n {\\n require(tokenA != tokenB, \\\"Router: IDENTICAL_ADDRESSES\\\");\\n (token0, token1) = tokenA < tokenB\\n ? (tokenA, tokenB)\\n : (tokenB, tokenA);\\n require(token0 != address(0), \\\"Router: ZERO_ADDRESS\\\");\\n }\\n\\n // calculates the CREATE2 address for a pair without making any external calls\\n function pairFor(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (address pair) {\\n (address token0, address token1) = sortTokens(tokenA, tokenB);\\n pair = address(\\n uint160(\\n uint256(\\n keccak256(\\n abi.encodePacked(\\n hex\\\"ff\\\",\\n factory,\\n keccak256(abi.encodePacked(token0, token1, stable)),\\n pairCodeHash // init code hash\\n )\\n )\\n )\\n )\\n );\\n }\\n\\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\\n function quoteLiquidity(\\n uint256 amountA,\\n uint256 reserveA,\\n uint256 reserveB\\n ) internal pure returns (uint256 amountB) {\\n require(amountA > 0, \\\"Router: INSUFFICIENT_AMOUNT\\\");\\n require(reserveA > 0 && reserveB > 0, \\\"Router: INSUFFICIENT_LIQUIDITY\\\");\\n amountB = (amountA * reserveB) / reserveA;\\n }\\n\\n // fetches and sorts the reserves for a pair\\n function getReserves(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (uint256 reserveA, uint256 reserveB) {\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (uint256 reserve0, uint256 reserve1, ) = IPair(\\n pairFor(tokenA, tokenB, stable)\\n ).getReserves();\\n (reserveA, reserveB) = tokenA == token0\\n ? (reserve0, reserve1)\\n : (reserve1, reserve0);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n address tokenOut\\n ) external view returns (uint256 amount, bool stable) {\\n address pair = pairFor(tokenIn, tokenOut, true);\\n uint256 amountStable;\\n uint256 amountVolatile;\\n if (IPairFactory(factory).isPair(pair)) {\\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n pair = pairFor(tokenIn, tokenOut, false);\\n if (IPairFactory(factory).isPair(pair)) {\\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n return\\n amountStable > amountVolatile\\n ? (amountStable, true)\\n : (amountVolatile, false);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountsOut(uint256 amountIn, route[] memory routes)\\n public\\n view\\n returns (uint256[] memory amounts)\\n {\\n require(routes.length >= 1, \\\"Router: INVALID_PATH\\\");\\n amounts = new uint256[](routes.length + 1);\\n amounts[0] = amountIn;\\n for (uint256 i = 0; i < routes.length; i++) {\\n address pair = pairFor(\\n routes[i].from,\\n routes[i].to,\\n routes[i].stable\\n );\\n if (IPairFactory(factory).isPair(pair)) {\\n amounts[i + 1] = IPair(pair).getAmountOut(\\n amounts[i],\\n routes[i].from\\n );\\n }\\n }\\n }\\n\\n function isPair(address pair) external view returns (bool) {\\n return IPairFactory(factory).isPair(pair);\\n }\\n\\n function quoteAddLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired\\n )\\n external\\n view\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n (uint256 reserveA, uint256 reserveB) = (0, 0);\\n uint256 _totalSupply = 0;\\n if (_pair != address(0)) {\\n _totalSupply = IERC20(_pair).totalSupply();\\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\\n }\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n }\\n }\\n }\\n\\n function quoteRemoveLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity\\n ) external view returns (uint256 amountA, uint256 amountB) {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n\\n if (_pair == address(0)) {\\n return (0, 0);\\n }\\n\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n uint256 _totalSupply = IERC20(_pair).totalSupply();\\n\\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\\n }\\n\\n function _addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin\\n ) internal returns (uint256 amountA, uint256 amountB) {\\n require(amountADesired >= amountAMin);\\n require(amountBDesired >= amountBMin);\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n if (_pair == address(0)) {\\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\\n }\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n require(\\n amountBOptimal >= amountBMin,\\n \\\"Router: INSUFFICIENT_B_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n assert(amountAOptimal <= amountADesired);\\n require(\\n amountAOptimal >= amountAMin,\\n \\\"Router: INSUFFICIENT_A_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n }\\n }\\n }\\n\\n function addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n ensure(deadline)\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n (amountA, amountB) = _addLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n amountADesired,\\n amountBDesired,\\n amountAMin,\\n amountBMin\\n );\\n address pair = pairFor(tokenA, tokenB, stable);\\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\\n liquidity = IPair(pair).mint(to);\\n }\\n\\n function addLiquidityETH(\\n address token,\\n bool stable,\\n uint256 amountTokenDesired,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n payable\\n ensure(deadline)\\n returns (\\n uint256 amountToken,\\n uint256 amountETH,\\n uint256 liquidity\\n )\\n {\\n (amountToken, amountETH) = _addLiquidity(\\n token,\\n address(weth),\\n stable,\\n amountTokenDesired,\\n msg.value,\\n amountTokenMin,\\n amountETHMin\\n );\\n address pair = pairFor(token, address(weth), stable);\\n _safeTransferFrom(token, msg.sender, pair, amountToken);\\n weth.deposit{value: amountETH}();\\n assert(weth.transfer(pair, amountETH));\\n liquidity = IPair(pair).mint(to);\\n // refund dust eth, if any\\n if (msg.value > amountETH)\\n _safeTransferETH(msg.sender, msg.value - amountETH);\\n }\\n\\n // **** REMOVE LIQUIDITY ****\\n function removeLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (amountA, amountB) = tokenA == token0\\n ? (amount0, amount1)\\n : (amount1, amount0);\\n require(amountA >= amountAMin, \\\"Router: INSUFFICIENT_A_AMOUNT\\\");\\n require(amountB >= amountBMin, \\\"Router: INSUFFICIENT_B_AMOUNT\\\");\\n }\\n\\n function removeLiquidityETH(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\\n (amountToken, amountETH) = removeLiquidity(\\n token,\\n address(weth),\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n address(this),\\n deadline\\n );\\n _safeTransfer(token, to, amountToken);\\n weth.withdraw(amountETH);\\n _safeTransferETH(to, amountETH);\\n }\\n\\n function removeLiquidityWithPermit(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n {\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(\\n msg.sender,\\n address(this),\\n value,\\n deadline,\\n v,\\n r,\\n s\\n );\\n }\\n\\n (amountA, amountB) = removeLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n liquidity,\\n amountAMin,\\n amountBMin,\\n to,\\n deadline\\n );\\n }\\n\\n function removeLiquidityETHWithPermit(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountToken, uint256 amountETH) {\\n address pair = pairFor(token, address(weth), stable);\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\\n (amountToken, amountETH) = removeLiquidityETH(\\n token,\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n to,\\n deadline\\n );\\n }\\n\\n // **** SWAP ****\\n // requires the initial amount to have already been sent to the first pair\\n function _swap(\\n uint256[] memory amounts,\\n route[] memory routes,\\n address _to\\n ) internal virtual {\\n for (uint256 i = 0; i < routes.length; i++) {\\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\\n uint256 amountOut = amounts[i + 1];\\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\\n ? (uint256(0), amountOut)\\n : (amountOut, uint256(0));\\n address to = i < routes.length - 1\\n ? pairFor(\\n routes[i + 1].from,\\n routes[i + 1].to,\\n routes[i + 1].stable\\n )\\n : _to;\\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\\n amount0Out,\\n amount1Out,\\n to,\\n new bytes(0)\\n );\\n }\\n }\\n\\n function swapExactTokensForTokensSimple(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n address tokenFrom,\\n address tokenTo,\\n bool stable,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n route[] memory routes = new route[](1);\\n routes[0].from = tokenFrom;\\n routes[0].to = tokenTo;\\n routes[0].stable = stable;\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForTokens(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactETHForTokens(\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\\n require(routes[0].from == address(weth), \\\"Router: INVALID_PATH\\\");\\n amounts = getAmountsOut(msg.value, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n weth.deposit{value: amounts[0]}();\\n assert(\\n weth.transfer(\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n )\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForETH(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n require(\\n routes[routes.length - 1].to == address(weth),\\n \\\"Router: INVALID_PATH\\\"\\n );\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, address(this));\\n weth.withdraw(amounts[amounts.length - 1]);\\n _safeTransferETH(to, amounts[amounts.length - 1]);\\n }\\n\\n function UNSAFE_swapExactTokensForTokens(\\n uint256[] memory amounts,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory) {\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n return amounts;\\n }\\n\\n function _safeTransferETH(address to, uint256 value) internal {\\n (bool success, ) = to.call{value: value}(new bytes(0));\\n require(success, \\\"TransferHelper: ETH_TRANSFER_FAILED\\\");\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x3d84c846129d645eec66c37a493bb7fb401a2524497f450eaced155088305ead\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"},\"contracts/interfaces/IWETH.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n function transfer(address to, uint256 value) external returns (bool);\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0x20ad0b3a319a36e3430f0d8512ee3755de8f85a80effe78d06f333f5326ee3d7\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x60e06040523480156200001157600080fd5b50604051620039bc380380620039bc8339810160408190526200003491620000d8565b6001600160a01b038216608081905260408051631355724960e31b81529051639aab9248916004808201926020929091908290030181865afa1580156200007f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000a5919062000110565b60c0526001600160a01b031660a052506200012a565b80516001600160a01b0381168114620000d357600080fd5b919050565b60008060408385031215620000ec57600080fd5b620000f783620000bb565b91506200010760208401620000bb565b90509250929050565b6000602082840312156200012357600080fd5b5051919050565b60805160a05160c0516137c8620001f46000396000610ef901526000818161013e0152818161020b0152818161091901528181610b5801528181610da901528181611470015281816115830152818161161101528181611de901528181611e1f01528181611e5401528181611ee901528181612028015261207801526000818161042d01528181610c3e01528181610ebe015281816111770152818161128b0152818161199601528181611b0a01528181612115015281816126ff01526127a001526137c86000f3fe60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea264697066735822122090d96761dbb6e8825206a0750dfd27f72cd188ce3d6549fa2db5061a5beacc4464736f6c634300080d0033", + "deployedBytecode": "0x60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea264697066735822122090d96761dbb6e8825206a0750dfd27f72cd188ce3d6549fa2db5061a5beacc4464736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/VeArtProxy.json b/deployments/arbitrumGoerli/VeArtProxy.json index 27792c1c..ccc1185c 100644 --- a/deployments/arbitrumGoerli/VeArtProxy.json +++ b/deployments/arbitrumGoerli/VeArtProxy.json @@ -1,5 +1,5 @@ { - "address": "0xfC27470547FA0b96D19146C0490cc444a18A71a9", + "address": "0x053238ccA3E4A334D97c424567C9Add44259cd18", "abi": [ { "inputs": [ @@ -36,28 +36,28 @@ "type": "function" } ], - "transactionHash": "0xcc3e7c5e17dc740d5fcfc82647d4216ced66ebd4bde18bfe153d6e2cb4359c39", + "transactionHash": "0xa1ddf1f3ba03745972958eb09e0dff912cc5efa57b876052dcf64f7e54f32af0", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xfC27470547FA0b96D19146C0490cc444a18A71a9", + "contractAddress": "0x053238ccA3E4A334D97c424567C9Add44259cd18", "transactionIndex": 1, - "gasUsed": "615428", + "gasUsed": "615440", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x3347a930d9e57684ba326a35e06d296d30ed8ad1e9e06f99505184d5d7f24ed2", - "transactionHash": "0xcc3e7c5e17dc740d5fcfc82647d4216ced66ebd4bde18bfe153d6e2cb4359c39", + "blockHash": "0xcc29349c8ad111720e036eb710cd2fa2c9079ae1d8a862e98a3aba834e26803f", + "transactionHash": "0xa1ddf1f3ba03745972958eb09e0dff912cc5efa57b876052dcf64f7e54f32af0", "logs": [], - "blockNumber": 5814426, - "cumulativeGasUsed": "615428", + "blockNumber": 5849198, + "cumulativeGasUsed": "615440", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 5, - "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_locked_end\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"_tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"output\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VeArtProxy.sol\":\"VeArtProxy\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\nimport {Base64} from \\\"contracts/libraries/Base64.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\n\\ncontract VeArtProxy is IVeArtProxy {\\n function toString(uint value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT license\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint temp = value;\\n uint digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\\n output = '';\\n output = string(abi.encodePacked(output, \\\"token \\\", toString(_tokenId), ''));\\n output = string(abi.encodePacked(output, \\\"balanceOf \\\", toString(_balanceOf), ''));\\n output = string(abi.encodePacked(output, \\\"locked_end \\\", toString(_locked_end), ''));\\n output = string(abi.encodePacked(output, \\\"value \\\", toString(_value), ''));\\n\\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\\\"name\\\": \\\"lock #', toString(_tokenId), '\\\", \\\"description\\\": \\\"Velocimeter locks, can be used to boost gauge yields, vote on token emission, and receive bribes\\\", \\\"image\\\": \\\"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\\\"}'))));\\n output = string(abi.encodePacked('data:application/json;base64,', json));\\n }\\n}\\n\",\"keccak256\":\"0xc526ae7232c93412d664837d1171f1bf5d231a4ea33bcc7a8d0b4e3fa6a9e227\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/libraries/Base64.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n/// [MIT License]\\n/// @title Base64\\n/// @notice Provides a function for encoding some bytes in base64\\n/// @author Brecht Devos \\nlibrary Base64 {\\n bytes internal constant TABLE = \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\";\\n\\n /// @notice Encodes some bytes to the base64 representation\\n function encode(bytes memory data) internal pure returns (string memory) {\\n uint len = data.length;\\n if (len == 0) return \\\"\\\";\\n\\n // multiply by 4/3 rounded up\\n uint encodedLen = 4 * ((len + 2) / 3);\\n\\n // Add some extra buffer at the end\\n bytes memory result = new bytes(encodedLen + 32);\\n\\n bytes memory table = TABLE;\\n\\n assembly {\\n let tablePtr := add(table, 1)\\n let resultPtr := add(result, 32)\\n\\n for {\\n let i := 0\\n } lt(i, len) {\\n\\n } {\\n i := add(i, 3)\\n let input := and(mload(add(data, i)), 0xffffff)\\n\\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\\n out := shl(224, out)\\n\\n mstore(resultPtr, out)\\n\\n resultPtr := add(resultPtr, 4)\\n }\\n\\n switch mod(len, 3)\\n case 1 {\\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\\n }\\n case 2 {\\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\\n }\\n\\n mstore(result, encodedLen)\\n }\\n\\n return string(result);\\n }\\n}\\n\",\"keccak256\":\"0x55535e1e0a14bbac370fe5f25df23aa88c678b915af53517672130f9a54f7e3e\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50610a2b806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f63696d65746572206c6010918401918201527f6f636b732c2063616e206265207573656420746f20626f6f737420676175676560308201527f207969656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c60508201527f20616e64207265636569766520627269626573222c2022696d616765223a202260708201527f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000609082015283516107718160aa840160208801610435565b61227d60f01b60aa929091019182015260ac01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220d32850b2e04daace866129af9d711d9b5045829d473d001adcabace3bd6d30c764736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f63696d65746572206c6010918401918201527f6f636b732c2063616e206265207573656420746f20626f6f737420676175676560308201527f207969656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c60508201527f20616e64207265636569766520627269626573222c2022696d616765223a202260708201527f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000609082015283516107718160aa840160208801610435565b61227d60f01b60aa929091019182015260ac01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220d32850b2e04daace866129af9d711d9b5045829d473d001adcabace3bd6d30c764736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_locked_end\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"_tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"output\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VeArtProxy.sol\":\"VeArtProxy\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\nimport {Base64} from \\\"contracts/libraries/Base64.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\n\\ncontract VeArtProxy is IVeArtProxy {\\n function toString(uint value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT license\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint temp = value;\\n uint digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\\n output = '';\\n output = string(abi.encodePacked(output, \\\"token \\\", toString(_tokenId), ''));\\n output = string(abi.encodePacked(output, \\\"balanceOf \\\", toString(_balanceOf), ''));\\n output = string(abi.encodePacked(output, \\\"locked_end \\\", toString(_locked_end), ''));\\n output = string(abi.encodePacked(output, \\\"value \\\", toString(_value), ''));\\n\\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\\\"name\\\": \\\"lock #', toString(_tokenId), '\\\", \\\"description\\\": \\\"Velocimeter locks, can be used to boost gauge yields, vote on token emission, and receive bribes\\\", \\\"image\\\": \\\"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\\\"}'))));\\n output = string(abi.encodePacked('data:application/json;base64,', json));\\n }\\n}\\n\",\"keccak256\":\"0xc526ae7232c93412d664837d1171f1bf5d231a4ea33bcc7a8d0b4e3fa6a9e227\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/libraries/Base64.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n/// [MIT License]\\n/// @title Base64\\n/// @notice Provides a function for encoding some bytes in base64\\n/// @author Brecht Devos \\nlibrary Base64 {\\n bytes internal constant TABLE = \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\";\\n\\n /// @notice Encodes some bytes to the base64 representation\\n function encode(bytes memory data) internal pure returns (string memory) {\\n uint len = data.length;\\n if (len == 0) return \\\"\\\";\\n\\n // multiply by 4/3 rounded up\\n uint encodedLen = 4 * ((len + 2) / 3);\\n\\n // Add some extra buffer at the end\\n bytes memory result = new bytes(encodedLen + 32);\\n\\n bytes memory table = TABLE;\\n\\n assembly {\\n let tablePtr := add(table, 1)\\n let resultPtr := add(result, 32)\\n\\n for {\\n let i := 0\\n } lt(i, len) {\\n\\n } {\\n i := add(i, 3)\\n let input := and(mload(add(data, i)), 0xffffff)\\n\\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\\n out := shl(224, out)\\n\\n mstore(resultPtr, out)\\n\\n resultPtr := add(resultPtr, 4)\\n }\\n\\n switch mod(len, 3)\\n case 1 {\\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\\n }\\n case 2 {\\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\\n }\\n\\n mstore(result, encodedLen)\\n }\\n\\n return string(result);\\n }\\n}\\n\",\"keccak256\":\"0x55535e1e0a14bbac370fe5f25df23aa88c678b915af53517672130f9a54f7e3e\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610a2b806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f63696d65746572206c6010918401918201527f6f636b732c2063616e206265207573656420746f20626f6f737420676175676560308201527f207969656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c60508201527f20616e64207265636569766520627269626573222c2022696d616765223a202260708201527f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000609082015283516107718160aa840160208801610435565b61227d60f01b60aa929091019182015260ac01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220e12e7c208efb5910624d3c73f85e2831968bd06a9ade7ff3b401f20786fbb8de64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f63696d65746572206c6010918401918201527f6f636b732c2063616e206265207573656420746f20626f6f737420676175676560308201527f207969656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c60508201527f20616e64207265636569766520627269626573222c2022696d616765223a202260708201527f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000609082015283516107718160aa840160208801610435565b61227d60f01b60aa929091019182015260ac01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220e12e7c208efb5910624d3c73f85e2831968bd06a9ade7ff3b401f20786fbb8de64736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/Velo.json b/deployments/arbitrumGoerli/Velo.json deleted file mode 100644 index 2efd133c..00000000 --- a/deployments/arbitrumGoerli/Velo.json +++ /dev/null @@ -1,522 +0,0 @@ -{ - "address": "0x84Ca387E7ede764A3284c67Ff8c68a305a9030a0", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "claim", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_recipient", - "type": "address" - } - ], - "name": "initialMint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "initialMinted", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "merkleClaim", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "mint", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "minter", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "redemptionReceiver", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_merkleClaim", - "type": "address" - } - ], - "name": "setMerkleClaim", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_minter", - "type": "address" - } - ], - "name": "setMinter", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_receiver", - "type": "address" - } - ], - "name": "setRedemptionReceiver", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0xbbd7f88f2b70de030ef83ee08f21e48441fa45a4d6417cfd4572bb922dac2c90", - "receipt": { - "to": null, - "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x84Ca387E7ede764A3284c67Ff8c68a305a9030a0", - "transactionIndex": 1, - "gasUsed": "560637", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000008000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000010000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000008000000000000000000004200000000000002000000000000000000000000000000000000000000000000000020000000000000000000000000080000000000000000000000000000000000000000", - "blockHash": "0x002c02bea3e5ceb325db6c195e62ae108d8a7f5b97f991cffb6d72be896c5aa7", - "transactionHash": "0xbbd7f88f2b70de030ef83ee08f21e48441fa45a4d6417cfd4572bb922dac2c90", - "logs": [ - { - "transactionIndex": 1, - "blockNumber": 4455863, - "transactionHash": "0xbbd7f88f2b70de030ef83ee08f21e48441fa45a4d6417cfd4572bb922dac2c90", - "address": "0x84Ca387E7ede764A3284c67Ff8c68a305a9030a0", - "topics": [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000053f3b51fd7f327e1ec4e6eaa3a049149cb2acad2" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000000", - "logIndex": 0, - "blockHash": "0x002c02bea3e5ceb325db6c195e62ae108d8a7f5b97f991cffb6d72be896c5aa7" - } - ], - "blockNumber": 4455863, - "cumulativeGasUsed": "560637", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 1, - "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"initialMint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialMinted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleClaim\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redemptionReceiver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_merkleClaim\",\"type\":\"address\"}],\"name\":\"setMerkleClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"setMinter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_receiver\",\"type\":\"address\"}],\"name\":\"setRedemptionReceiver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Velo.sol\":\"Velo\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Velo.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IVelo.sol\\\";\\n\\ncontract Velo is IVelo {\\n\\n string public constant name = \\\"Velodrome\\\";\\n string public constant symbol = \\\"VELO\\\";\\n uint8 public constant decimals = 18;\\n uint public totalSupply = 0;\\n\\n mapping(address => uint) public balanceOf;\\n mapping(address => mapping(address => uint)) public allowance;\\n\\n bool public initialMinted;\\n address public minter;\\n address public redemptionReceiver;\\n address public merkleClaim;\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n\\n constructor() {\\n minter = msg.sender;\\n _mint(msg.sender, 0);\\n }\\n\\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\\n function setMinter(address _minter) external {\\n require(msg.sender == minter);\\n minter = _minter;\\n }\\n\\n function setRedemptionReceiver(address _receiver) external {\\n require(msg.sender == minter);\\n redemptionReceiver = _receiver;\\n }\\n\\n function setMerkleClaim(address _merkleClaim) external {\\n require(msg.sender == minter);\\n merkleClaim = _merkleClaim;\\n }\\n\\n // Initial mint: total 82M\\n // 4M for \\\"Genesis\\\" pools\\n // 30M for liquid team allocation (40M excl init veNFT)\\n // 48M for future partners\\n function initialMint(address _recipient) external {\\n require(msg.sender == minter && !initialMinted);\\n initialMinted = true;\\n _mint(_recipient, 82 * 1e6 * 1e18);\\n }\\n\\n function approve(address _spender, uint _value) external returns (bool) {\\n allowance[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n function _mint(address _to, uint _amount) internal returns (bool) {\\n totalSupply += _amount;\\n unchecked {\\n balanceOf[_to] += _amount;\\n }\\n emit Transfer(address(0x0), _to, _amount);\\n return true;\\n }\\n\\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\\n balanceOf[_from] -= _value;\\n unchecked {\\n balanceOf[_to] += _value;\\n }\\n emit Transfer(_from, _to, _value);\\n return true;\\n }\\n\\n function transfer(address _to, uint _value) external returns (bool) {\\n return _transfer(msg.sender, _to, _value);\\n }\\n\\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\\n uint allowed_from = allowance[_from][msg.sender];\\n if (allowed_from != type(uint).max) {\\n allowance[_from][msg.sender] -= _value;\\n }\\n return _transfer(_from, _to, _value);\\n }\\n\\n function mint(address account, uint amount) external returns (bool) {\\n require(msg.sender == minter);\\n _mint(account, amount);\\n return true;\\n }\\n\\n function claim(address account, uint amount) external returns (bool) {\\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\\n _mint(account, amount);\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xb5231de79b43d576febc9d6a0ebee8c4f251ec109869ce7a3e0afc2a185d0246\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"}},\"version\":1}", - "bytecode": "0x60806040526000805534801561001457600080fd5b5060038054610100600160a81b0319163361010081029190911790915561003c906000610042565b506100d9565b60008160008082825461005591906100b3565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a350600192915050565b600082198211156100d457634e487b7160e01b600052601160045260246000fd5b500190565b61082c806100e86000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ac578063dd62ed3e146102bf578063e752c44a146102ea578063ec676a25146102fd578063fca3b5aa1461031057600080fd5b806395d89b4114610241578063a9059cbb14610264578063aad3ec9614610277578063c268f9ba1461028a578063ca1c4de91461029f57600080fd5b806323b872dd116100f457806323b872dd146101ce578063313ce567146101e157806340c10f19146101fb5780635e05fe501461020e57806370a082311461022157600080fd5b806306fdde03146101265780630754617214610164578063095ea7b31461019457806318160ddd146101b7575b600080fd5b61014e6040518060400160405280600981526020016856656c6f64726f6d6560b81b81525081565b60405161015b919061068c565b60405180910390f35b60035461017c9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015b565b6101a76101a23660046106fd565b610323565b604051901515815260200161015b565b6101c060005481565b60405190815260200161015b565b6101a76101dc366004610727565b61038f565b6101e9601281565b60405160ff909116815260200161015b565b6101a76102093660046106fd565b610409565b60045461017c906001600160a01b031681565b6101c061022f366004610763565b60016020526000908152604090205481565b61014e6040518060400160405280600481526020016356454c4f60e01b81525081565b6101a76102723660046106fd565b61043c565b6101a76102853660046106fd565b610450565b61029d610298366004610763565b61047f565b005b6003546101a79060ff1681565b61029d6102ba366004610763565b6104d0565b6101c06102cd36600461077e565b600260209081526000928352604080842090915290825290205481565b60055461017c906001600160a01b031681565b61029d61030b366004610763565b61050e565b61029d61031e366004610763565b61054c565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259061037e9086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f5576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103ef9084906107c7565b90915550505b610400858585610590565b95945050505050565b60035460009061010090046001600160a01b0316331461042857600080fd5b6104328383610627565b5060019392505050565b6000610449338484610590565b9392505050565b6004546000906001600160a01b031633148061047657506005546001600160a01b031633145b61042857600080fd5b60035461010090046001600160a01b0316331480156104a1575060035460ff16155b6104aa57600080fd5b6003805460ff191660011790556104cc816a43d42ce83da41d92000000610627565b5050565b60035461010090046001600160a01b031633146104ec57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052a57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056857600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105ba9084906107c7565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106159086815260200190565b60405180910390a35060019392505050565b60008160008082825461063a91906107de565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910161037e565b600060208083528351808285015260005b818110156106b95785810183015185820160400152820161069d565b818111156106cb576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106f857600080fd5b919050565b6000806040838503121561071057600080fd5b610719836106e1565b946020939093013593505050565b60008060006060848603121561073c57600080fd5b610745846106e1565b9250610753602085016106e1565b9150604084013590509250925092565b60006020828403121561077557600080fd5b610449826106e1565b6000806040838503121561079157600080fd5b61079a836106e1565b91506107a8602084016106e1565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107d9576107d96107b1565b500390565b600082198211156107f1576107f16107b1565b50019056fea26469706673582212205c10bf292220f7b70a6a720da510bc53600c2c817ee2a5030f9ab74b3a2a711364736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ac578063dd62ed3e146102bf578063e752c44a146102ea578063ec676a25146102fd578063fca3b5aa1461031057600080fd5b806395d89b4114610241578063a9059cbb14610264578063aad3ec9614610277578063c268f9ba1461028a578063ca1c4de91461029f57600080fd5b806323b872dd116100f457806323b872dd146101ce578063313ce567146101e157806340c10f19146101fb5780635e05fe501461020e57806370a082311461022157600080fd5b806306fdde03146101265780630754617214610164578063095ea7b31461019457806318160ddd146101b7575b600080fd5b61014e6040518060400160405280600981526020016856656c6f64726f6d6560b81b81525081565b60405161015b919061068c565b60405180910390f35b60035461017c9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015b565b6101a76101a23660046106fd565b610323565b604051901515815260200161015b565b6101c060005481565b60405190815260200161015b565b6101a76101dc366004610727565b61038f565b6101e9601281565b60405160ff909116815260200161015b565b6101a76102093660046106fd565b610409565b60045461017c906001600160a01b031681565b6101c061022f366004610763565b60016020526000908152604090205481565b61014e6040518060400160405280600481526020016356454c4f60e01b81525081565b6101a76102723660046106fd565b61043c565b6101a76102853660046106fd565b610450565b61029d610298366004610763565b61047f565b005b6003546101a79060ff1681565b61029d6102ba366004610763565b6104d0565b6101c06102cd36600461077e565b600260209081526000928352604080842090915290825290205481565b60055461017c906001600160a01b031681565b61029d61030b366004610763565b61050e565b61029d61031e366004610763565b61054c565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259061037e9086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f5576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103ef9084906107c7565b90915550505b610400858585610590565b95945050505050565b60035460009061010090046001600160a01b0316331461042857600080fd5b6104328383610627565b5060019392505050565b6000610449338484610590565b9392505050565b6004546000906001600160a01b031633148061047657506005546001600160a01b031633145b61042857600080fd5b60035461010090046001600160a01b0316331480156104a1575060035460ff16155b6104aa57600080fd5b6003805460ff191660011790556104cc816a43d42ce83da41d92000000610627565b5050565b60035461010090046001600160a01b031633146104ec57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052a57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056857600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105ba9084906107c7565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106159086815260200190565b60405180910390a35060019392505050565b60008160008082825461063a91906107de565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910161037e565b600060208083528351808285015260005b818110156106b95785810183015185820160400152820161069d565b818111156106cb576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106f857600080fd5b919050565b6000806040838503121561071057600080fd5b610719836106e1565b946020939093013593505050565b60008060006060848603121561073c57600080fd5b610745846106e1565b9250610753602085016106e1565b9150604084013590509250925092565b60006020828403121561077557600080fd5b610449826106e1565b6000806040838503121561079157600080fd5b61079a836106e1565b91506107a8602084016106e1565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107d9576107d96107b1565b500390565b600082198211156107f1576107f16107b1565b50019056fea26469706673582212205c10bf292220f7b70a6a720da510bc53600c2c817ee2a5030f9ab74b3a2a711364736f6c634300080d0033", - "devdoc": { - "kind": "dev", - "methods": {}, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": {}, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 13061, - "contract": "contracts/Velo.sol:Velo", - "label": "totalSupply", - "offset": 0, - "slot": "0", - "type": "t_uint256" - }, - { - "astId": 13065, - "contract": "contracts/Velo.sol:Velo", - "label": "balanceOf", - "offset": 0, - "slot": "1", - "type": "t_mapping(t_address,t_uint256)" - }, - { - "astId": 13071, - "contract": "contracts/Velo.sol:Velo", - "label": "allowance", - "offset": 0, - "slot": "2", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" - }, - { - "astId": 13073, - "contract": "contracts/Velo.sol:Velo", - "label": "initialMinted", - "offset": 0, - "slot": "3", - "type": "t_bool" - }, - { - "astId": 13075, - "contract": "contracts/Velo.sol:Velo", - "label": "minter", - "offset": 1, - "slot": "3", - "type": "t_address" - }, - { - "astId": 13077, - "contract": "contracts/Velo.sol:Velo", - "label": "redemptionReceiver", - "offset": 0, - "slot": "4", - "type": "t_address" - }, - { - "astId": 13079, - "contract": "contracts/Velo.sol:Velo", - "label": "merkleClaim", - "offset": 0, - "slot": "5", - "type": "t_address" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_mapping(t_address,t_mapping(t_address,t_uint256))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(address => uint256))", - "numberOfBytes": "32", - "value": "t_mapping(t_address,t_uint256)" - }, - "t_mapping(t_address,t_uint256)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/VeloGovernor.json b/deployments/arbitrumGoerli/VeloGovernor.json deleted file mode 100644 index 3fe08805..00000000 --- a/deployments/arbitrumGoerli/VeloGovernor.json +++ /dev/null @@ -1,1459 +0,0 @@ -{ - "address": "0x02b7Ed5Bb16ed471C281ab2E34CC41f94aF53651", - "abi": [ - { - "inputs": [ - { - "internalType": "contract IVotes", - "name": "_ve", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "Empty", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" - } - ], - "name": "ProposalCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "proposer", - "type": "address" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "targets", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "values", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "string[]", - "name": "signatures", - "type": "string[]" - }, - { - "indexed": false, - "internalType": "bytes[]", - "name": "calldatas", - "type": "bytes[]" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startBlock", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "endBlock", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "string", - "name": "description", - "type": "string" - } - ], - "name": "ProposalCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" - } - ], - "name": "ProposalExecuted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldQuorumNumerator", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newQuorumNumerator", - "type": "uint256" - } - ], - "name": "QuorumNumeratorUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "voter", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "support", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "weight", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "string", - "name": "reason", - "type": "string" - } - ], - "name": "VoteCast", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "voter", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "support", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "weight", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "string", - "name": "reason", - "type": "string" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "params", - "type": "bytes" - } - ], - "name": "VoteCastWithParams", - "type": "event" - }, - { - "inputs": [], - "name": "BALLOT_TYPEHASH", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "COUNTING_MODE", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "EXTENDED_BALLOT_TYPEHASH", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_PROPOSAL_NUMERATOR", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PROPOSAL_DENOMINATOR", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "support", - "type": "uint8" - } - ], - "name": "castVote", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "support", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "name": "castVoteBySig", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "support", - "type": "uint8" - }, - { - "internalType": "string", - "name": "reason", - "type": "string" - } - ], - "name": "castVoteWithReason", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "support", - "type": "uint8" - }, - { - "internalType": "string", - "name": "reason", - "type": "string" - }, - { - "internalType": "bytes", - "name": "params", - "type": "bytes" - } - ], - "name": "castVoteWithReasonAndParams", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "support", - "type": "uint8" - }, - { - "internalType": "string", - "name": "reason", - "type": "string" - }, - { - "internalType": "bytes", - "name": "params", - "type": "bytes" - }, - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "name": "castVoteWithReasonAndParamsBySig", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "targets", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "values", - "type": "uint256[]" - }, - { - "internalType": "bytes[]", - "name": "calldatas", - "type": "bytes[]" - }, - { - "internalType": "bytes32", - "name": "descriptionHash", - "type": "bytes32" - } - ], - "name": "execute", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "blockTimestamp", - "type": "uint256" - } - ], - "name": "getVotes", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "blockTimestamp", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "params", - "type": "bytes" - } - ], - "name": "getVotesWithParams", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "hasVoted", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "targets", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "values", - "type": "uint256[]" - }, - { - "internalType": "bytes[]", - "name": "calldatas", - "type": "bytes[]" - }, - { - "internalType": "bytes32", - "name": "descriptionHash", - "type": "bytes32" - } - ], - "name": "hashProposal", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "onERC1155BatchReceived", - "outputs": [ - { - "internalType": "bytes4", - "name": "", - "type": "bytes4" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "onERC1155Received", - "outputs": [ - { - "internalType": "bytes4", - "name": "", - "type": "bytes4" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "onERC721Received", - "outputs": [ - { - "internalType": "bytes4", - "name": "", - "type": "bytes4" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" - } - ], - "name": "proposalDeadline", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "proposalNumerator", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" - } - ], - "name": "proposalSnapshot", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "proposalThreshold", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" - } - ], - "name": "proposalVotes", - "outputs": [ - { - "internalType": "uint256", - "name": "againstVotes", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "forVotes", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "abstainVotes", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "targets", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "values", - "type": "uint256[]" - }, - { - "internalType": "bytes[]", - "name": "calldatas", - "type": "bytes[]" - }, - { - "internalType": "string", - "name": "description", - "type": "string" - } - ], - "name": "propose", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "blockTimestamp", - "type": "uint256" - } - ], - "name": "quorum", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "quorumDenominator", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "quorumNumerator", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "relay", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "numerator", - "type": "uint256" - } - ], - "name": "setProposalNumerator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newTeam", - "type": "address" - } - ], - "name": "setTeam", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" - } - ], - "name": "state", - "outputs": [ - { - "internalType": "enum IGovernor.ProposalState", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "team", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "token", - "outputs": [ - { - "internalType": "contract IVotes", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "newQuorumNumerator", - "type": "uint256" - } - ], - "name": "updateQuorumNumerator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "votingDelay", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "votingPeriod", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "transactionHash": "0x0a1bdcff96c4c1b114f8350524da9927872c969605440d290bd00cb57718a144", - "receipt": { - "to": null, - "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x02b7Ed5Bb16ed471C281ab2E34CC41f94aF53651", - "transactionIndex": 1, - "gasUsed": "2742890", - "logsBloom": "0x00000000000000000100000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000008000000000000000000000000000000000000000000000000000000000000020000000080000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x5c6dc00c3df8bf4a0f368dad2c1a298cae0fe0376a719f184449114d2d1c80e1", - "transactionHash": "0x0a1bdcff96c4c1b114f8350524da9927872c969605440d290bd00cb57718a144", - "logs": [ - { - "transactionIndex": 1, - "blockNumber": 5814091, - "transactionHash": "0x0a1bdcff96c4c1b114f8350524da9927872c969605440d290bd00cb57718a144", - "address": "0x02b7Ed5Bb16ed471C281ab2E34CC41f94aF53651", - "topics": [ - "0x0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004", - "logIndex": 0, - "blockHash": "0x5c6dc00c3df8bf4a0f368dad2c1a298cae0fe0376a719f184449114d2d1c80e1" - } - ], - "blockNumber": 5814091, - "cumulativeGasUsed": "2742890", - "status": 1, - "byzantium": true - }, - "args": [ - "0x5EfA4BBD5BcF5D113683512483c71D37Af61942F" - ], - "numDeployments": 4, - "solcInputHash": "87c2a0284a68497703d818e47e6d0a63", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"_ve\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"Empty\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"proposer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"string[]\",\"name\":\"signatures\",\"type\":\"string[]\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"ProposalCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldQuorumNumerator\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"QuorumNumeratorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"VoteCast\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"VoteCastWithParams\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"COUNTING_MODE\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EXTENDED_BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_PROPOSAL_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROPOSAL_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"}],\"name\":\"castVote\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"castVoteWithReason\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"castVoteWithReasonAndParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteWithReasonAndParamsBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"execute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"getVotesWithParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasVoted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"hashProposal\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalDeadline\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalSnapshot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"againstVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"forVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"abstainVotes\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"propose\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"quorum\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumDenominator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"}],\"name\":\"setProposalNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTeam\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"state\",\"outputs\":[{\"internalType\":\"enum IGovernor.ProposalState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"updateQuorumNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"Empty()\":[{\"details\":\"An operation (e.g. {front}) couldn't be completed due to the queue being empty.\"}]},\"kind\":\"dev\",\"methods\":{\"COUNTING_MODE()\":{\"details\":\"See {IGovernor-COUNTING_MODE}.\"},\"castVote(uint256,uint8)\":{\"details\":\"See {IGovernor-castVote}.\"},\"castVoteBySig(uint256,uint8,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteBySig}.\"},\"castVoteWithReason(uint256,uint8,string)\":{\"details\":\"See {IGovernor-castVoteWithReason}.\"},\"castVoteWithReasonAndParams(uint256,uint8,string,bytes)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParams}.\"},\"castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParamsBySig}.\"},\"execute(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-execute}.\"},\"getVotes(address,uint256)\":{\"details\":\"See {IGovernor-getVotes}.\"},\"getVotesWithParams(address,uint256,bytes)\":{\"details\":\"See {IGovernor-getVotesWithParams}.\"},\"hasVoted(uint256,address)\":{\"details\":\"See {IGovernor-hasVoted}.\"},\"hashProposal(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-hashProposal}. The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in advance, before the proposal is submitted. Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the same proposal (with same operation and same description) will have the same id if submitted on multiple governors across multiple networks. This also means that in order to execute the same operation twice (on the same governor) the proposer will have to change the description in order to avoid proposal id conflicts.\"},\"name()\":{\"details\":\"See {IGovernor-name}.\"},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155BatchReceived}.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155Received}.\"},\"onERC721Received(address,address,uint256,bytes)\":{\"details\":\"See {IERC721Receiver-onERC721Received}.\"},\"proposalDeadline(uint256)\":{\"details\":\"See {IGovernor-proposalDeadline}.\"},\"proposalSnapshot(uint256)\":{\"details\":\"See {IGovernor-proposalSnapshot}.\"},\"proposalThreshold()\":{\"details\":\"Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\"},\"proposalVotes(uint256)\":{\"details\":\"Accessor to the internal vote counts.\"},\"propose(address[],uint256[],bytes[],string)\":{\"details\":\"See {IGovernor-propose}.\"},\"quorum(uint256)\":{\"details\":\"Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\"},\"quorumDenominator()\":{\"details\":\"Returns the quorum denominator. Defaults to 100, but may be overridden.\"},\"quorumNumerator()\":{\"details\":\"Returns the current quorum numerator. See {quorumDenominator}.\"},\"relay(address,uint256,bytes)\":{\"details\":\"Relays a transaction or function call to an arbitrary target. In cases where the governance executor is some contract other than the governor itself, like when using a timelock, this function can be invoked in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake. Note that if the executor is simply the governor itself, use of `relay` is redundant.\"},\"state(uint256)\":{\"details\":\"See {IGovernor-state}.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"updateQuorumNumerator(uint256)\":{\"details\":\"Changes the quorum numerator. Emits a {QuorumNumeratorUpdated} event. Requirements: - Must be called through a governance proposal. - New numerator must be smaller or equal to the denominator.\"},\"version()\":{\"details\":\"See {IGovernor-version}.\"},\"votingDelay()\":{\"details\":\"Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\"},\"votingPeriod()\":{\"details\":\"Delay, in number of blocks, between the vote start and vote ends. NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting duration compared to the voting delay.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"votingDelay()\":{\"notice\":\"module:user-config\"},\"votingPeriod()\":{\"notice\":\"module:user-config\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/FlowGovernor.sol\":\"VeloGovernor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736303733333539\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/FlowGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IGovernor} from \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\nimport {L2GovernorCountingSimple} from \\\"contracts/governance/L2GovernorCountingSimple.sol\\\";\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\nimport {L2GovernorVotesQuorumFraction} from \\\"contracts/governance/L2GovernorVotesQuorumFraction.sol\\\";\\n\\ncontract VeloGovernor is\\n L2Governor,\\n L2GovernorCountingSimple,\\n L2GovernorVotes,\\n L2GovernorVotesQuorumFraction\\n{\\n address public team;\\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\\n uint256 public proposalNumerator = 2; // start at 0.02%\\n\\n constructor(IVotes _ve)\\n L2Governor(\\\"Velocimeter Governor\\\")\\n L2GovernorVotes(_ve)\\n L2GovernorVotesQuorumFraction(4) // 4%\\n {\\n team = msg.sender;\\n }\\n\\n function votingDelay() public pure override(IGovernor) returns (uint256) {\\n return 15 minutes; // 1 block\\n }\\n\\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\\n return 1 weeks;\\n }\\n\\n function setTeam(address newTeam) external {\\n require(msg.sender == team, \\\"not team\\\");\\n team = newTeam;\\n }\\n\\n function setProposalNumerator(uint256 numerator) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \\\"numerator too high\\\");\\n proposalNumerator = numerator;\\n }\\n\\n function proposalThreshold()\\n public\\n view\\n override(L2Governor)\\n returns (uint256)\\n {\\n return\\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\\n PROPOSAL_DENOMINATOR;\\n }\\n}\\n\",\"keccak256\":\"0x0386aabd5b5db4aee3d584995ec6e3546dbfdcd2c9006c125918bcfd2d496020\",\"license\":\"MIT\"},\"contracts/governance/L2Governor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Address.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Context.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\\n *\\n * @dev Core of the governance system, designed to be extended though various modules.\\n *\\n * This contract is abstract and requires several function to be implemented in various modules:\\n *\\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\\n * - A voting module must implement {_getVotes}\\n * - Additionanly, the {votingPeriod} must also be implemented\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\\n using SafeCast for uint256;\\n using Timers for Timers.Timestamp;\\n\\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\\\"Ballot(uint256 proposalId,uint8 support)\\\");\\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\\n keccak256(\\\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\\\");\\n\\n struct ProposalCore {\\n Timers.Timestamp voteStart;\\n Timers.Timestamp voteEnd;\\n bool executed;\\n bool canceled;\\n }\\n\\n string private _name;\\n\\n mapping(uint256 => ProposalCore) private _proposals;\\n\\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\\n\\n /**\\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\\n * parameter setters in {GovernorSettings} are protected using this modifier.\\n *\\n * The governance executing address may be different from the Governor's own address, for example it could be a\\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\\n * for example, additional timelock proposers are not able to change governance parameters without going through the\\n * governance protocol (since v4.6).\\n */\\n modifier onlyGovernance() {\\n require(_msgSender() == _executor(), \\\"Governor: onlyGovernance\\\");\\n if (_executor() != address(this)) {\\n bytes32 msgDataHash = keccak256(_msgData());\\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\\n while (_governanceCall.popFront() != msgDataHash) {}\\n }\\n _;\\n }\\n\\n /**\\n * @dev Sets the value for {name} and {version}\\n */\\n constructor(string memory name_) EIP712(name_, version()) {\\n _name = name_;\\n }\\n\\n /**\\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\\n */\\n receive() external payable virtual {\\n require(_executor() == address(this));\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\\n // include the castVoteWithReasonAndParams() function as standard\\n return\\n interfaceId ==\\n (type(IGovernor).interfaceId ^\\n this.castVoteWithReasonAndParams.selector ^\\n this.castVoteWithReasonAndParamsBySig.selector ^\\n this.getVotesWithParams.selector) ||\\n interfaceId == type(IGovernor).interfaceId ||\\n interfaceId == type(IERC1155Receiver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IGovernor-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IGovernor-version}.\\n */\\n function version() public view virtual override returns (string memory) {\\n return \\\"1\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hashProposal}.\\n *\\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\\n * advance, before the proposal is submitted.\\n *\\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual override returns (uint256) {\\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\\n }\\n\\n /**\\n * @dev See {IGovernor-state}.\\n */\\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n\\n if (proposal.executed) {\\n return ProposalState.Executed;\\n }\\n\\n if (proposal.canceled) {\\n return ProposalState.Canceled;\\n }\\n\\n uint256 start = proposalSnapshot(proposalId);\\n\\n if (start == 0) {\\n revert(\\\"Governor: unknown proposal id\\\");\\n }\\n\\n if (start >= block.timestamp) {\\n return ProposalState.Pending;\\n }\\n\\n uint256 deadline = proposalDeadline(proposalId);\\n\\n if (deadline >= block.timestamp) {\\n return ProposalState.Active;\\n }\\n\\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\\n return ProposalState.Succeeded;\\n } else {\\n return ProposalState.Defeated;\\n }\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalSnapshot}.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteStart.getDeadline();\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalDeadline}.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteEnd.getDeadline();\\n }\\n\\n /**\\n * @dev Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\\n */\\n function proposalThreshold() public view virtual returns (uint256) {\\n return 0;\\n }\\n\\n /**\\n * @dev Amount of votes already cast passes the threshold limit.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Is the proposal successful or not.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) internal view virtual returns (uint256);\\n\\n /**\\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\\n *\\n * Note: Support is generic and can represent various things depending on the voting system used.\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory params\\n ) internal virtual;\\n\\n /**\\n * @dev Default additional encoded parameters used by castVote methods that don't include them\\n *\\n * Note: Should be overridden by specific implementations to use an appropriate value, the\\n * meaning of the additional params, in the context of that implementation\\n */\\n function _defaultParams() internal view virtual returns (bytes memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-propose}.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual override returns (uint256) {\\n require(\\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\\n \\\"Governor: proposer votes below proposal threshold\\\"\\n );\\n\\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\\n\\n require(targets.length == values.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length == calldatas.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length > 0, \\\"Governor: empty proposal\\\");\\n\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(proposal.voteStart.isUnset(), \\\"Governor: proposal already exists\\\");\\n\\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\\n uint64 deadline = start + votingPeriod().toUint64();\\n\\n proposal.voteStart.setDeadline(start);\\n proposal.voteEnd.setDeadline(deadline);\\n\\n emit ProposalCreated(\\n proposalId,\\n _msgSender(),\\n targets,\\n values,\\n new string[](targets.length),\\n calldatas,\\n start,\\n deadline,\\n description\\n );\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-execute}.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual override returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n\\n ProposalState status = state(proposalId);\\n require(\\n status == ProposalState.Succeeded || status == ProposalState.Queued,\\n \\\"Governor: proposal not successful\\\"\\n );\\n _proposals[proposalId].executed = true;\\n\\n emit ProposalExecuted(proposalId);\\n\\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\\n _execute(proposalId, targets, values, calldatas, descriptionHash);\\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\\n */\\n function _execute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n string memory errorMessage = \\\"Governor: call reverted without message\\\";\\n for (uint256 i = 0; i < targets.length; ++i) {\\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\\n Address.verifyCallResult(success, returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Hook before execution is triggered.\\n */\\n function _beforeExecute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory, /* values */\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n for (uint256 i = 0; i < targets.length; ++i) {\\n if (targets[i] == address(this)) {\\n _governanceCall.pushBack(keccak256(calldatas[i]));\\n }\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook after execution is triggered.\\n */\\n function _afterExecute(\\n uint256, /* proposalId */\\n address[] memory, /* targets */\\n uint256[] memory, /* values */\\n bytes[] memory, /* calldatas */\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n if (!_governanceCall.empty()) {\\n _governanceCall.clear();\\n }\\n }\\n }\\n\\n /**\\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\\n * canceled to allow distinguishing it from executed proposals.\\n *\\n * Emits a {IGovernor-ProposalCanceled} event.\\n */\\n function _cancel(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) internal virtual returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n ProposalState status = state(proposalId);\\n\\n require(\\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\\n \\\"Governor: proposal not active\\\"\\n );\\n _proposals[proposalId].canceled = true;\\n\\n emit ProposalCanceled(proposalId);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotes}.\\n */\\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, _defaultParams());\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotesWithParams}.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVote}.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReason}.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteBySig}.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\\n v,\\n r,\\n s\\n );\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(\\n keccak256(\\n abi.encode(\\n EXTENDED_BALLOT_TYPEHASH,\\n proposalId,\\n support,\\n keccak256(bytes(reason)),\\n keccak256(params)\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason\\n ) internal virtual returns (uint256) {\\n return _castVote(proposalId, account, support, reason, _defaultParams());\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason,\\n bytes memory params\\n ) internal virtual returns (uint256) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(state(proposalId) == ProposalState.Active, \\\"Governor: vote not currently active\\\");\\n\\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\\n _countVote(proposalId, account, support, weight, params);\\n\\n if (params.length == 0) {\\n emit VoteCast(account, proposalId, support, weight, reason);\\n } else {\\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\\n }\\n\\n return weight;\\n }\\n\\n /**\\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\\n */\\n function relay(\\n address target,\\n uint256 value,\\n bytes calldata data\\n ) external virtual onlyGovernance {\\n Address.functionCallWithValue(target, data, value);\\n }\\n\\n /**\\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\\n * through another contract such as a timelock.\\n */\\n function _executor() internal view virtual returns (address) {\\n return address(this);\\n }\\n\\n /**\\n * @dev See {IERC721Receiver-onERC721Received}.\\n */\\n function onERC721Received(\\n address,\\n address,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155Received}.\\n */\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\\n */\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] memory,\\n uint256[] memory,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155BatchReceived.selector;\\n }\\n}\\n\",\"keccak256\":\"0xa2846313b89a871807cdebd0225b0bf8f23b17505ab8b3288549ec54a5a4a71b\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorCountingSimple.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\\n *\\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorCountingSimple is L2Governor {\\n /**\\n * @dev Supported vote types. Matches Governor Bravo ordering.\\n */\\n enum VoteType {\\n Against,\\n For,\\n Abstain\\n }\\n\\n struct ProposalVote {\\n uint256 againstVotes;\\n uint256 forVotes;\\n uint256 abstainVotes;\\n mapping(address => bool) hasVoted;\\n }\\n\\n mapping(uint256 => ProposalVote) private _proposalVotes;\\n\\n /**\\n * @dev See {IGovernor-COUNTING_MODE}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual override returns (string memory) {\\n return \\\"support=bravo&quorum=for,abstain\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hasVoted}.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\\n return _proposalVotes[proposalId].hasVoted[account];\\n }\\n\\n /**\\n * @dev Accessor to the internal vote counts.\\n */\\n function proposalVotes(uint256 proposalId)\\n public\\n view\\n virtual\\n returns (\\n uint256 againstVotes,\\n uint256 forVotes,\\n uint256 abstainVotes\\n )\\n {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\\n }\\n\\n /**\\n * @dev See {Governor-_quorumReached}.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return proposalvote.forVotes > proposalvote.againstVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory // params\\n ) internal virtual override {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n require(!proposalvote.hasVoted[account], \\\"GovernorVotingSimple: vote already cast\\\");\\n proposalvote.hasVoted[account] = true;\\n\\n if (support == uint8(VoteType.Against)) {\\n proposalvote.againstVotes += weight;\\n } else if (support == uint8(VoteType.For)) {\\n proposalvote.forVotes += weight;\\n } else if (support == uint8(VoteType.Abstain)) {\\n proposalvote.abstainVotes += weight;\\n } else {\\n revert(\\\"GovernorVotingSimple: invalid value for enum VoteType\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xdc37daa24118a6e6ba5208b4abefa1632af2ff340135ca6c6d7237f70102d5db\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotes is L2Governor {\\n IVotes public immutable token;\\n\\n constructor(IVotes tokenAddress) {\\n token = tokenAddress;\\n }\\n\\n /**\\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory /*params*/\\n ) internal view virtual override returns (uint256) {\\n return token.getPastVotes(account, blockTimestamp);\\n }\\n}\\n\",\"keccak256\":\"0x605a7de71228dda3cb8fd878cac313a86bc5841fd34d7344214346ba46e63af1\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotesQuorumFraction.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\\n * fraction of the total supply.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\\n uint256 private _quorumNumerator;\\n\\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\\n\\n /**\\n * @dev Initialize quorum as a fraction of the token's total supply.\\n *\\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\\n * customized by overriding {quorumDenominator}.\\n */\\n constructor(uint256 quorumNumeratorValue) {\\n _updateQuorumNumerator(quorumNumeratorValue);\\n }\\n\\n /**\\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\\n */\\n function quorumNumerator() public view virtual returns (uint256) {\\n return _quorumNumerator;\\n }\\n\\n /**\\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\\n */\\n function quorumDenominator() public view virtual returns (uint256) {\\n return 100;\\n }\\n\\n /**\\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\\n */\\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - Must be called through a governance proposal.\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\\n _updateQuorumNumerator(newQuorumNumerator);\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\\n require(\\n newQuorumNumerator <= quorumDenominator(),\\n \\\"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\\\"\\n );\\n\\n uint256 oldQuorumNumerator = _quorumNumerator;\\n _quorumNumerator = newQuorumNumerator;\\n\\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\\n }\\n}\\n\",\"keccak256\":\"0xe66d29c0ffd2274de933d80e11d68891f3acc3f078be4560a2b493b7d88dcb7f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Interface of the {Governor} core.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract IGovernor is IERC165 {\\n enum ProposalState {\\n Pending,\\n Active,\\n Canceled,\\n Defeated,\\n Succeeded,\\n Queued,\\n Expired,\\n Executed\\n }\\n\\n /**\\n * @dev Emitted when a proposal is created.\\n */\\n event ProposalCreated(\\n uint256 proposalId,\\n address proposer,\\n address[] targets,\\n uint256[] values,\\n string[] signatures,\\n bytes[] calldatas,\\n uint256 startBlock,\\n uint256 endBlock,\\n string description\\n );\\n\\n /**\\n * @dev Emitted when a proposal is canceled.\\n */\\n event ProposalCanceled(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a proposal is executed.\\n */\\n event ProposalExecuted(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a vote is cast without params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n */\\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\\n\\n /**\\n * @dev Emitted when a vote is cast with params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\\n */\\n event VoteCastWithParams(\\n address indexed voter,\\n uint256 proposalId,\\n uint8 support,\\n uint256 weight,\\n string reason,\\n bytes params\\n );\\n\\n /**\\n * @notice module:core\\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\\n */\\n function name() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \\\"1\\\"\\n */\\n function version() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:voting\\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\\n *\\n * There are 2 standard keys: `support` and `quorum`.\\n *\\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\\n * - `quorum=bravo` means that only For votes are counted towards quorum.\\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\\n *\\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\\n * name that describes the behavior. For example:\\n *\\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\\n *\\n * NOTE: The string can be decoded by the standard\\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\\n * JavaScript class.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Current state of a proposal, following Compound's convention\\n */\\n function state(uint256 proposalId) public view virtual returns (ProposalState);\\n\\n /**\\n * @notice module:core\\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\\n * beginning of the following block.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\\n * during this block.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\\n */\\n function votingDelay() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of blocks, between the vote start and vote ends.\\n *\\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\\n * duration compared to the voting delay.\\n */\\n function votingPeriod() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Minimum number of cast voted required for a proposal to be successful.\\n *\\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\\n */\\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber`.\\n *\\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\\n * multiple), {ERC20Votes} tokens.\\n */\\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockNumber,\\n bytes memory params\\n ) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:voting\\n * @dev Returns whether `account` has cast a vote on `proposalId`.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\\n\\n /**\\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\\n * {IGovernor-votingPeriod} blocks after the voting starts.\\n *\\n * Emits a {ProposalCreated} event.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\\n * deadline to be reached.\\n *\\n * Emits a {ProposalExecuted} event.\\n *\\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Cast a vote\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xa52d593ff06a2353f78fa149da31f2ca94f03d1eff99bde41977fa2fe985a92f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2e53602b96c1bf97c731ed3e2a981b4f85e23a9410a5ebd36e549a4cc93340dc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x2626d8ab3dfdad0fad630c212ad146d59473d0f48b771784c61a7c1dbbea1f3f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Tooling for timepoints, timers and delays\\n */\\nlibrary Timers {\\n struct Timestamp {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(Timestamp storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(Timestamp memory timer) internal view returns (bool) {\\n return timer._deadline > block.timestamp;\\n }\\n\\n function isExpired(Timestamp memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.timestamp;\\n }\\n\\n struct BlockNumber {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(BlockNumber storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(BlockNumber memory timer) internal view returns (bool) {\\n return timer._deadline > block.number;\\n }\\n\\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.number;\\n }\\n}\\n\",\"keccak256\":\"0x29791a62950a7983e02a673639c1a781d1e448691800456c2ce4b99715391b14\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS,\\n InvalidSignatureV // Deprecated in v4.8\\n }\\n\\n function _throwError(RecoverError error) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert(\\\"ECDSA: invalid signature\\\");\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert(\\\"ECDSA: invalid signature 's' value\\\");\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature` or error string. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\\n if (signature.length == 65) {\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n /// @solidity memory-safe-assembly\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n return tryRecover(hash, v, r, s);\\n } else {\\n return (address(0), RecoverError.InvalidSignatureLength);\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, signature);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n *\\n * _Available since v4.2._\\n */\\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature);\\n }\\n\\n return (signer, RecoverError.NoError);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from `s`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", Strings.toString(s.length), s));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Typed Data, created from a\\n * `domainSeparator` and a `structHash`. This produces hash corresponding\\n * to the one signed with the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\\n * JSON-RPC method as part of EIP-712.\\n *\\n * See {recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n }\\n}\\n\",\"keccak256\":\"0x54ee424bfc83ce63b2a918b9a1efb5090a0fb68dbd1de3b10bc667776885dd4f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ECDSA.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n /* solhint-disable var-name-mixedcase */\\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n // invalidate the cached domain separator if the chain id changes.\\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n uint256 private immutable _CACHED_CHAIN_ID;\\n address private immutable _CACHED_THIS;\\n\\n bytes32 private immutable _HASHED_NAME;\\n bytes32 private immutable _HASHED_VERSION;\\n bytes32 private immutable _TYPE_HASH;\\n\\n /* solhint-enable var-name-mixedcase */\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n constructor(string memory name, string memory version) {\\n bytes32 hashedName = keccak256(bytes(name));\\n bytes32 hashedVersion = keccak256(bytes(version));\\n bytes32 typeHash = keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n );\\n _HASHED_NAME = hashedName;\\n _HASHED_VERSION = hashedVersion;\\n _CACHED_CHAIN_ID = block.chainid;\\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n _CACHED_THIS = address(this);\\n _TYPE_HASH = typeHash;\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\\n return _CACHED_DOMAIN_SEPARATOR;\\n } else {\\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n }\\n }\\n\\n function _buildDomainSeparator(\\n bytes32 typeHash,\\n bytes32 nameHash,\\n bytes32 versionHash\\n ) private view returns (bytes32) {\\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\\n }\\n}\\n\",\"keccak256\":\"0x948d8b2d18f38141ec78c5229d770d950ebc781ed3f44cc9e3ccbb9fded5846a\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\\n\\nimport \\\"./EIP712.sol\\\";\\n\",\"keccak256\":\"0xea30c402170bc240354b74e6c6f6a8e5bdb1935d90d168cc58c0654461c6a72b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3546b156d97633f7f8cad536d5454c81d1d604687c02b2eb105fdc33cb962b41\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\\npragma solidity ^0.8.4;\\n\\nimport \\\"../math/SafeCast.sol\\\";\\n\\n/**\\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\\n * the existing queue contents are left in storage.\\n *\\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\\n * used in storage, and not in memory.\\n * ```\\n * DoubleEndedQueue.Bytes32Deque queue;\\n * ```\\n *\\n * _Available since v4.6._\\n */\\nlibrary DoubleEndedQueue {\\n /**\\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\\n */\\n error Empty();\\n\\n /**\\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\\n */\\n error OutOfBounds();\\n\\n /**\\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\\n *\\n * Struct members have an underscore prefix indicating that they are \\\"private\\\" and should not be read or written to\\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\\n * lead to unexpected behavior.\\n *\\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\\n * data[end - 1].\\n */\\n struct Bytes32Deque {\\n int128 _begin;\\n int128 _end;\\n mapping(int128 => bytes32) _data;\\n }\\n\\n /**\\n * @dev Inserts an item at the end of the queue.\\n */\\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 backIndex = deque._end;\\n deque._data[backIndex] = value;\\n unchecked {\\n deque._end = backIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Removes the item at the end of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n value = deque._data[backIndex];\\n delete deque._data[backIndex];\\n deque._end = backIndex;\\n }\\n\\n /**\\n * @dev Inserts an item at the beginning of the queue.\\n */\\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 frontIndex;\\n unchecked {\\n frontIndex = deque._begin - 1;\\n }\\n deque._data[frontIndex] = value;\\n deque._begin = frontIndex;\\n }\\n\\n /**\\n * @dev Removes the item at the beginning of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n value = deque._data[frontIndex];\\n delete deque._data[frontIndex];\\n unchecked {\\n deque._begin = frontIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Returns the item at the beginning of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n return deque._data[frontIndex];\\n }\\n\\n /**\\n * @dev Returns the item at the end of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n return deque._data[backIndex];\\n }\\n\\n /**\\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\\n * `length(deque) - 1`.\\n *\\n * Reverts with `OutOfBounds` if the index is out of bounds.\\n */\\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\\n // int256(deque._begin) is a safe upcast\\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\\n if (idx >= deque._end) revert OutOfBounds();\\n return deque._data[idx];\\n }\\n\\n /**\\n * @dev Resets the queue back to being empty.\\n *\\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\\n * out on potential gas refunds.\\n */\\n function clear(Bytes32Deque storage deque) internal {\\n deque._begin = 0;\\n deque._end = 0;\\n }\\n\\n /**\\n * @dev Returns the number of items in the queue.\\n */\\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\\n // We also assume there are at most int256.max items in the queue.\\n unchecked {\\n return uint256(int256(deque._end) - int256(deque._begin));\\n }\\n }\\n\\n /**\\n * @dev Returns true if the queue is empty.\\n */\\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\\n return deque._end <= deque._begin;\\n }\\n}\\n\",\"keccak256\":\"0x4859ffd6dd69382a1462930c00b6e394007da80e78e510f56930271034737bf2\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x61016060405260026007553480156200001757600080fd5b506040516200329a3803806200329a8339810160408190526200003a91620002ec565b6004816040518060400160405280601481526020017f56656c6f63696d6574657220476f7665726e6f7200000000000000000000000081525080620000846200015e60201b60201c565b815160208084019190912082518383012060e08290526101008190524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81880181905281830187905260608201869052608082019490945230818401528151808203909301835260c00190528051940193909320919290916080523060c05261012052505082516200012a925060009150602084019062000246565b50506001600160a01b031661014052620001448162000179565b5050600680546001600160a01b031916331790556200035a565b6040805180820190915260018152603160f81b602082015290565b6064811115620002015760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a40160405180910390fd5b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b82805462000254906200031e565b90600052602060002090601f016020900481019282620002785760008555620002c3565b82601f106200029357805160ff1916838001178555620002c3565b82800160010185558215620002c3579182015b82811115620002c3578251825591602001919060010190620002a6565b50620002d1929150620002d5565b5090565b5b80821115620002d15760008155600101620002d6565b600060208284031215620002ff57600080fd5b81516001600160a01b03811681146200031757600080fd5b9392505050565b600181811c908216806200033357607f821691505b6020821081036200035457634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e051610100516101205161014051612ed0620003ca600039600081816107df0152818161120f015281816113e40152611a0601526000611b2301526000611b7201526000611b4d01526000611aa601526000611ad001526000611afa0152612ed06000f3fe6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a26469706673582212206f0f82bb23a18ee7761f1fc6bb1fd57e88de4c2a0483dd749cbd707fba2dbedd64736f6c634300080d0033", - "deployedBytecode": "0x6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a26469706673582212206f0f82bb23a18ee7761f1fc6bb1fd57e88de4c2a0483dd749cbd707fba2dbedd64736f6c634300080d0033", - "devdoc": { - "errors": { - "Empty()": [ - { - "details": "An operation (e.g. {front}) couldn't be completed due to the queue being empty." - } - ] - }, - "kind": "dev", - "methods": { - "COUNTING_MODE()": { - "details": "See {IGovernor-COUNTING_MODE}." - }, - "castVote(uint256,uint8)": { - "details": "See {IGovernor-castVote}." - }, - "castVoteBySig(uint256,uint8,uint8,bytes32,bytes32)": { - "details": "See {IGovernor-castVoteBySig}." - }, - "castVoteWithReason(uint256,uint8,string)": { - "details": "See {IGovernor-castVoteWithReason}." - }, - "castVoteWithReasonAndParams(uint256,uint8,string,bytes)": { - "details": "See {IGovernor-castVoteWithReasonAndParams}." - }, - "castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32)": { - "details": "See {IGovernor-castVoteWithReasonAndParamsBySig}." - }, - "execute(address[],uint256[],bytes[],bytes32)": { - "details": "See {IGovernor-execute}." - }, - "getVotes(address,uint256)": { - "details": "See {IGovernor-getVotes}." - }, - "getVotesWithParams(address,uint256,bytes)": { - "details": "See {IGovernor-getVotesWithParams}." - }, - "hasVoted(uint256,address)": { - "details": "See {IGovernor-hasVoted}." - }, - "hashProposal(address[],uint256[],bytes[],bytes32)": { - "details": "See {IGovernor-hashProposal}. The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in advance, before the proposal is submitted. Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the same proposal (with same operation and same description) will have the same id if submitted on multiple governors across multiple networks. This also means that in order to execute the same operation twice (on the same governor) the proposer will have to change the description in order to avoid proposal id conflicts." - }, - "name()": { - "details": "See {IGovernor-name}." - }, - "onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)": { - "details": "See {IERC1155Receiver-onERC1155BatchReceived}." - }, - "onERC1155Received(address,address,uint256,uint256,bytes)": { - "details": "See {IERC1155Receiver-onERC1155Received}." - }, - "onERC721Received(address,address,uint256,bytes)": { - "details": "See {IERC721Receiver-onERC721Received}." - }, - "proposalDeadline(uint256)": { - "details": "See {IGovernor-proposalDeadline}." - }, - "proposalSnapshot(uint256)": { - "details": "See {IGovernor-proposalSnapshot}." - }, - "proposalThreshold()": { - "details": "Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_." - }, - "proposalVotes(uint256)": { - "details": "Accessor to the internal vote counts." - }, - "propose(address[],uint256[],bytes[],string)": { - "details": "See {IGovernor-propose}." - }, - "quorum(uint256)": { - "details": "Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`." - }, - "quorumDenominator()": { - "details": "Returns the quorum denominator. Defaults to 100, but may be overridden." - }, - "quorumNumerator()": { - "details": "Returns the current quorum numerator. See {quorumDenominator}." - }, - "relay(address,uint256,bytes)": { - "details": "Relays a transaction or function call to an arbitrary target. In cases where the governance executor is some contract other than the governor itself, like when using a timelock, this function can be invoked in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake. Note that if the executor is simply the governor itself, use of `relay` is redundant." - }, - "state(uint256)": { - "details": "See {IGovernor-state}." - }, - "supportsInterface(bytes4)": { - "details": "See {IERC165-supportsInterface}." - }, - "updateQuorumNumerator(uint256)": { - "details": "Changes the quorum numerator. Emits a {QuorumNumeratorUpdated} event. Requirements: - Must be called through a governance proposal. - New numerator must be smaller or equal to the denominator." - }, - "version()": { - "details": "See {IGovernor-version}." - }, - "votingDelay()": { - "details": "Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to leave time for users to buy voting power, or delegate it, before the voting of a proposal starts." - }, - "votingPeriod()": { - "details": "Delay, in number of blocks, between the vote start and vote ends. NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting duration compared to the voting delay." - } - }, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "votingDelay()": { - "notice": "module:user-config" - }, - "votingPeriod()": { - "notice": "module:user-config" - } - }, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 21935, - "contract": "contracts/FlowGovernor.sol:VeloGovernor", - "label": "_name", - "offset": 0, - "slot": "0", - "type": "t_string_storage" - }, - { - "astId": 21940, - "contract": "contracts/FlowGovernor.sol:VeloGovernor", - "label": "_proposals", - "offset": 0, - "slot": "1", - "type": "t_mapping(t_uint256,t_struct(ProposalCore)21933_storage)" - }, - { - "astId": 21943, - "contract": "contracts/FlowGovernor.sol:VeloGovernor", - "label": "_governanceCall", - "offset": 0, - "slot": "2", - "type": "t_struct(Bytes32Deque)30247_storage" - }, - { - "astId": 23199, - "contract": "contracts/FlowGovernor.sol:VeloGovernor", - "label": "_proposalVotes", - "offset": 0, - "slot": "4", - "type": "t_mapping(t_uint256,t_struct(ProposalVote)23194_storage)" - }, - { - "astId": 23452, - "contract": "contracts/FlowGovernor.sol:VeloGovernor", - "label": "_quorumNumerator", - "offset": 0, - "slot": "5", - "type": "t_uint256" - }, - { - "astId": 1704, - "contract": "contracts/FlowGovernor.sol:VeloGovernor", - "label": "team", - "offset": 0, - "slot": "6", - "type": "t_address" - }, - { - "astId": 1713, - "contract": "contracts/FlowGovernor.sol:VeloGovernor", - "label": "proposalNumerator", - "offset": 0, - "slot": "7", - "type": "t_uint256" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_int128": { - "encoding": "inplace", - "label": "int128", - "numberOfBytes": "16" - }, - "t_mapping(t_address,t_bool)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => bool)", - "numberOfBytes": "32", - "value": "t_bool" - }, - "t_mapping(t_int128,t_bytes32)": { - "encoding": "mapping", - "key": "t_int128", - "label": "mapping(int128 => bytes32)", - "numberOfBytes": "32", - "value": "t_bytes32" - }, - "t_mapping(t_uint256,t_struct(ProposalCore)21933_storage)": { - "encoding": "mapping", - "key": "t_uint256", - "label": "mapping(uint256 => struct L2Governor.ProposalCore)", - "numberOfBytes": "32", - "value": "t_struct(ProposalCore)21933_storage" - }, - "t_mapping(t_uint256,t_struct(ProposalVote)23194_storage)": { - "encoding": "mapping", - "key": "t_uint256", - "label": "mapping(uint256 => struct L2GovernorCountingSimple.ProposalVote)", - "numberOfBytes": "32", - "value": "t_struct(ProposalVote)23194_storage" - }, - "t_string_storage": { - "encoding": "bytes", - "label": "string", - "numberOfBytes": "32" - }, - "t_struct(Bytes32Deque)30247_storage": { - "encoding": "inplace", - "label": "struct DoubleEndedQueue.Bytes32Deque", - "members": [ - { - "astId": 30240, - "contract": "contracts/FlowGovernor.sol:VeloGovernor", - "label": "_begin", - "offset": 0, - "slot": "0", - "type": "t_int128" - }, - { - "astId": 30242, - "contract": "contracts/FlowGovernor.sol:VeloGovernor", - "label": "_end", - "offset": 16, - "slot": "0", - "type": "t_int128" - }, - { - "astId": 30246, - "contract": "contracts/FlowGovernor.sol:VeloGovernor", - "label": "_data", - "offset": 0, - "slot": "1", - "type": "t_mapping(t_int128,t_bytes32)" - } - ], - "numberOfBytes": "64" - }, - "t_struct(ProposalCore)21933_storage": { - "encoding": "inplace", - "label": "struct L2Governor.ProposalCore", - "members": [ - { - "astId": 21925, - "contract": "contracts/FlowGovernor.sol:VeloGovernor", - "label": "voteStart", - "offset": 0, - "slot": "0", - "type": "t_struct(Timestamp)26448_storage" - }, - { - "astId": 21928, - "contract": "contracts/FlowGovernor.sol:VeloGovernor", - "label": "voteEnd", - "offset": 0, - "slot": "1", - "type": "t_struct(Timestamp)26448_storage" - }, - { - "astId": 21930, - "contract": "contracts/FlowGovernor.sol:VeloGovernor", - "label": "executed", - "offset": 0, - "slot": "2", - "type": "t_bool" - }, - { - "astId": 21932, - "contract": "contracts/FlowGovernor.sol:VeloGovernor", - "label": "canceled", - "offset": 1, - "slot": "2", - "type": "t_bool" - } - ], - "numberOfBytes": "96" - }, - "t_struct(ProposalVote)23194_storage": { - "encoding": "inplace", - "label": "struct L2GovernorCountingSimple.ProposalVote", - "members": [ - { - "astId": 23185, - "contract": "contracts/FlowGovernor.sol:VeloGovernor", - "label": "againstVotes", - "offset": 0, - "slot": "0", - "type": "t_uint256" - }, - { - "astId": 23187, - "contract": "contracts/FlowGovernor.sol:VeloGovernor", - "label": "forVotes", - "offset": 0, - "slot": "1", - "type": "t_uint256" - }, - { - "astId": 23189, - "contract": "contracts/FlowGovernor.sol:VeloGovernor", - "label": "abstainVotes", - "offset": 0, - "slot": "2", - "type": "t_uint256" - }, - { - "astId": 23193, - "contract": "contracts/FlowGovernor.sol:VeloGovernor", - "label": "hasVoted", - "offset": 0, - "slot": "3", - "type": "t_mapping(t_address,t_bool)" - } - ], - "numberOfBytes": "128" - }, - "t_struct(Timestamp)26448_storage": { - "encoding": "inplace", - "label": "struct Timers.Timestamp", - "members": [ - { - "astId": 26447, - "contract": "contracts/FlowGovernor.sol:VeloGovernor", - "label": "_deadline", - "offset": 0, - "slot": "0", - "type": "t_uint64" - } - ], - "numberOfBytes": "32" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint64": { - "encoding": "inplace", - "label": "uint64", - "numberOfBytes": "8" - } - } - } -} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/VelocimeterLibrary.json b/deployments/arbitrumGoerli/VelocimeterLibrary.json index a75b7503..66038c4b 100644 --- a/deployments/arbitrumGoerli/VelocimeterLibrary.json +++ b/deployments/arbitrumGoerli/VelocimeterLibrary.json @@ -1,5 +1,5 @@ { - "address": "0x7AFfb8901B7D43241068bc804004373147c7c34c", + "address": "0x142667449d5d6228a9Bd95A52749e3187235a91D", "abi": [ { "inputs": [ @@ -188,30 +188,30 @@ "type": "function" } ], - "transactionHash": "0x84b182f1ae5440071a4c19fa636d33f91d5d1b24f207b34e290248aec1d62114", + "transactionHash": "0x7c6da1ee94ad5cea5213f0141c5b07332199ef1ef219b2aede9969b5f4559cf9", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x7AFfb8901B7D43241068bc804004373147c7c34c", + "contractAddress": "0x142667449d5d6228a9Bd95A52749e3187235a91D", "transactionIndex": 1, "gasUsed": "904028", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x6a8800e70c3e5abfa90cd04dcb2fe67133c4724d963602d12a1f4ffd6f1b28f9", - "transactionHash": "0x84b182f1ae5440071a4c19fa636d33f91d5d1b24f207b34e290248aec1d62114", + "blockHash": "0xae7b46c7446b0e1d5d86ff3ef4bb2859feac4b1277ded395b0fee98fe3a84778", + "transactionHash": "0x7c6da1ee94ad5cea5213f0141c5b07332199ef1ef219b2aede9969b5f4559cf9", "logs": [], - "blockNumber": 5814417, + "blockNumber": 5849185, "cumulativeGasUsed": "904028", "status": 1, "byzantium": true }, "args": [ - "0xD2D41340706472DEf3b8A1d6143743D03Da38fed" + "0x7620a00A75f7fAE135A7236E79982A98Cfd120e1" ], - "numDeployments": 4, - "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getMinimumValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getSample\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VelocimeterLibrary.sol\":\"VelocimeterLibrary\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VelocimeterLibrary.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\n\\ncontract VelocimeterLibrary {\\n IRouter internal immutable router;\\n\\n constructor(address _router) {\\n router = IRouter(_router);\\n }\\n\\n function _f(uint x0, uint y) internal pure returns (uint) {\\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\\n }\\n\\n function _d(uint x0, uint y) internal pure returns (uint) {\\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\\n }\\n\\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\\n for (uint i = 0; i < 255; i++) {\\n uint y_prev = y;\\n uint k = _f(x0, y);\\n if (k < xy) {\\n uint dy = (xy - k)*1e18/_d(x0, y);\\n y = y + dy;\\n } else {\\n uint dy = (k - xy)*1e18/_d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n }\\n\\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return (sample, r0, r1);\\n }\\n\\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\\n if (stable) {\\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\\n _reserve0 = _reserve0 * 1e18 / decimals0;\\n _reserve1 = _reserve1 * 1e18 / decimals1;\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\\n } else {\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n return amountIn * reserveB / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\\n if (stable) {\\n uint _x = x * 1e18 / decimals0;\\n uint _y = y * 1e18 / decimals1;\\n uint _a = (_x * _y) / 1e18;\\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return _a * _b / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n \\n}\\n\",\"keccak256\":\"0x8fa888fd7bda7d3d44a2cc0fd62aeb594c767907f24e7cd390a5fe998d60f388\",\"license\":\"MIT\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"}},\"version\":1}", - "bytecode": "0x60a060405234801561001057600080fd5b5060405161100238038061100283398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051610f626100a06000396000818161010c015281816102730152818161043701526105cb0152610f626000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea2646970667358221220dbb4fa9d04c8f4c99ed7b55c6cda8fa05e9ceb4b7047d53d1879f8abe0b6da4464736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea2646970667358221220dbb4fa9d04c8f4c99ed7b55c6cda8fa05e9ceb4b7047d53d1879f8abe0b6da4464736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getMinimumValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getSample\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VelocimeterLibrary.sol\":\"VelocimeterLibrary\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VelocimeterLibrary.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\n\\ncontract VelocimeterLibrary {\\n IRouter internal immutable router;\\n\\n constructor(address _router) {\\n router = IRouter(_router);\\n }\\n\\n function _f(uint x0, uint y) internal pure returns (uint) {\\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\\n }\\n\\n function _d(uint x0, uint y) internal pure returns (uint) {\\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\\n }\\n\\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\\n for (uint i = 0; i < 255; i++) {\\n uint y_prev = y;\\n uint k = _f(x0, y);\\n if (k < xy) {\\n uint dy = (xy - k)*1e18/_d(x0, y);\\n y = y + dy;\\n } else {\\n uint dy = (k - xy)*1e18/_d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n }\\n\\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return (sample, r0, r1);\\n }\\n\\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\\n if (stable) {\\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\\n _reserve0 = _reserve0 * 1e18 / decimals0;\\n _reserve1 = _reserve1 * 1e18 / decimals1;\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\\n } else {\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n return amountIn * reserveB / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\\n if (stable) {\\n uint _x = x * 1e18 / decimals0;\\n uint _y = y * 1e18 / decimals1;\\n uint _a = (_x * _y) / 1e18;\\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return _a * _b / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n \\n}\\n\",\"keccak256\":\"0x8fa888fd7bda7d3d44a2cc0fd62aeb594c767907f24e7cd390a5fe998d60f388\",\"license\":\"MIT\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"}},\"version\":1}", + "bytecode": "0x60a060405234801561001057600080fd5b5060405161100238038061100283398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051610f626100a06000396000818161010c015281816102730152818161043701526105cb0152610f626000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea2646970667358221220c149725fc6d1c1832794d0b74e88c810171ce1f9cb66ae61e5c1d3478d59b4f064736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea2646970667358221220c149725fc6d1c1832794d0b74e88c810171ce1f9cb66ae61e5c1d3478d59b4f064736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/VelodromeLibrary.json b/deployments/arbitrumGoerli/VelodromeLibrary.json deleted file mode 100644 index 6610b2af..00000000 --- a/deployments/arbitrumGoerli/VelodromeLibrary.json +++ /dev/null @@ -1,229 +0,0 @@ -{ - "address": "0xcbE4714A95f866EB9C2eB50856F431f9E7353Ab6", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_router", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "address", - "name": "tokenIn", - "type": "address" - }, - { - "internalType": "address", - "name": "tokenOut", - "type": "address" - }, - { - "internalType": "bool", - "name": "stable", - "type": "bool" - } - ], - "name": "getAmountOut", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "tokenIn", - "type": "address" - }, - { - "internalType": "address", - "name": "tokenOut", - "type": "address" - }, - { - "internalType": "bool", - "name": "stable", - "type": "bool" - } - ], - "name": "getMinimumValue", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "tokenIn", - "type": "address" - }, - { - "internalType": "address", - "name": "tokenOut", - "type": "address" - }, - { - "internalType": "bool", - "name": "stable", - "type": "bool" - } - ], - "name": "getSample", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "address", - "name": "tokenIn", - "type": "address" - }, - { - "internalType": "address", - "name": "tokenOut", - "type": "address" - }, - { - "internalType": "bool", - "name": "stable", - "type": "bool" - } - ], - "name": "getTradeDiff", - "outputs": [ - { - "internalType": "uint256", - "name": "a", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "b", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "address", - "name": "tokenIn", - "type": "address" - }, - { - "internalType": "address", - "name": "pair", - "type": "address" - } - ], - "name": "getTradeDiff", - "outputs": [ - { - "internalType": "uint256", - "name": "a", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "b", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0x508b39bf1e550abd528db525f3d3904ddb006efa56ccb949a2a66b36ce016c3c", - "receipt": { - "to": null, - "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xcbE4714A95f866EB9C2eB50856F431f9E7353Ab6", - "transactionIndex": 1, - "gasUsed": "934860", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xb00a1be00151b9c41209b0d01f7af864660fc687f8d2abfe8d555309b5fdb98b", - "transactionHash": "0x508b39bf1e550abd528db525f3d3904ddb006efa56ccb949a2a66b36ce016c3c", - "logs": [], - "blockNumber": 4455881, - "cumulativeGasUsed": "934860", - "status": 1, - "byzantium": true - }, - "args": [ - "0x1B0aC6bf6f35E638f6cce8D69C6074561273dc52" - ], - "numDeployments": 1, - "solcInputHash": "44ac1d7fba4690e053e773a8c0d73438", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getMinimumValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getSample\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VelodromeLibrary.sol\":\"VelodromeLibrary\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733373432343733333937\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VelodromeLibrary.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\n\\ncontract VelodromeLibrary {\\n IRouter internal immutable router;\\n\\n constructor(address _router) {\\n router = IRouter(_router);\\n }\\n\\n function _f(uint x0, uint y) internal pure returns (uint) {\\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\\n }\\n\\n function _d(uint x0, uint y) internal pure returns (uint) {\\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\\n }\\n\\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\\n for (uint i = 0; i < 255; i++) {\\n uint y_prev = y;\\n uint k = _f(x0, y);\\n if (k < xy) {\\n uint dy = (xy - k)*1e18/_d(x0, y);\\n y = y + dy;\\n } else {\\n uint dy = (k - xy)*1e18/_d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n }\\n\\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return (sample, r0, r1);\\n }\\n\\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\\n if (stable) {\\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\\n _reserve0 = _reserve0 * 1e18 / decimals0;\\n _reserve1 = _reserve1 * 1e18 / decimals1;\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\\n } else {\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n return amountIn * reserveB / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\\n if (stable) {\\n uint _x = x * 1e18 / decimals0;\\n uint _y = y * 1e18 / decimals1;\\n uint _a = (_x * _y) / 1e18;\\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return _a * _b / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n \\n}\\n\",\"keccak256\":\"0x01df9d4f97d905560776a0b2d29e6dc1337dc952fdc3d8bfbfde99a510a62c1c\",\"license\":\"MIT\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"}},\"version\":1}", - "bytecode": "0x60a060405234801561001057600080fd5b5060405161100238038061100283398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051610f626100a06000396000818161010c015281816102730152818161043701526105cb0152610f626000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea2646970667358221220093d2ed1e54290287c6817778d55455c8a9d3c98dd723f7a03a8f09fc41e3d3364736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea2646970667358221220093d2ed1e54290287c6817778d55455c8a9d3c98dd723f7a03a8f09fc41e3d3364736f6c634300080d0033", - "devdoc": { - "kind": "dev", - "methods": {}, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": {}, - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/Voter.json b/deployments/arbitrumGoerli/Voter.json index 4aa02cd5..5bc9be5d 100644 --- a/deployments/arbitrumGoerli/Voter.json +++ b/deployments/arbitrumGoerli/Voter.json @@ -1,5 +1,5 @@ { - "address": "0xfD6108E8FDD2e6D125f71E68C7B8eD48f997c2Ad", + "address": "0xe08A284C791c72E59C9020303b9B70E67bCf1d6C", "abi": [ { "inputs": [ @@ -1141,33 +1141,33 @@ "type": "function" } ], - "transactionHash": "0xe6e46dfdae997cda4d724b4e5e2e614bd2faad5809fd9348881232fe6e94f383", + "transactionHash": "0xcf999bcc29a80f8e010dd7a6cb465ea938e9f5f908506cd9dc563fc8f6c35212", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xfD6108E8FDD2e6D125f71E68C7B8eD48f997c2Ad", + "contractAddress": "0xe08A284C791c72E59C9020303b9B70E67bCf1d6C", "transactionIndex": 1, "gasUsed": "3013820", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc595717945fe967d6e9616e7f803588e2526f7305e1069ec94d42e05ea427906", - "transactionHash": "0xe6e46dfdae997cda4d724b4e5e2e614bd2faad5809fd9348881232fe6e94f383", + "blockHash": "0xe86d3d76185a541e47caa4c82a1e06e5dd9c4af11d3fb2c3fc02a1ee3e8f0ee1", + "transactionHash": "0xcf999bcc29a80f8e010dd7a6cb465ea938e9f5f908506cd9dc563fc8f6c35212", "logs": [], - "blockNumber": 5814437, + "blockNumber": 5849232, "cumulativeGasUsed": "3013820", "status": 1, "byzantium": true }, "args": [ - "0xad0F425b3edB0FC3a06096092B5736A280C90C40", - "0xE4a96d05579a4306e19E1C36F8e6A1567c982750", - "0x18B8e4fEf12a17BFe35f0A1a4ca3cA7208F30123", - "0xb6270b92939c7b3676dcecA9a32D50Be27Db1291" + "0xF003091B78974ee3F99ec70fC5F42fc9810664EC", + "0x32bB8e83F877948Db847BDB6A8DB51d441324c1F", + "0x596CAFB654c2281838b570F3801a8288b7B7bE8a", + "0x6e724702DfB7bCd31Af55852D67aa6A785aB85e6" ], - "numDeployments": 5, - "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_gauges\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_bribes\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Abstained\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Attach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Detach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributeReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"internal_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"external_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"name\":\"GaugeCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeKilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeRevived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"reward\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NotifyReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Voted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"whitelister\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"Whitelisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"attachTokenToGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bribefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_bribes\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimBribes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_fees\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"}],\"name\":\"claimRewards\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"detachTokenFromGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"finish\",\"type\":\"uint256\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distributeFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distro\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"emergencyCouncil\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"external_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gaugefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"gauges\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_tokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"internal_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isAlive\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isGauge\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isWhitelisted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"killGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"lastVoted\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"length\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"notifyRewardAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"poke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolForGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"poolVote\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"reset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"reviveGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_council\",\"type\":\"address\"}],\"name\":\"setEmergencyCouncil\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"setGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalWeight\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"updateFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"name\":\"updateForRange\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"updateGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedWeights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"_poolVote\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_weights\",\"type\":\"uint256[]\"}],\"name\":\"vote\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"votes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"weights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"whitelist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Voter.sol\":\"Voter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Voter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/libraries/Math.sol';\\nimport 'contracts/interfaces/IBribe.sol';\\nimport 'contracts/interfaces/IBribeFactory.sol';\\nimport 'contracts/interfaces/IGauge.sol';\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/interfaces/IERC20.sol';\\nimport 'contracts/interfaces/IMinter.sol';\\nimport 'contracts/interfaces/IPair.sol';\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/interfaces/IVoter.sol';\\nimport 'contracts/interfaces/IVotingEscrow.sol';\\n\\ncontract Voter is IVoter {\\n\\n address public immutable _ve; // the ve token that governs these contracts\\n address public immutable factory; // the PairFactory\\n address internal immutable base;\\n address public immutable gaugefactory;\\n address public immutable bribefactory;\\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\\n address public minter;\\n address public governor; // should be set to an IGovernor\\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\\n\\n uint public totalWeight; // total voting weight\\n\\n address[] public pools; // all pools viable for incentives\\n mapping(address => address) public gauges; // pool => gauge\\n mapping(address => address) public poolForGauge; // gauge => pool\\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\\n mapping(address => uint256) public weights; // pool => weight\\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\\n mapping(uint => address[]) public poolVote; // nft => pools\\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\\n mapping(address => bool) public isGauge;\\n mapping(address => bool) public isWhitelisted;\\n mapping(address => bool) public isAlive;\\n\\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\\n event GaugeKilled(address indexed gauge);\\n event GaugeRevived(address indexed gauge);\\n event Voted(address indexed voter, uint tokenId, uint256 weight);\\n event Abstained(uint tokenId, uint256 weight);\\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\\n event Whitelisted(address indexed whitelister, address indexed token);\\n\\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\\n _ve = __ve;\\n factory = _factory;\\n base = IVotingEscrow(__ve).token();\\n gaugefactory = _gauges;\\n bribefactory = _bribes;\\n minter = msg.sender;\\n governor = msg.sender;\\n emergencyCouncil = msg.sender;\\n }\\n\\n // simple re-entrancy check\\n uint internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n modifier onlyNewEpoch(uint _tokenId) {\\n // ensure new epoch since last vote \\n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \\\"TOKEN_ALREADY_VOTED_THIS_EPOCH\\\");\\n _;\\n }\\n\\n function initialize(address[] memory _tokens, address _minter) external {\\n require(msg.sender == minter);\\n for (uint i = 0; i < _tokens.length; i++) {\\n _whitelist(_tokens[i]);\\n }\\n minter = _minter;\\n }\\n\\n function setGovernor(address _governor) public {\\n require(msg.sender == governor);\\n governor = _governor;\\n }\\n\\n function setEmergencyCouncil(address _council) public {\\n require(msg.sender == emergencyCouncil);\\n emergencyCouncil = _council;\\n }\\n\\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n lastVoted[_tokenId] = block.timestamp;\\n _reset(_tokenId);\\n IVotingEscrow(_ve).abstain(_tokenId);\\n }\\n\\n function _reset(uint _tokenId) internal {\\n address[] storage _poolVote = poolVote[_tokenId];\\n uint _poolVoteCnt = _poolVote.length;\\n uint256 _totalWeight = 0;\\n\\n for (uint i = 0; i < _poolVoteCnt; i ++) {\\n address _pool = _poolVote[i];\\n uint256 _votes = votes[_tokenId][_pool];\\n\\n if (_votes != 0) {\\n _updateFor(gauges[_pool]);\\n weights[_pool] -= _votes;\\n votes[_tokenId][_pool] -= _votes;\\n if (_votes > 0) {\\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n _totalWeight += _votes;\\n } else {\\n _totalWeight -= _votes;\\n }\\n emit Abstained(_tokenId, _votes);\\n }\\n }\\n totalWeight -= uint256(_totalWeight);\\n usedWeights[_tokenId] = 0;\\n delete poolVote[_tokenId];\\n }\\n\\n function poke(uint _tokenId) external {\\n address[] memory _poolVote = poolVote[_tokenId];\\n uint _poolCnt = _poolVote.length;\\n uint256[] memory _weights = new uint256[](_poolCnt);\\n\\n for (uint i = 0; i < _poolCnt; i ++) {\\n _weights[i] = votes[_tokenId][_poolVote[i]];\\n }\\n\\n _vote(_tokenId, _poolVote, _weights);\\n }\\n\\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\\n _reset(_tokenId);\\n uint _poolCnt = _poolVote.length;\\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\\n uint256 _totalVoteWeight = 0;\\n uint256 _totalWeight = 0;\\n uint256 _usedWeight = 0;\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n _totalVoteWeight += _weights[i];\\n }\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n address _pool = _poolVote[i];\\n address _gauge = gauges[_pool];\\n\\n if (isGauge[_gauge]) {\\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\\n require(votes[_tokenId][_pool] == 0);\\n require(_poolWeight != 0);\\n _updateFor(_gauge);\\n\\n poolVote[_tokenId].push(_pool);\\n\\n weights[_pool] += _poolWeight;\\n votes[_tokenId][_pool] += _poolWeight;\\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n _usedWeight += _poolWeight;\\n _totalWeight += _poolWeight;\\n emit Voted(msg.sender, _tokenId, _poolWeight);\\n }\\n }\\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\\n totalWeight += uint256(_totalWeight);\\n usedWeights[_tokenId] = uint256(_usedWeight);\\n }\\n\\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n require(_poolVote.length == _weights.length);\\n lastVoted[tokenId] = block.timestamp;\\n _vote(tokenId, _poolVote, _weights);\\n }\\n\\n function whitelist(address _token) public {\\n require(msg.sender == governor);\\n _whitelist(_token);\\n }\\n\\n function _whitelist(address _token) internal {\\n require(!isWhitelisted[_token]);\\n isWhitelisted[_token] = true;\\n emit Whitelisted(msg.sender, _token);\\n }\\n\\n function createGauge(address _pool) external returns (address) {\\n require(gauges[_pool] == address(0x0), \\\"exists\\\");\\n address[] memory allowedRewards = new address[](3);\\n address[] memory internalRewards = new address[](2);\\n bool isPair = IPairFactory(factory).isPair(_pool);\\n address tokenA;\\n address tokenB;\\n\\n if (isPair) {\\n (tokenA, tokenB) = IPair(_pool).tokens();\\n allowedRewards[0] = tokenA;\\n allowedRewards[1] = tokenB;\\n internalRewards[0] = tokenA;\\n internalRewards[1] = tokenB;\\n\\n if (base != tokenA && base != tokenB) {\\n allowedRewards[2] = base;\\n }\\n }\\n\\n if (msg.sender != governor) { // gov can create for any pool, even non-Velocimeter pairs\\n require(isPair, \\\"!_pool\\\");\\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \\\"!whitelisted\\\");\\n }\\n\\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\\n\\n IERC20(base).approve(_gauge, type(uint).max);\\n internal_bribes[_gauge] = _internal_bribe;\\n external_bribes[_gauge] = _external_bribe;\\n gauges[_pool] = _gauge;\\n poolForGauge[_gauge] = _pool;\\n isGauge[_gauge] = true;\\n isAlive[_gauge] = true;\\n _updateFor(_gauge);\\n pools.push(_pool);\\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\\n return _gauge;\\n }\\n\\n function killGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(isAlive[_gauge], \\\"gauge already dead\\\");\\n isAlive[_gauge] = false;\\n claimable[_gauge] = 0;\\n emit GaugeKilled(_gauge);\\n }\\n\\n function reviveGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(!isAlive[_gauge], \\\"gauge already alive\\\");\\n isAlive[_gauge] = true;\\n emit GaugeRevived(_gauge);\\n }\\n\\n function attachTokenToGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\\n emit Attach(account, msg.sender, tokenId);\\n }\\n\\n function emitDeposit(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]);\\n emit Deposit(account, msg.sender, tokenId, amount);\\n }\\n\\n function detachTokenFromGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\\n emit Detach(account, msg.sender, tokenId);\\n }\\n\\n function emitWithdraw(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n emit Withdraw(account, msg.sender, tokenId, amount);\\n }\\n\\n function length() external view returns (uint) {\\n return pools.length;\\n }\\n\\n uint internal index;\\n mapping(address => uint) internal supplyIndex;\\n mapping(address => uint) public claimable;\\n\\n function notifyRewardAmount(uint amount) external {\\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index += _ratio;\\n }\\n emit NotifyReward(msg.sender, base, amount);\\n }\\n\\n function updateFor(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n _updateFor(_gauges[i]);\\n }\\n }\\n\\n function updateForRange(uint start, uint end) public {\\n for (uint i = start; i < end; i++) {\\n _updateFor(gauges[pools[i]]);\\n }\\n }\\n\\n function updateAll() external {\\n updateForRange(0, pools.length);\\n }\\n\\n function updateGauge(address _gauge) external {\\n _updateFor(_gauge);\\n }\\n\\n function _updateFor(address _gauge) internal {\\n address _pool = poolForGauge[_gauge];\\n uint256 _supplied = weights[_pool];\\n if (_supplied > 0) {\\n uint _supplyIndex = supplyIndex[_gauge];\\n uint _index = index; // get global index0 for accumulated distro\\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\\n if (_delta > 0) {\\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\\n if (isAlive[_gauge]) {\\n claimable[_gauge] += _share;\\n }\\n }\\n } else {\\n supplyIndex[_gauge] = index; // new users are set to the default global state\\n }\\n }\\n\\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\\n }\\n }\\n\\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _bribes.length; i++) {\\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _fees.length; i++) {\\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function distributeFees(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n if (IGauge(_gauges[i]).isForPair()){\\n IGauge(_gauges[i]).claimFees();\\n }\\n }\\n }\\n\\n function distribute(address _gauge) public lock {\\n IMinter(minter).update_period();\\n _updateFor(_gauge); // should set claimable to 0 if killed\\n uint _claimable = claimable[_gauge];\\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\\n claimable[_gauge] = 0;\\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\\n emit DistributeReward(msg.sender, _gauge, _claimable);\\n }\\n }\\n\\n function distro() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute(uint start, uint finish) public {\\n for (uint x = start; x < finish; x++) {\\n distribute(gauges[pools[x]]);\\n }\\n }\\n\\n function distribute(address[] memory _gauges) external {\\n for (uint x = 0; x < _gauges.length; x++) {\\n distribute(_gauges[x]);\\n }\\n }\\n\\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x16f98751f0144d1758ecb2bec2062be56c718e18d65f0b948fd2a1404b37e6f8\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x61012060405260016011553480156200001757600080fd5b5060405162003656380380620036568339810160408190526200003a916200011c565b6001600160a01b03808516608081905290841660a05260408051637e062a3560e11b8152905163fc0c546a916004808201926020929091908290030181865afa1580156200008c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b2919062000179565b6001600160a01b0390811660c05291821660e0521661010052505060008054336001600160a01b03199182168117909255600180548216831790556002805490911690911790556200019e565b80516001600160a01b03811681146200011757600080fd5b919050565b600080600080608085870312156200013357600080fd5b6200013e85620000ff565b93506200014e60208601620000ff565b92506200015e60408601620000ff565b91506200016e60608601620000ff565b905092959194509250565b6000602082840312156200018c57600080fd5b6200019782620000ff565b9392505050565b60805160a05160c05160e051610100516133e062000276600039600081816103e701528181611c680152611ce60152600081816104d30152611d79015260008181610b9401528181610c0d01528181610edd01528181610f9901528181611acd01528181611b0601528181611b380152611e5a0152600081816106fc015261192401526000818161058c0152818161092b015281816109d701528181610c9a01528181611069015281816111ea0152818161131a015281816114d901528181611dab015281816125e501526129a801526133e06000f3fe608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea264697066735822122025be4046326372dd6cda8be695c22be10d8182eeaeb93fef3c4d85b3e87398fe64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea264697066735822122025be4046326372dd6cda8be695c22be10d8182eeaeb93fef3c4d85b3e87398fe64736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_gauges\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_bribes\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Abstained\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Attach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Detach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributeReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"internal_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"external_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"name\":\"GaugeCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeKilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeRevived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"reward\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NotifyReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Voted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"whitelister\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"Whitelisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"attachTokenToGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bribefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_bribes\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimBribes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_fees\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"}],\"name\":\"claimRewards\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"detachTokenFromGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"finish\",\"type\":\"uint256\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distributeFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distro\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"emergencyCouncil\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"external_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gaugefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"gauges\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_tokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"internal_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isAlive\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isGauge\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isWhitelisted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"killGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"lastVoted\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"length\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"notifyRewardAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"poke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolForGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"poolVote\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"reset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"reviveGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_council\",\"type\":\"address\"}],\"name\":\"setEmergencyCouncil\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"setGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalWeight\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"updateFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"name\":\"updateForRange\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"updateGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedWeights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"_poolVote\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_weights\",\"type\":\"uint256[]\"}],\"name\":\"vote\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"votes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"weights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"whitelist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Voter.sol\":\"Voter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Voter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/libraries/Math.sol';\\nimport 'contracts/interfaces/IBribe.sol';\\nimport 'contracts/interfaces/IBribeFactory.sol';\\nimport 'contracts/interfaces/IGauge.sol';\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/interfaces/IERC20.sol';\\nimport 'contracts/interfaces/IMinter.sol';\\nimport 'contracts/interfaces/IPair.sol';\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/interfaces/IVoter.sol';\\nimport 'contracts/interfaces/IVotingEscrow.sol';\\n\\ncontract Voter is IVoter {\\n\\n address public immutable _ve; // the ve token that governs these contracts\\n address public immutable factory; // the PairFactory\\n address internal immutable base;\\n address public immutable gaugefactory;\\n address public immutable bribefactory;\\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\\n address public minter;\\n address public governor; // should be set to an IGovernor\\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\\n\\n uint public totalWeight; // total voting weight\\n\\n address[] public pools; // all pools viable for incentives\\n mapping(address => address) public gauges; // pool => gauge\\n mapping(address => address) public poolForGauge; // gauge => pool\\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\\n mapping(address => uint256) public weights; // pool => weight\\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\\n mapping(uint => address[]) public poolVote; // nft => pools\\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\\n mapping(address => bool) public isGauge;\\n mapping(address => bool) public isWhitelisted;\\n mapping(address => bool) public isAlive;\\n\\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\\n event GaugeKilled(address indexed gauge);\\n event GaugeRevived(address indexed gauge);\\n event Voted(address indexed voter, uint tokenId, uint256 weight);\\n event Abstained(uint tokenId, uint256 weight);\\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\\n event Whitelisted(address indexed whitelister, address indexed token);\\n\\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\\n _ve = __ve;\\n factory = _factory;\\n base = IVotingEscrow(__ve).token();\\n gaugefactory = _gauges;\\n bribefactory = _bribes;\\n minter = msg.sender;\\n governor = msg.sender;\\n emergencyCouncil = msg.sender;\\n }\\n\\n // simple re-entrancy check\\n uint internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n modifier onlyNewEpoch(uint _tokenId) {\\n // ensure new epoch since last vote \\n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \\\"TOKEN_ALREADY_VOTED_THIS_EPOCH\\\");\\n _;\\n }\\n\\n function initialize(address[] memory _tokens, address _minter) external {\\n require(msg.sender == minter);\\n for (uint i = 0; i < _tokens.length; i++) {\\n _whitelist(_tokens[i]);\\n }\\n minter = _minter;\\n }\\n\\n function setGovernor(address _governor) public {\\n require(msg.sender == governor);\\n governor = _governor;\\n }\\n\\n function setEmergencyCouncil(address _council) public {\\n require(msg.sender == emergencyCouncil);\\n emergencyCouncil = _council;\\n }\\n\\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n lastVoted[_tokenId] = block.timestamp;\\n _reset(_tokenId);\\n IVotingEscrow(_ve).abstain(_tokenId);\\n }\\n\\n function _reset(uint _tokenId) internal {\\n address[] storage _poolVote = poolVote[_tokenId];\\n uint _poolVoteCnt = _poolVote.length;\\n uint256 _totalWeight = 0;\\n\\n for (uint i = 0; i < _poolVoteCnt; i ++) {\\n address _pool = _poolVote[i];\\n uint256 _votes = votes[_tokenId][_pool];\\n\\n if (_votes != 0) {\\n _updateFor(gauges[_pool]);\\n weights[_pool] -= _votes;\\n votes[_tokenId][_pool] -= _votes;\\n if (_votes > 0) {\\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n _totalWeight += _votes;\\n } else {\\n _totalWeight -= _votes;\\n }\\n emit Abstained(_tokenId, _votes);\\n }\\n }\\n totalWeight -= uint256(_totalWeight);\\n usedWeights[_tokenId] = 0;\\n delete poolVote[_tokenId];\\n }\\n\\n function poke(uint _tokenId) external {\\n address[] memory _poolVote = poolVote[_tokenId];\\n uint _poolCnt = _poolVote.length;\\n uint256[] memory _weights = new uint256[](_poolCnt);\\n\\n for (uint i = 0; i < _poolCnt; i ++) {\\n _weights[i] = votes[_tokenId][_poolVote[i]];\\n }\\n\\n _vote(_tokenId, _poolVote, _weights);\\n }\\n\\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\\n _reset(_tokenId);\\n uint _poolCnt = _poolVote.length;\\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\\n uint256 _totalVoteWeight = 0;\\n uint256 _totalWeight = 0;\\n uint256 _usedWeight = 0;\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n _totalVoteWeight += _weights[i];\\n }\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n address _pool = _poolVote[i];\\n address _gauge = gauges[_pool];\\n\\n if (isGauge[_gauge]) {\\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\\n require(votes[_tokenId][_pool] == 0);\\n require(_poolWeight != 0);\\n _updateFor(_gauge);\\n\\n poolVote[_tokenId].push(_pool);\\n\\n weights[_pool] += _poolWeight;\\n votes[_tokenId][_pool] += _poolWeight;\\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n _usedWeight += _poolWeight;\\n _totalWeight += _poolWeight;\\n emit Voted(msg.sender, _tokenId, _poolWeight);\\n }\\n }\\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\\n totalWeight += uint256(_totalWeight);\\n usedWeights[_tokenId] = uint256(_usedWeight);\\n }\\n\\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n require(_poolVote.length == _weights.length);\\n lastVoted[tokenId] = block.timestamp;\\n _vote(tokenId, _poolVote, _weights);\\n }\\n\\n function whitelist(address _token) public {\\n require(msg.sender == governor);\\n _whitelist(_token);\\n }\\n\\n function _whitelist(address _token) internal {\\n require(!isWhitelisted[_token]);\\n isWhitelisted[_token] = true;\\n emit Whitelisted(msg.sender, _token);\\n }\\n\\n function createGauge(address _pool) external returns (address) {\\n require(gauges[_pool] == address(0x0), \\\"exists\\\");\\n address[] memory allowedRewards = new address[](3);\\n address[] memory internalRewards = new address[](2);\\n bool isPair = IPairFactory(factory).isPair(_pool);\\n address tokenA;\\n address tokenB;\\n\\n if (isPair) {\\n (tokenA, tokenB) = IPair(_pool).tokens();\\n allowedRewards[0] = tokenA;\\n allowedRewards[1] = tokenB;\\n internalRewards[0] = tokenA;\\n internalRewards[1] = tokenB;\\n\\n if (base != tokenA && base != tokenB) {\\n allowedRewards[2] = base;\\n }\\n }\\n\\n if (msg.sender != governor) { // gov can create for any pool, even non-Velocimeter pairs\\n require(isPair, \\\"!_pool\\\");\\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \\\"!whitelisted\\\");\\n }\\n\\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\\n\\n IERC20(base).approve(_gauge, type(uint).max);\\n internal_bribes[_gauge] = _internal_bribe;\\n external_bribes[_gauge] = _external_bribe;\\n gauges[_pool] = _gauge;\\n poolForGauge[_gauge] = _pool;\\n isGauge[_gauge] = true;\\n isAlive[_gauge] = true;\\n _updateFor(_gauge);\\n pools.push(_pool);\\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\\n return _gauge;\\n }\\n\\n function killGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(isAlive[_gauge], \\\"gauge already dead\\\");\\n isAlive[_gauge] = false;\\n claimable[_gauge] = 0;\\n emit GaugeKilled(_gauge);\\n }\\n\\n function reviveGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(!isAlive[_gauge], \\\"gauge already alive\\\");\\n isAlive[_gauge] = true;\\n emit GaugeRevived(_gauge);\\n }\\n\\n function attachTokenToGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\\n emit Attach(account, msg.sender, tokenId);\\n }\\n\\n function emitDeposit(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]);\\n emit Deposit(account, msg.sender, tokenId, amount);\\n }\\n\\n function detachTokenFromGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\\n emit Detach(account, msg.sender, tokenId);\\n }\\n\\n function emitWithdraw(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n emit Withdraw(account, msg.sender, tokenId, amount);\\n }\\n\\n function length() external view returns (uint) {\\n return pools.length;\\n }\\n\\n uint internal index;\\n mapping(address => uint) internal supplyIndex;\\n mapping(address => uint) public claimable;\\n\\n function notifyRewardAmount(uint amount) external {\\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index += _ratio;\\n }\\n emit NotifyReward(msg.sender, base, amount);\\n }\\n\\n function updateFor(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n _updateFor(_gauges[i]);\\n }\\n }\\n\\n function updateForRange(uint start, uint end) public {\\n for (uint i = start; i < end; i++) {\\n _updateFor(gauges[pools[i]]);\\n }\\n }\\n\\n function updateAll() external {\\n updateForRange(0, pools.length);\\n }\\n\\n function updateGauge(address _gauge) external {\\n _updateFor(_gauge);\\n }\\n\\n function _updateFor(address _gauge) internal {\\n address _pool = poolForGauge[_gauge];\\n uint256 _supplied = weights[_pool];\\n if (_supplied > 0) {\\n uint _supplyIndex = supplyIndex[_gauge];\\n uint _index = index; // get global index0 for accumulated distro\\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\\n if (_delta > 0) {\\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\\n if (isAlive[_gauge]) {\\n claimable[_gauge] += _share;\\n }\\n }\\n } else {\\n supplyIndex[_gauge] = index; // new users are set to the default global state\\n }\\n }\\n\\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\\n }\\n }\\n\\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _bribes.length; i++) {\\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _fees.length; i++) {\\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function distributeFees(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n if (IGauge(_gauges[i]).isForPair()){\\n IGauge(_gauges[i]).claimFees();\\n }\\n }\\n }\\n\\n function distribute(address _gauge) public lock {\\n IMinter(minter).update_period();\\n _updateFor(_gauge); // should set claimable to 0 if killed\\n uint _claimable = claimable[_gauge];\\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\\n claimable[_gauge] = 0;\\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\\n emit DistributeReward(msg.sender, _gauge, _claimable);\\n }\\n }\\n\\n function distro() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute(uint start, uint finish) public {\\n for (uint x = start; x < finish; x++) {\\n distribute(gauges[pools[x]]);\\n }\\n }\\n\\n function distribute(address[] memory _gauges) external {\\n for (uint x = 0; x < _gauges.length; x++) {\\n distribute(_gauges[x]);\\n }\\n }\\n\\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x16f98751f0144d1758ecb2bec2062be56c718e18d65f0b948fd2a1404b37e6f8\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x61012060405260016011553480156200001757600080fd5b5060405162003656380380620036568339810160408190526200003a916200011c565b6001600160a01b03808516608081905290841660a05260408051637e062a3560e11b8152905163fc0c546a916004808201926020929091908290030181865afa1580156200008c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b2919062000179565b6001600160a01b0390811660c05291821660e0521661010052505060008054336001600160a01b03199182168117909255600180548216831790556002805490911690911790556200019e565b80516001600160a01b03811681146200011757600080fd5b919050565b600080600080608085870312156200013357600080fd5b6200013e85620000ff565b93506200014e60208601620000ff565b92506200015e60408601620000ff565b91506200016e60608601620000ff565b905092959194509250565b6000602082840312156200018c57600080fd5b6200019782620000ff565b9392505050565b60805160a05160c05160e051610100516133e062000276600039600081816103e701528181611c680152611ce60152600081816104d30152611d79015260008181610b9401528181610c0d01528181610edd01528181610f9901528181611acd01528181611b0601528181611b380152611e5a0152600081816106fc015261192401526000818161058c0152818161092b015281816109d701528181610c9a01528181611069015281816111ea0152818161131a015281816114d901528181611dab015281816125e501526129a801526133e06000f3fe608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea264697066735822122080dd20abddf540a84978cd8d25d18b280221a750a6a97ab6b2ae63e4f085c69a64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea264697066735822122080dd20abddf540a84978cd8d25d18b280221a750a6a97ab6b2ae63e4f085c69a64736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/VotingEscrow.json b/deployments/arbitrumGoerli/VotingEscrow.json index b79a084e..7f28abb4 100644 --- a/deployments/arbitrumGoerli/VotingEscrow.json +++ b/deployments/arbitrumGoerli/VotingEscrow.json @@ -1,5 +1,5 @@ { - "address": "0xad0F425b3edB0FC3a06096092B5736A280C90C40", + "address": "0xF003091B78974ee3F99ec70fC5F42fc9810664EC", "abi": [ { "inputs": [ @@ -1521,62 +1521,62 @@ "type": "function" } ], - "transactionHash": "0x3ea792695fe60b47c21fe408f7140a3e8138225c7e1bc8ade003f69f772c9ae2", + "transactionHash": "0xbff671b0179d6778fbe1940e7cc937755277dac04244840fe289626c2920a82e", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xad0F425b3edB0FC3a06096092B5736A280C90C40", + "contractAddress": "0xF003091B78974ee3F99ec70fC5F42fc9810664EC", "transactionIndex": 1, "gasUsed": "4240754", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000200010000000000000000000000000000000000000000000000000000000000008000000000000000000000004000000000000000000000000020400000000000000000800000000000000000000000010000000000000000000000000000000000000040000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xec24a5c8aa055782bd421029ecf458252e5f0195a2d9fc5f2a2ca0ad0a4d2eaa", - "transactionHash": "0x3ea792695fe60b47c21fe408f7140a3e8138225c7e1bc8ade003f69f772c9ae2", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000400000000000000000008000000000000000000000000000000000000000000000000020080000000000000000800000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000008000000000000000000000000000000000000002000000000000000200000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7c564810cfa3661e63b5073dcb86f6ac7d77a5010fa76e3a1622c8107f969043", + "transactionHash": "0xbff671b0179d6778fbe1940e7cc937755277dac04244840fe289626c2920a82e", "logs": [ { "transactionIndex": 1, - "blockNumber": 5814431, - "transactionHash": "0x3ea792695fe60b47c21fe408f7140a3e8138225c7e1bc8ade003f69f772c9ae2", - "address": "0xad0F425b3edB0FC3a06096092B5736A280C90C40", + "blockNumber": 5849210, + "transactionHash": "0xbff671b0179d6778fbe1940e7cc937755277dac04244840fe289626c2920a82e", + "address": "0xF003091B78974ee3F99ec70fC5F42fc9810664EC", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000ad0f425b3edb0fc3a06096092b5736a280c90c40", + "0x000000000000000000000000f003091b78974ee3f99ec70fc5f42fc9810664ec", "0x0000000000000000000000000000000000000000000000000000000000000000" ], "data": "0x", "logIndex": 0, - "blockHash": "0xec24a5c8aa055782bd421029ecf458252e5f0195a2d9fc5f2a2ca0ad0a4d2eaa" + "blockHash": "0x7c564810cfa3661e63b5073dcb86f6ac7d77a5010fa76e3a1622c8107f969043" }, { "transactionIndex": 1, - "blockNumber": 5814431, - "transactionHash": "0x3ea792695fe60b47c21fe408f7140a3e8138225c7e1bc8ade003f69f772c9ae2", - "address": "0xad0F425b3edB0FC3a06096092B5736A280C90C40", + "blockNumber": 5849210, + "transactionHash": "0xbff671b0179d6778fbe1940e7cc937755277dac04244840fe289626c2920a82e", + "address": "0xF003091B78974ee3F99ec70fC5F42fc9810664EC", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x000000000000000000000000ad0f425b3edb0fc3a06096092b5736a280c90c40", + "0x000000000000000000000000f003091b78974ee3f99ec70fc5f42fc9810664ec", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000" ], "data": "0x", "logIndex": 1, - "blockHash": "0xec24a5c8aa055782bd421029ecf458252e5f0195a2d9fc5f2a2ca0ad0a4d2eaa" + "blockHash": "0x7c564810cfa3661e63b5073dcb86f6ac7d77a5010fa76e3a1622c8107f969043" } ], - "blockNumber": 5814431, + "blockNumber": 5849210, "cumulativeGasUsed": "4240754", "status": 1, "byzantium": true }, "args": [ - "0x8c35578054126d4DD063CFaBA40B7F9B63A13981", - "0xfC27470547FA0b96D19146C0490cc444a18A71a9" + "0x0432f39386A9B1d0339c8Ba0af617b16C86ADA05", + "0x053238ccA3E4A334D97c424567C9Add44259cd18" ], - "numDeployments": 5, - "solcInputHash": "1dbda4b04c9e26660611556bc8d2a346", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token_addr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"art_proxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromDelegate\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toDelegate\",\"type\":\"address\"}],\"name\":\"DelegateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"DelegateVotesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"locktime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum VotingEscrow.DepositType\",\"name\":\"deposit_type\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"prevSupply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"supply\",\"type\":\"uint256\"}],\"name\":\"Supply\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DELEGATION_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_DELEGATES\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"abstain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_approved\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"artProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"attach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"attachments\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"balanceOfAtNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_t\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFTAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"block_number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"checkpoints\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"create_lock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"create_lock_for\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"}],\"name\":\"delegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"delegateBySig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"}],\"name\":\"delegates\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"deposit_for\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"detach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastTotalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotesIndex\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"get_last_user_slope\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"increase_amount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"increase_unlock_time\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"isApprovedOrOwner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"locked\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"amount\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"locked__end\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_from\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_to\",\"type\":\"uint256\"}],\"name\":\"merge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"numCheckpoints\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ownership_change\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_proxy\",\"type\":\"address\"}],\"name\":\"setArtProxy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voter\",\"type\":\"address\"}],\"name\":\"setVoter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"slope_changes\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenIndex\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"t\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAtT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_idx\",\"type\":\"uint256\"}],\"name\":\"user_point_history__ts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"voted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"voting\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\",\"details\":\"Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\",\"kind\":\"dev\",\"methods\":{\"approve(address,uint256)\":{\"details\":\"Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address. Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner. Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP) Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"Address to be approved for the given NFT ID.\",\"_tokenId\":\"ID of the token to be approved.\"}},\"balanceOf(address)\":{\"details\":\"Returns the number of NFTs owned by `_owner`. Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\",\"params\":{\"_owner\":\"Address for whom to query the balance.\"}},\"constructor\":{\"params\":{\"token_addr\":\"`FLOW` token address\"}},\"create_lock(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_value\":\"Amount to deposit\"}},\"create_lock_for(uint256,uint256,address)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_to\":\"Address to deposit\",\"_value\":\"Amount to deposit\"}},\"delegate(address)\":{\"params\":{\"delegatee\":\"The address to delegate votes to\"}},\"delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Delegates votes from signer to `delegatee`.\"},\"deposit_for(uint256,uint256)\":{\"details\":\"Anyone (even a smart contract) can deposit for someone else, but cannot extend their locktime and deposit for a brand new user\",\"params\":{\"_tokenId\":\"lock NFT\",\"_value\":\"Amount to add to user's lock\"}},\"getApproved(uint256)\":{\"details\":\"Get the approved address for a single NFT.\",\"params\":{\"_tokenId\":\"ID of the NFT to query the approval of.\"}},\"getVotes(address)\":{\"params\":{\"account\":\"The address to get votes balance\"},\"returns\":{\"_0\":\"The number of current votes for `account`\"}},\"get_last_user_slope(uint256)\":{\"params\":{\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Value of the slope\"}},\"increase_amount(uint256,uint256)\":{\"params\":{\"_value\":\"Amount of tokens to deposit and add to the lock\"}},\"increase_unlock_time(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"New number of seconds until tokens unlock\"}},\"isApprovedForAll(address,address)\":{\"details\":\"Checks if `_operator` is an approved operator for `_owner`.\",\"params\":{\"_operator\":\"The address that acts on behalf of the owner.\",\"_owner\":\"The address that owns the NFTs.\"}},\"locked__end(uint256)\":{\"params\":{\"_tokenId\":\"User NFT\"},\"returns\":{\"_0\":\"Epoch time of the lock end\"}},\"ownerOf(uint256)\":{\"details\":\"Returns the address of the owner of the NFT.\",\"params\":{\"_tokenId\":\"The identifier for an NFT.\"}},\"safeTransferFrom(address,address,uint256)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"safeTransferFrom(address,address,uint256,bytes)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_data\":\"Additional data with no specified format, sent in call to `_to`.\",\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"details\":\"Enables or disables approval for a third party (\\\"operator\\\") to manage all of `msg.sender`'s assets. It also emits the ApprovalForAll event. Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"True if the operators is approved, false to revoke approval.\",\"_operator\":\"Address to add to the set of authorized operators.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Interface identification is specified in ERC-165.\",\"params\":{\"_interfaceID\":\"Id of the interface\"}},\"tokenOfOwnerByIndex(address,uint256)\":{\"details\":\"Get token by index\"},\"tokenURI(uint256)\":{\"details\":\"Returns current token URI metadata\",\"params\":{\"_tokenId\":\"Token ID to fetch URI for.\"}},\"totalSupplyAt(uint256)\":{\"params\":{\"_block\":\"Block to calculate the total voting power at\"},\"returns\":{\"_0\":\"Total voting power at `_block`\"}},\"totalSupplyAtT(uint256)\":{\"details\":\"Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\",\"returns\":{\"_0\":\"Total voting power\"}},\"transferFrom(address,address,uint256)\":{\"details\":\"Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"user_point_history__ts(uint256,uint256)\":{\"params\":{\"_idx\":\"User epoch number\",\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Epoch time of the checkpoint\"}},\"withdraw(uint256)\":{\"details\":\"Only possible if the lock has expired\"}},\"stateVariables\":{\"ERC165_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC165\"},\"ERC721_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721\"},\"ERC721_METADATA_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721Metadata\"},\"_not_entered\":{\"details\":\"reentrancy guard\"},\"idToApprovals\":{\"details\":\"Mapping from NFT ID to approved address.\"},\"idToOwner\":{\"details\":\"Mapping from NFT ID to the address that owns it.\"},\"name\":{\"details\":\"Returns the token collection name.\"},\"ownerToNFTokenCount\":{\"details\":\"Mapping from owner address to count of his tokens.\"},\"ownerToNFTokenIdList\":{\"details\":\"Mapping from owner address to mapping of index to tokenIds\"},\"ownerToOperators\":{\"details\":\"Mapping from owner address to mapping of operator addresses.\"},\"supportedInterfaces\":{\"details\":\"Mapping of interface id to bool about whether or not it's supported\"},\"symbol\":{\"details\":\"Returns the token collection symbol.\"},\"tokenId\":{\"details\":\"Current count of token\"},\"tokenToOwnerIndex\":{\"details\":\"Mapping from NFT ID to index of owner\"}},\"title\":\"Voting Escrow\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DELEGATION_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the delegation struct used by the contract\"},\"DOMAIN_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the contract's domain\"},\"checkpoint()\":{\"notice\":\"Record global data to checkpoint\"},\"checkpoints(address,uint32)\":{\"notice\":\"A record of delegated token checkpoints for each account, by index\"},\"constructor\":{\"notice\":\"Contract constructor\"},\"create_lock(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\"},\"create_lock_for(uint256,uint256,address)\":{\"notice\":\"Deposit `_value` tokens for `_to` and lock for `_lock_duration`\"},\"delegate(address)\":{\"notice\":\"Delegate votes from `msg.sender` to `delegatee`\"},\"delegates(address)\":{\"notice\":\"Overrides the standard `Comp.sol` delegates mapping to return the delegator's own address if they haven't delegated. This avoids having to delegate to oneself.\"},\"deposit_for(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `_tokenId` and add to the lock\"},\"getVotes(address)\":{\"notice\":\"Gets the current votes balance for `account`\"},\"get_last_user_slope(uint256)\":{\"notice\":\"Get the most recently recorded rate of voting power decrease for `_tokenId`\"},\"increase_amount(uint256,uint256)\":{\"notice\":\"Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\"},\"increase_unlock_time(uint256,uint256)\":{\"notice\":\"Extend the unlock time for `_tokenId`\"},\"locked__end(uint256)\":{\"notice\":\"Get timestamp when `_tokenId`'s lock finishes\"},\"nonces(address)\":{\"notice\":\"A record of states for signing / validating signatures\"},\"numCheckpoints(address)\":{\"notice\":\"The number of checkpoints for each account\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"This works even if sender doesn't own any tokens at the time.\"},\"totalSupplyAt(uint256)\":{\"notice\":\"Calculate total voting power at some point in the past\"},\"totalSupplyAtT(uint256)\":{\"notice\":\"Calculate total voting power\"},\"transferFrom(address,address,uint256)\":{\"notice\":\"The caller is responsible to confirm that `_to` is capable of receiving NFTs or else they maybe be permanently lost.\"},\"user_point_history__ts(uint256,uint256)\":{\"notice\":\"Get the timestamp for checkpoint `_idx` for `_tokenId`\"},\"withdraw(uint256)\":{\"notice\":\"Withdraw all tokens for `_tokenId`\"}},\"notice\":\"veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFTVotes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VotingEscrow.sol\":\"VotingEscrow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734383736373131383433\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VotingEscrow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IERC721, IERC721Metadata} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {IERC721Receiver} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {IERC20} from \\\"contracts/interfaces/IERC20.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\nimport {IVotingEscrow} from \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/// @title Voting Escrow\\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\\n enum DepositType {\\n DEPOSIT_FOR_TYPE,\\n CREATE_LOCK_TYPE,\\n INCREASE_LOCK_AMOUNT,\\n INCREASE_UNLOCK_TIME,\\n MERGE_TYPE\\n }\\n\\n struct LockedBalance {\\n int128 amount;\\n uint end;\\n }\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint ts;\\n uint blk; // block\\n }\\n /* We cannot really do block numbers per se b/c slope is per time, not per block\\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\\n * What we can do is to extrapolate ***At functions */\\n\\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\\n struct Checkpoint {\\n uint timestamp;\\n uint[] tokenIds;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Deposit(\\n address indexed provider,\\n uint tokenId,\\n uint value,\\n uint indexed locktime,\\n DepositType deposit_type,\\n uint ts\\n );\\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\\n event Supply(uint prevSupply, uint supply);\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n address public immutable token;\\n address public voter;\\n address public team;\\n address public artProxy;\\n\\n mapping(uint => Point) public point_history; // epoch -> unsigned point\\n\\n /// @dev Mapping of interface id to bool about whether or not it's supported\\n mapping(bytes4 => bool) internal supportedInterfaces;\\n\\n /// @dev ERC165 interface ID of ERC165\\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\\n\\n /// @dev ERC165 interface ID of ERC721\\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\\n\\n /// @dev ERC165 interface ID of ERC721Metadata\\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\\n\\n /// @dev Current count of token\\n uint internal tokenId;\\n\\n /// @notice Contract constructor\\n /// @param token_addr `FLOW` token address\\n constructor(address token_addr, address art_proxy) {\\n token = token_addr;\\n voter = msg.sender;\\n team = msg.sender;\\n artProxy = art_proxy;\\n\\n point_history[0].blk = block.number;\\n point_history[0].ts = block.timestamp;\\n\\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\\n\\n // mint-ish\\n emit Transfer(address(0), address(this), tokenId);\\n // burn-ish\\n emit Transfer(address(this), address(0), tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n MODIFIERS\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev reentrancy guard\\n uint8 internal constant _not_entered = 1;\\n uint8 internal constant _entered = 2;\\n uint8 internal _entered_state = 1;\\n modifier nonreentrant() {\\n require(_entered_state == _not_entered);\\n _entered_state = _entered;\\n _;\\n _entered_state = _not_entered;\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string constant public name = \\\"veNFT\\\";\\n string constant public symbol = \\\"veNFT\\\";\\n string constant public version = \\\"1.0.0\\\";\\n uint8 constant public decimals = 18;\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team);\\n team = _team;\\n }\\n\\n function setArtProxy(address _proxy) external {\\n require(msg.sender == team);\\n artProxy = _proxy;\\n }\\n\\n /// @dev Returns current token URI metadata\\n /// @param _tokenId Token ID to fetch URI for.\\n function tokenURI(uint _tokenId) external view returns (string memory) {\\n require(idToOwner[_tokenId] != address(0), \\\"Query for nonexistent token\\\");\\n LockedBalance memory _locked = locked[_tokenId];\\n return IVeArtProxy(artProxy)._tokenURI(\\n _tokenId,\\n _balanceOfNFT(_tokenId, block.timestamp),\\n _locked.end,\\n uint(int256(_locked.amount))\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 BALANCE/OWNER STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to the address that owns it.\\n mapping(uint => address) internal idToOwner;\\n\\n /// @dev Mapping from owner address to count of his tokens.\\n mapping(address => uint) internal ownerToNFTokenCount;\\n\\n /// @dev Returns the address of the owner of the NFT.\\n /// @param _tokenId The identifier for an NFT.\\n function ownerOf(uint _tokenId) public view returns (address) {\\n return idToOwner[_tokenId];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function _balance(address _owner) internal view returns (uint) {\\n return ownerToNFTokenCount[_owner];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function balanceOf(address _owner) external view returns (uint) {\\n return _balance(_owner);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 APPROVAL STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to approved address.\\n mapping(uint => address) internal idToApprovals;\\n\\n /// @dev Mapping from owner address to mapping of operator addresses.\\n mapping(address => mapping(address => bool)) internal ownerToOperators;\\n\\n mapping(uint => uint) public ownership_change;\\n\\n /// @dev Get the approved address for a single NFT.\\n /// @param _tokenId ID of the NFT to query the approval of.\\n function getApproved(uint _tokenId) external view returns (address) {\\n return idToApprovals[_tokenId];\\n }\\n\\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\\n /// @param _owner The address that owns the NFTs.\\n /// @param _operator The address that acts on behalf of the owner.\\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\\n return (ownerToOperators[_owner])[_operator];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\\n /// @param _approved Address to be approved for the given NFT ID.\\n /// @param _tokenId ID of the token to be approved.\\n function approve(address _approved, uint _tokenId) public {\\n address owner = idToOwner[_tokenId];\\n // Throws if `_tokenId` is not a valid NFT\\n require(owner != address(0));\\n // Throws if `_approved` is the current owner\\n require(_approved != owner);\\n // Check requirements\\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\\n require(senderIsOwner || senderIsApprovedForAll);\\n // Set the approval\\n idToApprovals[_tokenId] = _approved;\\n emit Approval(owner, _approved, _tokenId);\\n }\\n\\n /// @dev Enables or disables approval for a third party (\\\"operator\\\") to manage all of\\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\\n /// @notice This works even if sender doesn't own any tokens at the time.\\n /// @param _operator Address to add to the set of authorized operators.\\n /// @param _approved True if the operators is approved, false to revoke approval.\\n function setApprovalForAll(address _operator, bool _approved) external {\\n // Throws if `_operator` is the `msg.sender`\\n assert(_operator != msg.sender);\\n ownerToOperators[msg.sender][_operator] = _approved;\\n emit ApprovalForAll(msg.sender, _operator, _approved);\\n }\\n\\n /* TRANSFER FUNCTIONS */\\n /// @dev Clear an approval of a given address\\n /// Throws if `_owner` is not the current owner.\\n function _clearApproval(address _owner, uint _tokenId) internal {\\n // Throws if `_owner` is not the current owner\\n assert(idToOwner[_tokenId] == _owner);\\n if (idToApprovals[_tokenId] != address(0)) {\\n // Reset approvals\\n idToApprovals[_tokenId] = address(0);\\n }\\n }\\n\\n /// @dev Returns whether the given spender can transfer a given token ID\\n /// @param _spender address of the spender to query\\n /// @param _tokenId uint ID of the token to be transferred\\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\\n address owner = idToOwner[_tokenId];\\n bool spenderIsOwner = owner == _spender;\\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\\n }\\n\\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\\n return _isApprovedOrOwner(_spender, _tokenId);\\n }\\n\\n /// @dev Exeute transfer of a NFT.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_tokenId` is not a valid NFT.\\n function _transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n address _sender\\n ) internal {\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n // Check requirements\\n require(_isApprovedOrOwner(_sender, _tokenId));\\n // Clear approval. Throws if `_from` is not the current owner\\n _clearApproval(_from, _tokenId);\\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\\n _removeTokenFrom(_from, _tokenId);\\n // auto re-delegate\\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\\n // Add NFT\\n _addTokenTo(_to, _tokenId);\\n // Set the block of ownership transfer (for Flash NFT protection)\\n ownership_change[_tokenId] = block.number;\\n // Log the transfer\\n emit Transfer(_from, _to, _tokenId);\\n }\\n\\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\\n /// they maybe be permanently lost.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n safeTransferFrom(_from, _to, _tokenId, \\\"\\\");\\n }\\n\\n function _isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n uint size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n /// @param _data Additional data with no specified format, sent in call to `_to`.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n bytes memory _data\\n ) public {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n\\n if (_isContract(_to)) {\\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\\n revert(\\\"ERC721: ERC721Receiver rejected tokens\\\");\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert('ERC721: transfer to non ERC721Receiver implementer');\\n } else {\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC165 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Interface identification is specified in ERC-165.\\n /// @param _interfaceID Id of the interface\\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\\n return supportedInterfaces[_interfaceID];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from owner address to mapping of index to tokenIds\\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\\n\\n /// @dev Mapping from NFT ID to index of owner\\n mapping(uint => uint) internal tokenToOwnerIndex;\\n\\n /// @dev Get token by index\\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\\n return ownerToNFTokenIdList[_owner][_tokenIndex];\\n }\\n\\n /// @dev Add a NFT to an index mapping to a given address\\n /// @param _to address of the receiver\\n /// @param _tokenId uint ID Of the token to be added\\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\\n uint current_count = _balance(_to);\\n\\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\\n tokenToOwnerIndex[_tokenId] = current_count;\\n }\\n\\n /// @dev Add a NFT to a given address\\n /// Throws if `_tokenId` is owned by someone.\\n function _addTokenTo(address _to, uint _tokenId) internal {\\n // Throws if `_tokenId` is owned by someone\\n assert(idToOwner[_tokenId] == address(0));\\n // Change the owner\\n idToOwner[_tokenId] = _to;\\n // Update owner token index tracking\\n _addTokenToOwnerList(_to, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_to] += 1;\\n }\\n\\n /// @dev Function to mint tokens\\n /// Throws if `_to` is zero address.\\n /// Throws if `_tokenId` is owned by someone.\\n /// @param _to The address that will receive the minted tokens.\\n /// @param _tokenId The token id to mint.\\n /// @return A boolean that indicates if the operation was successful.\\n function _mint(address _to, uint _tokenId) internal returns (bool) {\\n // Throws if `_to` is zero address\\n assert(_to != address(0));\\n // checkpoint for gov\\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\\n // Add NFT. Throws if `_tokenId` is owned by someone\\n _addTokenTo(_to, _tokenId);\\n emit Transfer(address(0), _to, _tokenId);\\n return true;\\n }\\n\\n /// @dev Remove a NFT from an index mapping to a given address\\n /// @param _from address of the sender\\n /// @param _tokenId uint ID Of the token to be removed\\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\\n // Delete\\n uint current_count = _balance(_from) - 1;\\n uint current_index = tokenToOwnerIndex[_tokenId];\\n\\n if (current_count == current_index) {\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n } else {\\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\\n\\n // Add\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[lastTokenId] = current_index;\\n\\n // Delete\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n }\\n }\\n\\n /// @dev Remove a NFT from a given address\\n /// Throws if `_from` is not the current owner.\\n function _removeTokenFrom(address _from, uint _tokenId) internal {\\n // Throws if `_from` is not the current owner\\n assert(idToOwner[_tokenId] == _from);\\n // Change the owner\\n idToOwner[_tokenId] = address(0);\\n // Update owner token index tracking\\n _removeTokenFromOwnerList(_from, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_from] -= 1;\\n }\\n\\n function _burn(uint _tokenId) internal {\\n require(_isApprovedOrOwner(msg.sender, _tokenId), \\\"caller is not owner nor approved\\\");\\n\\n address owner = ownerOf(_tokenId);\\n\\n // Clear approval\\n approve(address(0), _tokenId);\\n // checkpoint for gov\\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\\n // Remove token\\n _removeTokenFrom(msg.sender, _tokenId);\\n emit Transfer(owner, address(0), _tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public user_point_epoch;\\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\\n mapping(uint => LockedBalance) public locked;\\n uint public epoch;\\n mapping(uint => int128) public slope_changes; // time -> signed slope change\\n uint public supply;\\n\\n uint internal constant WEEK = 1 weeks;\\n uint internal constant MAXTIME = 4 * 365 * 86400;\\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\\n uint internal constant MULTIPLIER = 1 ether;\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @return Value of the slope\\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\\n uint uepoch = user_point_epoch[_tokenId];\\n return user_point_history[_tokenId][uepoch].slope;\\n }\\n\\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @param _idx User epoch number\\n /// @return Epoch time of the checkpoint\\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\\n return user_point_history[_tokenId][_idx].ts;\\n }\\n\\n /// @notice Get timestamp when `_tokenId`'s lock finishes\\n /// @param _tokenId User NFT\\n /// @return Epoch time of the lock end\\n function locked__end(uint _tokenId) external view returns (uint) {\\n return locked[_tokenId].end;\\n }\\n\\n /// @notice Record global and per-user data to checkpoint\\n /// @param _tokenId NFT token ID. No user checkpoint if 0\\n /// @param old_locked Pevious locked amount / end lock time for the user\\n /// @param new_locked New locked amount / end lock time for the user\\n function _checkpoint(\\n uint _tokenId,\\n LockedBalance memory old_locked,\\n LockedBalance memory new_locked\\n ) internal {\\n Point memory u_old;\\n Point memory u_new;\\n int128 old_dslope = 0;\\n int128 new_dslope = 0;\\n uint _epoch = epoch;\\n\\n if (_tokenId != 0) {\\n // Calculate slopes and biases\\n // Kept at zero when they have to\\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\\n u_old.slope = old_locked.amount / iMAXTIME;\\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\\n }\\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\\n u_new.slope = new_locked.amount / iMAXTIME;\\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\\n }\\n\\n // Read values of scheduled changes in the slope\\n // old_locked.end can be in the past and in the future\\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\\n old_dslope = slope_changes[old_locked.end];\\n if (new_locked.end != 0) {\\n if (new_locked.end == old_locked.end) {\\n new_dslope = old_dslope;\\n } else {\\n new_dslope = slope_changes[new_locked.end];\\n }\\n }\\n }\\n\\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\\n if (_epoch > 0) {\\n last_point = point_history[_epoch];\\n }\\n uint last_checkpoint = last_point.ts;\\n // initial_last_point is used for extrapolation to calculate block number\\n // (approximately, for *At methods) and save them\\n // as we cannot figure that out exactly from inside the contract\\n Point memory initial_last_point = last_point;\\n uint block_slope = 0; // dblock/dt\\n if (block.timestamp > last_point.ts) {\\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\\n }\\n // If last point is already recorded in this block, slope=0\\n // But that's ok b/c we know the block in such case\\n\\n // Go over weeks to fill history and calculate what the current point is\\n {\\n uint t_i = (last_checkpoint / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n // Hopefully it won't happen that this won't get used in 5 years!\\n // If it does, users will be able to withdraw but vote weight will be broken\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > block.timestamp) {\\n t_i = block.timestamp;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\\n last_point.slope += d_slope;\\n if (last_point.bias < 0) {\\n // This can happen\\n last_point.bias = 0;\\n }\\n if (last_point.slope < 0) {\\n // This cannot happen - just in case\\n last_point.slope = 0;\\n }\\n last_checkpoint = t_i;\\n last_point.ts = t_i;\\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\\n _epoch += 1;\\n if (t_i == block.timestamp) {\\n last_point.blk = block.number;\\n break;\\n } else {\\n point_history[_epoch] = last_point;\\n }\\n }\\n }\\n\\n epoch = _epoch;\\n // Now point_history is filled until t=now\\n\\n if (_tokenId != 0) {\\n // If last point was in this block, the slope change has been applied already\\n // But in such case we have 0 slope(s)\\n last_point.slope += (u_new.slope - u_old.slope);\\n last_point.bias += (u_new.bias - u_old.bias);\\n if (last_point.slope < 0) {\\n last_point.slope = 0;\\n }\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n }\\n\\n // Record the changed point into history\\n point_history[_epoch] = last_point;\\n\\n if (_tokenId != 0) {\\n // Schedule the slope changes (slope is going down)\\n // We subtract new_user_slope from [new_locked.end]\\n // and add old_user_slope to [old_locked.end]\\n if (old_locked.end > block.timestamp) {\\n // old_dslope was - u_old.slope, so we cancel that\\n old_dslope += u_old.slope;\\n if (new_locked.end == old_locked.end) {\\n old_dslope -= u_new.slope; // It was a new deposit, not extension\\n }\\n slope_changes[old_locked.end] = old_dslope;\\n }\\n\\n if (new_locked.end > block.timestamp) {\\n if (new_locked.end > old_locked.end) {\\n new_dslope -= u_new.slope; // old slope disappeared at this point\\n slope_changes[new_locked.end] = new_dslope;\\n }\\n // else: we recorded it already in old_dslope\\n }\\n // Now handle user history\\n uint user_epoch = user_point_epoch[_tokenId] + 1;\\n\\n user_point_epoch[_tokenId] = user_epoch;\\n u_new.ts = block.timestamp;\\n u_new.blk = block.number;\\n user_point_history[_tokenId][user_epoch] = u_new;\\n }\\n }\\n\\n /// @notice Deposit and lock tokens for a user\\n /// @param _tokenId NFT that holds lock\\n /// @param _value Amount to deposit\\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\\n /// @param locked_balance Previous locked amount / timestamp\\n /// @param deposit_type The type of deposit\\n function _deposit_for(\\n uint _tokenId,\\n uint _value,\\n uint unlock_time,\\n LockedBalance memory locked_balance,\\n DepositType deposit_type\\n ) internal {\\n LockedBalance memory _locked = locked_balance;\\n uint supply_before = supply;\\n\\n supply = supply_before + _value;\\n LockedBalance memory old_locked;\\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\\n // Adding to existing lock, or if a lock is expired - creating a new one\\n _locked.amount += int128(int256(_value));\\n if (unlock_time != 0) {\\n _locked.end = unlock_time;\\n }\\n locked[_tokenId] = _locked;\\n\\n // Possibilities:\\n // Both old_locked.end could be current or expired (>/< block.timestamp)\\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\\n // _locked.end > block.timestamp (always)\\n _checkpoint(_tokenId, old_locked, _locked);\\n\\n address from = msg.sender;\\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\\n assert(IERC20(token).transferFrom(from, address(this), _value));\\n }\\n\\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\\n emit Supply(supply_before, supply_before + _value);\\n }\\n\\n function block_number() external view returns (uint) {\\n return block.number;\\n }\\n\\n /// @notice Record global data to checkpoint\\n function checkpoint() external {\\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\\n }\\n\\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\\n /// cannot extend their locktime and deposit for a brand new user\\n /// @param _tokenId lock NFT\\n /// @param _value Amount to add to user's lock\\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n require(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_value > 0); // dev: need non-zero value\\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n ++tokenId;\\n uint _tokenId = tokenId;\\n _mint(_to, _tokenId);\\n\\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\\n return _tokenId;\\n }\\n\\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, msg.sender);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, _to);\\n }\\n\\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\\n /// @param _value Amount of tokens to deposit and add to the lock\\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n assert(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\\n }\\n\\n /// @notice Extend the unlock time for `_tokenId`\\n /// @param _lock_duration New number of seconds until tokens unlock\\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_locked.end > block.timestamp, 'Lock expired');\\n require(_locked.amount > 0, 'Nothing is locked');\\n require(unlock_time > _locked.end, 'Can only increase lock duration');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\\n }\\n\\n /// @notice Withdraw all tokens for `_tokenId`\\n /// @dev Only possible if the lock has expired\\n function withdraw(uint _tokenId) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n require(block.timestamp >= _locked.end, \\\"The lock didn't expire\\\");\\n uint value = uint(int256(_locked.amount));\\n\\n locked[_tokenId] = LockedBalance(0,0);\\n uint supply_before = supply;\\n supply = supply_before - value;\\n\\n // old_locked can have either expired <= timestamp or zero end\\n // _locked has only 0 end\\n // Both can have >= 0 amount\\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\\n\\n assert(IERC20(token).transfer(msg.sender, value));\\n\\n // Burn the NFT\\n _burn(_tokenId);\\n\\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\\n emit Supply(supply_before, supply_before - value);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\\n // They measure the weights for the purpose of voting, so they don't represent\\n // real coins.\\n\\n /// @notice Binary search to estimate timestamp for block number\\n /// @param _block Block to find\\n /// @param max_epoch Don't go beyond this epoch\\n /// @return Approximate timestamp for block\\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\\n // Binary search\\n uint _min = 0;\\n uint _max = max_epoch;\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (point_history[_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n /// @notice Get the current voting power for `_tokenId`\\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\\n /// @param _tokenId NFT for lock\\n /// @param _t Epoch time to return voting power at\\n /// @return User voting power\\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\\n uint _epoch = user_point_epoch[_tokenId];\\n if (_epoch == 0) {\\n return 0;\\n } else {\\n Point memory last_point = user_point_history[_tokenId][_epoch];\\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(int256(last_point.bias));\\n }\\n }\\n\\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\\n if (ownership_change[_tokenId] == block.number) return 0;\\n return _balanceOfNFT(_tokenId, block.timestamp);\\n }\\n\\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\\n return _balanceOfNFT(_tokenId, _t);\\n }\\n\\n /// @notice Measure voting power of `_tokenId` at block height `_block`\\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\\n /// @param _tokenId User's wallet NFT\\n /// @param _block Block to calculate the voting power at\\n /// @return Voting power\\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\\n // Copying and pasting totalSupply code because Vyper cannot pass by\\n // reference yet\\n assert(_block <= block.number);\\n\\n // Binary search\\n uint _min = 0;\\n uint _max = user_point_epoch[_tokenId];\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (user_point_history[_tokenId][_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n\\n Point memory upoint = user_point_history[_tokenId][_min];\\n\\n uint max_epoch = epoch;\\n uint _epoch = _find_block_epoch(_block, max_epoch);\\n Point memory point_0 = point_history[_epoch];\\n uint d_block = 0;\\n uint d_t = 0;\\n if (_epoch < max_epoch) {\\n Point memory point_1 = point_history[_epoch + 1];\\n d_block = point_1.blk - point_0.blk;\\n d_t = point_1.ts - point_0.ts;\\n } else {\\n d_block = block.number - point_0.blk;\\n d_t = block.timestamp - point_0.ts;\\n }\\n uint block_time = point_0.ts;\\n if (d_block != 0) {\\n block_time += (d_t * (_block - point_0.blk)) / d_block;\\n }\\n\\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\\n if (upoint.bias >= 0) {\\n return uint(uint128(upoint.bias));\\n } else {\\n return 0;\\n }\\n }\\n\\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\\n return _balanceOfAtNFT(_tokenId, _block);\\n }\\n\\n /// @notice Calculate total voting power at some point in the past\\n /// @param _block Block to calculate the total voting power at\\n /// @return Total voting power at `_block`\\n function totalSupplyAt(uint _block) external view returns (uint) {\\n assert(_block <= block.number);\\n uint _epoch = epoch;\\n uint target_epoch = _find_block_epoch(_block, _epoch);\\n\\n Point memory point = point_history[target_epoch];\\n uint dt = 0;\\n if (target_epoch < _epoch) {\\n Point memory point_next = point_history[target_epoch + 1];\\n if (point.blk != point_next.blk) {\\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\\n }\\n } else {\\n if (point.blk != block.number) {\\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\\n }\\n }\\n // Now dt contains info on how far are we beyond point\\n return _supply_at(point, point.ts + dt);\\n }\\n /// @notice Calculate total voting power at some point in the past\\n /// @param point The point (bias/slope) to start search from\\n /// @param t Time to calculate the total voting power at\\n /// @return Total voting power at that time\\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\\n Point memory last_point = point;\\n uint t_i = (last_point.ts / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > t) {\\n t_i = t;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\\n if (t_i == t) {\\n break;\\n }\\n last_point.slope += d_slope;\\n last_point.ts = t_i;\\n }\\n\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(uint128(last_point.bias));\\n }\\n\\n function totalSupply() external view returns (uint) {\\n return totalSupplyAtT(block.timestamp);\\n }\\n\\n /// @notice Calculate total voting power\\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\\n /// @return Total voting power\\n function totalSupplyAtT(uint t) public view returns (uint) {\\n uint _epoch = epoch;\\n Point memory last_point = point_history[_epoch];\\n return _supply_at(last_point, t);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public attachments;\\n mapping(uint => bool) public voted;\\n\\n function setVoter(address _voter) external {\\n require(msg.sender == voter);\\n voter = _voter;\\n }\\n\\n function voting(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = true;\\n }\\n\\n function abstain(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = false;\\n }\\n\\n function attach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] + 1;\\n }\\n\\n function detach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] - 1;\\n }\\n\\n function merge(uint _from, uint _to) external {\\n require(attachments[_from] == 0 && !voted[_from], \\\"attached\\\");\\n require(_from != _to);\\n require(_isApprovedOrOwner(msg.sender, _from));\\n require(_isApprovedOrOwner(msg.sender, _to));\\n\\n LockedBalance memory _locked0 = locked[_from];\\n LockedBalance memory _locked1 = locked[_to];\\n uint value0 = uint(int256(_locked0.amount));\\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\\n\\n locked[_from] = LockedBalance(0, 0);\\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\\n _burn(_from);\\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of each accounts delegate\\n mapping(address => address) private _delegates;\\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\\n\\n /// @notice A record of delegated token checkpoints for each account, by index\\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint32) public numCheckpoints;\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping(address => uint) public nonces;\\n\\n /**\\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\\n * the delegator's own address if they haven't delegated.\\n * This avoids having to delegate to oneself.\\n */\\n function delegates(address delegator) public view returns (address) {\\n address current = _delegates[delegator];\\n return current == address(0) ? delegator : current;\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getVotes(address account) external view returns (uint) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n votes = votes + _balanceOfNFT(tId, block.timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint storage cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPastVotes(address account, uint timestamp)\\n public\\n view\\n returns (uint)\\n {\\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\\n // Sum votes\\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n // Use the provided input timestamp here to get the right decay\\n votes = votes + _balanceOfNFT(tId, timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\\n return totalSupplyAtT(timestamp);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _moveTokenDelegates(\\n address srcRep,\\n address dstRep,\\n uint _tokenId\\n ) internal {\\n if (srcRep != dstRep && _tokenId > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except _tokenId\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (tId != _tokenId) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n // All the same plus _tokenId\\n require(\\n dstRepOld.length + 1 <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n dstRepNew.push(_tokenId);\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _findWhatCheckpointToWrite(address account)\\n internal\\n view\\n returns (uint32)\\n {\\n uint _timestamp = block.timestamp;\\n uint32 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n return _nCheckPoints - 1;\\n } else {\\n return _nCheckPoints;\\n }\\n }\\n\\n function _moveAllDelegates(\\n address owner,\\n address srcRep,\\n address dstRep\\n ) internal {\\n // You can only redelegate what you own\\n if (srcRep != dstRep) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except what owner owns\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (idToOwner[tId] != owner) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n uint ownerTokenCount = ownerToNFTokenCount[owner];\\n require(\\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n // All the same\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n // Plus all that's owned\\n for (uint i = 0; i < ownerTokenCount; i++) {\\n uint tId = ownerToNFTokenIdList[owner][i];\\n dstRepNew.push(tId);\\n }\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\\n address currentDelegate = delegates(delegator);\\n\\n _delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n _moveAllDelegates(delegator, currentDelegate, delegatee);\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n if (delegatee == address(0)) delegatee = msg.sender;\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n function delegateBySig(\\n address delegatee,\\n uint nonce,\\n uint expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public {\\n bytes32 domainSeparator = keccak256(\\n abi.encode(\\n DOMAIN_TYPEHASH,\\n keccak256(bytes(name)),\\n keccak256(bytes(version)),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 structHash = keccak256(\\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash)\\n );\\n address signatory = ecrecover(digest, v, r, s);\\n require(\\n signatory != address(0),\\n \\\"VotingEscrow::delegateBySig: invalid signature\\\"\\n );\\n require(\\n nonce == nonces[signatory]++,\\n \\\"VotingEscrow::delegateBySig: invalid nonce\\\"\\n );\\n require(\\n block.timestamp <= expiry,\\n \\\"VotingEscrow::delegateBySig: signature expired\\\"\\n );\\n return _delegate(signatory, delegatee);\\n }\\n}\\n\",\"keccak256\":\"0x7109ed9d84b5504fe5d4c73d5a10997a0b73f2f4d45813ce5e161997d405fd73\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x41bbb2c41036ca64b2f6c9e973e8cfaa113ebc42af86702cd0d267f915a7e886\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60a06040526006805460ff191660011790553480156200001e57600080fd5b5060405162004a1c38038062004a1c8339810160408190526200004191620001b8565b6001600160a01b0382811660805260008054336001600160a01b031991821681178355600180548316909117815560028054909216938516939093179055437f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f0155427f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f005560046020527f9fe05126d2d9ecf60592e254dead906a4b2e492f36cca727682c38e9008c6ac1805460ff1990811684179091557f4267c0a6fd96b7a87f183ee8744f24d011423cd0e0142b3f563f183d8d9a456b8054821684179055635b5e139f60e01b82527e24030bcf4927897dffe721c2d8dda4bfd8910861687c42b03a463b43b04147805490911690921790915560055460405190913091600080516020620049fc833981519152908290a46005546040516000903090600080516020620049fc833981519152908390a45050620001f0565b80516001600160a01b0381168114620001b357600080fd5b919050565b60008060408385031215620001cc57600080fd5b620001d7836200019b565b9150620001e7602084016200019b565b90509250929050565b6080516147e26200021a60003960008181610b220152818161101801526133b501526147e26000f3fe608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea26469706673582212206c2b69851a7522f6049cd18d9499b246a4af4b4db4af524e781f547e9873d04764736f6c634300080d0033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea26469706673582212206c2b69851a7522f6049cd18d9499b246a4af4b4db4af524e781f547e9873d04764736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token_addr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"art_proxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromDelegate\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toDelegate\",\"type\":\"address\"}],\"name\":\"DelegateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"DelegateVotesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"locktime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum VotingEscrow.DepositType\",\"name\":\"deposit_type\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"prevSupply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"supply\",\"type\":\"uint256\"}],\"name\":\"Supply\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DELEGATION_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_DELEGATES\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"abstain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_approved\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"artProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"attach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"attachments\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"balanceOfAtNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_t\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFTAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"block_number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"checkpoints\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"create_lock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"create_lock_for\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"}],\"name\":\"delegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"delegateBySig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"}],\"name\":\"delegates\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"deposit_for\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"detach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastTotalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotesIndex\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"get_last_user_slope\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"increase_amount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"increase_unlock_time\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"isApprovedOrOwner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"locked\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"amount\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"locked__end\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_from\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_to\",\"type\":\"uint256\"}],\"name\":\"merge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"numCheckpoints\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ownership_change\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_proxy\",\"type\":\"address\"}],\"name\":\"setArtProxy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voter\",\"type\":\"address\"}],\"name\":\"setVoter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"slope_changes\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenIndex\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"t\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAtT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_idx\",\"type\":\"uint256\"}],\"name\":\"user_point_history__ts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"voted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"voting\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\",\"details\":\"Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\",\"kind\":\"dev\",\"methods\":{\"approve(address,uint256)\":{\"details\":\"Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address. Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner. Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP) Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"Address to be approved for the given NFT ID.\",\"_tokenId\":\"ID of the token to be approved.\"}},\"balanceOf(address)\":{\"details\":\"Returns the number of NFTs owned by `_owner`. Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\",\"params\":{\"_owner\":\"Address for whom to query the balance.\"}},\"constructor\":{\"params\":{\"token_addr\":\"`FLOW` token address\"}},\"create_lock(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_value\":\"Amount to deposit\"}},\"create_lock_for(uint256,uint256,address)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_to\":\"Address to deposit\",\"_value\":\"Amount to deposit\"}},\"delegate(address)\":{\"params\":{\"delegatee\":\"The address to delegate votes to\"}},\"delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Delegates votes from signer to `delegatee`.\"},\"deposit_for(uint256,uint256)\":{\"details\":\"Anyone (even a smart contract) can deposit for someone else, but cannot extend their locktime and deposit for a brand new user\",\"params\":{\"_tokenId\":\"lock NFT\",\"_value\":\"Amount to add to user's lock\"}},\"getApproved(uint256)\":{\"details\":\"Get the approved address for a single NFT.\",\"params\":{\"_tokenId\":\"ID of the NFT to query the approval of.\"}},\"getVotes(address)\":{\"params\":{\"account\":\"The address to get votes balance\"},\"returns\":{\"_0\":\"The number of current votes for `account`\"}},\"get_last_user_slope(uint256)\":{\"params\":{\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Value of the slope\"}},\"increase_amount(uint256,uint256)\":{\"params\":{\"_value\":\"Amount of tokens to deposit and add to the lock\"}},\"increase_unlock_time(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"New number of seconds until tokens unlock\"}},\"isApprovedForAll(address,address)\":{\"details\":\"Checks if `_operator` is an approved operator for `_owner`.\",\"params\":{\"_operator\":\"The address that acts on behalf of the owner.\",\"_owner\":\"The address that owns the NFTs.\"}},\"locked__end(uint256)\":{\"params\":{\"_tokenId\":\"User NFT\"},\"returns\":{\"_0\":\"Epoch time of the lock end\"}},\"ownerOf(uint256)\":{\"details\":\"Returns the address of the owner of the NFT.\",\"params\":{\"_tokenId\":\"The identifier for an NFT.\"}},\"safeTransferFrom(address,address,uint256)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"safeTransferFrom(address,address,uint256,bytes)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_data\":\"Additional data with no specified format, sent in call to `_to`.\",\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"details\":\"Enables or disables approval for a third party (\\\"operator\\\") to manage all of `msg.sender`'s assets. It also emits the ApprovalForAll event. Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"True if the operators is approved, false to revoke approval.\",\"_operator\":\"Address to add to the set of authorized operators.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Interface identification is specified in ERC-165.\",\"params\":{\"_interfaceID\":\"Id of the interface\"}},\"tokenOfOwnerByIndex(address,uint256)\":{\"details\":\"Get token by index\"},\"tokenURI(uint256)\":{\"details\":\"Returns current token URI metadata\",\"params\":{\"_tokenId\":\"Token ID to fetch URI for.\"}},\"totalSupplyAt(uint256)\":{\"params\":{\"_block\":\"Block to calculate the total voting power at\"},\"returns\":{\"_0\":\"Total voting power at `_block`\"}},\"totalSupplyAtT(uint256)\":{\"details\":\"Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\",\"returns\":{\"_0\":\"Total voting power\"}},\"transferFrom(address,address,uint256)\":{\"details\":\"Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"user_point_history__ts(uint256,uint256)\":{\"params\":{\"_idx\":\"User epoch number\",\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Epoch time of the checkpoint\"}},\"withdraw(uint256)\":{\"details\":\"Only possible if the lock has expired\"}},\"stateVariables\":{\"ERC165_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC165\"},\"ERC721_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721\"},\"ERC721_METADATA_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721Metadata\"},\"_not_entered\":{\"details\":\"reentrancy guard\"},\"idToApprovals\":{\"details\":\"Mapping from NFT ID to approved address.\"},\"idToOwner\":{\"details\":\"Mapping from NFT ID to the address that owns it.\"},\"name\":{\"details\":\"Returns the token collection name.\"},\"ownerToNFTokenCount\":{\"details\":\"Mapping from owner address to count of his tokens.\"},\"ownerToNFTokenIdList\":{\"details\":\"Mapping from owner address to mapping of index to tokenIds\"},\"ownerToOperators\":{\"details\":\"Mapping from owner address to mapping of operator addresses.\"},\"supportedInterfaces\":{\"details\":\"Mapping of interface id to bool about whether or not it's supported\"},\"symbol\":{\"details\":\"Returns the token collection symbol.\"},\"tokenId\":{\"details\":\"Current count of token\"},\"tokenToOwnerIndex\":{\"details\":\"Mapping from NFT ID to index of owner\"}},\"title\":\"Voting Escrow\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DELEGATION_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the delegation struct used by the contract\"},\"DOMAIN_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the contract's domain\"},\"checkpoint()\":{\"notice\":\"Record global data to checkpoint\"},\"checkpoints(address,uint32)\":{\"notice\":\"A record of delegated token checkpoints for each account, by index\"},\"constructor\":{\"notice\":\"Contract constructor\"},\"create_lock(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\"},\"create_lock_for(uint256,uint256,address)\":{\"notice\":\"Deposit `_value` tokens for `_to` and lock for `_lock_duration`\"},\"delegate(address)\":{\"notice\":\"Delegate votes from `msg.sender` to `delegatee`\"},\"delegates(address)\":{\"notice\":\"Overrides the standard `Comp.sol` delegates mapping to return the delegator's own address if they haven't delegated. This avoids having to delegate to oneself.\"},\"deposit_for(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `_tokenId` and add to the lock\"},\"getVotes(address)\":{\"notice\":\"Gets the current votes balance for `account`\"},\"get_last_user_slope(uint256)\":{\"notice\":\"Get the most recently recorded rate of voting power decrease for `_tokenId`\"},\"increase_amount(uint256,uint256)\":{\"notice\":\"Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\"},\"increase_unlock_time(uint256,uint256)\":{\"notice\":\"Extend the unlock time for `_tokenId`\"},\"locked__end(uint256)\":{\"notice\":\"Get timestamp when `_tokenId`'s lock finishes\"},\"nonces(address)\":{\"notice\":\"A record of states for signing / validating signatures\"},\"numCheckpoints(address)\":{\"notice\":\"The number of checkpoints for each account\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"This works even if sender doesn't own any tokens at the time.\"},\"totalSupplyAt(uint256)\":{\"notice\":\"Calculate total voting power at some point in the past\"},\"totalSupplyAtT(uint256)\":{\"notice\":\"Calculate total voting power\"},\"transferFrom(address,address,uint256)\":{\"notice\":\"The caller is responsible to confirm that `_to` is capable of receiving NFTs or else they maybe be permanently lost.\"},\"user_point_history__ts(uint256,uint256)\":{\"notice\":\"Get the timestamp for checkpoint `_idx` for `_tokenId`\"},\"withdraw(uint256)\":{\"notice\":\"Withdraw all tokens for `_tokenId`\"}},\"notice\":\"veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFTVotes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VotingEscrow.sol\":\"VotingEscrow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VotingEscrow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IERC721, IERC721Metadata} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {IERC721Receiver} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {IERC20} from \\\"contracts/interfaces/IERC20.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\nimport {IVotingEscrow} from \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/// @title Voting Escrow\\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\\n enum DepositType {\\n DEPOSIT_FOR_TYPE,\\n CREATE_LOCK_TYPE,\\n INCREASE_LOCK_AMOUNT,\\n INCREASE_UNLOCK_TIME,\\n MERGE_TYPE\\n }\\n\\n struct LockedBalance {\\n int128 amount;\\n uint end;\\n }\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint ts;\\n uint blk; // block\\n }\\n /* We cannot really do block numbers per se b/c slope is per time, not per block\\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\\n * What we can do is to extrapolate ***At functions */\\n\\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\\n struct Checkpoint {\\n uint timestamp;\\n uint[] tokenIds;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Deposit(\\n address indexed provider,\\n uint tokenId,\\n uint value,\\n uint indexed locktime,\\n DepositType deposit_type,\\n uint ts\\n );\\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\\n event Supply(uint prevSupply, uint supply);\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n address public immutable token;\\n address public voter;\\n address public team;\\n address public artProxy;\\n\\n mapping(uint => Point) public point_history; // epoch -> unsigned point\\n\\n /// @dev Mapping of interface id to bool about whether or not it's supported\\n mapping(bytes4 => bool) internal supportedInterfaces;\\n\\n /// @dev ERC165 interface ID of ERC165\\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\\n\\n /// @dev ERC165 interface ID of ERC721\\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\\n\\n /// @dev ERC165 interface ID of ERC721Metadata\\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\\n\\n /// @dev Current count of token\\n uint internal tokenId;\\n\\n /// @notice Contract constructor\\n /// @param token_addr `FLOW` token address\\n constructor(address token_addr, address art_proxy) {\\n token = token_addr;\\n voter = msg.sender;\\n team = msg.sender;\\n artProxy = art_proxy;\\n\\n point_history[0].blk = block.number;\\n point_history[0].ts = block.timestamp;\\n\\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\\n\\n // mint-ish\\n emit Transfer(address(0), address(this), tokenId);\\n // burn-ish\\n emit Transfer(address(this), address(0), tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n MODIFIERS\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev reentrancy guard\\n uint8 internal constant _not_entered = 1;\\n uint8 internal constant _entered = 2;\\n uint8 internal _entered_state = 1;\\n modifier nonreentrant() {\\n require(_entered_state == _not_entered);\\n _entered_state = _entered;\\n _;\\n _entered_state = _not_entered;\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string constant public name = \\\"veNFT\\\";\\n string constant public symbol = \\\"veNFT\\\";\\n string constant public version = \\\"1.0.0\\\";\\n uint8 constant public decimals = 18;\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team);\\n team = _team;\\n }\\n\\n function setArtProxy(address _proxy) external {\\n require(msg.sender == team);\\n artProxy = _proxy;\\n }\\n\\n /// @dev Returns current token URI metadata\\n /// @param _tokenId Token ID to fetch URI for.\\n function tokenURI(uint _tokenId) external view returns (string memory) {\\n require(idToOwner[_tokenId] != address(0), \\\"Query for nonexistent token\\\");\\n LockedBalance memory _locked = locked[_tokenId];\\n return IVeArtProxy(artProxy)._tokenURI(\\n _tokenId,\\n _balanceOfNFT(_tokenId, block.timestamp),\\n _locked.end,\\n uint(int256(_locked.amount))\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 BALANCE/OWNER STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to the address that owns it.\\n mapping(uint => address) internal idToOwner;\\n\\n /// @dev Mapping from owner address to count of his tokens.\\n mapping(address => uint) internal ownerToNFTokenCount;\\n\\n /// @dev Returns the address of the owner of the NFT.\\n /// @param _tokenId The identifier for an NFT.\\n function ownerOf(uint _tokenId) public view returns (address) {\\n return idToOwner[_tokenId];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function _balance(address _owner) internal view returns (uint) {\\n return ownerToNFTokenCount[_owner];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function balanceOf(address _owner) external view returns (uint) {\\n return _balance(_owner);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 APPROVAL STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to approved address.\\n mapping(uint => address) internal idToApprovals;\\n\\n /// @dev Mapping from owner address to mapping of operator addresses.\\n mapping(address => mapping(address => bool)) internal ownerToOperators;\\n\\n mapping(uint => uint) public ownership_change;\\n\\n /// @dev Get the approved address for a single NFT.\\n /// @param _tokenId ID of the NFT to query the approval of.\\n function getApproved(uint _tokenId) external view returns (address) {\\n return idToApprovals[_tokenId];\\n }\\n\\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\\n /// @param _owner The address that owns the NFTs.\\n /// @param _operator The address that acts on behalf of the owner.\\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\\n return (ownerToOperators[_owner])[_operator];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\\n /// @param _approved Address to be approved for the given NFT ID.\\n /// @param _tokenId ID of the token to be approved.\\n function approve(address _approved, uint _tokenId) public {\\n address owner = idToOwner[_tokenId];\\n // Throws if `_tokenId` is not a valid NFT\\n require(owner != address(0));\\n // Throws if `_approved` is the current owner\\n require(_approved != owner);\\n // Check requirements\\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\\n require(senderIsOwner || senderIsApprovedForAll);\\n // Set the approval\\n idToApprovals[_tokenId] = _approved;\\n emit Approval(owner, _approved, _tokenId);\\n }\\n\\n /// @dev Enables or disables approval for a third party (\\\"operator\\\") to manage all of\\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\\n /// @notice This works even if sender doesn't own any tokens at the time.\\n /// @param _operator Address to add to the set of authorized operators.\\n /// @param _approved True if the operators is approved, false to revoke approval.\\n function setApprovalForAll(address _operator, bool _approved) external {\\n // Throws if `_operator` is the `msg.sender`\\n assert(_operator != msg.sender);\\n ownerToOperators[msg.sender][_operator] = _approved;\\n emit ApprovalForAll(msg.sender, _operator, _approved);\\n }\\n\\n /* TRANSFER FUNCTIONS */\\n /// @dev Clear an approval of a given address\\n /// Throws if `_owner` is not the current owner.\\n function _clearApproval(address _owner, uint _tokenId) internal {\\n // Throws if `_owner` is not the current owner\\n assert(idToOwner[_tokenId] == _owner);\\n if (idToApprovals[_tokenId] != address(0)) {\\n // Reset approvals\\n idToApprovals[_tokenId] = address(0);\\n }\\n }\\n\\n /// @dev Returns whether the given spender can transfer a given token ID\\n /// @param _spender address of the spender to query\\n /// @param _tokenId uint ID of the token to be transferred\\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\\n address owner = idToOwner[_tokenId];\\n bool spenderIsOwner = owner == _spender;\\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\\n }\\n\\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\\n return _isApprovedOrOwner(_spender, _tokenId);\\n }\\n\\n /// @dev Exeute transfer of a NFT.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_tokenId` is not a valid NFT.\\n function _transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n address _sender\\n ) internal {\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n // Check requirements\\n require(_isApprovedOrOwner(_sender, _tokenId));\\n // Clear approval. Throws if `_from` is not the current owner\\n _clearApproval(_from, _tokenId);\\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\\n _removeTokenFrom(_from, _tokenId);\\n // auto re-delegate\\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\\n // Add NFT\\n _addTokenTo(_to, _tokenId);\\n // Set the block of ownership transfer (for Flash NFT protection)\\n ownership_change[_tokenId] = block.number;\\n // Log the transfer\\n emit Transfer(_from, _to, _tokenId);\\n }\\n\\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\\n /// they maybe be permanently lost.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n safeTransferFrom(_from, _to, _tokenId, \\\"\\\");\\n }\\n\\n function _isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n uint size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n /// @param _data Additional data with no specified format, sent in call to `_to`.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n bytes memory _data\\n ) public {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n\\n if (_isContract(_to)) {\\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\\n revert(\\\"ERC721: ERC721Receiver rejected tokens\\\");\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert('ERC721: transfer to non ERC721Receiver implementer');\\n } else {\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC165 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Interface identification is specified in ERC-165.\\n /// @param _interfaceID Id of the interface\\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\\n return supportedInterfaces[_interfaceID];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from owner address to mapping of index to tokenIds\\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\\n\\n /// @dev Mapping from NFT ID to index of owner\\n mapping(uint => uint) internal tokenToOwnerIndex;\\n\\n /// @dev Get token by index\\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\\n return ownerToNFTokenIdList[_owner][_tokenIndex];\\n }\\n\\n /// @dev Add a NFT to an index mapping to a given address\\n /// @param _to address of the receiver\\n /// @param _tokenId uint ID Of the token to be added\\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\\n uint current_count = _balance(_to);\\n\\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\\n tokenToOwnerIndex[_tokenId] = current_count;\\n }\\n\\n /// @dev Add a NFT to a given address\\n /// Throws if `_tokenId` is owned by someone.\\n function _addTokenTo(address _to, uint _tokenId) internal {\\n // Throws if `_tokenId` is owned by someone\\n assert(idToOwner[_tokenId] == address(0));\\n // Change the owner\\n idToOwner[_tokenId] = _to;\\n // Update owner token index tracking\\n _addTokenToOwnerList(_to, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_to] += 1;\\n }\\n\\n /// @dev Function to mint tokens\\n /// Throws if `_to` is zero address.\\n /// Throws if `_tokenId` is owned by someone.\\n /// @param _to The address that will receive the minted tokens.\\n /// @param _tokenId The token id to mint.\\n /// @return A boolean that indicates if the operation was successful.\\n function _mint(address _to, uint _tokenId) internal returns (bool) {\\n // Throws if `_to` is zero address\\n assert(_to != address(0));\\n // checkpoint for gov\\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\\n // Add NFT. Throws if `_tokenId` is owned by someone\\n _addTokenTo(_to, _tokenId);\\n emit Transfer(address(0), _to, _tokenId);\\n return true;\\n }\\n\\n /// @dev Remove a NFT from an index mapping to a given address\\n /// @param _from address of the sender\\n /// @param _tokenId uint ID Of the token to be removed\\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\\n // Delete\\n uint current_count = _balance(_from) - 1;\\n uint current_index = tokenToOwnerIndex[_tokenId];\\n\\n if (current_count == current_index) {\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n } else {\\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\\n\\n // Add\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[lastTokenId] = current_index;\\n\\n // Delete\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n }\\n }\\n\\n /// @dev Remove a NFT from a given address\\n /// Throws if `_from` is not the current owner.\\n function _removeTokenFrom(address _from, uint _tokenId) internal {\\n // Throws if `_from` is not the current owner\\n assert(idToOwner[_tokenId] == _from);\\n // Change the owner\\n idToOwner[_tokenId] = address(0);\\n // Update owner token index tracking\\n _removeTokenFromOwnerList(_from, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_from] -= 1;\\n }\\n\\n function _burn(uint _tokenId) internal {\\n require(_isApprovedOrOwner(msg.sender, _tokenId), \\\"caller is not owner nor approved\\\");\\n\\n address owner = ownerOf(_tokenId);\\n\\n // Clear approval\\n approve(address(0), _tokenId);\\n // checkpoint for gov\\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\\n // Remove token\\n _removeTokenFrom(msg.sender, _tokenId);\\n emit Transfer(owner, address(0), _tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public user_point_epoch;\\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\\n mapping(uint => LockedBalance) public locked;\\n uint public epoch;\\n mapping(uint => int128) public slope_changes; // time -> signed slope change\\n uint public supply;\\n\\n uint internal constant WEEK = 1 weeks;\\n uint internal constant MAXTIME = 4 * 365 * 86400;\\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\\n uint internal constant MULTIPLIER = 1 ether;\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @return Value of the slope\\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\\n uint uepoch = user_point_epoch[_tokenId];\\n return user_point_history[_tokenId][uepoch].slope;\\n }\\n\\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @param _idx User epoch number\\n /// @return Epoch time of the checkpoint\\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\\n return user_point_history[_tokenId][_idx].ts;\\n }\\n\\n /// @notice Get timestamp when `_tokenId`'s lock finishes\\n /// @param _tokenId User NFT\\n /// @return Epoch time of the lock end\\n function locked__end(uint _tokenId) external view returns (uint) {\\n return locked[_tokenId].end;\\n }\\n\\n /// @notice Record global and per-user data to checkpoint\\n /// @param _tokenId NFT token ID. No user checkpoint if 0\\n /// @param old_locked Pevious locked amount / end lock time for the user\\n /// @param new_locked New locked amount / end lock time for the user\\n function _checkpoint(\\n uint _tokenId,\\n LockedBalance memory old_locked,\\n LockedBalance memory new_locked\\n ) internal {\\n Point memory u_old;\\n Point memory u_new;\\n int128 old_dslope = 0;\\n int128 new_dslope = 0;\\n uint _epoch = epoch;\\n\\n if (_tokenId != 0) {\\n // Calculate slopes and biases\\n // Kept at zero when they have to\\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\\n u_old.slope = old_locked.amount / iMAXTIME;\\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\\n }\\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\\n u_new.slope = new_locked.amount / iMAXTIME;\\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\\n }\\n\\n // Read values of scheduled changes in the slope\\n // old_locked.end can be in the past and in the future\\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\\n old_dslope = slope_changes[old_locked.end];\\n if (new_locked.end != 0) {\\n if (new_locked.end == old_locked.end) {\\n new_dslope = old_dslope;\\n } else {\\n new_dslope = slope_changes[new_locked.end];\\n }\\n }\\n }\\n\\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\\n if (_epoch > 0) {\\n last_point = point_history[_epoch];\\n }\\n uint last_checkpoint = last_point.ts;\\n // initial_last_point is used for extrapolation to calculate block number\\n // (approximately, for *At methods) and save them\\n // as we cannot figure that out exactly from inside the contract\\n Point memory initial_last_point = last_point;\\n uint block_slope = 0; // dblock/dt\\n if (block.timestamp > last_point.ts) {\\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\\n }\\n // If last point is already recorded in this block, slope=0\\n // But that's ok b/c we know the block in such case\\n\\n // Go over weeks to fill history and calculate what the current point is\\n {\\n uint t_i = (last_checkpoint / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n // Hopefully it won't happen that this won't get used in 5 years!\\n // If it does, users will be able to withdraw but vote weight will be broken\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > block.timestamp) {\\n t_i = block.timestamp;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\\n last_point.slope += d_slope;\\n if (last_point.bias < 0) {\\n // This can happen\\n last_point.bias = 0;\\n }\\n if (last_point.slope < 0) {\\n // This cannot happen - just in case\\n last_point.slope = 0;\\n }\\n last_checkpoint = t_i;\\n last_point.ts = t_i;\\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\\n _epoch += 1;\\n if (t_i == block.timestamp) {\\n last_point.blk = block.number;\\n break;\\n } else {\\n point_history[_epoch] = last_point;\\n }\\n }\\n }\\n\\n epoch = _epoch;\\n // Now point_history is filled until t=now\\n\\n if (_tokenId != 0) {\\n // If last point was in this block, the slope change has been applied already\\n // But in such case we have 0 slope(s)\\n last_point.slope += (u_new.slope - u_old.slope);\\n last_point.bias += (u_new.bias - u_old.bias);\\n if (last_point.slope < 0) {\\n last_point.slope = 0;\\n }\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n }\\n\\n // Record the changed point into history\\n point_history[_epoch] = last_point;\\n\\n if (_tokenId != 0) {\\n // Schedule the slope changes (slope is going down)\\n // We subtract new_user_slope from [new_locked.end]\\n // and add old_user_slope to [old_locked.end]\\n if (old_locked.end > block.timestamp) {\\n // old_dslope was - u_old.slope, so we cancel that\\n old_dslope += u_old.slope;\\n if (new_locked.end == old_locked.end) {\\n old_dslope -= u_new.slope; // It was a new deposit, not extension\\n }\\n slope_changes[old_locked.end] = old_dslope;\\n }\\n\\n if (new_locked.end > block.timestamp) {\\n if (new_locked.end > old_locked.end) {\\n new_dslope -= u_new.slope; // old slope disappeared at this point\\n slope_changes[new_locked.end] = new_dslope;\\n }\\n // else: we recorded it already in old_dslope\\n }\\n // Now handle user history\\n uint user_epoch = user_point_epoch[_tokenId] + 1;\\n\\n user_point_epoch[_tokenId] = user_epoch;\\n u_new.ts = block.timestamp;\\n u_new.blk = block.number;\\n user_point_history[_tokenId][user_epoch] = u_new;\\n }\\n }\\n\\n /// @notice Deposit and lock tokens for a user\\n /// @param _tokenId NFT that holds lock\\n /// @param _value Amount to deposit\\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\\n /// @param locked_balance Previous locked amount / timestamp\\n /// @param deposit_type The type of deposit\\n function _deposit_for(\\n uint _tokenId,\\n uint _value,\\n uint unlock_time,\\n LockedBalance memory locked_balance,\\n DepositType deposit_type\\n ) internal {\\n LockedBalance memory _locked = locked_balance;\\n uint supply_before = supply;\\n\\n supply = supply_before + _value;\\n LockedBalance memory old_locked;\\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\\n // Adding to existing lock, or if a lock is expired - creating a new one\\n _locked.amount += int128(int256(_value));\\n if (unlock_time != 0) {\\n _locked.end = unlock_time;\\n }\\n locked[_tokenId] = _locked;\\n\\n // Possibilities:\\n // Both old_locked.end could be current or expired (>/< block.timestamp)\\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\\n // _locked.end > block.timestamp (always)\\n _checkpoint(_tokenId, old_locked, _locked);\\n\\n address from = msg.sender;\\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\\n assert(IERC20(token).transferFrom(from, address(this), _value));\\n }\\n\\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\\n emit Supply(supply_before, supply_before + _value);\\n }\\n\\n function block_number() external view returns (uint) {\\n return block.number;\\n }\\n\\n /// @notice Record global data to checkpoint\\n function checkpoint() external {\\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\\n }\\n\\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\\n /// cannot extend their locktime and deposit for a brand new user\\n /// @param _tokenId lock NFT\\n /// @param _value Amount to add to user's lock\\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n require(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_value > 0); // dev: need non-zero value\\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n ++tokenId;\\n uint _tokenId = tokenId;\\n _mint(_to, _tokenId);\\n\\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\\n return _tokenId;\\n }\\n\\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, msg.sender);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, _to);\\n }\\n\\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\\n /// @param _value Amount of tokens to deposit and add to the lock\\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n assert(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\\n }\\n\\n /// @notice Extend the unlock time for `_tokenId`\\n /// @param _lock_duration New number of seconds until tokens unlock\\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_locked.end > block.timestamp, 'Lock expired');\\n require(_locked.amount > 0, 'Nothing is locked');\\n require(unlock_time > _locked.end, 'Can only increase lock duration');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\\n }\\n\\n /// @notice Withdraw all tokens for `_tokenId`\\n /// @dev Only possible if the lock has expired\\n function withdraw(uint _tokenId) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n require(block.timestamp >= _locked.end, \\\"The lock didn't expire\\\");\\n uint value = uint(int256(_locked.amount));\\n\\n locked[_tokenId] = LockedBalance(0,0);\\n uint supply_before = supply;\\n supply = supply_before - value;\\n\\n // old_locked can have either expired <= timestamp or zero end\\n // _locked has only 0 end\\n // Both can have >= 0 amount\\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\\n\\n assert(IERC20(token).transfer(msg.sender, value));\\n\\n // Burn the NFT\\n _burn(_tokenId);\\n\\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\\n emit Supply(supply_before, supply_before - value);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\\n // They measure the weights for the purpose of voting, so they don't represent\\n // real coins.\\n\\n /// @notice Binary search to estimate timestamp for block number\\n /// @param _block Block to find\\n /// @param max_epoch Don't go beyond this epoch\\n /// @return Approximate timestamp for block\\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\\n // Binary search\\n uint _min = 0;\\n uint _max = max_epoch;\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (point_history[_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n /// @notice Get the current voting power for `_tokenId`\\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\\n /// @param _tokenId NFT for lock\\n /// @param _t Epoch time to return voting power at\\n /// @return User voting power\\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\\n uint _epoch = user_point_epoch[_tokenId];\\n if (_epoch == 0) {\\n return 0;\\n } else {\\n Point memory last_point = user_point_history[_tokenId][_epoch];\\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(int256(last_point.bias));\\n }\\n }\\n\\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\\n if (ownership_change[_tokenId] == block.number) return 0;\\n return _balanceOfNFT(_tokenId, block.timestamp);\\n }\\n\\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\\n return _balanceOfNFT(_tokenId, _t);\\n }\\n\\n /// @notice Measure voting power of `_tokenId` at block height `_block`\\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\\n /// @param _tokenId User's wallet NFT\\n /// @param _block Block to calculate the voting power at\\n /// @return Voting power\\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\\n // Copying and pasting totalSupply code because Vyper cannot pass by\\n // reference yet\\n assert(_block <= block.number);\\n\\n // Binary search\\n uint _min = 0;\\n uint _max = user_point_epoch[_tokenId];\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (user_point_history[_tokenId][_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n\\n Point memory upoint = user_point_history[_tokenId][_min];\\n\\n uint max_epoch = epoch;\\n uint _epoch = _find_block_epoch(_block, max_epoch);\\n Point memory point_0 = point_history[_epoch];\\n uint d_block = 0;\\n uint d_t = 0;\\n if (_epoch < max_epoch) {\\n Point memory point_1 = point_history[_epoch + 1];\\n d_block = point_1.blk - point_0.blk;\\n d_t = point_1.ts - point_0.ts;\\n } else {\\n d_block = block.number - point_0.blk;\\n d_t = block.timestamp - point_0.ts;\\n }\\n uint block_time = point_0.ts;\\n if (d_block != 0) {\\n block_time += (d_t * (_block - point_0.blk)) / d_block;\\n }\\n\\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\\n if (upoint.bias >= 0) {\\n return uint(uint128(upoint.bias));\\n } else {\\n return 0;\\n }\\n }\\n\\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\\n return _balanceOfAtNFT(_tokenId, _block);\\n }\\n\\n /// @notice Calculate total voting power at some point in the past\\n /// @param _block Block to calculate the total voting power at\\n /// @return Total voting power at `_block`\\n function totalSupplyAt(uint _block) external view returns (uint) {\\n assert(_block <= block.number);\\n uint _epoch = epoch;\\n uint target_epoch = _find_block_epoch(_block, _epoch);\\n\\n Point memory point = point_history[target_epoch];\\n uint dt = 0;\\n if (target_epoch < _epoch) {\\n Point memory point_next = point_history[target_epoch + 1];\\n if (point.blk != point_next.blk) {\\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\\n }\\n } else {\\n if (point.blk != block.number) {\\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\\n }\\n }\\n // Now dt contains info on how far are we beyond point\\n return _supply_at(point, point.ts + dt);\\n }\\n /// @notice Calculate total voting power at some point in the past\\n /// @param point The point (bias/slope) to start search from\\n /// @param t Time to calculate the total voting power at\\n /// @return Total voting power at that time\\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\\n Point memory last_point = point;\\n uint t_i = (last_point.ts / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > t) {\\n t_i = t;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\\n if (t_i == t) {\\n break;\\n }\\n last_point.slope += d_slope;\\n last_point.ts = t_i;\\n }\\n\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(uint128(last_point.bias));\\n }\\n\\n function totalSupply() external view returns (uint) {\\n return totalSupplyAtT(block.timestamp);\\n }\\n\\n /// @notice Calculate total voting power\\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\\n /// @return Total voting power\\n function totalSupplyAtT(uint t) public view returns (uint) {\\n uint _epoch = epoch;\\n Point memory last_point = point_history[_epoch];\\n return _supply_at(last_point, t);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public attachments;\\n mapping(uint => bool) public voted;\\n\\n function setVoter(address _voter) external {\\n require(msg.sender == voter);\\n voter = _voter;\\n }\\n\\n function voting(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = true;\\n }\\n\\n function abstain(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = false;\\n }\\n\\n function attach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] + 1;\\n }\\n\\n function detach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] - 1;\\n }\\n\\n function merge(uint _from, uint _to) external {\\n require(attachments[_from] == 0 && !voted[_from], \\\"attached\\\");\\n require(_from != _to);\\n require(_isApprovedOrOwner(msg.sender, _from));\\n require(_isApprovedOrOwner(msg.sender, _to));\\n\\n LockedBalance memory _locked0 = locked[_from];\\n LockedBalance memory _locked1 = locked[_to];\\n uint value0 = uint(int256(_locked0.amount));\\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\\n\\n locked[_from] = LockedBalance(0, 0);\\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\\n _burn(_from);\\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of each accounts delegate\\n mapping(address => address) private _delegates;\\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\\n\\n /// @notice A record of delegated token checkpoints for each account, by index\\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint32) public numCheckpoints;\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping(address => uint) public nonces;\\n\\n /**\\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\\n * the delegator's own address if they haven't delegated.\\n * This avoids having to delegate to oneself.\\n */\\n function delegates(address delegator) public view returns (address) {\\n address current = _delegates[delegator];\\n return current == address(0) ? delegator : current;\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getVotes(address account) external view returns (uint) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n votes = votes + _balanceOfNFT(tId, block.timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint storage cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPastVotes(address account, uint timestamp)\\n public\\n view\\n returns (uint)\\n {\\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\\n // Sum votes\\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n // Use the provided input timestamp here to get the right decay\\n votes = votes + _balanceOfNFT(tId, timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\\n return totalSupplyAtT(timestamp);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _moveTokenDelegates(\\n address srcRep,\\n address dstRep,\\n uint _tokenId\\n ) internal {\\n if (srcRep != dstRep && _tokenId > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except _tokenId\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (tId != _tokenId) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n // All the same plus _tokenId\\n require(\\n dstRepOld.length + 1 <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n dstRepNew.push(_tokenId);\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _findWhatCheckpointToWrite(address account)\\n internal\\n view\\n returns (uint32)\\n {\\n uint _timestamp = block.timestamp;\\n uint32 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n return _nCheckPoints - 1;\\n } else {\\n return _nCheckPoints;\\n }\\n }\\n\\n function _moveAllDelegates(\\n address owner,\\n address srcRep,\\n address dstRep\\n ) internal {\\n // You can only redelegate what you own\\n if (srcRep != dstRep) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except what owner owns\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (idToOwner[tId] != owner) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n uint ownerTokenCount = ownerToNFTokenCount[owner];\\n require(\\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n // All the same\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n // Plus all that's owned\\n for (uint i = 0; i < ownerTokenCount; i++) {\\n uint tId = ownerToNFTokenIdList[owner][i];\\n dstRepNew.push(tId);\\n }\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\\n address currentDelegate = delegates(delegator);\\n\\n _delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n _moveAllDelegates(delegator, currentDelegate, delegatee);\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n if (delegatee == address(0)) delegatee = msg.sender;\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n function delegateBySig(\\n address delegatee,\\n uint nonce,\\n uint expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public {\\n bytes32 domainSeparator = keccak256(\\n abi.encode(\\n DOMAIN_TYPEHASH,\\n keccak256(bytes(name)),\\n keccak256(bytes(version)),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 structHash = keccak256(\\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash)\\n );\\n address signatory = ecrecover(digest, v, r, s);\\n require(\\n signatory != address(0),\\n \\\"VotingEscrow::delegateBySig: invalid signature\\\"\\n );\\n require(\\n nonce == nonces[signatory]++,\\n \\\"VotingEscrow::delegateBySig: invalid nonce\\\"\\n );\\n require(\\n block.timestamp <= expiry,\\n \\\"VotingEscrow::delegateBySig: signature expired\\\"\\n );\\n return _delegate(signatory, delegatee);\\n }\\n}\\n\",\"keccak256\":\"0x7109ed9d84b5504fe5d4c73d5a10997a0b73f2f4d45813ce5e161997d405fd73\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x41bbb2c41036ca64b2f6c9e973e8cfaa113ebc42af86702cd0d267f915a7e886\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a06040526006805460ff191660011790553480156200001e57600080fd5b5060405162004a1c38038062004a1c8339810160408190526200004191620001b8565b6001600160a01b0382811660805260008054336001600160a01b031991821681178355600180548316909117815560028054909216938516939093179055437f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f0155427f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f005560046020527f9fe05126d2d9ecf60592e254dead906a4b2e492f36cca727682c38e9008c6ac1805460ff1990811684179091557f4267c0a6fd96b7a87f183ee8744f24d011423cd0e0142b3f563f183d8d9a456b8054821684179055635b5e139f60e01b82527e24030bcf4927897dffe721c2d8dda4bfd8910861687c42b03a463b43b04147805490911690921790915560055460405190913091600080516020620049fc833981519152908290a46005546040516000903090600080516020620049fc833981519152908390a45050620001f0565b80516001600160a01b0381168114620001b357600080fd5b919050565b60008060408385031215620001cc57600080fd5b620001d7836200019b565b9150620001e7602084016200019b565b90509250929050565b6080516147e26200021a60003960008181610b220152818161101801526133b501526147e26000f3fe608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea2646970667358221220e191f45ee9b9ddd82838199fcaf044fa9ba45ffb29c39aba72aeb1c4753b392e64736f6c634300080d0033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea2646970667358221220e191f45ee9b9ddd82838199fcaf044fa9ba45ffb29c39aba72aeb1c4753b392e64736f6c634300080d0033", "devdoc": { "author": "Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)", "details": "Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).", diff --git a/deployments/arbitrumGoerli/solcInputs/0faaa79d8b79020b765ba7705413c447.json b/deployments/arbitrumGoerli/solcInputs/0faaa79d8b79020b765ba7705413c447.json deleted file mode 100644 index 8e0ee1a1..00000000 --- a/deployments/arbitrumGoerli/solcInputs/0faaa79d8b79020b765ba7705413c447.json +++ /dev/null @@ -1,238 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/ExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/factories/BribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" - }, - "contracts/factories/GaugeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" - }, - "contracts/factories/PairFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" - }, - "contracts/factories/WrappedExternalBribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" - }, - "contracts/Gauge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/governance/L2Governor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" - }, - "contracts/governance/L2GovernorCountingSimple.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" - }, - "contracts/governance/L2GovernorVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" - }, - "contracts/governance/L2GovernorVotesQuorumFraction.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" - }, - "contracts/interfaces/IBribe.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IBribeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IERC20.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" - }, - "contracts/interfaces/IGauge.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" - }, - "contracts/interfaces/IGaugeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IMinter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" - }, - "contracts/interfaces/IPair.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IPairCallee.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" - }, - "contracts/interfaces/IPairFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" - }, - "contracts/interfaces/IRewardsDistributor.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" - }, - "contracts/interfaces/IRouter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" - }, - "contracts/interfaces/IVeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" - }, - "contracts/interfaces/IVelo.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" - }, - "contracts/interfaces/IVoter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" - }, - "contracts/interfaces/IVotingEscrow.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" - }, - "contracts/interfaces/IWETH.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" - }, - "contracts/InternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/libraries/Base64.sol": { - "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" - }, - "contracts/libraries/Math.sol": { - "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" - }, - "contracts/Minter.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" - }, - "contracts/Pair.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/PairFees.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" - }, - "contracts/redeem/MerkleClaim.sol": { - "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" - }, - "contracts/redeem/RedemptionReceiver.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" - }, - "contracts/redeem/RedemptionSender.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" - }, - "contracts/RewardsDistributor.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" - }, - "contracts/Router.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" - }, - "contracts/Velo.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" - }, - "contracts/VelodromeLibrary.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" - }, - "contracts/VeloGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" - }, - "contracts/Voter.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VotingEscrow.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" - }, - "contracts/WrappedExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - }, - "metadata": { - "useLiteralContent": true - }, - "libraries": { - "": { - "__CACHE_BREAKER__": "0x0000000000000031363733323636393538333833" - } - } - } -} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/1bc83d498cf3ed68f4ca9abac087a4fd.json b/deployments/arbitrumGoerli/solcInputs/1bc83d498cf3ed68f4ca9abac087a4fd.json deleted file mode 100644 index 58ad9c07..00000000 --- a/deployments/arbitrumGoerli/solcInputs/1bc83d498cf3ed68f4ca9abac087a4fd.json +++ /dev/null @@ -1,238 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/ExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/factories/BribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" - }, - "contracts/factories/GaugeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" - }, - "contracts/factories/PairFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" - }, - "contracts/factories/WrappedExternalBribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" - }, - "contracts/Gauge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/governance/L2Governor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" - }, - "contracts/governance/L2GovernorCountingSimple.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" - }, - "contracts/governance/L2GovernorVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" - }, - "contracts/governance/L2GovernorVotesQuorumFraction.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" - }, - "contracts/interfaces/IBribe.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IBribeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IERC20.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" - }, - "contracts/interfaces/IGauge.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" - }, - "contracts/interfaces/IGaugeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IMinter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" - }, - "contracts/interfaces/IPair.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IPairCallee.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" - }, - "contracts/interfaces/IPairFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" - }, - "contracts/interfaces/IRewardsDistributor.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" - }, - "contracts/interfaces/IRouter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" - }, - "contracts/interfaces/IVeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" - }, - "contracts/interfaces/IVelo.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" - }, - "contracts/interfaces/IVoter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" - }, - "contracts/interfaces/IVotingEscrow.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" - }, - "contracts/interfaces/IWETH.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" - }, - "contracts/InternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/libraries/Base64.sol": { - "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" - }, - "contracts/libraries/Math.sol": { - "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" - }, - "contracts/Minter.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" - }, - "contracts/Pair.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/PairFees.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" - }, - "contracts/redeem/MerkleClaim.sol": { - "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" - }, - "contracts/redeem/RedemptionReceiver.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" - }, - "contracts/redeem/RedemptionSender.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" - }, - "contracts/RewardsDistributor.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" - }, - "contracts/Router.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" - }, - "contracts/Velo.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" - }, - "contracts/VelodromeLibrary.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" - }, - "contracts/VeloGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" - }, - "contracts/Voter.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VotingEscrow.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" - }, - "contracts/WrappedExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - }, - "metadata": { - "useLiteralContent": true - }, - "libraries": { - "": { - "__CACHE_BREAKER__": "0x0000000000000031363733323631313736343534" - } - } - } -} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/230cd08a65e08d438d74567532df4760.json b/deployments/arbitrumGoerli/solcInputs/230cd08a65e08d438d74567532df4760.json deleted file mode 100644 index 260b8af2..00000000 --- a/deployments/arbitrumGoerli/solcInputs/230cd08a65e08d438d74567532df4760.json +++ /dev/null @@ -1,238 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/ExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/factories/BribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" - }, - "contracts/factories/GaugeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" - }, - "contracts/factories/PairFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" - }, - "contracts/factories/WrappedExternalBribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" - }, - "contracts/Gauge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/governance/L2Governor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" - }, - "contracts/governance/L2GovernorCountingSimple.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" - }, - "contracts/governance/L2GovernorVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" - }, - "contracts/governance/L2GovernorVotesQuorumFraction.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" - }, - "contracts/interfaces/IBribe.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IBribeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IERC20.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" - }, - "contracts/interfaces/IGauge.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" - }, - "contracts/interfaces/IGaugeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IMinter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" - }, - "contracts/interfaces/IPair.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IPairCallee.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" - }, - "contracts/interfaces/IPairFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" - }, - "contracts/interfaces/IRewardsDistributor.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" - }, - "contracts/interfaces/IRouter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" - }, - "contracts/interfaces/IVeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" - }, - "contracts/interfaces/IVelo.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" - }, - "contracts/interfaces/IVoter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" - }, - "contracts/interfaces/IVotingEscrow.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" - }, - "contracts/interfaces/IWETH.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" - }, - "contracts/InternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/libraries/Base64.sol": { - "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" - }, - "contracts/libraries/Math.sol": { - "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" - }, - "contracts/Minter.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" - }, - "contracts/Pair.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/PairFees.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" - }, - "contracts/redeem/MerkleClaim.sol": { - "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" - }, - "contracts/redeem/RedemptionReceiver.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" - }, - "contracts/redeem/RedemptionSender.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" - }, - "contracts/RewardsDistributor.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" - }, - "contracts/Router.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" - }, - "contracts/Velo.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" - }, - "contracts/VelodromeLibrary.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" - }, - "contracts/VeloGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" - }, - "contracts/Voter.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VotingEscrow.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" - }, - "contracts/WrappedExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - }, - "metadata": { - "useLiteralContent": true - }, - "libraries": { - "": { - "__CACHE_BREAKER__": "0x0000000000000031363733363638383730363032" - } - } - } -} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/2aff87e12ab2599f097157a40df1b1f2.json b/deployments/arbitrumGoerli/solcInputs/2aff87e12ab2599f097157a40df1b1f2.json deleted file mode 100644 index b313280b..00000000 --- a/deployments/arbitrumGoerli/solcInputs/2aff87e12ab2599f097157a40df1b1f2.json +++ /dev/null @@ -1,238 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/ExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/factories/BribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" - }, - "contracts/factories/GaugeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" - }, - "contracts/factories/PairFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" - }, - "contracts/factories/WrappedExternalBribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" - }, - "contracts/Gauge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/governance/L2Governor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" - }, - "contracts/governance/L2GovernorCountingSimple.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" - }, - "contracts/governance/L2GovernorVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" - }, - "contracts/governance/L2GovernorVotesQuorumFraction.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" - }, - "contracts/interfaces/IBribe.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IBribeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IERC20.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" - }, - "contracts/interfaces/IGauge.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" - }, - "contracts/interfaces/IGaugeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IMinter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" - }, - "contracts/interfaces/IPair.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IPairCallee.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" - }, - "contracts/interfaces/IPairFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" - }, - "contracts/interfaces/IRewardsDistributor.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" - }, - "contracts/interfaces/IRouter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" - }, - "contracts/interfaces/IVeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" - }, - "contracts/interfaces/IVelo.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" - }, - "contracts/interfaces/IVoter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" - }, - "contracts/interfaces/IVotingEscrow.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" - }, - "contracts/interfaces/IWETH.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" - }, - "contracts/InternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/libraries/Base64.sol": { - "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" - }, - "contracts/libraries/Math.sol": { - "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" - }, - "contracts/Minter.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" - }, - "contracts/Pair.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/PairFees.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" - }, - "contracts/redeem/MerkleClaim.sol": { - "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" - }, - "contracts/redeem/RedemptionReceiver.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" - }, - "contracts/redeem/RedemptionSender.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" - }, - "contracts/RewardsDistributor.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" - }, - "contracts/Router.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" - }, - "contracts/Velo.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" - }, - "contracts/VelodromeLibrary.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" - }, - "contracts/VeloGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" - }, - "contracts/Voter.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VotingEscrow.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" - }, - "contracts/WrappedExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - }, - "metadata": { - "useLiteralContent": true - }, - "libraries": { - "": { - "__CACHE_BREAKER__": "0x0000000000000031363733363638353936353432" - } - } - } -} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/44ac1d7fba4690e053e773a8c0d73438.json b/deployments/arbitrumGoerli/solcInputs/44ac1d7fba4690e053e773a8c0d73438.json deleted file mode 100644 index 32ed5454..00000000 --- a/deployments/arbitrumGoerli/solcInputs/44ac1d7fba4690e053e773a8c0d73438.json +++ /dev/null @@ -1,238 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/ExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/factories/BribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" - }, - "contracts/factories/GaugeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" - }, - "contracts/factories/PairFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" - }, - "contracts/factories/WrappedExternalBribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" - }, - "contracts/Gauge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/governance/L2Governor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" - }, - "contracts/governance/L2GovernorCountingSimple.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" - }, - "contracts/governance/L2GovernorVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" - }, - "contracts/governance/L2GovernorVotesQuorumFraction.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" - }, - "contracts/interfaces/IBribe.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IBribeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IERC20.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" - }, - "contracts/interfaces/IGauge.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" - }, - "contracts/interfaces/IGaugeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IMinter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" - }, - "contracts/interfaces/IPair.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IPairCallee.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" - }, - "contracts/interfaces/IPairFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" - }, - "contracts/interfaces/IRewardsDistributor.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" - }, - "contracts/interfaces/IRouter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" - }, - "contracts/interfaces/IVeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" - }, - "contracts/interfaces/IVelo.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" - }, - "contracts/interfaces/IVoter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" - }, - "contracts/interfaces/IVotingEscrow.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" - }, - "contracts/interfaces/IWETH.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" - }, - "contracts/InternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/libraries/Base64.sol": { - "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" - }, - "contracts/libraries/Math.sol": { - "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" - }, - "contracts/Minter.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" - }, - "contracts/Pair.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/PairFees.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" - }, - "contracts/redeem/MerkleClaim.sol": { - "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" - }, - "contracts/redeem/RedemptionReceiver.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" - }, - "contracts/redeem/RedemptionSender.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" - }, - "contracts/RewardsDistributor.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" - }, - "contracts/Router.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" - }, - "contracts/Velo.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" - }, - "contracts/VelodromeLibrary.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" - }, - "contracts/VeloGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" - }, - "contracts/Voter.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VotingEscrow.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" - }, - "contracts/WrappedExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - }, - "metadata": { - "useLiteralContent": true - }, - "libraries": { - "": { - "__CACHE_BREAKER__": "0x0000000000000031363733373432343733333937" - } - } - } -} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/52dedb568751596f5f7bda36f8e139c0.json b/deployments/arbitrumGoerli/solcInputs/52dedb568751596f5f7bda36f8e139c0.json deleted file mode 100644 index 08f67481..00000000 --- a/deployments/arbitrumGoerli/solcInputs/52dedb568751596f5f7bda36f8e139c0.json +++ /dev/null @@ -1,238 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/ExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/factories/BribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" - }, - "contracts/factories/GaugeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" - }, - "contracts/factories/PairFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" - }, - "contracts/factories/WrappedExternalBribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" - }, - "contracts/Gauge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/governance/L2Governor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" - }, - "contracts/governance/L2GovernorCountingSimple.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" - }, - "contracts/governance/L2GovernorVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" - }, - "contracts/governance/L2GovernorVotesQuorumFraction.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" - }, - "contracts/interfaces/IBribe.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IBribeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IERC20.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" - }, - "contracts/interfaces/IGauge.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" - }, - "contracts/interfaces/IGaugeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IMinter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" - }, - "contracts/interfaces/IPair.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IPairCallee.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" - }, - "contracts/interfaces/IPairFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" - }, - "contracts/interfaces/IRewardsDistributor.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" - }, - "contracts/interfaces/IRouter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" - }, - "contracts/interfaces/IVeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" - }, - "contracts/interfaces/IVelo.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" - }, - "contracts/interfaces/IVoter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" - }, - "contracts/interfaces/IVotingEscrow.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" - }, - "contracts/interfaces/IWETH.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" - }, - "contracts/InternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/libraries/Base64.sol": { - "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" - }, - "contracts/libraries/Math.sol": { - "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" - }, - "contracts/Minter.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" - }, - "contracts/Pair.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/PairFees.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" - }, - "contracts/redeem/MerkleClaim.sol": { - "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" - }, - "contracts/redeem/RedemptionReceiver.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" - }, - "contracts/redeem/RedemptionSender.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" - }, - "contracts/RewardsDistributor.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" - }, - "contracts/Router.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" - }, - "contracts/Velo.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" - }, - "contracts/VelodromeLibrary.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" - }, - "contracts/VeloGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" - }, - "contracts/Voter.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VotingEscrow.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" - }, - "contracts/WrappedExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - }, - "metadata": { - "useLiteralContent": true - }, - "libraries": { - "": { - "__CACHE_BREAKER__": "0x0000000000000031363733343336323330373831" - } - } - } -} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/1dbda4b04c9e26660611556bc8d2a346.json b/deployments/arbitrumGoerli/solcInputs/539b862778415c77e4d39b17addb6c5e.json similarity index 99% rename from deployments/arbitrumGoerli/solcInputs/1dbda4b04c9e26660611556bc8d2a346.json rename to deployments/arbitrumGoerli/solcInputs/539b862778415c77e4d39b17addb6c5e.json index 0d153047..41c1d6e5 100644 --- a/deployments/arbitrumGoerli/solcInputs/1dbda4b04c9e26660611556bc8d2a346.json +++ b/deployments/arbitrumGoerli/solcInputs/539b862778415c77e4d39b17addb6c5e.json @@ -231,7 +231,7 @@ }, "libraries": { "": { - "__CACHE_BREAKER__": "0x0000000000000031363734383736373131383433" + "__CACHE_BREAKER__": "0x0000000000000031363734393030303739343537" } } } diff --git a/deployments/arbitrumGoerli/solcInputs/55f774ad815c4347b8fbe726bc77554f.json b/deployments/arbitrumGoerli/solcInputs/55f774ad815c4347b8fbe726bc77554f.json deleted file mode 100644 index 9a06aa66..00000000 --- a/deployments/arbitrumGoerli/solcInputs/55f774ad815c4347b8fbe726bc77554f.json +++ /dev/null @@ -1,238 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/ExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/factories/BribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" - }, - "contracts/factories/GaugeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" - }, - "contracts/factories/PairFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" - }, - "contracts/factories/WrappedExternalBribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" - }, - "contracts/Gauge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/governance/L2Governor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" - }, - "contracts/governance/L2GovernorCountingSimple.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" - }, - "contracts/governance/L2GovernorVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" - }, - "contracts/governance/L2GovernorVotesQuorumFraction.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" - }, - "contracts/interfaces/IBribe.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IBribeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IERC20.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" - }, - "contracts/interfaces/IGauge.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" - }, - "contracts/interfaces/IGaugeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IMinter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" - }, - "contracts/interfaces/IPair.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IPairCallee.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" - }, - "contracts/interfaces/IPairFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" - }, - "contracts/interfaces/IRewardsDistributor.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" - }, - "contracts/interfaces/IRouter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" - }, - "contracts/interfaces/IVeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" - }, - "contracts/interfaces/IVelo.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" - }, - "contracts/interfaces/IVoter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" - }, - "contracts/interfaces/IVotingEscrow.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" - }, - "contracts/interfaces/IWETH.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" - }, - "contracts/InternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/libraries/Base64.sol": { - "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" - }, - "contracts/libraries/Math.sol": { - "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" - }, - "contracts/Minter.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" - }, - "contracts/Pair.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/PairFees.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" - }, - "contracts/redeem/MerkleClaim.sol": { - "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" - }, - "contracts/redeem/RedemptionReceiver.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" - }, - "contracts/redeem/RedemptionSender.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" - }, - "contracts/RewardsDistributor.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" - }, - "contracts/Router.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" - }, - "contracts/Velo.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" - }, - "contracts/VelodromeLibrary.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" - }, - "contracts/VeloGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" - }, - "contracts/Voter.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VotingEscrow.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" - }, - "contracts/WrappedExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - }, - "metadata": { - "useLiteralContent": true - }, - "libraries": { - "": { - "__CACHE_BREAKER__": "0x0000000000000031363733343334303532363533" - } - } - } -} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/4fb7d8e79af343f7b73620261b95024e.json b/deployments/arbitrumGoerli/solcInputs/5e3bd610e528b3bcf2b3d4c538d2d553.json similarity index 99% rename from deployments/arbitrumGoerli/solcInputs/4fb7d8e79af343f7b73620261b95024e.json rename to deployments/arbitrumGoerli/solcInputs/5e3bd610e528b3bcf2b3d4c538d2d553.json index 83a20d4b..e4e82ece 100644 --- a/deployments/arbitrumGoerli/solcInputs/4fb7d8e79af343f7b73620261b95024e.json +++ b/deployments/arbitrumGoerli/solcInputs/5e3bd610e528b3bcf2b3d4c538d2d553.json @@ -20,7 +20,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IFlow.sol\";\n\ncontract Flow is IFlow {\n\n string public constant name = \"Velocimeter\";\n string public constant symbol = \"FLOW\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" }, "contracts/FlowGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velocimeter Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract FlowGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velocimeter Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" }, "contracts/Gauge.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" @@ -231,7 +231,7 @@ }, "libraries": { "": { - "__CACHE_BREAKER__": "0x0000000000000031363734373930343136383836" + "__CACHE_BREAKER__": "0x0000000000000031363734383938323035393133" } } } diff --git a/deployments/arbitrumGoerli/solcInputs/6045e31091c7162ece1e348fdb6fb21d.json b/deployments/arbitrumGoerli/solcInputs/6045e31091c7162ece1e348fdb6fb21d.json deleted file mode 100644 index 8533a328..00000000 --- a/deployments/arbitrumGoerli/solcInputs/6045e31091c7162ece1e348fdb6fb21d.json +++ /dev/null @@ -1,238 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/ExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/factories/BribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" - }, - "contracts/factories/GaugeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" - }, - "contracts/factories/PairFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" - }, - "contracts/factories/WrappedExternalBribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" - }, - "contracts/Gauge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/governance/L2Governor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" - }, - "contracts/governance/L2GovernorCountingSimple.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" - }, - "contracts/governance/L2GovernorVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" - }, - "contracts/governance/L2GovernorVotesQuorumFraction.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" - }, - "contracts/interfaces/IBribe.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IBribeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IERC20.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" - }, - "contracts/interfaces/IGauge.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" - }, - "contracts/interfaces/IGaugeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IMinter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" - }, - "contracts/interfaces/IPair.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IPairCallee.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" - }, - "contracts/interfaces/IPairFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" - }, - "contracts/interfaces/IRewardsDistributor.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" - }, - "contracts/interfaces/IRouter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" - }, - "contracts/interfaces/IVeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" - }, - "contracts/interfaces/IVelo.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" - }, - "contracts/interfaces/IVoter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" - }, - "contracts/interfaces/IVotingEscrow.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" - }, - "contracts/interfaces/IWETH.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" - }, - "contracts/InternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/libraries/Base64.sol": { - "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" - }, - "contracts/libraries/Math.sol": { - "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" - }, - "contracts/Minter.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" - }, - "contracts/Pair.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/PairFees.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" - }, - "contracts/redeem/MerkleClaim.sol": { - "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" - }, - "contracts/redeem/RedemptionReceiver.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" - }, - "contracts/redeem/RedemptionSender.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" - }, - "contracts/RewardsDistributor.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" - }, - "contracts/Router.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" - }, - "contracts/Velo.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" - }, - "contracts/VelodromeLibrary.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" - }, - "contracts/VeloGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" - }, - "contracts/Voter.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VotingEscrow.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" - }, - "contracts/WrappedExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - }, - "metadata": { - "useLiteralContent": true - }, - "libraries": { - "": { - "__CACHE_BREAKER__": "0x0000000000000031363733323539333237323139" - } - } - } -} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/7fabbf584e02c1cd20d7799a434dc4a7.json b/deployments/arbitrumGoerli/solcInputs/7fabbf584e02c1cd20d7799a434dc4a7.json deleted file mode 100644 index affb14c3..00000000 --- a/deployments/arbitrumGoerli/solcInputs/7fabbf584e02c1cd20d7799a434dc4a7.json +++ /dev/null @@ -1,238 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/ExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/factories/BribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" - }, - "contracts/factories/GaugeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" - }, - "contracts/factories/PairFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" - }, - "contracts/factories/WrappedExternalBribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" - }, - "contracts/Gauge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/governance/L2Governor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" - }, - "contracts/governance/L2GovernorCountingSimple.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" - }, - "contracts/governance/L2GovernorVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" - }, - "contracts/governance/L2GovernorVotesQuorumFraction.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" - }, - "contracts/interfaces/IBribe.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IBribeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IERC20.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" - }, - "contracts/interfaces/IGauge.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" - }, - "contracts/interfaces/IGaugeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IMinter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" - }, - "contracts/interfaces/IPair.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IPairCallee.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" - }, - "contracts/interfaces/IPairFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" - }, - "contracts/interfaces/IRewardsDistributor.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" - }, - "contracts/interfaces/IRouter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" - }, - "contracts/interfaces/IVeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" - }, - "contracts/interfaces/IVelo.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" - }, - "contracts/interfaces/IVoter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" - }, - "contracts/interfaces/IVotingEscrow.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" - }, - "contracts/interfaces/IWETH.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" - }, - "contracts/InternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/libraries/Base64.sol": { - "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" - }, - "contracts/libraries/Math.sol": { - "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" - }, - "contracts/Minter.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" - }, - "contracts/Pair.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/PairFees.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" - }, - "contracts/redeem/MerkleClaim.sol": { - "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" - }, - "contracts/redeem/RedemptionReceiver.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" - }, - "contracts/redeem/RedemptionSender.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" - }, - "contracts/RewardsDistributor.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" - }, - "contracts/Router.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" - }, - "contracts/Velo.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" - }, - "contracts/VelodromeLibrary.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" - }, - "contracts/VeloGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" - }, - "contracts/Voter.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VotingEscrow.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" - }, - "contracts/WrappedExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - }, - "metadata": { - "useLiteralContent": true - }, - "libraries": { - "": { - "__CACHE_BREAKER__": "0x0000000000000031363733343336363832383931" - } - } - } -} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/97fe41ab3f7afe2e310d7855146d97a7.json b/deployments/arbitrumGoerli/solcInputs/97fe41ab3f7afe2e310d7855146d97a7.json deleted file mode 100644 index ab266da5..00000000 --- a/deployments/arbitrumGoerli/solcInputs/97fe41ab3f7afe2e310d7855146d97a7.json +++ /dev/null @@ -1,238 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/ExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/factories/BribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" - }, - "contracts/factories/GaugeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" - }, - "contracts/factories/PairFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" - }, - "contracts/factories/WrappedExternalBribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" - }, - "contracts/Gauge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/governance/L2Governor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" - }, - "contracts/governance/L2GovernorCountingSimple.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" - }, - "contracts/governance/L2GovernorVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" - }, - "contracts/governance/L2GovernorVotesQuorumFraction.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" - }, - "contracts/interfaces/IBribe.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IBribeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IERC20.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" - }, - "contracts/interfaces/IGauge.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" - }, - "contracts/interfaces/IGaugeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IMinter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" - }, - "contracts/interfaces/IPair.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IPairCallee.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" - }, - "contracts/interfaces/IPairFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" - }, - "contracts/interfaces/IRewardsDistributor.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" - }, - "contracts/interfaces/IRouter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" - }, - "contracts/interfaces/IVeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" - }, - "contracts/interfaces/IVelo.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" - }, - "contracts/interfaces/IVoter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" - }, - "contracts/interfaces/IVotingEscrow.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" - }, - "contracts/interfaces/IWETH.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" - }, - "contracts/InternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/libraries/Base64.sol": { - "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" - }, - "contracts/libraries/Math.sol": { - "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" - }, - "contracts/Minter.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" - }, - "contracts/Pair.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/PairFees.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" - }, - "contracts/redeem/MerkleClaim.sol": { - "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" - }, - "contracts/redeem/RedemptionReceiver.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" - }, - "contracts/redeem/RedemptionSender.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" - }, - "contracts/RewardsDistributor.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" - }, - "contracts/Router.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" - }, - "contracts/Velo.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" - }, - "contracts/VelodromeLibrary.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" - }, - "contracts/VeloGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" - }, - "contracts/Voter.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VotingEscrow.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" - }, - "contracts/WrappedExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - }, - "metadata": { - "useLiteralContent": true - }, - "libraries": { - "": { - "__CACHE_BREAKER__": "0x0000000000000031363733363638333035323839" - } - } - } -} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/87c2a0284a68497703d818e47e6d0a63.json b/deployments/arbitrumGoerli/solcInputs/98b870afa86e9d5388a96f4e867892a9.json similarity index 99% rename from deployments/arbitrumGoerli/solcInputs/87c2a0284a68497703d818e47e6d0a63.json rename to deployments/arbitrumGoerli/solcInputs/98b870afa86e9d5388a96f4e867892a9.json index 66b1f5f1..bc1c3ae0 100644 --- a/deployments/arbitrumGoerli/solcInputs/87c2a0284a68497703d818e47e6d0a63.json +++ b/deployments/arbitrumGoerli/solcInputs/98b870afa86e9d5388a96f4e867892a9.json @@ -20,7 +20,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IFlow.sol\";\n\ncontract Flow is IFlow {\n\n string public constant name = \"Velocimeter\";\n string public constant symbol = \"FLOW\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" }, "contracts/FlowGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velocimeter Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract FlowGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velocimeter Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" }, "contracts/Gauge.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" @@ -231,7 +231,7 @@ }, "libraries": { "": { - "__CACHE_BREAKER__": "0x0000000000000031363734383736303733333539" + "__CACHE_BREAKER__": "0x0000000000000031363734393030323136323532" } } } diff --git a/deployments/arbitrumGoerli/solcInputs/a6a0d6751205558353275c1f5e5364e9.json b/deployments/arbitrumGoerli/solcInputs/a6a0d6751205558353275c1f5e5364e9.json deleted file mode 100644 index 9b6f3828..00000000 --- a/deployments/arbitrumGoerli/solcInputs/a6a0d6751205558353275c1f5e5364e9.json +++ /dev/null @@ -1,238 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/ExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/factories/BribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" - }, - "contracts/factories/GaugeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" - }, - "contracts/factories/PairFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" - }, - "contracts/factories/WrappedExternalBribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" - }, - "contracts/Gauge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/governance/L2Governor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" - }, - "contracts/governance/L2GovernorCountingSimple.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" - }, - "contracts/governance/L2GovernorVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" - }, - "contracts/governance/L2GovernorVotesQuorumFraction.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" - }, - "contracts/interfaces/IBribe.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IBribeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IERC20.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" - }, - "contracts/interfaces/IGauge.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" - }, - "contracts/interfaces/IGaugeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IMinter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" - }, - "contracts/interfaces/IPair.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IPairCallee.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" - }, - "contracts/interfaces/IPairFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" - }, - "contracts/interfaces/IRewardsDistributor.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" - }, - "contracts/interfaces/IRouter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" - }, - "contracts/interfaces/IVeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" - }, - "contracts/interfaces/IVelo.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" - }, - "contracts/interfaces/IVoter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" - }, - "contracts/interfaces/IVotingEscrow.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" - }, - "contracts/interfaces/IWETH.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" - }, - "contracts/InternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/libraries/Base64.sol": { - "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" - }, - "contracts/libraries/Math.sol": { - "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" - }, - "contracts/Minter.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" - }, - "contracts/Pair.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/PairFees.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" - }, - "contracts/redeem/MerkleClaim.sol": { - "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" - }, - "contracts/redeem/RedemptionReceiver.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" - }, - "contracts/redeem/RedemptionSender.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" - }, - "contracts/RewardsDistributor.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" - }, - "contracts/Router.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" - }, - "contracts/Velo.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" - }, - "contracts/VelodromeLibrary.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" - }, - "contracts/VeloGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" - }, - "contracts/Voter.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VotingEscrow.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" - }, - "contracts/WrappedExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - }, - "metadata": { - "useLiteralContent": true - }, - "libraries": { - "": { - "__CACHE_BREAKER__": "0x0000000000000031363733373430393437383838" - } - } - } -} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/b32caaa26f5963725c04cc29c5c19ad6.json b/deployments/arbitrumGoerli/solcInputs/b32caaa26f5963725c04cc29c5c19ad6.json deleted file mode 100644 index df96ac00..00000000 --- a/deployments/arbitrumGoerli/solcInputs/b32caaa26f5963725c04cc29c5c19ad6.json +++ /dev/null @@ -1,238 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/ExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/factories/BribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" - }, - "contracts/factories/GaugeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" - }, - "contracts/factories/PairFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" - }, - "contracts/factories/WrappedExternalBribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" - }, - "contracts/Gauge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/governance/L2Governor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" - }, - "contracts/governance/L2GovernorCountingSimple.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" - }, - "contracts/governance/L2GovernorVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" - }, - "contracts/governance/L2GovernorVotesQuorumFraction.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" - }, - "contracts/interfaces/IBribe.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IBribeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IERC20.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" - }, - "contracts/interfaces/IGauge.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" - }, - "contracts/interfaces/IGaugeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IMinter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" - }, - "contracts/interfaces/IPair.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IPairCallee.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" - }, - "contracts/interfaces/IPairFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" - }, - "contracts/interfaces/IRewardsDistributor.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" - }, - "contracts/interfaces/IRouter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" - }, - "contracts/interfaces/IVeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" - }, - "contracts/interfaces/IVelo.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" - }, - "contracts/interfaces/IVoter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" - }, - "contracts/interfaces/IVotingEscrow.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" - }, - "contracts/interfaces/IWETH.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" - }, - "contracts/InternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/libraries/Base64.sol": { - "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" - }, - "contracts/libraries/Math.sol": { - "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" - }, - "contracts/Minter.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" - }, - "contracts/Pair.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/PairFees.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" - }, - "contracts/redeem/MerkleClaim.sol": { - "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" - }, - "contracts/redeem/RedemptionReceiver.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" - }, - "contracts/redeem/RedemptionSender.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" - }, - "contracts/RewardsDistributor.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" - }, - "contracts/Router.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" - }, - "contracts/Velo.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" - }, - "contracts/VelodromeLibrary.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" - }, - "contracts/VeloGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" - }, - "contracts/Voter.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VotingEscrow.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" - }, - "contracts/WrappedExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - }, - "metadata": { - "useLiteralContent": true - }, - "libraries": { - "": { - "__CACHE_BREAKER__": "0x0000000000000031363733373336393333303139" - } - } - } -} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/bb56ebd0528f2e0f691b8bc31f08a7c1.json b/deployments/arbitrumGoerli/solcInputs/bb56ebd0528f2e0f691b8bc31f08a7c1.json deleted file mode 100644 index a1310587..00000000 --- a/deployments/arbitrumGoerli/solcInputs/bb56ebd0528f2e0f691b8bc31f08a7c1.json +++ /dev/null @@ -1,238 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/ExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/factories/BribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" - }, - "contracts/factories/GaugeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" - }, - "contracts/factories/PairFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" - }, - "contracts/factories/WrappedExternalBribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" - }, - "contracts/Gauge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/governance/L2Governor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" - }, - "contracts/governance/L2GovernorCountingSimple.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" - }, - "contracts/governance/L2GovernorVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" - }, - "contracts/governance/L2GovernorVotesQuorumFraction.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" - }, - "contracts/interfaces/IBribe.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IBribeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IERC20.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" - }, - "contracts/interfaces/IGauge.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" - }, - "contracts/interfaces/IGaugeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IMinter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" - }, - "contracts/interfaces/IPair.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IPairCallee.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" - }, - "contracts/interfaces/IPairFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" - }, - "contracts/interfaces/IRewardsDistributor.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" - }, - "contracts/interfaces/IRouter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" - }, - "contracts/interfaces/IVeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" - }, - "contracts/interfaces/IVelo.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" - }, - "contracts/interfaces/IVoter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" - }, - "contracts/interfaces/IVotingEscrow.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" - }, - "contracts/interfaces/IWETH.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" - }, - "contracts/InternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/libraries/Base64.sol": { - "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" - }, - "contracts/libraries/Math.sol": { - "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" - }, - "contracts/Minter.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" - }, - "contracts/Pair.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/PairFees.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" - }, - "contracts/redeem/MerkleClaim.sol": { - "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" - }, - "contracts/redeem/RedemptionReceiver.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" - }, - "contracts/redeem/RedemptionSender.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" - }, - "contracts/RewardsDistributor.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" - }, - "contracts/Router.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" - }, - "contracts/Velo.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" - }, - "contracts/VelodromeLibrary.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" - }, - "contracts/VeloGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" - }, - "contracts/Voter.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VotingEscrow.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" - }, - "contracts/WrappedExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - }, - "metadata": { - "useLiteralContent": true - }, - "libraries": { - "": { - "__CACHE_BREAKER__": "0x0000000000000031363733323630303234313031" - } - } - } -} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/d10aa8d28a580b2f5faf1ce0f5049c27.json b/deployments/arbitrumGoerli/solcInputs/d10aa8d28a580b2f5faf1ce0f5049c27.json deleted file mode 100644 index 68471bda..00000000 --- a/deployments/arbitrumGoerli/solcInputs/d10aa8d28a580b2f5faf1ce0f5049c27.json +++ /dev/null @@ -1,238 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/ExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/factories/BribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n\n// if this imports int and ext bribe why is the the gauge factory asking for those address as if they are deployed to an address.\n" - }, - "contracts/factories/GaugeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" - }, - "contracts/factories/PairFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" - }, - "contracts/factories/WrappedExternalBribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" - }, - "contracts/Flow.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IFlow.sol\";\n\ncontract Flow is IFlow {\n\n string public constant name = \"Velocimeter\";\n string public constant symbol = \"FLOW\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" - }, - "contracts/Gauge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/governance/L2Governor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" - }, - "contracts/governance/L2GovernorCountingSimple.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" - }, - "contracts/governance/L2GovernorVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" - }, - "contracts/governance/L2GovernorVotesQuorumFraction.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" - }, - "contracts/interfaces/IBribe.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IBribeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IERC20.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" - }, - "contracts/interfaces/IFlow.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IFlow {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" - }, - "contracts/interfaces/IGauge.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" - }, - "contracts/interfaces/IGaugeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IMinter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" - }, - "contracts/interfaces/IPair.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IPairCallee.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" - }, - "contracts/interfaces/IPairFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" - }, - "contracts/interfaces/IRewardsDistributor.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" - }, - "contracts/interfaces/IRouter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" - }, - "contracts/interfaces/IVeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" - }, - "contracts/interfaces/IVoter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" - }, - "contracts/interfaces/IVotingEscrow.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" - }, - "contracts/interfaces/IWETH.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" - }, - "contracts/InternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/libraries/Base64.sol": { - "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" - }, - "contracts/libraries/Math.sol": { - "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" - }, - "contracts/Minter.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IFlow.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IFlow public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M FLOW (FLOW has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IFlow(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" - }, - "contracts/Pair.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/PairFees.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" - }, - "contracts/redeem/MerkleClaim.sol": { - "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IFlow} from \"contracts/interfaces/IFlow.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims FLOW for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice FLOW token to claim\n IFlow public immutable FLOW;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n FLOW = IFlow(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(FLOW.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" - }, - "contracts/redeem/RedemptionReceiver.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IFlow.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + FLOW\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IFlow public immutable FLOW;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableFLOW;\n uint256 public leftoverFLOW;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n FLOW = IFlow(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableFLOW);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableFLOW\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableFLOW = _redeemableFLOW;\n leftoverFLOW = _redeemableFLOW;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableFLOW);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfFLOW)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata FLOW\n shareOfFLOW = (amountWEVE * redeemableFLOW) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfFLOW) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverFLOW -= shareOfFLOW; // this will revert if underflows\n require(\n FLOW.claim(redemptionAddress, shareOfFLOW),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" - }, - "contracts/redeem/RedemptionSender.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" - }, - "contracts/RewardsDistributor.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" - }, - "contracts/Router.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velocimeter locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" - }, - "contracts/VelodromeLibrary.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" - }, - "contracts/VeloGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velocimeter Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" - }, - "contracts/Voter.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velocimeter pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VotingEscrow.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `FLOW` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" - }, - "contracts/WrappedExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - }, - "metadata": { - "useLiteralContent": true - }, - "libraries": { - "": { - "__CACHE_BREAKER__": "0x0000000000000031363734373837383339303038" - } - } - } -} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/d1b0dfe2e40ce60c1a0cf04472752ec9.json b/deployments/arbitrumGoerli/solcInputs/d1b0dfe2e40ce60c1a0cf04472752ec9.json deleted file mode 100644 index 906e7671..00000000 --- a/deployments/arbitrumGoerli/solcInputs/d1b0dfe2e40ce60c1a0cf04472752ec9.json +++ /dev/null @@ -1,238 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/ExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/factories/BribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n\n// if this imports int and ext bribe why is the the gauge factory asking for those address as if they are deployed to an address.\n" - }, - "contracts/factories/GaugeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" - }, - "contracts/factories/PairFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" - }, - "contracts/factories/WrappedExternalBribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" - }, - "contracts/Flow.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IFlow.sol\";\n\ncontract Flow is IFlow {\n\n string public constant name = \"Velocimeter\";\n string public constant symbol = \"FLOW\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" - }, - "contracts/FlowGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velocimeter Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" - }, - "contracts/Gauge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/governance/L2Governor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" - }, - "contracts/governance/L2GovernorCountingSimple.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" - }, - "contracts/governance/L2GovernorVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" - }, - "contracts/governance/L2GovernorVotesQuorumFraction.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" - }, - "contracts/interfaces/IBribe.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IBribeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IERC20.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" - }, - "contracts/interfaces/IFlow.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IFlow {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" - }, - "contracts/interfaces/IGauge.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" - }, - "contracts/interfaces/IGaugeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IMinter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" - }, - "contracts/interfaces/IPair.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IPairCallee.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" - }, - "contracts/interfaces/IPairFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" - }, - "contracts/interfaces/IRewardsDistributor.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" - }, - "contracts/interfaces/IRouter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" - }, - "contracts/interfaces/IVeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" - }, - "contracts/interfaces/IVoter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" - }, - "contracts/interfaces/IVotingEscrow.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" - }, - "contracts/interfaces/IWETH.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" - }, - "contracts/InternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/libraries/Base64.sol": { - "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" - }, - "contracts/libraries/Math.sol": { - "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" - }, - "contracts/Minter.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IFlow.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IFlow public immutable _flow;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M FLOW (FLOW has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _flow = IFlow(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _flow.mint(address(this), max);\n _flow.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _flow.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _flowTotal = _flow.totalSupply();\n return\n (((((_minted * _veTotal) / _flowTotal) * _veTotal) / _flowTotal) *\n _veTotal) /\n _flowTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _flow.balanceOf(address(this));\n if (_balanceOf < _required) {\n _flow.mint(address(this), _required - _balanceOf);\n }\n\n require(_flow.transfer(team, _teamEmissions));\n require(_flow.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _flow.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" - }, - "contracts/Pair.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/PairFees.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" - }, - "contracts/redeem/MerkleClaim.sol": { - "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IFlow} from \"contracts/interfaces/IFlow.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims FLOW for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice FLOW token to claim\n IFlow public immutable FLOW;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _flow address\n /// @param _merkleRoot of claimees\n constructor(address _flow, bytes32 _merkleRoot) {\n FLOW = IFlow(_flow);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(FLOW.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" - }, - "contracts/redeem/RedemptionReceiver.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IFlow.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + FLOW\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IFlow public immutable FLOW;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableFLOW;\n uint256 public leftoverFLOW;\n\n constructor(\n address _usdc,\n address _flow,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n FLOW = IFlow(_flow);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableFLOW);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableFLOW\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableFLOW = _redeemableFLOW;\n leftoverFLOW = _redeemableFLOW;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableFLOW);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfFLOW)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata FLOW\n shareOfFLOW = (amountWEVE * redeemableFLOW) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfFLOW) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverFLOW -= shareOfFLOW; // this will revert if underflows\n require(\n FLOW.claim(redemptionAddress, shareOfFLOW),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" - }, - "contracts/redeem/RedemptionSender.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" - }, - "contracts/RewardsDistributor.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" - }, - "contracts/Router.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velocimeter locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" - }, - "contracts/VelocimeterLibrary.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelocimeterLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" - }, - "contracts/Voter.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velocimeter pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VotingEscrow.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `FLOW` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" - }, - "contracts/WrappedExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - }, - "metadata": { - "useLiteralContent": true - }, - "libraries": { - "": { - "__CACHE_BREAKER__": "0x0000000000000031363734373930313535343434" - } - } - } -} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/e6fbf9feea298b0eb6ed1dc19df1c5ab.json b/deployments/arbitrumGoerli/solcInputs/e6fbf9feea298b0eb6ed1dc19df1c5ab.json deleted file mode 100644 index bcacefe1..00000000 --- a/deployments/arbitrumGoerli/solcInputs/e6fbf9feea298b0eb6ed1dc19df1c5ab.json +++ /dev/null @@ -1,238 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/ExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/factories/BribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n" - }, - "contracts/factories/GaugeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" - }, - "contracts/factories/PairFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" - }, - "contracts/factories/WrappedExternalBribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" - }, - "contracts/Gauge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/governance/L2Governor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" - }, - "contracts/governance/L2GovernorCountingSimple.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" - }, - "contracts/governance/L2GovernorVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" - }, - "contracts/governance/L2GovernorVotesQuorumFraction.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" - }, - "contracts/interfaces/IBribe.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IBribeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IERC20.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" - }, - "contracts/interfaces/IGauge.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" - }, - "contracts/interfaces/IGaugeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IMinter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" - }, - "contracts/interfaces/IPair.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IPairCallee.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" - }, - "contracts/interfaces/IPairFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" - }, - "contracts/interfaces/IRewardsDistributor.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" - }, - "contracts/interfaces/IRouter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" - }, - "contracts/interfaces/IVeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" - }, - "contracts/interfaces/IVelo.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVelo {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" - }, - "contracts/interfaces/IVoter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" - }, - "contracts/interfaces/IVotingEscrow.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" - }, - "contracts/interfaces/IWETH.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" - }, - "contracts/InternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/libraries/Base64.sol": { - "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" - }, - "contracts/libraries/Math.sol": { - "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" - }, - "contracts/Minter.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IVelo public immutable _velo;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _velo = IVelo(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _velo.mint(address(this), max);\n _velo.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _velo.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _veloTotal = _velo.totalSupply();\n return\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\n _veTotal) /\n _veloTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _velo.balanceOf(address(this));\n if (_balanceOf < _required) {\n _velo.mint(address(this), _required - _balanceOf);\n }\n\n require(_velo.transfer(team, _teamEmissions));\n require(_velo.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _velo.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" - }, - "contracts/Pair.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/PairFees.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" - }, - "contracts/redeem/MerkleClaim.sol": { - "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IVelo} from \"contracts/interfaces/IVelo.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims VELO for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice VELO token to claim\n IVelo public immutable VELO;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _velo address\n /// @param _merkleRoot of claimees\n constructor(address _velo, bytes32 _merkleRoot) {\n VELO = IVelo(_velo);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(VELO.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" - }, - "contracts/redeem/RedemptionReceiver.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVelo.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + VELO\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IVelo public immutable VELO;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableVELO;\n uint256 public leftoverVELO;\n\n constructor(\n address _usdc,\n address _velo,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n VELO = IVelo(_velo);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableVELO);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableVELO\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableVELO = _redeemableVELO;\n leftoverVELO = _redeemableVELO;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableVELO);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfVELO)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata VELO\n shareOfVELO = (amountWEVE * redeemableVELO) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfVELO) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverVELO -= shareOfVELO; // this will revert if underflows\n require(\n VELO.claim(redemptionAddress, shareOfVELO),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" - }, - "contracts/redeem/RedemptionSender.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + VELO (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" - }, - "contracts/RewardsDistributor.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" - }, - "contracts/Router.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" - }, - "contracts/Velo.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IVelo.sol\";\n\ncontract Velo is IVelo {\n\n string public constant name = \"Velodrome\";\n string public constant symbol = \"VELO\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" - }, - "contracts/VelodromeLibrary.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelodromeLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" - }, - "contracts/VeloGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract VeloGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velodrome Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" - }, - "contracts/Voter.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VotingEscrow.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `VELO` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" - }, - "contracts/WrappedExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - }, - "metadata": { - "useLiteralContent": true - }, - "libraries": { - "": { - "__CACHE_BREAKER__": "0x0000000000000031363733323539353134343839" - } - } - } -} \ No newline at end of file diff --git a/dist/deploy/00_velo.d.ts b/dist/deploy/00_velo.d.ts index 68b368bb..d4011bce 100644 --- a/dist/deploy/00_velo.d.ts +++ b/dist/deploy/00_velo.d.ts @@ -1,3 +1,3 @@ -import { DeployFunction } from "hardhat-deploy/types"; -declare const func: DeployFunction; -export default func; +import { DeployFunction } from 'hardhat-deploy/types' +declare const func: DeployFunction +export default func diff --git a/dist/deploy/05_router.js b/dist/deploy/05_router.js index 1f69cde6..d794e0dd 100644 --- a/dist/deploy/05_router.js +++ b/dist/deploy/05_router.js @@ -6,7 +6,7 @@ var __importDefault = } Object.defineProperty(exports, '__esModule', { value: true }) const arbTestnetConfig_1 = __importDefault( - require('../tasks/deploy/constants/arbTestnetConfig') + require('../tasks/deploy/constants/arbConfig') ) const ARB_TEST_CONFIG = arbTestnetConfig_1.default const func = async function (hre) { diff --git a/dist/deploy/13_redemptionReceiver.js b/dist/deploy/13_redemptionReceiver.js index 762b26ea..9860c1de 100644 --- a/dist/deploy/13_redemptionReceiver.js +++ b/dist/deploy/13_redemptionReceiver.js @@ -6,7 +6,7 @@ var __importDefault = } Object.defineProperty(exports, '__esModule', { value: true }) const arbTestnetConfig_1 = __importDefault( - require('../tasks/deploy/constants/arbTestnetConfig') + require('../tasks/deploy/constants/arbConfig') ) const testFantomConfig_1 = __importDefault( require('../tasks/deploy/constants/testFantomConfig') diff --git a/dist/deploy/14_merkleClaim.js b/dist/deploy/14_merkleClaim.js index ed8a6f72..8fab7147 100644 --- a/dist/deploy/14_merkleClaim.js +++ b/dist/deploy/14_merkleClaim.js @@ -6,7 +6,7 @@ var __importDefault = } Object.defineProperty(exports, '__esModule', { value: true }) const arbTestnetConfig_1 = __importDefault( - require('../tasks/deploy/constants/arbTestnetConfig') + require('../tasks/deploy/constants/arbConfig') ) const ARB_TEST_CONFIG = arbTestnetConfig_1.default const func = async function (hre) { diff --git a/dist/deploy/15_init.js b/dist/deploy/15_init.js index 9f2bb6fa..c50722e7 100644 --- a/dist/deploy/15_init.js +++ b/dist/deploy/15_init.js @@ -56,5 +56,5 @@ const func = async function (hre) { return true } exports.default = func -func.tags = ['init_deploy'] -func.id = 'init_deploy' +func.tags = ['Init'] +func.id = 'init' diff --git a/dist/deploy/16_whitelist.js b/dist/deploy/16_whitelist.js index 50cd6bab..b1a40644 100644 --- a/dist/deploy/16_whitelist.js +++ b/dist/deploy/16_whitelist.js @@ -6,7 +6,7 @@ var __importDefault = } Object.defineProperty(exports, '__esModule', { value: true }) const arbTestnetConfig_1 = __importDefault( - require('../tasks/deploy/constants/arbTestnetConfig') + require('../tasks/deploy/constants/arbConfig') ) const ARB_TEST_CONFIG = arbTestnetConfig_1.default const func = async function (hre) { diff --git a/dist/deploy/17_dist.js b/dist/deploy/17_dist.js index 9d3bead7..d5e2dc9b 100644 --- a/dist/deploy/17_dist.js +++ b/dist/deploy/17_dist.js @@ -1,19 +1,27 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const arbTestnetConfig_1 = __importDefault(require("../tasks/deploy/constants/arbTestnetConfig")); -const ARB_TEST_CONFIG = arbTestnetConfig_1.default; +'use strict' +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod } + } +Object.defineProperty(exports, '__esModule', { value: true }) +const arbTestnetConfig_1 = __importDefault( + require('../tasks/deploy/constants/arbConfig') +) +const ARB_TEST_CONFIG = arbTestnetConfig_1.default const func = async function (hre) { - const { ethers } = hre; - const minter = await ethers.getContract("Minter"); - // Initial veVELO distro - await minter.initialize(ARB_TEST_CONFIG.partnerAddrs, ARB_TEST_CONFIG.partnerAmts, ARB_TEST_CONFIG.partnerMax); - console.log("veVELO distributed"); - console.log("Arbitrum Goerli Velocimeter Instruments deployed"); - return true; -}; -exports.default = func; -func.tags = ["initial_dist"]; -func.id = "initial_dist"; + const { ethers } = hre + const minter = await ethers.getContract('Minter') + // Initial veVELO distro + await minter.initialize( + ARB_TEST_CONFIG.partnerAddrs, + ARB_TEST_CONFIG.partnerAmts, + ARB_TEST_CONFIG.partnerMax + ) + console.log('veVELO distributed') + console.log('Arbitrum Goerli Velocimeter Instruments deployed') + return true +} +exports.default = func +func.tags = ['initial_dist'] +func.id = 'initial_dist' diff --git a/dist/hardhat.config.js b/dist/hardhat.config.js index 8a77776c..da26b4ea 100644 --- a/dist/hardhat.config.js +++ b/dist/hardhat.config.js @@ -50,7 +50,7 @@ const config = { url: `https://arb-goerli.g.alchemy.com/v2/${process.env.ALCHEMY_GOERLI_ARBITRUM_API_KEY}`, accounts: [process.env.PRIVATE_KEY], chainId: 421613, - saveDeployments: true, + saveDeployments: false, verify: { etherscan: { apiUrl: 'https://api-goerli.arbiscan.io/', diff --git a/dist/tasks/deploy/arb.js b/dist/tasks/deploy/arb.js index 64b25b66..c112e8a5 100644 --- a/dist/tasks/deploy/arb.js +++ b/dist/tasks/deploy/arb.js @@ -7,9 +7,7 @@ var __importDefault = Object.defineProperty(exports, '__esModule', { value: true }) const config_1 = require('hardhat/config') const arbConfig_1 = __importDefault(require('./constants/arbConfig')) -const arbTestnetConfig_1 = __importDefault( - require('./constants/arbTestnetConfig') -) +const arbTestnetConfig_1 = __importDefault(require('./constants/arbConfig')) const fantomConfig_1 = __importDefault(require('./constants/fantomConfig')) const testFantomConfig_1 = __importDefault( require('./constants/testFantomConfig') @@ -40,7 +38,7 @@ const testFantomConfig_1 = __importDefault( RewardsDistributor, Voter, Minter, - FlowGovernor, + VeloGovernor, RedemptionReceiver, MerkleClaim ] = await Promise.all([ @@ -55,7 +53,7 @@ const testFantomConfig_1 = __importDefault( ethers.getContractFactory('RewardsDistributor'), ethers.getContractFactory('Voter'), ethers.getContractFactory('Minter'), - ethers.getContractFactory('FlowGovernor'), + ethers.getContractFactory('VeloGovernor'), ethers.getContractFactory('RedemptionReceiver'), ethers.getContractFactory('MerkleClaim') ]) @@ -136,9 +134,9 @@ const testFantomConfig_1 = __importDefault( ARB_CONFIG.lzEndpoint, '\n' ) - const governor = await FlowGovernor.deploy(escrow.address) + const governor = await VeloGovernor.deploy(escrow.address) await governor.deployed() - console.log('FlowGovernor deployed to: ', governor.address) + console.log('VeloGovernor deployed to: ', governor.address) console.log('Args: ', escrow.address, '\n') // Airdrop const claim = await MerkleClaim.deploy(flow.address, ARB_CONFIG.merkleRoot) diff --git a/dist/tasks/deploy/constants/arbConfig.js b/dist/tasks/deploy/constants/arbConfig.js index 83452314..0da093d6 100644 --- a/dist/tasks/deploy/constants/arbConfig.js +++ b/dist/tasks/deploy/constants/arbConfig.js @@ -27,7 +27,11 @@ const PARTNER_MAX = ethers_1.ethers.BigNumber.from('78') .mul(MILLION) .mul(TOKEN_DECIMALS) const TEAM_MULTISIG = '0x16ec7CD5E35682B751d0c77c41A4e6a1A3E2DE01' -const TEAM_EOA = '0x16ec7CD5E35682B751d0c77c41A4e6a1A3E2DE01' +const TEAM_EOA = '0x069e85D4F1010DD961897dC8C095FBB5FF297434' +const arbitrumTeam = TEAM_MULTISIG +const velodromeMultisig = TEAM_MULTISIG +const anton = TEAM_MULTISIG +const andre = TEAM_MULTISIG const arbConfig = { // Chain const lzChainId: 110, @@ -39,7 +43,7 @@ const arbConfig = { // Addresses teamEOA: TEAM_EOA, teamMultisig: TEAM_MULTISIG, - coolie: TEAM_EOA, + coolie: 0x03b88dacb7c21b54cefecc297d981e5b721a9df1, dunks: '0x069e85D4F1010DD961897dC8C095FBB5FF297434', ceazor: '0x3c5Aac016EF2F178e8699D6208796A2D67557fe2', faeflow: TEAM_EOA, //update @@ -55,27 +59,19 @@ const arbConfig = { merkleRoot: '0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f', tokenWhitelist: [ - // tokens whitelisted for gauges - '0x4200000000000000000000000000000000000042', - '0x4200000000000000000000000000000000000006', - '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', - '0x2E3D870790dC77A83DD1d18184Acc7439A53f475', - '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', - '0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9', - '0x217D47011b23BB961eB6D93cA9945B7501a5BB11', - '0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb', - '0x67CCEA5bb16181E7b4109c9c2143c24a1c2205Be', - '0x9e1028F5F1D5eDE59748FFceE5532509976840E0', - '0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4', - '0xCB8FA9a76b8e203D8C3797bF438d8FB81Ea3326A', - '0x3E29D3A9316dAB217754d13b28646B76607c5f04', - '0x8aE125E8653821E851F12A49F7765db9a9ce7384', - '0x10010078a54396F62c96dF8532dc2B4847d47ED3', - // "", // BTRFLY -- N/A - // "", // pxFLOW -- N/A - '0xc40F949F8a4e094D1b49a23ea9241D289B7b2819' // LUSD - // "", // wstETH -- N/A - // "", // HOP -- N/A + // '0x4200000000000000000000000000000000000042', // OP + '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', // WETH updated + '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', // USDC updated but do we want to whitelist it? + '0x17FC002b466eEc40DaE837Fc4bE5c67993ddBd6F', // FRAX updated + '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', // DAI + // '0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9', // sUSD not sure on this one + '0x10663b695b8f75647bD3FF0ff609e16D35BbD1eC', // AGG + '0xb96B904ba83DdEeCE47CAADa8B40EE6936D92091' //CRE8R + + // '0x8aE125E8653821E851F12A49F7765db9a9ce7384', // DOLA + // '0x10010078a54396F62c96dF8532dc2B4847d47ED3', // HND + + // '0xc40F949F8a4e094D1b49a23ea9241D289B7b2819' // LUSD ], partnerAddrs: [ TEAM_MULTISIG, // 1 Protocol owned NFT 64m @@ -130,7 +126,7 @@ const arbConfig = { TEAM_MULTISIG // 38 x protcol / partner NFTs # 49 ], partnerAmts: [ - SIXTY_MILLION, // 60 million for protcol owned NFT 15% 1 + SIXTY_MILLION, // 60 million for protcol owned NFT 15% #1 TWO_MILLION, // dunks presale 2 TWO_MILLION, // ceazor presale 3 FOUR_MILLION, // team veFLOW 1% 4 diff --git a/hardhat.config.ts b/hardhat.config.ts index 6d36c6c4..b8699f90 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -53,6 +53,7 @@ const config: HardhatUserConfig = { accounts: [process.env.PRIVATE_KEY!], chainId: 421613, saveDeployments: true, + // deploy: ['dist/deploy/'], verify: { etherscan: { apiUrl: 'https://api-goerli.arbiscan.io', diff --git a/tasks/deploy/arb.ts b/tasks/deploy/arb.ts index fe7166e3..6a28d550 100644 --- a/tasks/deploy/arb.ts +++ b/tasks/deploy/arb.ts @@ -1,6 +1,6 @@ import { task } from 'hardhat/config' import arbConfig from './constants/arbConfig' -import arbTestnetConfig from './constants/arbTestnetConfig' +import arbTestnetConfig from './constants/arbConfig' import arbHardhatConfig from './constants/arbHardhatConfig' import optimismConfig from './constants/optimismConfig' diff --git a/tasks/deploy/arbTest.ts b/tasks/deploy/arbTest.ts index e03b62fc..b77fdaf0 100644 --- a/tasks/deploy/arbTest.ts +++ b/tasks/deploy/arbTest.ts @@ -3,7 +3,7 @@ var fs = require('fs') import optimismConfig from './constants/optimismConfig' import testOptimismConfig from './constants/testOptimismConfig' -import arbTestnetConfig from './constants/arbTestnetConfig' +import arbTestnetConfig from './constants/arbConfig' import fantomConfig from './constants/fantomConfig' import testFantomConfig from './constants/testFantomConfig' diff --git a/tasks/deploy/constants/arbConfig.ts b/tasks/deploy/constants/arbConfig.ts index d8c03b76..cd5be229 100644 --- a/tasks/deploy/constants/arbConfig.ts +++ b/tasks/deploy/constants/arbConfig.ts @@ -4,16 +4,26 @@ const TOKEN_DECIMALS = ethers.BigNumber.from('10').pow( ethers.BigNumber.from('18') ) const MILLION = ethers.BigNumber.from('10').pow(ethers.BigNumber.from('6')) - +const TWO_MILLION = ethers.BigNumber.from('2').mul(MILLION).mul(TOKEN_DECIMALS) const FOUR_MILLION = ethers.BigNumber.from('4').mul(MILLION).mul(TOKEN_DECIMALS) const TEN_MILLION = ethers.BigNumber.from('10').mul(MILLION).mul(TOKEN_DECIMALS) +const TWELEVE_MILLION = ethers.BigNumber.from('12') + .mul(MILLION) + .mul(TOKEN_DECIMALS) const TWENTY_MILLION = ethers.BigNumber.from('20') .mul(MILLION) .mul(TOKEN_DECIMALS) +const SIXTY_MILLION = ethers.BigNumber.from('60') + .mul(MILLION) + .mul(TOKEN_DECIMALS) const PARTNER_MAX = ethers.BigNumber.from('78').mul(MILLION).mul(TOKEN_DECIMALS) -const TEAM_MULTISIG = '0x069e85D4F1010DD961897dC8C095FBB5FF297434' +const TEAM_MULTISIG = '0x16ec7CD5E35682B751d0c77c41A4e6a1A3E2DE01' const TEAM_EOA = '0x069e85D4F1010DD961897dC8C095FBB5FF297434' +const arbitrumTeam = TEAM_MULTISIG +const velodromeMultisig = TEAM_MULTISIG +const anton = TEAM_MULTISIG +const andre = TEAM_MULTISIG const arbConfig = { // Chain const @@ -27,63 +37,139 @@ const arbConfig = { // Addresses teamEOA: TEAM_EOA, teamMultisig: TEAM_MULTISIG, + coolie: TEAM_EOA, + dunks: '0x069e85D4F1010DD961897dC8C095FBB5FF297434', + ceazor: '0x3c5Aac016EF2F178e8699D6208796A2D67557fe2', + faeflow: TEAM_EOA, //update + wtck: TEAM_EOA, + torbik: TEAM_EOA, + + arbitrumTeam: TEAM_MULTISIG, + velodromeMultisig: TEAM_MULTISIG, + anton: TEAM_MULTISIG, + andre: TEAM_MULTISIG, + emergencyCouncil: '0xcC2D01030eC2cd187346F70bFc483F24488C32E8', merkleRoot: '0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f', tokenWhitelist: [ - '0x4200000000000000000000000000000000000042', // OP - '0x4200000000000000000000000000000000000006', // WETH - '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', // USDC - '0x2E3D870790dC77A83DD1d18184Acc7439A53f475', // FRAX + // '0x4200000000000000000000000000000000000042', // OP + '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', // WETH updated + '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', // USDC updated but do we want to whitelist it? + '0x17FC002b466eEc40DaE837Fc4bE5c67993ddBd6F', // FRAX updated '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', // DAI - '0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9', // sUSD - '0x217D47011b23BB961eB6D93cA9945B7501a5BB11', // THALES - '0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb', // LYRA - '0x67CCEA5bb16181E7b4109c9c2143c24a1c2205Be', // FXS - '0x9e1028F5F1D5eDE59748FFceE5532509976840E0', // PERP - '0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4', // SNX - '0xCB8FA9a76b8e203D8C3797bF438d8FB81Ea3326A', // alUSD - '0x3E29D3A9316dAB217754d13b28646B76607c5f04', // alETH - '0x8aE125E8653821E851F12A49F7765db9a9ce7384', // DOLA - '0x10010078a54396F62c96dF8532dc2B4847d47ED3', // HND - // "", // BTRFLY -- N/A - // "", // pxVELO -- N/A - '0xc40F949F8a4e094D1b49a23ea9241D289B7b2819' // LUSD - // "", // wstETH -- N/A - // "", // HOP -- N/A + // '0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9', // sUSD not sure on this one + '0x10663b695b8f75647bD3FF0ff609e16D35BbD1eC', // AGG + '0xb96B904ba83DdEeCE47CAADa8B40EE6936D92091' //CRE8R + + // '0x8aE125E8653821E851F12A49F7765db9a9ce7384', // DOLA + // '0x10010078a54396F62c96dF8532dc2B4847d47ED3', // HND + + // '0xc40F949F8a4e094D1b49a23ea9241D289B7b2819' // LUSD ], partnerAddrs: [ - TEAM_EOA, // VELO - '0x4a84675512949f81EBFEAAcC6C00D03eDd329de5', // OP - TEAM_EOA, // SNX -- custodied - '0xa283139017a2f5BAdE8d8e25412C600055D318F8', // INV - '0xDcf664d0f76E99eaA2DBD569474d0E75dC899FCD', // PERP - '0x489863b61C625a15C74FB4C21486baCb4A3937AB', // THALES - '0x641f26c67A5D0829Ae61019131093B6a7c7d18a3', // HND - '0xC224bf25Dcc99236F00843c7D8C4194abE8AA94a', // ALCX - '0xB6DACAE4eF97b4817d54df8e005269f509f803f9', // LYRA - TEAM_EOA, // MKR -- custodied - TEAM_EOA, // HOP -- custodied - '0x0dF840dCbf1229262A4125C1fc559bd338eC9491', // FRAX - '0x2E33A660742e813aD948fB9f7d682FE461E5fbf3', // BTRFLY - '0xd2D4e9024D8C90aB52032a9F1e0d92D4cE20191B' // LUSD + TEAM_MULTISIG, // 1 Protocol owned NFT 64m + '0x069e85D4F1010DD961897dC8C095FBB5FF297434', // 2 dunks + '0x3c5Aac016EF2F178e8699D6208796A2D67557fe2', // 3 ceazor + '0x03B88DacB7c21B54cEfEcC297D981E5b721A9dF1', // 4coolie + + '0xf78da0B8Ae888C318e1A19415d593729A61Ac0c3', // 5 faeflow, + '0x78e801136F77805239A7F533521A7a5570F572C8', // 6 wtck, + '0x0b776552c1Aef1Dc33005DD25AcDA22493b6615d', // 7 torbik, + velodromeMultisig, // 8 should we split this up? + anton, // 9 half % + andre, // 10 half % + arbitrumTeam, // 11 minimum 1% could be more if they help us + TEAM_MULTISIG, // 12 + TEAM_MULTISIG, // 13 + TEAM_MULTISIG, // 14 + TEAM_MULTISIG, // 15 + TEAM_MULTISIG, // 16 + TEAM_MULTISIG, // 17 + TEAM_MULTISIG, // 18 + TEAM_MULTISIG, // 19 + TEAM_MULTISIG, // 20 + TEAM_MULTISIG, // 21 + TEAM_MULTISIG, // 22 + TEAM_MULTISIG, // 23 + TEAM_MULTISIG, // 24 + TEAM_MULTISIG, // 25 + TEAM_MULTISIG, // 26 + TEAM_MULTISIG, // 27 + TEAM_MULTISIG, // 28 + TEAM_MULTISIG, // 29 + TEAM_MULTISIG, // 30 + TEAM_MULTISIG, // 31 + TEAM_MULTISIG, // 32 + TEAM_MULTISIG, // 33 + TEAM_MULTISIG, // 34 + TEAM_MULTISIG, // 35 + TEAM_MULTISIG, // 36 + TEAM_MULTISIG, // 37 + TEAM_MULTISIG, // 38 + TEAM_MULTISIG, // 39 + TEAM_MULTISIG, // 40 + TEAM_MULTISIG, // 41 + TEAM_MULTISIG, // 42 + TEAM_MULTISIG, // 43 + TEAM_MULTISIG, // 44 + TEAM_MULTISIG, // 45 + TEAM_MULTISIG, // 46 + TEAM_MULTISIG, // 47 + TEAM_MULTISIG, // 48 + TEAM_MULTISIG // 38 x protcol / partner NFTs # 49 ], partnerAmts: [ - TEN_MILLION, - TWENTY_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION + SIXTY_MILLION, // 60 million for protcol owned NFT 15% #1 + TWO_MILLION, // dunks presale 2 + TWO_MILLION, // ceazor presale 3 + FOUR_MILLION, // team veFLOW 1% 4 + FOUR_MILLION, // team veFLOW 1% 5 + FOUR_MILLION, // team veFLOW 1% 6 + FOUR_MILLION, // team veFLOW 1% 7 + FOUR_MILLION, // team veFLOW 1% 8 + FOUR_MILLION, // team veFLOW 1% 9 + FOUR_MILLION, // 10 tribute to velodrome (need to get their arb address DO NOT USE MULTISIG FROM OP) + FOUR_MILLION, //11 + FOUR_MILLION, // 12 + FOUR_MILLION, // 13 + FOUR_MILLION, // 14 + FOUR_MILLION, // 15 + FOUR_MILLION, // 16 + FOUR_MILLION, // 17 + FOUR_MILLION, // 18 + FOUR_MILLION, // 19 + FOUR_MILLION, // 20 + FOUR_MILLION, // 21 + FOUR_MILLION, // 22 + FOUR_MILLION, // 23 + FOUR_MILLION, // 24 + FOUR_MILLION, // 25 + FOUR_MILLION, // 26 + FOUR_MILLION, // 27 + FOUR_MILLION, // 28 + FOUR_MILLION, // 29 + FOUR_MILLION, // 30 + FOUR_MILLION, // 31 + FOUR_MILLION, // 32 + FOUR_MILLION, // 33 + FOUR_MILLION, // 34 + FOUR_MILLION, // 35 + FOUR_MILLION, // 36 + FOUR_MILLION, // 37 + FOUR_MILLION, // 38 + FOUR_MILLION, // 39 + FOUR_MILLION, // 40 + FOUR_MILLION, // 41 + FOUR_MILLION, // 42 + FOUR_MILLION, // 43 + FOUR_MILLION, // 44 + FOUR_MILLION, // 45 + FOUR_MILLION, // 46 + FOUR_MILLION, // 47 + FOUR_MILLION, // 48 + FOUR_MILLION // 1% to each partner x 38 partners # 49 ], partnerMax: PARTNER_MAX } From 9e2ecf12c984caed6c8e483e383510a695e4889c Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Sun, 29 Jan 2023 14:33:53 +1100 Subject: [PATCH 24/43] locked error down to partner NFTs config --- deploy/17_dist.ts | 12 +- dist/deploy/17_dist.js | 12 +- tasks/deploy/constants/arbConfig.ts | 208 +++++++++++++++------------- 3 files changed, 120 insertions(+), 112 deletions(-) diff --git a/deploy/17_dist.ts b/deploy/17_dist.ts index e7e940fb..87824097 100644 --- a/deploy/17_dist.ts +++ b/deploy/17_dist.ts @@ -18,12 +18,12 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const flow = await deployments.get('Flow') - // Initial veVELO distro - await minter.initialize( - ARB_TEST_CONFIG.partnerAddrs, - ARB_TEST_CONFIG.partnerAmts, - ARB_TEST_CONFIG.partnerMax - ) + // Initial veVELO distro // this is not inside dist lets see if its being used for deploys?? + // await minter.initialize( + // ARB_TEST_CONFIG.partnerAddrs, + // ARB_TEST_CONFIG.partnerAmts, + // ARB_TEST_CONFIG.partnerMax + // ) console.log('veVELO distributed') // console.log('Arbitrum Goerli Velocimeter Instruments deployed') diff --git a/dist/deploy/17_dist.js b/dist/deploy/17_dist.js index d5e2dc9b..f0a62e23 100644 --- a/dist/deploy/17_dist.js +++ b/dist/deploy/17_dist.js @@ -12,12 +12,12 @@ const ARB_TEST_CONFIG = arbTestnetConfig_1.default const func = async function (hre) { const { ethers } = hre const minter = await ethers.getContract('Minter') - // Initial veVELO distro - await minter.initialize( - ARB_TEST_CONFIG.partnerAddrs, - ARB_TEST_CONFIG.partnerAmts, - ARB_TEST_CONFIG.partnerMax - ) + // Initial veVELO distro this is already done by now in init... + // await minter.initialize( + // ARB_TEST_CONFIG.partnerAddrs, + // ARB_TEST_CONFIG.partnerAmts, + // ARB_TEST_CONFIG.partnerMax + // ) this is inside of dist and it does not run apparently... console.log('veVELO distributed') console.log('Arbitrum Goerli Velocimeter Instruments deployed') return true diff --git a/tasks/deploy/constants/arbConfig.ts b/tasks/deploy/constants/arbConfig.ts index cd5be229..bb89c779 100644 --- a/tasks/deploy/constants/arbConfig.ts +++ b/tasks/deploy/constants/arbConfig.ts @@ -16,7 +16,9 @@ const TWENTY_MILLION = ethers.BigNumber.from('20') const SIXTY_MILLION = ethers.BigNumber.from('60') .mul(MILLION) .mul(TOKEN_DECIMALS) -const PARTNER_MAX = ethers.BigNumber.from('78').mul(MILLION).mul(TOKEN_DECIMALS) +const PARTNER_MAX = ethers.BigNumber.from('9000') + .mul(MILLION) + .mul(TOKEN_DECIMALS) const TEAM_MULTISIG = '0x16ec7CD5E35682B751d0c77c41A4e6a1A3E2DE01' const TEAM_EOA = '0x069e85D4F1010DD961897dC8C095FBB5FF297434' @@ -68,108 +70,114 @@ const arbConfig = { // '0xc40F949F8a4e094D1b49a23ea9241D289B7b2819' // LUSD ], - partnerAddrs: [ - TEAM_MULTISIG, // 1 Protocol owned NFT 64m - '0x069e85D4F1010DD961897dC8C095FBB5FF297434', // 2 dunks - '0x3c5Aac016EF2F178e8699D6208796A2D67557fe2', // 3 ceazor - '0x03B88DacB7c21B54cEfEcC297D981E5b721A9dF1', // 4coolie + // partnerAddrs: [ + // TEAM_MULTISIG, // 1 Protocol owned NFT 64m + // '0x069e85D4F1010DD961897dC8C095FBB5FF297434', // 2 dunks + // '0x3c5Aac016EF2F178e8699D6208796A2D67557fe2', // 3 ceazor + // '0x03B88DacB7c21B54cEfEcC297D981E5b721A9dF1', // 4coolie - '0xf78da0B8Ae888C318e1A19415d593729A61Ac0c3', // 5 faeflow, - '0x78e801136F77805239A7F533521A7a5570F572C8', // 6 wtck, - '0x0b776552c1Aef1Dc33005DD25AcDA22493b6615d', // 7 torbik, - velodromeMultisig, // 8 should we split this up? - anton, // 9 half % - andre, // 10 half % - arbitrumTeam, // 11 minimum 1% could be more if they help us - TEAM_MULTISIG, // 12 - TEAM_MULTISIG, // 13 - TEAM_MULTISIG, // 14 - TEAM_MULTISIG, // 15 - TEAM_MULTISIG, // 16 - TEAM_MULTISIG, // 17 - TEAM_MULTISIG, // 18 - TEAM_MULTISIG, // 19 - TEAM_MULTISIG, // 20 - TEAM_MULTISIG, // 21 - TEAM_MULTISIG, // 22 - TEAM_MULTISIG, // 23 - TEAM_MULTISIG, // 24 - TEAM_MULTISIG, // 25 - TEAM_MULTISIG, // 26 - TEAM_MULTISIG, // 27 - TEAM_MULTISIG, // 28 - TEAM_MULTISIG, // 29 - TEAM_MULTISIG, // 30 - TEAM_MULTISIG, // 31 - TEAM_MULTISIG, // 32 - TEAM_MULTISIG, // 33 - TEAM_MULTISIG, // 34 - TEAM_MULTISIG, // 35 - TEAM_MULTISIG, // 36 - TEAM_MULTISIG, // 37 - TEAM_MULTISIG, // 38 - TEAM_MULTISIG, // 39 - TEAM_MULTISIG, // 40 - TEAM_MULTISIG, // 41 - TEAM_MULTISIG, // 42 - TEAM_MULTISIG, // 43 - TEAM_MULTISIG, // 44 - TEAM_MULTISIG, // 45 - TEAM_MULTISIG, // 46 - TEAM_MULTISIG, // 47 - TEAM_MULTISIG, // 48 - TEAM_MULTISIG // 38 x protcol / partner NFTs # 49 + // '0xf78da0B8Ae888C318e1A19415d593729A61Ac0c3', // 5 faeflow, + // '0x78e801136F77805239A7F533521A7a5570F572C8', // 6 wtck, + // '0x0b776552c1Aef1Dc33005DD25AcDA22493b6615d', // 7 torbik, + // velodromeMultisig, // 8 should we split this up? + // anton, // 9 half % + // andre, // 10 half % + // arbitrumTeam, // 11 minimum 1% could be more if they help us + // TEAM_MULTISIG, // 12 + // TEAM_MULTISIG, // 13 + // TEAM_MULTISIG, // 14 + // TEAM_MULTISIG, // 15 + // TEAM_MULTISIG, // 16 + // TEAM_MULTISIG, // 17 + // TEAM_MULTISIG, // 18 + // TEAM_MULTISIG, // 19 + // TEAM_MULTISIG, // 20 + // TEAM_MULTISIG, // 21 + // TEAM_MULTISIG, // 22 + // TEAM_MULTISIG, // 23 + // TEAM_MULTISIG, // 24 + // TEAM_MULTISIG, // 25 + // TEAM_MULTISIG, // 26 + // TEAM_MULTISIG, // 27 + // TEAM_MULTISIG, // 28 + // TEAM_MULTISIG, // 29 + // TEAM_MULTISIG, // 30 + // TEAM_MULTISIG, // 31 + // TEAM_MULTISIG, // 32 + // TEAM_MULTISIG, // 33 + // TEAM_MULTISIG, // 34 + // TEAM_MULTISIG, // 35 + // TEAM_MULTISIG, // 36 + // TEAM_MULTISIG, // 37 + // TEAM_MULTISIG, // 38 + // TEAM_MULTISIG, // 39 + // TEAM_MULTISIG, // 40 + // TEAM_MULTISIG, // 41 + // TEAM_MULTISIG, // 42 + // TEAM_MULTISIG, // 43 + // TEAM_MULTISIG, // 44 + // TEAM_MULTISIG, // 45 + // TEAM_MULTISIG, // 46 + // TEAM_MULTISIG, // 47 + // TEAM_MULTISIG, // 48 + // TEAM_MULTISIG // 38 x protcol / partner NFTs # 49 + // ], + // partnerAmts: [ + // SIXTY_MILLION, // 60 million for protcol owned NFT 15% #1 + // TWO_MILLION, // dunks presale 2 + // TWO_MILLION, // ceazor presale 3 + // FOUR_MILLION, // team veFLOW 1% 4 + // FOUR_MILLION, // team veFLOW 1% 5 + // FOUR_MILLION, // team veFLOW 1% 6 + // FOUR_MILLION, // team veFLOW 1% 7 + // FOUR_MILLION, // team veFLOW 1% 8 + // FOUR_MILLION, // team veFLOW 1% 9 + // FOUR_MILLION, // 10 tribute to velodrome (need to get their arb address DO NOT USE MULTISIG FROM OP) + // FOUR_MILLION, //11 + // FOUR_MILLION, // 12 + // FOUR_MILLION, // 13 + // FOUR_MILLION, // 14 + // FOUR_MILLION, // 15 + // FOUR_MILLION, // 16 + // FOUR_MILLION, // 17 + // FOUR_MILLION, // 18 + // FOUR_MILLION, // 19 + // FOUR_MILLION, // 20 + // FOUR_MILLION, // 21 + // FOUR_MILLION, // 22 + // FOUR_MILLION, // 23 + // FOUR_MILLION, // 24 + // FOUR_MILLION, // 25 + // FOUR_MILLION, // 26 + // FOUR_MILLION, // 27 + // FOUR_MILLION, // 28 + // FOUR_MILLION, // 29 + // FOUR_MILLION, // 30 + // FOUR_MILLION, // 31 + // FOUR_MILLION, // 32 + // FOUR_MILLION, // 33 + // FOUR_MILLION, // 34 + // FOUR_MILLION, // 35 + // FOUR_MILLION, // 36 + // FOUR_MILLION, // 37 + // FOUR_MILLION, // 38 + // FOUR_MILLION, // 39 + // FOUR_MILLION, // 40 + // FOUR_MILLION, // 41 + // FOUR_MILLION, // 42 + // FOUR_MILLION, // 43 + // FOUR_MILLION, // 44 + // FOUR_MILLION, // 45 + // FOUR_MILLION, // 46 + // FOUR_MILLION, // 47 + // FOUR_MILLION, // 48 + // FOUR_MILLION // 1% to each partner x 38 partners # 49 + // ], + partnerAddrs: [ + TEAM_MULTISIG // 1 Protocol owned NFT 64m ], partnerAmts: [ - SIXTY_MILLION, // 60 million for protcol owned NFT 15% #1 - TWO_MILLION, // dunks presale 2 - TWO_MILLION, // ceazor presale 3 - FOUR_MILLION, // team veFLOW 1% 4 - FOUR_MILLION, // team veFLOW 1% 5 - FOUR_MILLION, // team veFLOW 1% 6 - FOUR_MILLION, // team veFLOW 1% 7 - FOUR_MILLION, // team veFLOW 1% 8 - FOUR_MILLION, // team veFLOW 1% 9 - FOUR_MILLION, // 10 tribute to velodrome (need to get their arb address DO NOT USE MULTISIG FROM OP) - FOUR_MILLION, //11 - FOUR_MILLION, // 12 - FOUR_MILLION, // 13 - FOUR_MILLION, // 14 - FOUR_MILLION, // 15 - FOUR_MILLION, // 16 - FOUR_MILLION, // 17 - FOUR_MILLION, // 18 - FOUR_MILLION, // 19 - FOUR_MILLION, // 20 - FOUR_MILLION, // 21 - FOUR_MILLION, // 22 - FOUR_MILLION, // 23 - FOUR_MILLION, // 24 - FOUR_MILLION, // 25 - FOUR_MILLION, // 26 - FOUR_MILLION, // 27 - FOUR_MILLION, // 28 - FOUR_MILLION, // 29 - FOUR_MILLION, // 30 - FOUR_MILLION, // 31 - FOUR_MILLION, // 32 - FOUR_MILLION, // 33 - FOUR_MILLION, // 34 - FOUR_MILLION, // 35 - FOUR_MILLION, // 36 - FOUR_MILLION, // 37 - FOUR_MILLION, // 38 - FOUR_MILLION, // 39 - FOUR_MILLION, // 40 - FOUR_MILLION, // 41 - FOUR_MILLION, // 42 - FOUR_MILLION, // 43 - FOUR_MILLION, // 44 - FOUR_MILLION, // 45 - FOUR_MILLION, // 46 - FOUR_MILLION, // 47 - FOUR_MILLION, // 48 - FOUR_MILLION // 1% to each partner x 38 partners # 49 + SIXTY_MILLION // 60 million for protcol owned NFT 15% #1 ], partnerMax: PARTNER_MAX } From 932ba05c1908298f4235f8e7cebbfed962e311c0 Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Mon, 30 Jan 2023 00:19:59 +1100 Subject: [PATCH 25/43] ad ONE_MILLION --- deploy/15_init.ts | 10 +- deploy/17_dist.ts | 10 +- deployments/arbitrumGoerli/.migrations.json | 5 + deployments/arbitrumGoerli/BribeFactory.json | 26 +- deployments/arbitrumGoerli/Flow.json | 40 +-- deployments/arbitrumGoerli/FlowGovernor.json | 34 +- deployments/arbitrumGoerli/GaugeFactory.json | 26 +- deployments/arbitrumGoerli/MerkleClaim.json | 24 +- deployments/arbitrumGoerli/Minter.json | 32 +- deployments/arbitrumGoerli/PairFactory.json | 26 +- .../arbitrumGoerli/RedemptionReceiver.json | 24 +- .../arbitrumGoerli/RewardsDistributor.json | 38 +- deployments/arbitrumGoerli/Router.json | 28 +- deployments/arbitrumGoerli/VeArtProxy.json | 22 +- .../arbitrumGoerli/VelocimeterLibrary.json | 24 +- deployments/arbitrumGoerli/Voter.json | 34 +- deployments/arbitrumGoerli/VotingEscrow.json | 56 +-- .../5e3bd610e528b3bcf2b3d4c538d2d553.json | 238 ------------- .../98b870afa86e9d5388a96f4e867892a9.json | 238 ------------- ... => d2a2160297444b93438826228d1e185d.json} | 2 +- dist/deploy/00_velo.d.ts | 6 +- dist/deploy/00_velo.js | 30 +- dist/deploy/01_gaugeFactory.d.ts | 2 +- dist/deploy/01_gaugeFactory.js | 30 +- dist/deploy/02_bribeFactory.d.ts | 2 +- dist/deploy/02_bribeFactory.js | 30 +- dist/deploy/04_pairFactory.d.ts | 2 +- dist/deploy/04_pairFactory.js | 30 +- dist/deploy/05_router.d.ts | 2 +- dist/deploy/05_router.js | 46 ++- dist/deploy/06_library.d.ts | 2 +- dist/deploy/06_library.js | 32 +- dist/deploy/07_veArtProxy.d.ts | 2 +- dist/deploy/07_veArtProxy.js | 30 +- dist/deploy/08_votingEscrow.d.ts | 2 +- dist/deploy/08_votingEscrow.js | 34 +- dist/deploy/09_rewardsDist.d.ts | 2 +- dist/deploy/09_rewardsDist.js | 32 +- dist/deploy/10_voter.d.ts | 2 +- dist/deploy/10_voter.js | 48 +-- dist/deploy/11_minter.d.ts | 2 +- dist/deploy/11_minter.js | 36 +- dist/deploy/12_veloGovernor.d.ts | 2 +- dist/deploy/12_veloGovernor.js | 32 +- dist/deploy/13_redemptionReceiver.d.ts | 2 +- dist/deploy/13_redemptionReceiver.js | 62 ++-- dist/deploy/14_merkleClaim.d.ts | 2 +- dist/deploy/14_merkleClaim.js | 47 ++- dist/deploy/15_init.d.ts | 2 +- dist/deploy/15_init.js | 113 +++--- dist/deploy/16_whitelist.d.ts | 2 +- dist/deploy/16_whitelist.js | 46 ++- dist/deploy/17_dist.d.ts | 2 +- dist/deploy/17_dist.js | 79 +++-- dist/hardhat.config.d.ts | 20 +- dist/hardhat.config.js | 201 +++++------ dist/tasks/accounts.d.ts | 1 + dist/tasks/accounts.js | 9 + dist/tasks/deploy/arb.js | 298 +++++++--------- dist/tasks/deploy/arbHardhat.js | 309 +++++++---------- dist/tasks/deploy/arbTest.js | 326 +++++++----------- dist/tasks/deploy/constants/arbConfig.d.ts | 10 + dist/tasks/deploy/constants/arbConfig.js | 259 +++++++------- .../deploy/constants/arbHardhatConfig.js | 5 +- .../deploy/constants/arbTestnetConfig.d.ts | 16 + .../deploy/constants/arbTestnetConfig.js | 172 +++++---- dist/tasks/deploy/init.js | 2 +- dist/tasks/deploy/op.js | 295 ++++++---------- tasks/deploy/constants/arbConfig.ts | 62 +++- 69 files changed, 1538 insertions(+), 2179 deletions(-) create mode 100644 deployments/arbitrumGoerli/.migrations.json delete mode 100644 deployments/arbitrumGoerli/solcInputs/5e3bd610e528b3bcf2b3d4c538d2d553.json delete mode 100644 deployments/arbitrumGoerli/solcInputs/98b870afa86e9d5388a96f4e867892a9.json rename deployments/arbitrumGoerli/solcInputs/{539b862778415c77e4d39b17addb6c5e.json => d2a2160297444b93438826228d1e185d.json} (99%) create mode 100644 dist/tasks/accounts.d.ts create mode 100644 dist/tasks/accounts.js create mode 100644 dist/tasks/deploy/constants/arbTestnetConfig.d.ts diff --git a/deploy/15_init.ts b/deploy/15_init.ts index 19422806..571fe2bc 100644 --- a/deploy/15_init.ts +++ b/deploy/15_init.ts @@ -65,11 +65,11 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { await minter.setTeam(ARB_TEST_CONFIG.teamMultisig) console.log('Team set for minter') - await minter.initialize( - ARB_TEST_CONFIG.partnerAddrs, - ARB_TEST_CONFIG.partnerAmts, - ARB_TEST_CONFIG.partnerMax - ) + // await minter.initialize( + // ARB_TEST_CONFIG.partnerAddrs, + // ARB_TEST_CONFIG.partnerAmts, + // ARB_TEST_CONFIG.partnerMax + // ) // create pair // provide liq diff --git a/deploy/17_dist.ts b/deploy/17_dist.ts index 87824097..7197686e 100644 --- a/deploy/17_dist.ts +++ b/deploy/17_dist.ts @@ -19,11 +19,11 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const flow = await deployments.get('Flow') // Initial veVELO distro // this is not inside dist lets see if its being used for deploys?? - // await minter.initialize( - // ARB_TEST_CONFIG.partnerAddrs, - // ARB_TEST_CONFIG.partnerAmts, - // ARB_TEST_CONFIG.partnerMax - // ) + await minter.initialize( + ARB_TEST_CONFIG.partnerAddrs, + ARB_TEST_CONFIG.partnerAmts, + ARB_TEST_CONFIG.partnerMax + ) console.log('veVELO distributed') // console.log('Arbitrum Goerli Velocimeter Instruments deployed') diff --git a/deployments/arbitrumGoerli/.migrations.json b/deployments/arbitrumGoerli/.migrations.json new file mode 100644 index 00000000..9619fea5 --- /dev/null +++ b/deployments/arbitrumGoerli/.migrations.json @@ -0,0 +1,5 @@ +{ + "init_deploy": 1674988734, + "whitelist": 1674988736, + "initial_dist": 1674988738 +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/BribeFactory.json b/deployments/arbitrumGoerli/BribeFactory.json index cd43dee4..9a162864 100644 --- a/deployments/arbitrumGoerli/BribeFactory.json +++ b/deployments/arbitrumGoerli/BribeFactory.json @@ -1,5 +1,5 @@ { - "address": "0x6e724702DfB7bCd31Af55852D67aa6A785aB85e6", + "address": "0x751B8A4792de90f5c774032f688bcAFA976b78d2", "abi": [ { "inputs": [ @@ -66,28 +66,28 @@ "type": "function" } ], - "transactionHash": "0xcc125e746b6b8fd4fe60cc4ae7f7248997195abe16df333a04048a93d88e40ae", + "transactionHash": "0x185ad5311989350078ddf3d8ce0f922179054a69f7b6049aa302f25133264b4c", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x6e724702DfB7bCd31Af55852D67aa6A785aB85e6", + "contractAddress": "0x751B8A4792de90f5c774032f688bcAFA976b78d2", "transactionIndex": 1, - "gasUsed": "4288891", + "gasUsed": "4288879", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x810ac78f8b633bb0e98ce382ad637e1e66fb5ce73e61d9191fda39b2d44f5a6c", - "transactionHash": "0xcc125e746b6b8fd4fe60cc4ae7f7248997195abe16df333a04048a93d88e40ae", + "blockHash": "0xb1a2062a3985eacaefa187ab3b044c2fc8e97d6686037cc22f6fb856c480e9fb", + "transactionHash": "0x185ad5311989350078ddf3d8ce0f922179054a69f7b6049aa302f25133264b4c", "logs": [], - "blockNumber": 5849144, - "cumulativeGasUsed": "4288891", + "blockNumber": 6069377, + "cumulativeGasUsed": "4288879", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 3, - "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createExternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createInternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_external_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_internal_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/BribeFactory.sol\":\"BribeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/ExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract ExternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve; // \\u5929\\u4f7f\\u306e\\u305f\\u307e\\u3054\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balanceOf;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n _prevSupply = supplyCheckpoints[\\n getPriorSupplyIndex(_nextEpochStart + DURATION)\\n ].supply;\\n prevRewards.balanceOf =\\n (cp0.balanceOf *\\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (block.timestamp > _lastEpochEnd) {\\n reward +=\\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\\n }\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0xfe1e53dea8a63ce448c5856a740ed73038ad29a9dcd0f2a2752049b146bb4eb0\",\"license\":\"MIT\"},\"contracts/InternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract InternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve;\\n\\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 public constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n mapping(address => mapping(uint256 => uint256))\\n public userRewardPerTokenStored;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (totalSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / totalSupply);\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\\n _startTimestamp = endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][tokenId],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][tokenId]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n require(isReward[token]);\\n\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2dc302de5dfd95018d1fba7a3a1916d2c1fcf32859d19d38648767f13422a694\",\"license\":\"MIT\"},\"contracts/factories/BribeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IBribeFactory.sol\\\";\\nimport 'contracts/InternalBribe.sol';\\nimport 'contracts/ExternalBribe.sol';\\n\\ncontract BribeFactory is IBribeFactory {\\n address public last_internal_bribe;\\n address public last_external_bribe;\\n\\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\\n return last_internal_bribe;\\n }\\n\\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\\n return last_external_bribe;\\n }\\n}\\n\\n// if this imports int and ext bribe why is the the gauge factory asking for those address as if they are deployed to an address.\\n\",\"keccak256\":\"0xd107fb5a520bae9b655bec4ad2eb11d598e74d0eeda0db547e2526a907dea7ec\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50614cca806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea2646970667358221220b581a61c6270850b4ca41ed18a6ced4bddec0f335ea7da2f7e34bb8187fe5b5464736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea2646970667358221220bb88ad6720126cf96e24b2d25a87d3a518e2b3e2ae6d01962b74725b221784e964736f6c634300080d0033a2646970667358221220a28d90b20162c34cdc6c87f90d393aba381d7fe1852a758375129d7d68d7128564736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea2646970667358221220b581a61c6270850b4ca41ed18a6ced4bddec0f335ea7da2f7e34bb8187fe5b5464736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea2646970667358221220bb88ad6720126cf96e24b2d25a87d3a518e2b3e2ae6d01962b74725b221784e964736f6c634300080d0033a2646970667358221220a28d90b20162c34cdc6c87f90d393aba381d7fe1852a758375129d7d68d7128564736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "d2a2160297444b93438826228d1e185d", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createExternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createInternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_external_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_internal_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/BribeFactory.sol\":\"BribeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/ExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract ExternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve; // \\u5929\\u4f7f\\u306e\\u305f\\u307e\\u3054\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balanceOf;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n _prevSupply = supplyCheckpoints[\\n getPriorSupplyIndex(_nextEpochStart + DURATION)\\n ].supply;\\n prevRewards.balanceOf =\\n (cp0.balanceOf *\\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (block.timestamp > _lastEpochEnd) {\\n reward +=\\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\\n }\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0xfe1e53dea8a63ce448c5856a740ed73038ad29a9dcd0f2a2752049b146bb4eb0\",\"license\":\"MIT\"},\"contracts/InternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract InternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve;\\n\\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 public constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n mapping(address => mapping(uint256 => uint256))\\n public userRewardPerTokenStored;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (totalSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / totalSupply);\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\\n _startTimestamp = endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][tokenId],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][tokenId]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n require(isReward[token]);\\n\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2dc302de5dfd95018d1fba7a3a1916d2c1fcf32859d19d38648767f13422a694\",\"license\":\"MIT\"},\"contracts/factories/BribeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IBribeFactory.sol\\\";\\nimport 'contracts/InternalBribe.sol';\\nimport 'contracts/ExternalBribe.sol';\\n\\ncontract BribeFactory is IBribeFactory {\\n address public last_internal_bribe;\\n address public last_external_bribe;\\n\\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\\n return last_internal_bribe;\\n }\\n\\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\\n return last_external_bribe;\\n }\\n}\\n\\n// if this imports int and ext bribe why is the the gauge factory asking for those address as if they are deployed to an address.\\n\",\"keccak256\":\"0xd107fb5a520bae9b655bec4ad2eb11d598e74d0eeda0db547e2526a907dea7ec\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50614cca806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea26469706673582212205d5f561dc89344ce077e473fa6486d4404842add0024fedd5dd3b8d9b8c5096d64736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea26469706673582212209ae9b4f7cd05b4da457b63c0edae414d9a4c62879112ebdb5df9717dd23782d964736f6c634300080d0033a26469706673582212206095c7527ab4fbf61bbea631cc41141117e8abc6109d19e5a7eef414f0a2e86864736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea26469706673582212205d5f561dc89344ce077e473fa6486d4404842add0024fedd5dd3b8d9b8c5096d64736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea26469706673582212209ae9b4f7cd05b4da457b63c0edae414d9a4c62879112ebdb5df9717dd23782d964736f6c634300080d0033a26469706673582212206095c7527ab4fbf61bbea631cc41141117e8abc6109d19e5a7eef414f0a2e86864736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/Flow.json b/deployments/arbitrumGoerli/Flow.json index 7e63be64..fd78a140 100644 --- a/deployments/arbitrumGoerli/Flow.json +++ b/deployments/arbitrumGoerli/Flow.json @@ -1,5 +1,5 @@ { - "address": "0x0432f39386A9B1d0339c8Ba0af617b16C86ADA05", + "address": "0x4E13914872BFf7e58f3E231b2687fDd084014999", "abi": [ { "inputs": [], @@ -381,43 +381,43 @@ "type": "function" } ], - "transactionHash": "0x95f802a247d08a2c2f937a273690354da6f7361458e7e0ab710b1bf088d4e810", + "transactionHash": "0xaf60f3962ca09f925c640003d31a2aad7f667c470c0522811e6454723e43bfc4", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x0432f39386A9B1d0339c8Ba0af617b16C86ADA05", - "transactionIndex": 1, + "contractAddress": "0x4E13914872BFf7e58f3E231b2687fDd084014999", + "transactionIndex": 2, "gasUsed": "537302", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000020000000000020000000800000000000000000000000010000000000000000000000000000002000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000002000000000000000000000000000000000000000000000000000030000000000000000000000000080000000000000000000000000000000000000000", - "blockHash": "0x731e2358819105e46d82ccbebb1eb9fe1431f71da577ebac1de89b9e060a4474", - "transactionHash": "0x95f802a247d08a2c2f937a273690354da6f7361458e7e0ab710b1bf088d4e810", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000008100000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000010000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000002000000000000000000000000000000000000000000000000000020000000000000000040000000080000000000000000000000000000000000000000", + "blockHash": "0x1beedb944f7dc34a5fa26ab9e94b3a870d2c9af1dee43f8a5a69d240201566cd", + "transactionHash": "0xaf60f3962ca09f925c640003d31a2aad7f667c470c0522811e6454723e43bfc4", "logs": [ { - "transactionIndex": 1, - "blockNumber": 5849121, - "transactionHash": "0x95f802a247d08a2c2f937a273690354da6f7361458e7e0ab710b1bf088d4e810", - "address": "0x0432f39386A9B1d0339c8Ba0af617b16C86ADA05", + "transactionIndex": 2, + "blockNumber": 6069358, + "transactionHash": "0xaf60f3962ca09f925c640003d31a2aad7f667c470c0522811e6454723e43bfc4", + "address": "0x4E13914872BFf7e58f3E231b2687fDd084014999", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x00000000000000000000000053f3b51fd7f327e1ec4e6eaa3a049149cb2acad2" ], "data": "0x0000000000000000000000000000000000000000000000000000000000000000", - "logIndex": 0, - "blockHash": "0x731e2358819105e46d82ccbebb1eb9fe1431f71da577ebac1de89b9e060a4474" + "logIndex": 11, + "blockHash": "0x1beedb944f7dc34a5fa26ab9e94b3a870d2c9af1dee43f8a5a69d240201566cd" } ], - "blockNumber": 5849121, - "cumulativeGasUsed": "537302", + "blockNumber": 6069358, + "cumulativeGasUsed": "1022147", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 3, - "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"initialMint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialMinted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleClaim\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redemptionReceiver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_merkleClaim\",\"type\":\"address\"}],\"name\":\"setMerkleClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"setMinter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_receiver\",\"type\":\"address\"}],\"name\":\"setRedemptionReceiver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Flow.sol\":\"Flow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Flow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\n\\ncontract Flow is IFlow {\\n\\n string public constant name = \\\"Velocimeter\\\";\\n string public constant symbol = \\\"FLOW\\\";\\n uint8 public constant decimals = 18;\\n uint public totalSupply = 0;\\n\\n mapping(address => uint) public balanceOf;\\n mapping(address => mapping(address => uint)) public allowance;\\n\\n bool public initialMinted;\\n address public minter;\\n address public redemptionReceiver;\\n address public merkleClaim;\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n\\n constructor() {\\n minter = msg.sender;\\n _mint(msg.sender, 0);\\n }\\n\\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\\n function setMinter(address _minter) external {\\n require(msg.sender == minter);\\n minter = _minter;\\n }\\n\\n function setRedemptionReceiver(address _receiver) external {\\n require(msg.sender == minter);\\n redemptionReceiver = _receiver;\\n }\\n\\n function setMerkleClaim(address _merkleClaim) external {\\n require(msg.sender == minter);\\n merkleClaim = _merkleClaim;\\n }\\n\\n // Initial mint: total 82M\\n // 4M for \\\"Genesis\\\" pools\\n // 30M for liquid team allocation (40M excl init veNFT)\\n // 48M for future partners\\n function initialMint(address _recipient) external {\\n require(msg.sender == minter && !initialMinted);\\n initialMinted = true;\\n _mint(_recipient, 82 * 1e6 * 1e18);\\n }\\n\\n function approve(address _spender, uint _value) external returns (bool) {\\n allowance[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n function _mint(address _to, uint _amount) internal returns (bool) {\\n totalSupply += _amount;\\n unchecked {\\n balanceOf[_to] += _amount;\\n }\\n emit Transfer(address(0x0), _to, _amount);\\n return true;\\n }\\n\\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\\n balanceOf[_from] -= _value;\\n unchecked {\\n balanceOf[_to] += _value;\\n }\\n emit Transfer(_from, _to, _value);\\n return true;\\n }\\n\\n function transfer(address _to, uint _value) external returns (bool) {\\n return _transfer(msg.sender, _to, _value);\\n }\\n\\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\\n uint allowed_from = allowance[_from][msg.sender];\\n if (allowed_from != type(uint).max) {\\n allowance[_from][msg.sender] -= _value;\\n }\\n return _transfer(_from, _to, _value);\\n }\\n\\n function mint(address account, uint amount) external returns (bool) {\\n require(msg.sender == minter);\\n _mint(account, amount);\\n return true;\\n }\\n\\n function claim(address account, uint amount) external returns (bool) {\\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\\n _mint(account, amount);\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xe98c291786f74c8f02edb3673870ba99d6b9adac299bbe42f1df42c740d737ac\",\"license\":\"MIT\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"}},\"version\":1}", - "bytecode": "0x60806040526000805534801561001457600080fd5b5060038054610100600160a81b0319163361010081029190911790915561003c906000610042565b506100d9565b60008160008082825461005591906100b3565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a350600192915050565b600082198211156100d457634e487b7160e01b600052601160045260246000fd5b500190565b61082e806100e86000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ae578063dd62ed3e146102c1578063e752c44a146102ec578063ec676a25146102ff578063fca3b5aa1461031257600080fd5b806395d89b4114610243578063a9059cbb14610266578063aad3ec9614610279578063c268f9ba1461028c578063ca1c4de9146102a157600080fd5b806323b872dd116100f457806323b872dd146101d0578063313ce567146101e357806340c10f19146101fd5780635e05fe501461021057806370a082311461022357600080fd5b806306fdde03146101265780630754617214610166578063095ea7b31461019657806318160ddd146101b9575b600080fd5b6101506040518060400160405280600b81526020016a2b32b637b1b4b6b2ba32b960a91b81525081565b60405161015d919061068e565b60405180910390f35b60035461017e9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015d565b6101a96101a43660046106ff565b610325565b604051901515815260200161015d565b6101c260005481565b60405190815260200161015d565b6101a96101de366004610729565b610391565b6101eb601281565b60405160ff909116815260200161015d565b6101a961020b3660046106ff565b61040b565b60045461017e906001600160a01b031681565b6101c2610231366004610765565b60016020526000908152604090205481565b61015060405180604001604052806004815260200163464c4f5760e01b81525081565b6101a96102743660046106ff565b61043e565b6101a96102873660046106ff565b610452565b61029f61029a366004610765565b610481565b005b6003546101a99060ff1681565b61029f6102bc366004610765565b6104d2565b6101c26102cf366004610780565b600260209081526000928352604080842090915290825290205481565b60055461017e906001600160a01b031681565b61029f61030d366004610765565b610510565b61029f610320366004610765565b61054e565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103809086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f7576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103f19084906107c9565b90915550505b610402858585610592565b95945050505050565b60035460009061010090046001600160a01b0316331461042a57600080fd5b6104348383610629565b5060019392505050565b600061044b338484610592565b9392505050565b6004546000906001600160a01b031633148061047857506005546001600160a01b031633145b61042a57600080fd5b60035461010090046001600160a01b0316331480156104a3575060035460ff16155b6104ac57600080fd5b6003805460ff191660011790556104ce816a43d42ce83da41d92000000610629565b5050565b60035461010090046001600160a01b031633146104ee57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052c57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056a57600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105bc9084906107c9565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106179086815260200190565b60405180910390a35060019392505050565b60008160008082825461063c91906107e0565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610380565b600060208083528351808285015260005b818110156106bb5785810183015185820160400152820161069f565b818111156106cd576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106fa57600080fd5b919050565b6000806040838503121561071257600080fd5b61071b836106e3565b946020939093013593505050565b60008060006060848603121561073e57600080fd5b610747846106e3565b9250610755602085016106e3565b9150604084013590509250925092565b60006020828403121561077757600080fd5b61044b826106e3565b6000806040838503121561079357600080fd5b61079c836106e3565b91506107aa602084016106e3565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107db576107db6107b3565b500390565b600082198211156107f3576107f36107b3565b50019056fea26469706673582212204ffbadb8f52de29017f5adfb84dd15b297992d688e48de234f666a9925afdf5664736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ae578063dd62ed3e146102c1578063e752c44a146102ec578063ec676a25146102ff578063fca3b5aa1461031257600080fd5b806395d89b4114610243578063a9059cbb14610266578063aad3ec9614610279578063c268f9ba1461028c578063ca1c4de9146102a157600080fd5b806323b872dd116100f457806323b872dd146101d0578063313ce567146101e357806340c10f19146101fd5780635e05fe501461021057806370a082311461022357600080fd5b806306fdde03146101265780630754617214610166578063095ea7b31461019657806318160ddd146101b9575b600080fd5b6101506040518060400160405280600b81526020016a2b32b637b1b4b6b2ba32b960a91b81525081565b60405161015d919061068e565b60405180910390f35b60035461017e9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015d565b6101a96101a43660046106ff565b610325565b604051901515815260200161015d565b6101c260005481565b60405190815260200161015d565b6101a96101de366004610729565b610391565b6101eb601281565b60405160ff909116815260200161015d565b6101a961020b3660046106ff565b61040b565b60045461017e906001600160a01b031681565b6101c2610231366004610765565b60016020526000908152604090205481565b61015060405180604001604052806004815260200163464c4f5760e01b81525081565b6101a96102743660046106ff565b61043e565b6101a96102873660046106ff565b610452565b61029f61029a366004610765565b610481565b005b6003546101a99060ff1681565b61029f6102bc366004610765565b6104d2565b6101c26102cf366004610780565b600260209081526000928352604080842090915290825290205481565b60055461017e906001600160a01b031681565b61029f61030d366004610765565b610510565b61029f610320366004610765565b61054e565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103809086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f7576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103f19084906107c9565b90915550505b610402858585610592565b95945050505050565b60035460009061010090046001600160a01b0316331461042a57600080fd5b6104348383610629565b5060019392505050565b600061044b338484610592565b9392505050565b6004546000906001600160a01b031633148061047857506005546001600160a01b031633145b61042a57600080fd5b60035461010090046001600160a01b0316331480156104a3575060035460ff16155b6104ac57600080fd5b6003805460ff191660011790556104ce816a43d42ce83da41d92000000610629565b5050565b60035461010090046001600160a01b031633146104ee57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052c57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056a57600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105bc9084906107c9565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106179086815260200190565b60405180910390a35060019392505050565b60008160008082825461063c91906107e0565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610380565b600060208083528351808285015260005b818110156106bb5785810183015185820160400152820161069f565b818111156106cd576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106fa57600080fd5b919050565b6000806040838503121561071257600080fd5b61071b836106e3565b946020939093013593505050565b60008060006060848603121561073e57600080fd5b610747846106e3565b9250610755602085016106e3565b9150604084013590509250925092565b60006020828403121561077757600080fd5b61044b826106e3565b6000806040838503121561079357600080fd5b61079c836106e3565b91506107aa602084016106e3565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107db576107db6107b3565b500390565b600082198211156107f3576107f36107b3565b50019056fea26469706673582212204ffbadb8f52de29017f5adfb84dd15b297992d688e48de234f666a9925afdf5664736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "d2a2160297444b93438826228d1e185d", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"initialMint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialMinted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleClaim\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redemptionReceiver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_merkleClaim\",\"type\":\"address\"}],\"name\":\"setMerkleClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"setMinter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_receiver\",\"type\":\"address\"}],\"name\":\"setRedemptionReceiver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Flow.sol\":\"Flow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Flow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\n\\ncontract Flow is IFlow {\\n\\n string public constant name = \\\"Velocimeter\\\";\\n string public constant symbol = \\\"FLOW\\\";\\n uint8 public constant decimals = 18;\\n uint public totalSupply = 0;\\n\\n mapping(address => uint) public balanceOf;\\n mapping(address => mapping(address => uint)) public allowance;\\n\\n bool public initialMinted;\\n address public minter;\\n address public redemptionReceiver;\\n address public merkleClaim;\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n\\n constructor() {\\n minter = msg.sender;\\n _mint(msg.sender, 0);\\n }\\n\\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\\n function setMinter(address _minter) external {\\n require(msg.sender == minter);\\n minter = _minter;\\n }\\n\\n function setRedemptionReceiver(address _receiver) external {\\n require(msg.sender == minter);\\n redemptionReceiver = _receiver;\\n }\\n\\n function setMerkleClaim(address _merkleClaim) external {\\n require(msg.sender == minter);\\n merkleClaim = _merkleClaim;\\n }\\n\\n // Initial mint: total 82M\\n // 4M for \\\"Genesis\\\" pools\\n // 30M for liquid team allocation (40M excl init veNFT)\\n // 48M for future partners\\n function initialMint(address _recipient) external {\\n require(msg.sender == minter && !initialMinted);\\n initialMinted = true;\\n _mint(_recipient, 82 * 1e6 * 1e18);\\n }\\n\\n function approve(address _spender, uint _value) external returns (bool) {\\n allowance[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n function _mint(address _to, uint _amount) internal returns (bool) {\\n totalSupply += _amount;\\n unchecked {\\n balanceOf[_to] += _amount;\\n }\\n emit Transfer(address(0x0), _to, _amount);\\n return true;\\n }\\n\\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\\n balanceOf[_from] -= _value;\\n unchecked {\\n balanceOf[_to] += _value;\\n }\\n emit Transfer(_from, _to, _value);\\n return true;\\n }\\n\\n function transfer(address _to, uint _value) external returns (bool) {\\n return _transfer(msg.sender, _to, _value);\\n }\\n\\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\\n uint allowed_from = allowance[_from][msg.sender];\\n if (allowed_from != type(uint).max) {\\n allowance[_from][msg.sender] -= _value;\\n }\\n return _transfer(_from, _to, _value);\\n }\\n\\n function mint(address account, uint amount) external returns (bool) {\\n require(msg.sender == minter);\\n _mint(account, amount);\\n return true;\\n }\\n\\n function claim(address account, uint amount) external returns (bool) {\\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\\n _mint(account, amount);\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xe98c291786f74c8f02edb3673870ba99d6b9adac299bbe42f1df42c740d737ac\",\"license\":\"MIT\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"}},\"version\":1}", + "bytecode": "0x60806040526000805534801561001457600080fd5b5060038054610100600160a81b0319163361010081029190911790915561003c906000610042565b506100d9565b60008160008082825461005591906100b3565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a350600192915050565b600082198211156100d457634e487b7160e01b600052601160045260246000fd5b500190565b61082e806100e86000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ae578063dd62ed3e146102c1578063e752c44a146102ec578063ec676a25146102ff578063fca3b5aa1461031257600080fd5b806395d89b4114610243578063a9059cbb14610266578063aad3ec9614610279578063c268f9ba1461028c578063ca1c4de9146102a157600080fd5b806323b872dd116100f457806323b872dd146101d0578063313ce567146101e357806340c10f19146101fd5780635e05fe501461021057806370a082311461022357600080fd5b806306fdde03146101265780630754617214610166578063095ea7b31461019657806318160ddd146101b9575b600080fd5b6101506040518060400160405280600b81526020016a2b32b637b1b4b6b2ba32b960a91b81525081565b60405161015d919061068e565b60405180910390f35b60035461017e9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015d565b6101a96101a43660046106ff565b610325565b604051901515815260200161015d565b6101c260005481565b60405190815260200161015d565b6101a96101de366004610729565b610391565b6101eb601281565b60405160ff909116815260200161015d565b6101a961020b3660046106ff565b61040b565b60045461017e906001600160a01b031681565b6101c2610231366004610765565b60016020526000908152604090205481565b61015060405180604001604052806004815260200163464c4f5760e01b81525081565b6101a96102743660046106ff565b61043e565b6101a96102873660046106ff565b610452565b61029f61029a366004610765565b610481565b005b6003546101a99060ff1681565b61029f6102bc366004610765565b6104d2565b6101c26102cf366004610780565b600260209081526000928352604080842090915290825290205481565b60055461017e906001600160a01b031681565b61029f61030d366004610765565b610510565b61029f610320366004610765565b61054e565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103809086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f7576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103f19084906107c9565b90915550505b610402858585610592565b95945050505050565b60035460009061010090046001600160a01b0316331461042a57600080fd5b6104348383610629565b5060019392505050565b600061044b338484610592565b9392505050565b6004546000906001600160a01b031633148061047857506005546001600160a01b031633145b61042a57600080fd5b60035461010090046001600160a01b0316331480156104a3575060035460ff16155b6104ac57600080fd5b6003805460ff191660011790556104ce816a43d42ce83da41d92000000610629565b5050565b60035461010090046001600160a01b031633146104ee57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052c57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056a57600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105bc9084906107c9565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106179086815260200190565b60405180910390a35060019392505050565b60008160008082825461063c91906107e0565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610380565b600060208083528351808285015260005b818110156106bb5785810183015185820160400152820161069f565b818111156106cd576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106fa57600080fd5b919050565b6000806040838503121561071257600080fd5b61071b836106e3565b946020939093013593505050565b60008060006060848603121561073e57600080fd5b610747846106e3565b9250610755602085016106e3565b9150604084013590509250925092565b60006020828403121561077757600080fd5b61044b826106e3565b6000806040838503121561079357600080fd5b61079c836106e3565b91506107aa602084016106e3565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107db576107db6107b3565b500390565b600082198211156107f3576107f36107b3565b50019056fea2646970667358221220f8b02598ef222bea887cc1b8774b7a707d0d5af2989efc0c337c134d268c958864736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ae578063dd62ed3e146102c1578063e752c44a146102ec578063ec676a25146102ff578063fca3b5aa1461031257600080fd5b806395d89b4114610243578063a9059cbb14610266578063aad3ec9614610279578063c268f9ba1461028c578063ca1c4de9146102a157600080fd5b806323b872dd116100f457806323b872dd146101d0578063313ce567146101e357806340c10f19146101fd5780635e05fe501461021057806370a082311461022357600080fd5b806306fdde03146101265780630754617214610166578063095ea7b31461019657806318160ddd146101b9575b600080fd5b6101506040518060400160405280600b81526020016a2b32b637b1b4b6b2ba32b960a91b81525081565b60405161015d919061068e565b60405180910390f35b60035461017e9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015d565b6101a96101a43660046106ff565b610325565b604051901515815260200161015d565b6101c260005481565b60405190815260200161015d565b6101a96101de366004610729565b610391565b6101eb601281565b60405160ff909116815260200161015d565b6101a961020b3660046106ff565b61040b565b60045461017e906001600160a01b031681565b6101c2610231366004610765565b60016020526000908152604090205481565b61015060405180604001604052806004815260200163464c4f5760e01b81525081565b6101a96102743660046106ff565b61043e565b6101a96102873660046106ff565b610452565b61029f61029a366004610765565b610481565b005b6003546101a99060ff1681565b61029f6102bc366004610765565b6104d2565b6101c26102cf366004610780565b600260209081526000928352604080842090915290825290205481565b60055461017e906001600160a01b031681565b61029f61030d366004610765565b610510565b61029f610320366004610765565b61054e565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103809086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f7576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103f19084906107c9565b90915550505b610402858585610592565b95945050505050565b60035460009061010090046001600160a01b0316331461042a57600080fd5b6104348383610629565b5060019392505050565b600061044b338484610592565b9392505050565b6004546000906001600160a01b031633148061047857506005546001600160a01b031633145b61042a57600080fd5b60035461010090046001600160a01b0316331480156104a3575060035460ff16155b6104ac57600080fd5b6003805460ff191660011790556104ce816a43d42ce83da41d92000000610629565b5050565b60035461010090046001600160a01b031633146104ee57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052c57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056a57600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105bc9084906107c9565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106179086815260200190565b60405180910390a35060019392505050565b60008160008082825461063c91906107e0565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610380565b600060208083528351808285015260005b818110156106bb5785810183015185820160400152820161069f565b818111156106cd576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106fa57600080fd5b919050565b6000806040838503121561071257600080fd5b61071b836106e3565b946020939093013593505050565b60008060006060848603121561073e57600080fd5b610747846106e3565b9250610755602085016106e3565b9150604084013590509250925092565b60006020828403121561077757600080fd5b61044b826106e3565b6000806040838503121561079357600080fd5b61079c836106e3565b91506107aa602084016106e3565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107db576107db6107b3565b500390565b600082198211156107f3576107f36107b3565b50019056fea2646970667358221220f8b02598ef222bea887cc1b8774b7a707d0d5af2989efc0c337c134d268c958864736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/FlowGovernor.json b/deployments/arbitrumGoerli/FlowGovernor.json index 48852662..5bd87a17 100644 --- a/deployments/arbitrumGoerli/FlowGovernor.json +++ b/deployments/arbitrumGoerli/FlowGovernor.json @@ -1,5 +1,5 @@ { - "address": "0x98d89Bcf02e1142c8EB31959A38F498EcFCfAe57", + "address": "0x4C80ebcC6942543c83dA9cbD9aab41994307909c", "abi": [ { "inputs": [ @@ -1055,43 +1055,43 @@ "type": "receive" } ], - "transactionHash": "0x0eb80b49c044205bc02d913cff01f5fc43f92657c8afc9b835a517cea0b5ab3f", + "transactionHash": "0x5890f42548404912dc7a781bf48dfc717a9ee7fedcc2031802bc667f57427d43", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x98d89Bcf02e1142c8EB31959A38F498EcFCfAe57", + "contractAddress": "0x4C80ebcC6942543c83dA9cbD9aab41994307909c", "transactionIndex": 1, "gasUsed": "2742890", - "logsBloom": "0x00000000000000000100000000001000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x8a074d3df27305fa89663da6e667b01058e1ed0bdf7e7d827a3f7f21e99b4904", - "transactionHash": "0x0eb80b49c044205bc02d913cff01f5fc43f92657c8afc9b835a517cea0b5ab3f", + "logsBloom": "0x00000000000000000100000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x273df698ce46e21bb47c3fdaf3912c203104a6061471ed97193c8f892d851671", + "transactionHash": "0x5890f42548404912dc7a781bf48dfc717a9ee7fedcc2031802bc667f57427d43", "logs": [ { "transactionIndex": 1, - "blockNumber": 5849249, - "transactionHash": "0x0eb80b49c044205bc02d913cff01f5fc43f92657c8afc9b835a517cea0b5ab3f", - "address": "0x98d89Bcf02e1142c8EB31959A38F498EcFCfAe57", + "blockNumber": 6069454, + "transactionHash": "0x5890f42548404912dc7a781bf48dfc717a9ee7fedcc2031802bc667f57427d43", + "address": "0x4C80ebcC6942543c83dA9cbD9aab41994307909c", "topics": [ "0x0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997" ], "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004", "logIndex": 0, - "blockHash": "0x8a074d3df27305fa89663da6e667b01058e1ed0bdf7e7d827a3f7f21e99b4904" + "blockHash": "0x273df698ce46e21bb47c3fdaf3912c203104a6061471ed97193c8f892d851671" } ], - "blockNumber": 5849249, + "blockNumber": 6069454, "cumulativeGasUsed": "2742890", "status": 1, "byzantium": true }, "args": [ - "0xF003091B78974ee3F99ec70fC5F42fc9810664EC" + "0x6d55AFbF1cAf01E0bcA5255bbA730da6fAFD0aF4" ], - "numDeployments": 3, - "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"_ve\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"Empty\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"proposer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"string[]\",\"name\":\"signatures\",\"type\":\"string[]\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"ProposalCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldQuorumNumerator\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"QuorumNumeratorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"VoteCast\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"VoteCastWithParams\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"COUNTING_MODE\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EXTENDED_BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_PROPOSAL_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROPOSAL_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"}],\"name\":\"castVote\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"castVoteWithReason\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"castVoteWithReasonAndParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteWithReasonAndParamsBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"execute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"getVotesWithParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasVoted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"hashProposal\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalDeadline\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalSnapshot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"againstVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"forVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"abstainVotes\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"propose\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"quorum\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumDenominator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"}],\"name\":\"setProposalNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTeam\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"state\",\"outputs\":[{\"internalType\":\"enum IGovernor.ProposalState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"updateQuorumNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"Empty()\":[{\"details\":\"An operation (e.g. {front}) couldn't be completed due to the queue being empty.\"}]},\"kind\":\"dev\",\"methods\":{\"COUNTING_MODE()\":{\"details\":\"See {IGovernor-COUNTING_MODE}.\"},\"castVote(uint256,uint8)\":{\"details\":\"See {IGovernor-castVote}.\"},\"castVoteBySig(uint256,uint8,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteBySig}.\"},\"castVoteWithReason(uint256,uint8,string)\":{\"details\":\"See {IGovernor-castVoteWithReason}.\"},\"castVoteWithReasonAndParams(uint256,uint8,string,bytes)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParams}.\"},\"castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParamsBySig}.\"},\"execute(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-execute}.\"},\"getVotes(address,uint256)\":{\"details\":\"See {IGovernor-getVotes}.\"},\"getVotesWithParams(address,uint256,bytes)\":{\"details\":\"See {IGovernor-getVotesWithParams}.\"},\"hasVoted(uint256,address)\":{\"details\":\"See {IGovernor-hasVoted}.\"},\"hashProposal(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-hashProposal}. The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in advance, before the proposal is submitted. Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the same proposal (with same operation and same description) will have the same id if submitted on multiple governors across multiple networks. This also means that in order to execute the same operation twice (on the same governor) the proposer will have to change the description in order to avoid proposal id conflicts.\"},\"name()\":{\"details\":\"See {IGovernor-name}.\"},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155BatchReceived}.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155Received}.\"},\"onERC721Received(address,address,uint256,bytes)\":{\"details\":\"See {IERC721Receiver-onERC721Received}.\"},\"proposalDeadline(uint256)\":{\"details\":\"See {IGovernor-proposalDeadline}.\"},\"proposalSnapshot(uint256)\":{\"details\":\"See {IGovernor-proposalSnapshot}.\"},\"proposalThreshold()\":{\"details\":\"Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\"},\"proposalVotes(uint256)\":{\"details\":\"Accessor to the internal vote counts.\"},\"propose(address[],uint256[],bytes[],string)\":{\"details\":\"See {IGovernor-propose}.\"},\"quorum(uint256)\":{\"details\":\"Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\"},\"quorumDenominator()\":{\"details\":\"Returns the quorum denominator. Defaults to 100, but may be overridden.\"},\"quorumNumerator()\":{\"details\":\"Returns the current quorum numerator. See {quorumDenominator}.\"},\"relay(address,uint256,bytes)\":{\"details\":\"Relays a transaction or function call to an arbitrary target. In cases where the governance executor is some contract other than the governor itself, like when using a timelock, this function can be invoked in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake. Note that if the executor is simply the governor itself, use of `relay` is redundant.\"},\"state(uint256)\":{\"details\":\"See {IGovernor-state}.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"updateQuorumNumerator(uint256)\":{\"details\":\"Changes the quorum numerator. Emits a {QuorumNumeratorUpdated} event. Requirements: - Must be called through a governance proposal. - New numerator must be smaller or equal to the denominator.\"},\"version()\":{\"details\":\"See {IGovernor-version}.\"},\"votingDelay()\":{\"details\":\"Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\"},\"votingPeriod()\":{\"details\":\"Delay, in number of blocks, between the vote start and vote ends. NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting duration compared to the voting delay.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"votingDelay()\":{\"notice\":\"module:user-config\"},\"votingPeriod()\":{\"notice\":\"module:user-config\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/FlowGovernor.sol\":\"FlowGovernor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/FlowGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IGovernor} from \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\nimport {L2GovernorCountingSimple} from \\\"contracts/governance/L2GovernorCountingSimple.sol\\\";\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\nimport {L2GovernorVotesQuorumFraction} from \\\"contracts/governance/L2GovernorVotesQuorumFraction.sol\\\";\\n\\ncontract FlowGovernor is\\n L2Governor,\\n L2GovernorCountingSimple,\\n L2GovernorVotes,\\n L2GovernorVotesQuorumFraction\\n{\\n address public team;\\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\\n uint256 public proposalNumerator = 2; // start at 0.02%\\n\\n constructor(IVotes _ve)\\n L2Governor(\\\"Velocimeter Governor\\\")\\n L2GovernorVotes(_ve)\\n L2GovernorVotesQuorumFraction(4) // 4%\\n {\\n team = msg.sender;\\n }\\n\\n function votingDelay() public pure override(IGovernor) returns (uint256) {\\n return 15 minutes; // 1 block\\n }\\n\\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\\n return 1 weeks;\\n }\\n\\n function setTeam(address newTeam) external {\\n require(msg.sender == team, \\\"not team\\\");\\n team = newTeam;\\n }\\n\\n function setProposalNumerator(uint256 numerator) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \\\"numerator too high\\\");\\n proposalNumerator = numerator;\\n }\\n\\n function proposalThreshold()\\n public\\n view\\n override(L2Governor)\\n returns (uint256)\\n {\\n return\\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\\n PROPOSAL_DENOMINATOR;\\n }\\n}\\n\",\"keccak256\":\"0xbf02f2fa1b0179b06bba2274ce6720c31ba3783f899502567cc25a093b27edb6\",\"license\":\"MIT\"},\"contracts/governance/L2Governor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Address.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Context.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\\n *\\n * @dev Core of the governance system, designed to be extended though various modules.\\n *\\n * This contract is abstract and requires several function to be implemented in various modules:\\n *\\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\\n * - A voting module must implement {_getVotes}\\n * - Additionanly, the {votingPeriod} must also be implemented\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\\n using SafeCast for uint256;\\n using Timers for Timers.Timestamp;\\n\\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\\\"Ballot(uint256 proposalId,uint8 support)\\\");\\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\\n keccak256(\\\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\\\");\\n\\n struct ProposalCore {\\n Timers.Timestamp voteStart;\\n Timers.Timestamp voteEnd;\\n bool executed;\\n bool canceled;\\n }\\n\\n string private _name;\\n\\n mapping(uint256 => ProposalCore) private _proposals;\\n\\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\\n\\n /**\\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\\n * parameter setters in {GovernorSettings} are protected using this modifier.\\n *\\n * The governance executing address may be different from the Governor's own address, for example it could be a\\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\\n * for example, additional timelock proposers are not able to change governance parameters without going through the\\n * governance protocol (since v4.6).\\n */\\n modifier onlyGovernance() {\\n require(_msgSender() == _executor(), \\\"Governor: onlyGovernance\\\");\\n if (_executor() != address(this)) {\\n bytes32 msgDataHash = keccak256(_msgData());\\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\\n while (_governanceCall.popFront() != msgDataHash) {}\\n }\\n _;\\n }\\n\\n /**\\n * @dev Sets the value for {name} and {version}\\n */\\n constructor(string memory name_) EIP712(name_, version()) {\\n _name = name_;\\n }\\n\\n /**\\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\\n */\\n receive() external payable virtual {\\n require(_executor() == address(this));\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\\n // include the castVoteWithReasonAndParams() function as standard\\n return\\n interfaceId ==\\n (type(IGovernor).interfaceId ^\\n this.castVoteWithReasonAndParams.selector ^\\n this.castVoteWithReasonAndParamsBySig.selector ^\\n this.getVotesWithParams.selector) ||\\n interfaceId == type(IGovernor).interfaceId ||\\n interfaceId == type(IERC1155Receiver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IGovernor-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IGovernor-version}.\\n */\\n function version() public view virtual override returns (string memory) {\\n return \\\"1\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hashProposal}.\\n *\\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\\n * advance, before the proposal is submitted.\\n *\\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual override returns (uint256) {\\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\\n }\\n\\n /**\\n * @dev See {IGovernor-state}.\\n */\\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n\\n if (proposal.executed) {\\n return ProposalState.Executed;\\n }\\n\\n if (proposal.canceled) {\\n return ProposalState.Canceled;\\n }\\n\\n uint256 start = proposalSnapshot(proposalId);\\n\\n if (start == 0) {\\n revert(\\\"Governor: unknown proposal id\\\");\\n }\\n\\n if (start >= block.timestamp) {\\n return ProposalState.Pending;\\n }\\n\\n uint256 deadline = proposalDeadline(proposalId);\\n\\n if (deadline >= block.timestamp) {\\n return ProposalState.Active;\\n }\\n\\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\\n return ProposalState.Succeeded;\\n } else {\\n return ProposalState.Defeated;\\n }\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalSnapshot}.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteStart.getDeadline();\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalDeadline}.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteEnd.getDeadline();\\n }\\n\\n /**\\n * @dev Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\\n */\\n function proposalThreshold() public view virtual returns (uint256) {\\n return 0;\\n }\\n\\n /**\\n * @dev Amount of votes already cast passes the threshold limit.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Is the proposal successful or not.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) internal view virtual returns (uint256);\\n\\n /**\\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\\n *\\n * Note: Support is generic and can represent various things depending on the voting system used.\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory params\\n ) internal virtual;\\n\\n /**\\n * @dev Default additional encoded parameters used by castVote methods that don't include them\\n *\\n * Note: Should be overridden by specific implementations to use an appropriate value, the\\n * meaning of the additional params, in the context of that implementation\\n */\\n function _defaultParams() internal view virtual returns (bytes memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-propose}.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual override returns (uint256) {\\n require(\\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\\n \\\"Governor: proposer votes below proposal threshold\\\"\\n );\\n\\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\\n\\n require(targets.length == values.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length == calldatas.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length > 0, \\\"Governor: empty proposal\\\");\\n\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(proposal.voteStart.isUnset(), \\\"Governor: proposal already exists\\\");\\n\\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\\n uint64 deadline = start + votingPeriod().toUint64();\\n\\n proposal.voteStart.setDeadline(start);\\n proposal.voteEnd.setDeadline(deadline);\\n\\n emit ProposalCreated(\\n proposalId,\\n _msgSender(),\\n targets,\\n values,\\n new string[](targets.length),\\n calldatas,\\n start,\\n deadline,\\n description\\n );\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-execute}.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual override returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n\\n ProposalState status = state(proposalId);\\n require(\\n status == ProposalState.Succeeded || status == ProposalState.Queued,\\n \\\"Governor: proposal not successful\\\"\\n );\\n _proposals[proposalId].executed = true;\\n\\n emit ProposalExecuted(proposalId);\\n\\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\\n _execute(proposalId, targets, values, calldatas, descriptionHash);\\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\\n */\\n function _execute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n string memory errorMessage = \\\"Governor: call reverted without message\\\";\\n for (uint256 i = 0; i < targets.length; ++i) {\\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\\n Address.verifyCallResult(success, returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Hook before execution is triggered.\\n */\\n function _beforeExecute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory, /* values */\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n for (uint256 i = 0; i < targets.length; ++i) {\\n if (targets[i] == address(this)) {\\n _governanceCall.pushBack(keccak256(calldatas[i]));\\n }\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook after execution is triggered.\\n */\\n function _afterExecute(\\n uint256, /* proposalId */\\n address[] memory, /* targets */\\n uint256[] memory, /* values */\\n bytes[] memory, /* calldatas */\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n if (!_governanceCall.empty()) {\\n _governanceCall.clear();\\n }\\n }\\n }\\n\\n /**\\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\\n * canceled to allow distinguishing it from executed proposals.\\n *\\n * Emits a {IGovernor-ProposalCanceled} event.\\n */\\n function _cancel(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) internal virtual returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n ProposalState status = state(proposalId);\\n\\n require(\\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\\n \\\"Governor: proposal not active\\\"\\n );\\n _proposals[proposalId].canceled = true;\\n\\n emit ProposalCanceled(proposalId);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotes}.\\n */\\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, _defaultParams());\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotesWithParams}.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVote}.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReason}.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteBySig}.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\\n v,\\n r,\\n s\\n );\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(\\n keccak256(\\n abi.encode(\\n EXTENDED_BALLOT_TYPEHASH,\\n proposalId,\\n support,\\n keccak256(bytes(reason)),\\n keccak256(params)\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason\\n ) internal virtual returns (uint256) {\\n return _castVote(proposalId, account, support, reason, _defaultParams());\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason,\\n bytes memory params\\n ) internal virtual returns (uint256) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(state(proposalId) == ProposalState.Active, \\\"Governor: vote not currently active\\\");\\n\\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\\n _countVote(proposalId, account, support, weight, params);\\n\\n if (params.length == 0) {\\n emit VoteCast(account, proposalId, support, weight, reason);\\n } else {\\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\\n }\\n\\n return weight;\\n }\\n\\n /**\\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\\n */\\n function relay(\\n address target,\\n uint256 value,\\n bytes calldata data\\n ) external virtual onlyGovernance {\\n Address.functionCallWithValue(target, data, value);\\n }\\n\\n /**\\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\\n * through another contract such as a timelock.\\n */\\n function _executor() internal view virtual returns (address) {\\n return address(this);\\n }\\n\\n /**\\n * @dev See {IERC721Receiver-onERC721Received}.\\n */\\n function onERC721Received(\\n address,\\n address,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155Received}.\\n */\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\\n */\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] memory,\\n uint256[] memory,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155BatchReceived.selector;\\n }\\n}\\n\",\"keccak256\":\"0xa2846313b89a871807cdebd0225b0bf8f23b17505ab8b3288549ec54a5a4a71b\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorCountingSimple.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\\n *\\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorCountingSimple is L2Governor {\\n /**\\n * @dev Supported vote types. Matches Governor Bravo ordering.\\n */\\n enum VoteType {\\n Against,\\n For,\\n Abstain\\n }\\n\\n struct ProposalVote {\\n uint256 againstVotes;\\n uint256 forVotes;\\n uint256 abstainVotes;\\n mapping(address => bool) hasVoted;\\n }\\n\\n mapping(uint256 => ProposalVote) private _proposalVotes;\\n\\n /**\\n * @dev See {IGovernor-COUNTING_MODE}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual override returns (string memory) {\\n return \\\"support=bravo&quorum=for,abstain\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hasVoted}.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\\n return _proposalVotes[proposalId].hasVoted[account];\\n }\\n\\n /**\\n * @dev Accessor to the internal vote counts.\\n */\\n function proposalVotes(uint256 proposalId)\\n public\\n view\\n virtual\\n returns (\\n uint256 againstVotes,\\n uint256 forVotes,\\n uint256 abstainVotes\\n )\\n {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\\n }\\n\\n /**\\n * @dev See {Governor-_quorumReached}.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return proposalvote.forVotes > proposalvote.againstVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory // params\\n ) internal virtual override {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n require(!proposalvote.hasVoted[account], \\\"GovernorVotingSimple: vote already cast\\\");\\n proposalvote.hasVoted[account] = true;\\n\\n if (support == uint8(VoteType.Against)) {\\n proposalvote.againstVotes += weight;\\n } else if (support == uint8(VoteType.For)) {\\n proposalvote.forVotes += weight;\\n } else if (support == uint8(VoteType.Abstain)) {\\n proposalvote.abstainVotes += weight;\\n } else {\\n revert(\\\"GovernorVotingSimple: invalid value for enum VoteType\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xdc37daa24118a6e6ba5208b4abefa1632af2ff340135ca6c6d7237f70102d5db\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotes is L2Governor {\\n IVotes public immutable token;\\n\\n constructor(IVotes tokenAddress) {\\n token = tokenAddress;\\n }\\n\\n /**\\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory /*params*/\\n ) internal view virtual override returns (uint256) {\\n return token.getPastVotes(account, blockTimestamp);\\n }\\n}\\n\",\"keccak256\":\"0x605a7de71228dda3cb8fd878cac313a86bc5841fd34d7344214346ba46e63af1\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotesQuorumFraction.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\\n * fraction of the total supply.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\\n uint256 private _quorumNumerator;\\n\\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\\n\\n /**\\n * @dev Initialize quorum as a fraction of the token's total supply.\\n *\\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\\n * customized by overriding {quorumDenominator}.\\n */\\n constructor(uint256 quorumNumeratorValue) {\\n _updateQuorumNumerator(quorumNumeratorValue);\\n }\\n\\n /**\\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\\n */\\n function quorumNumerator() public view virtual returns (uint256) {\\n return _quorumNumerator;\\n }\\n\\n /**\\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\\n */\\n function quorumDenominator() public view virtual returns (uint256) {\\n return 100;\\n }\\n\\n /**\\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\\n */\\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - Must be called through a governance proposal.\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\\n _updateQuorumNumerator(newQuorumNumerator);\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\\n require(\\n newQuorumNumerator <= quorumDenominator(),\\n \\\"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\\\"\\n );\\n\\n uint256 oldQuorumNumerator = _quorumNumerator;\\n _quorumNumerator = newQuorumNumerator;\\n\\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\\n }\\n}\\n\",\"keccak256\":\"0xe66d29c0ffd2274de933d80e11d68891f3acc3f078be4560a2b493b7d88dcb7f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Interface of the {Governor} core.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract IGovernor is IERC165 {\\n enum ProposalState {\\n Pending,\\n Active,\\n Canceled,\\n Defeated,\\n Succeeded,\\n Queued,\\n Expired,\\n Executed\\n }\\n\\n /**\\n * @dev Emitted when a proposal is created.\\n */\\n event ProposalCreated(\\n uint256 proposalId,\\n address proposer,\\n address[] targets,\\n uint256[] values,\\n string[] signatures,\\n bytes[] calldatas,\\n uint256 startBlock,\\n uint256 endBlock,\\n string description\\n );\\n\\n /**\\n * @dev Emitted when a proposal is canceled.\\n */\\n event ProposalCanceled(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a proposal is executed.\\n */\\n event ProposalExecuted(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a vote is cast without params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n */\\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\\n\\n /**\\n * @dev Emitted when a vote is cast with params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\\n */\\n event VoteCastWithParams(\\n address indexed voter,\\n uint256 proposalId,\\n uint8 support,\\n uint256 weight,\\n string reason,\\n bytes params\\n );\\n\\n /**\\n * @notice module:core\\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\\n */\\n function name() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \\\"1\\\"\\n */\\n function version() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:voting\\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\\n *\\n * There are 2 standard keys: `support` and `quorum`.\\n *\\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\\n * - `quorum=bravo` means that only For votes are counted towards quorum.\\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\\n *\\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\\n * name that describes the behavior. For example:\\n *\\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\\n *\\n * NOTE: The string can be decoded by the standard\\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\\n * JavaScript class.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Current state of a proposal, following Compound's convention\\n */\\n function state(uint256 proposalId) public view virtual returns (ProposalState);\\n\\n /**\\n * @notice module:core\\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\\n * beginning of the following block.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\\n * during this block.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\\n */\\n function votingDelay() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of blocks, between the vote start and vote ends.\\n *\\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\\n * duration compared to the voting delay.\\n */\\n function votingPeriod() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Minimum number of cast voted required for a proposal to be successful.\\n *\\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\\n */\\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber`.\\n *\\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\\n * multiple), {ERC20Votes} tokens.\\n */\\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockNumber,\\n bytes memory params\\n ) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:voting\\n * @dev Returns whether `account` has cast a vote on `proposalId`.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\\n\\n /**\\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\\n * {IGovernor-votingPeriod} blocks after the voting starts.\\n *\\n * Emits a {ProposalCreated} event.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\\n * deadline to be reached.\\n *\\n * Emits a {ProposalExecuted} event.\\n *\\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Cast a vote\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xa52d593ff06a2353f78fa149da31f2ca94f03d1eff99bde41977fa2fe985a92f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2e53602b96c1bf97c731ed3e2a981b4f85e23a9410a5ebd36e549a4cc93340dc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x2626d8ab3dfdad0fad630c212ad146d59473d0f48b771784c61a7c1dbbea1f3f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Tooling for timepoints, timers and delays\\n */\\nlibrary Timers {\\n struct Timestamp {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(Timestamp storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(Timestamp memory timer) internal view returns (bool) {\\n return timer._deadline > block.timestamp;\\n }\\n\\n function isExpired(Timestamp memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.timestamp;\\n }\\n\\n struct BlockNumber {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(BlockNumber storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(BlockNumber memory timer) internal view returns (bool) {\\n return timer._deadline > block.number;\\n }\\n\\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.number;\\n }\\n}\\n\",\"keccak256\":\"0x29791a62950a7983e02a673639c1a781d1e448691800456c2ce4b99715391b14\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS,\\n InvalidSignatureV // Deprecated in v4.8\\n }\\n\\n function _throwError(RecoverError error) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert(\\\"ECDSA: invalid signature\\\");\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert(\\\"ECDSA: invalid signature 's' value\\\");\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature` or error string. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\\n if (signature.length == 65) {\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n /// @solidity memory-safe-assembly\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n return tryRecover(hash, v, r, s);\\n } else {\\n return (address(0), RecoverError.InvalidSignatureLength);\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, signature);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n *\\n * _Available since v4.2._\\n */\\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature);\\n }\\n\\n return (signer, RecoverError.NoError);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from `s`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", Strings.toString(s.length), s));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Typed Data, created from a\\n * `domainSeparator` and a `structHash`. This produces hash corresponding\\n * to the one signed with the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\\n * JSON-RPC method as part of EIP-712.\\n *\\n * See {recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n }\\n}\\n\",\"keccak256\":\"0x54ee424bfc83ce63b2a918b9a1efb5090a0fb68dbd1de3b10bc667776885dd4f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ECDSA.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n /* solhint-disable var-name-mixedcase */\\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n // invalidate the cached domain separator if the chain id changes.\\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n uint256 private immutable _CACHED_CHAIN_ID;\\n address private immutable _CACHED_THIS;\\n\\n bytes32 private immutable _HASHED_NAME;\\n bytes32 private immutable _HASHED_VERSION;\\n bytes32 private immutable _TYPE_HASH;\\n\\n /* solhint-enable var-name-mixedcase */\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n constructor(string memory name, string memory version) {\\n bytes32 hashedName = keccak256(bytes(name));\\n bytes32 hashedVersion = keccak256(bytes(version));\\n bytes32 typeHash = keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n );\\n _HASHED_NAME = hashedName;\\n _HASHED_VERSION = hashedVersion;\\n _CACHED_CHAIN_ID = block.chainid;\\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n _CACHED_THIS = address(this);\\n _TYPE_HASH = typeHash;\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\\n return _CACHED_DOMAIN_SEPARATOR;\\n } else {\\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n }\\n }\\n\\n function _buildDomainSeparator(\\n bytes32 typeHash,\\n bytes32 nameHash,\\n bytes32 versionHash\\n ) private view returns (bytes32) {\\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\\n }\\n}\\n\",\"keccak256\":\"0x948d8b2d18f38141ec78c5229d770d950ebc781ed3f44cc9e3ccbb9fded5846a\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\\n\\nimport \\\"./EIP712.sol\\\";\\n\",\"keccak256\":\"0xea30c402170bc240354b74e6c6f6a8e5bdb1935d90d168cc58c0654461c6a72b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3546b156d97633f7f8cad536d5454c81d1d604687c02b2eb105fdc33cb962b41\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\\npragma solidity ^0.8.4;\\n\\nimport \\\"../math/SafeCast.sol\\\";\\n\\n/**\\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\\n * the existing queue contents are left in storage.\\n *\\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\\n * used in storage, and not in memory.\\n * ```\\n * DoubleEndedQueue.Bytes32Deque queue;\\n * ```\\n *\\n * _Available since v4.6._\\n */\\nlibrary DoubleEndedQueue {\\n /**\\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\\n */\\n error Empty();\\n\\n /**\\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\\n */\\n error OutOfBounds();\\n\\n /**\\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\\n *\\n * Struct members have an underscore prefix indicating that they are \\\"private\\\" and should not be read or written to\\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\\n * lead to unexpected behavior.\\n *\\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\\n * data[end - 1].\\n */\\n struct Bytes32Deque {\\n int128 _begin;\\n int128 _end;\\n mapping(int128 => bytes32) _data;\\n }\\n\\n /**\\n * @dev Inserts an item at the end of the queue.\\n */\\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 backIndex = deque._end;\\n deque._data[backIndex] = value;\\n unchecked {\\n deque._end = backIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Removes the item at the end of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n value = deque._data[backIndex];\\n delete deque._data[backIndex];\\n deque._end = backIndex;\\n }\\n\\n /**\\n * @dev Inserts an item at the beginning of the queue.\\n */\\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 frontIndex;\\n unchecked {\\n frontIndex = deque._begin - 1;\\n }\\n deque._data[frontIndex] = value;\\n deque._begin = frontIndex;\\n }\\n\\n /**\\n * @dev Removes the item at the beginning of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n value = deque._data[frontIndex];\\n delete deque._data[frontIndex];\\n unchecked {\\n deque._begin = frontIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Returns the item at the beginning of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n return deque._data[frontIndex];\\n }\\n\\n /**\\n * @dev Returns the item at the end of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n return deque._data[backIndex];\\n }\\n\\n /**\\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\\n * `length(deque) - 1`.\\n *\\n * Reverts with `OutOfBounds` if the index is out of bounds.\\n */\\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\\n // int256(deque._begin) is a safe upcast\\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\\n if (idx >= deque._end) revert OutOfBounds();\\n return deque._data[idx];\\n }\\n\\n /**\\n * @dev Resets the queue back to being empty.\\n *\\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\\n * out on potential gas refunds.\\n */\\n function clear(Bytes32Deque storage deque) internal {\\n deque._begin = 0;\\n deque._end = 0;\\n }\\n\\n /**\\n * @dev Returns the number of items in the queue.\\n */\\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\\n // We also assume there are at most int256.max items in the queue.\\n unchecked {\\n return uint256(int256(deque._end) - int256(deque._begin));\\n }\\n }\\n\\n /**\\n * @dev Returns true if the queue is empty.\\n */\\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\\n return deque._end <= deque._begin;\\n }\\n}\\n\",\"keccak256\":\"0x4859ffd6dd69382a1462930c00b6e394007da80e78e510f56930271034737bf2\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x61016060405260026007553480156200001757600080fd5b506040516200329a3803806200329a8339810160408190526200003a91620002ec565b6004816040518060400160405280601481526020017f56656c6f63696d6574657220476f7665726e6f7200000000000000000000000081525080620000846200015e60201b60201c565b815160208084019190912082518383012060e08290526101008190524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81880181905281830187905260608201869052608082019490945230818401528151808203909301835260c00190528051940193909320919290916080523060c05261012052505082516200012a925060009150602084019062000246565b50506001600160a01b031661014052620001448162000179565b5050600680546001600160a01b031916331790556200035a565b6040805180820190915260018152603160f81b602082015290565b6064811115620002015760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a40160405180910390fd5b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b82805462000254906200031e565b90600052602060002090601f016020900481019282620002785760008555620002c3565b82601f106200029357805160ff1916838001178555620002c3565b82800160010185558215620002c3579182015b82811115620002c3578251825591602001919060010190620002a6565b50620002d1929150620002d5565b5090565b5b80821115620002d15760008155600101620002d6565b600060208284031215620002ff57600080fd5b81516001600160a01b03811681146200031757600080fd5b9392505050565b600181811c908216806200033357607f821691505b6020821081036200035457634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e051610100516101205161014051612ed0620003ca600039600081816107df0152818161120f015281816113e40152611a0601526000611b2301526000611b7201526000611b4d01526000611aa601526000611ad001526000611afa0152612ed06000f3fe6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220f1c9f7302b3d88ded5042644bb73ef24c2cd7fc463479870f81e5dbfe2cbed0b64736f6c634300080d0033", - "deployedBytecode": "0x6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220f1c9f7302b3d88ded5042644bb73ef24c2cd7fc463479870f81e5dbfe2cbed0b64736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "d2a2160297444b93438826228d1e185d", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"_ve\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"Empty\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"proposer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"string[]\",\"name\":\"signatures\",\"type\":\"string[]\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"ProposalCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldQuorumNumerator\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"QuorumNumeratorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"VoteCast\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"VoteCastWithParams\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"COUNTING_MODE\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EXTENDED_BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_PROPOSAL_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROPOSAL_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"}],\"name\":\"castVote\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"castVoteWithReason\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"castVoteWithReasonAndParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteWithReasonAndParamsBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"execute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"getVotesWithParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasVoted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"hashProposal\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalDeadline\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalSnapshot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"againstVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"forVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"abstainVotes\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"propose\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"quorum\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumDenominator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"}],\"name\":\"setProposalNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTeam\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"state\",\"outputs\":[{\"internalType\":\"enum IGovernor.ProposalState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"updateQuorumNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"Empty()\":[{\"details\":\"An operation (e.g. {front}) couldn't be completed due to the queue being empty.\"}]},\"kind\":\"dev\",\"methods\":{\"COUNTING_MODE()\":{\"details\":\"See {IGovernor-COUNTING_MODE}.\"},\"castVote(uint256,uint8)\":{\"details\":\"See {IGovernor-castVote}.\"},\"castVoteBySig(uint256,uint8,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteBySig}.\"},\"castVoteWithReason(uint256,uint8,string)\":{\"details\":\"See {IGovernor-castVoteWithReason}.\"},\"castVoteWithReasonAndParams(uint256,uint8,string,bytes)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParams}.\"},\"castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParamsBySig}.\"},\"execute(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-execute}.\"},\"getVotes(address,uint256)\":{\"details\":\"See {IGovernor-getVotes}.\"},\"getVotesWithParams(address,uint256,bytes)\":{\"details\":\"See {IGovernor-getVotesWithParams}.\"},\"hasVoted(uint256,address)\":{\"details\":\"See {IGovernor-hasVoted}.\"},\"hashProposal(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-hashProposal}. The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in advance, before the proposal is submitted. Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the same proposal (with same operation and same description) will have the same id if submitted on multiple governors across multiple networks. This also means that in order to execute the same operation twice (on the same governor) the proposer will have to change the description in order to avoid proposal id conflicts.\"},\"name()\":{\"details\":\"See {IGovernor-name}.\"},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155BatchReceived}.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155Received}.\"},\"onERC721Received(address,address,uint256,bytes)\":{\"details\":\"See {IERC721Receiver-onERC721Received}.\"},\"proposalDeadline(uint256)\":{\"details\":\"See {IGovernor-proposalDeadline}.\"},\"proposalSnapshot(uint256)\":{\"details\":\"See {IGovernor-proposalSnapshot}.\"},\"proposalThreshold()\":{\"details\":\"Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\"},\"proposalVotes(uint256)\":{\"details\":\"Accessor to the internal vote counts.\"},\"propose(address[],uint256[],bytes[],string)\":{\"details\":\"See {IGovernor-propose}.\"},\"quorum(uint256)\":{\"details\":\"Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\"},\"quorumDenominator()\":{\"details\":\"Returns the quorum denominator. Defaults to 100, but may be overridden.\"},\"quorumNumerator()\":{\"details\":\"Returns the current quorum numerator. See {quorumDenominator}.\"},\"relay(address,uint256,bytes)\":{\"details\":\"Relays a transaction or function call to an arbitrary target. In cases where the governance executor is some contract other than the governor itself, like when using a timelock, this function can be invoked in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake. Note that if the executor is simply the governor itself, use of `relay` is redundant.\"},\"state(uint256)\":{\"details\":\"See {IGovernor-state}.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"updateQuorumNumerator(uint256)\":{\"details\":\"Changes the quorum numerator. Emits a {QuorumNumeratorUpdated} event. Requirements: - Must be called through a governance proposal. - New numerator must be smaller or equal to the denominator.\"},\"version()\":{\"details\":\"See {IGovernor-version}.\"},\"votingDelay()\":{\"details\":\"Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\"},\"votingPeriod()\":{\"details\":\"Delay, in number of blocks, between the vote start and vote ends. NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting duration compared to the voting delay.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"votingDelay()\":{\"notice\":\"module:user-config\"},\"votingPeriod()\":{\"notice\":\"module:user-config\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/FlowGovernor.sol\":\"FlowGovernor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/FlowGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IGovernor} from \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\nimport {L2GovernorCountingSimple} from \\\"contracts/governance/L2GovernorCountingSimple.sol\\\";\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\nimport {L2GovernorVotesQuorumFraction} from \\\"contracts/governance/L2GovernorVotesQuorumFraction.sol\\\";\\n\\ncontract FlowGovernor is\\n L2Governor,\\n L2GovernorCountingSimple,\\n L2GovernorVotes,\\n L2GovernorVotesQuorumFraction\\n{\\n address public team;\\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\\n uint256 public proposalNumerator = 2; // start at 0.02%\\n\\n constructor(IVotes _ve)\\n L2Governor(\\\"Velocimeter Governor\\\")\\n L2GovernorVotes(_ve)\\n L2GovernorVotesQuorumFraction(4) // 4%\\n {\\n team = msg.sender;\\n }\\n\\n function votingDelay() public pure override(IGovernor) returns (uint256) {\\n return 15 minutes; // 1 block\\n }\\n\\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\\n return 1 weeks;\\n }\\n\\n function setTeam(address newTeam) external {\\n require(msg.sender == team, \\\"not team\\\");\\n team = newTeam;\\n }\\n\\n function setProposalNumerator(uint256 numerator) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \\\"numerator too high\\\");\\n proposalNumerator = numerator;\\n }\\n\\n function proposalThreshold()\\n public\\n view\\n override(L2Governor)\\n returns (uint256)\\n {\\n return\\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\\n PROPOSAL_DENOMINATOR;\\n }\\n}\\n\",\"keccak256\":\"0xbf02f2fa1b0179b06bba2274ce6720c31ba3783f899502567cc25a093b27edb6\",\"license\":\"MIT\"},\"contracts/governance/L2Governor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Address.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Context.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\\n *\\n * @dev Core of the governance system, designed to be extended though various modules.\\n *\\n * This contract is abstract and requires several function to be implemented in various modules:\\n *\\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\\n * - A voting module must implement {_getVotes}\\n * - Additionanly, the {votingPeriod} must also be implemented\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\\n using SafeCast for uint256;\\n using Timers for Timers.Timestamp;\\n\\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\\\"Ballot(uint256 proposalId,uint8 support)\\\");\\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\\n keccak256(\\\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\\\");\\n\\n struct ProposalCore {\\n Timers.Timestamp voteStart;\\n Timers.Timestamp voteEnd;\\n bool executed;\\n bool canceled;\\n }\\n\\n string private _name;\\n\\n mapping(uint256 => ProposalCore) private _proposals;\\n\\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\\n\\n /**\\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\\n * parameter setters in {GovernorSettings} are protected using this modifier.\\n *\\n * The governance executing address may be different from the Governor's own address, for example it could be a\\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\\n * for example, additional timelock proposers are not able to change governance parameters without going through the\\n * governance protocol (since v4.6).\\n */\\n modifier onlyGovernance() {\\n require(_msgSender() == _executor(), \\\"Governor: onlyGovernance\\\");\\n if (_executor() != address(this)) {\\n bytes32 msgDataHash = keccak256(_msgData());\\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\\n while (_governanceCall.popFront() != msgDataHash) {}\\n }\\n _;\\n }\\n\\n /**\\n * @dev Sets the value for {name} and {version}\\n */\\n constructor(string memory name_) EIP712(name_, version()) {\\n _name = name_;\\n }\\n\\n /**\\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\\n */\\n receive() external payable virtual {\\n require(_executor() == address(this));\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\\n // include the castVoteWithReasonAndParams() function as standard\\n return\\n interfaceId ==\\n (type(IGovernor).interfaceId ^\\n this.castVoteWithReasonAndParams.selector ^\\n this.castVoteWithReasonAndParamsBySig.selector ^\\n this.getVotesWithParams.selector) ||\\n interfaceId == type(IGovernor).interfaceId ||\\n interfaceId == type(IERC1155Receiver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IGovernor-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IGovernor-version}.\\n */\\n function version() public view virtual override returns (string memory) {\\n return \\\"1\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hashProposal}.\\n *\\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\\n * advance, before the proposal is submitted.\\n *\\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual override returns (uint256) {\\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\\n }\\n\\n /**\\n * @dev See {IGovernor-state}.\\n */\\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n\\n if (proposal.executed) {\\n return ProposalState.Executed;\\n }\\n\\n if (proposal.canceled) {\\n return ProposalState.Canceled;\\n }\\n\\n uint256 start = proposalSnapshot(proposalId);\\n\\n if (start == 0) {\\n revert(\\\"Governor: unknown proposal id\\\");\\n }\\n\\n if (start >= block.timestamp) {\\n return ProposalState.Pending;\\n }\\n\\n uint256 deadline = proposalDeadline(proposalId);\\n\\n if (deadline >= block.timestamp) {\\n return ProposalState.Active;\\n }\\n\\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\\n return ProposalState.Succeeded;\\n } else {\\n return ProposalState.Defeated;\\n }\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalSnapshot}.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteStart.getDeadline();\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalDeadline}.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteEnd.getDeadline();\\n }\\n\\n /**\\n * @dev Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\\n */\\n function proposalThreshold() public view virtual returns (uint256) {\\n return 0;\\n }\\n\\n /**\\n * @dev Amount of votes already cast passes the threshold limit.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Is the proposal successful or not.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) internal view virtual returns (uint256);\\n\\n /**\\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\\n *\\n * Note: Support is generic and can represent various things depending on the voting system used.\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory params\\n ) internal virtual;\\n\\n /**\\n * @dev Default additional encoded parameters used by castVote methods that don't include them\\n *\\n * Note: Should be overridden by specific implementations to use an appropriate value, the\\n * meaning of the additional params, in the context of that implementation\\n */\\n function _defaultParams() internal view virtual returns (bytes memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-propose}.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual override returns (uint256) {\\n require(\\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\\n \\\"Governor: proposer votes below proposal threshold\\\"\\n );\\n\\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\\n\\n require(targets.length == values.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length == calldatas.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length > 0, \\\"Governor: empty proposal\\\");\\n\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(proposal.voteStart.isUnset(), \\\"Governor: proposal already exists\\\");\\n\\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\\n uint64 deadline = start + votingPeriod().toUint64();\\n\\n proposal.voteStart.setDeadline(start);\\n proposal.voteEnd.setDeadline(deadline);\\n\\n emit ProposalCreated(\\n proposalId,\\n _msgSender(),\\n targets,\\n values,\\n new string[](targets.length),\\n calldatas,\\n start,\\n deadline,\\n description\\n );\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-execute}.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual override returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n\\n ProposalState status = state(proposalId);\\n require(\\n status == ProposalState.Succeeded || status == ProposalState.Queued,\\n \\\"Governor: proposal not successful\\\"\\n );\\n _proposals[proposalId].executed = true;\\n\\n emit ProposalExecuted(proposalId);\\n\\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\\n _execute(proposalId, targets, values, calldatas, descriptionHash);\\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\\n */\\n function _execute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n string memory errorMessage = \\\"Governor: call reverted without message\\\";\\n for (uint256 i = 0; i < targets.length; ++i) {\\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\\n Address.verifyCallResult(success, returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Hook before execution is triggered.\\n */\\n function _beforeExecute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory, /* values */\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n for (uint256 i = 0; i < targets.length; ++i) {\\n if (targets[i] == address(this)) {\\n _governanceCall.pushBack(keccak256(calldatas[i]));\\n }\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook after execution is triggered.\\n */\\n function _afterExecute(\\n uint256, /* proposalId */\\n address[] memory, /* targets */\\n uint256[] memory, /* values */\\n bytes[] memory, /* calldatas */\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n if (!_governanceCall.empty()) {\\n _governanceCall.clear();\\n }\\n }\\n }\\n\\n /**\\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\\n * canceled to allow distinguishing it from executed proposals.\\n *\\n * Emits a {IGovernor-ProposalCanceled} event.\\n */\\n function _cancel(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) internal virtual returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n ProposalState status = state(proposalId);\\n\\n require(\\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\\n \\\"Governor: proposal not active\\\"\\n );\\n _proposals[proposalId].canceled = true;\\n\\n emit ProposalCanceled(proposalId);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotes}.\\n */\\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, _defaultParams());\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotesWithParams}.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVote}.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReason}.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteBySig}.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\\n v,\\n r,\\n s\\n );\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(\\n keccak256(\\n abi.encode(\\n EXTENDED_BALLOT_TYPEHASH,\\n proposalId,\\n support,\\n keccak256(bytes(reason)),\\n keccak256(params)\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason\\n ) internal virtual returns (uint256) {\\n return _castVote(proposalId, account, support, reason, _defaultParams());\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason,\\n bytes memory params\\n ) internal virtual returns (uint256) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(state(proposalId) == ProposalState.Active, \\\"Governor: vote not currently active\\\");\\n\\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\\n _countVote(proposalId, account, support, weight, params);\\n\\n if (params.length == 0) {\\n emit VoteCast(account, proposalId, support, weight, reason);\\n } else {\\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\\n }\\n\\n return weight;\\n }\\n\\n /**\\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\\n */\\n function relay(\\n address target,\\n uint256 value,\\n bytes calldata data\\n ) external virtual onlyGovernance {\\n Address.functionCallWithValue(target, data, value);\\n }\\n\\n /**\\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\\n * through another contract such as a timelock.\\n */\\n function _executor() internal view virtual returns (address) {\\n return address(this);\\n }\\n\\n /**\\n * @dev See {IERC721Receiver-onERC721Received}.\\n */\\n function onERC721Received(\\n address,\\n address,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155Received}.\\n */\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\\n */\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] memory,\\n uint256[] memory,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155BatchReceived.selector;\\n }\\n}\\n\",\"keccak256\":\"0xa2846313b89a871807cdebd0225b0bf8f23b17505ab8b3288549ec54a5a4a71b\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorCountingSimple.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\\n *\\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorCountingSimple is L2Governor {\\n /**\\n * @dev Supported vote types. Matches Governor Bravo ordering.\\n */\\n enum VoteType {\\n Against,\\n For,\\n Abstain\\n }\\n\\n struct ProposalVote {\\n uint256 againstVotes;\\n uint256 forVotes;\\n uint256 abstainVotes;\\n mapping(address => bool) hasVoted;\\n }\\n\\n mapping(uint256 => ProposalVote) private _proposalVotes;\\n\\n /**\\n * @dev See {IGovernor-COUNTING_MODE}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual override returns (string memory) {\\n return \\\"support=bravo&quorum=for,abstain\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hasVoted}.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\\n return _proposalVotes[proposalId].hasVoted[account];\\n }\\n\\n /**\\n * @dev Accessor to the internal vote counts.\\n */\\n function proposalVotes(uint256 proposalId)\\n public\\n view\\n virtual\\n returns (\\n uint256 againstVotes,\\n uint256 forVotes,\\n uint256 abstainVotes\\n )\\n {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\\n }\\n\\n /**\\n * @dev See {Governor-_quorumReached}.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return proposalvote.forVotes > proposalvote.againstVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory // params\\n ) internal virtual override {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n require(!proposalvote.hasVoted[account], \\\"GovernorVotingSimple: vote already cast\\\");\\n proposalvote.hasVoted[account] = true;\\n\\n if (support == uint8(VoteType.Against)) {\\n proposalvote.againstVotes += weight;\\n } else if (support == uint8(VoteType.For)) {\\n proposalvote.forVotes += weight;\\n } else if (support == uint8(VoteType.Abstain)) {\\n proposalvote.abstainVotes += weight;\\n } else {\\n revert(\\\"GovernorVotingSimple: invalid value for enum VoteType\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xdc37daa24118a6e6ba5208b4abefa1632af2ff340135ca6c6d7237f70102d5db\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotes is L2Governor {\\n IVotes public immutable token;\\n\\n constructor(IVotes tokenAddress) {\\n token = tokenAddress;\\n }\\n\\n /**\\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory /*params*/\\n ) internal view virtual override returns (uint256) {\\n return token.getPastVotes(account, blockTimestamp);\\n }\\n}\\n\",\"keccak256\":\"0x605a7de71228dda3cb8fd878cac313a86bc5841fd34d7344214346ba46e63af1\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotesQuorumFraction.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\\n * fraction of the total supply.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\\n uint256 private _quorumNumerator;\\n\\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\\n\\n /**\\n * @dev Initialize quorum as a fraction of the token's total supply.\\n *\\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\\n * customized by overriding {quorumDenominator}.\\n */\\n constructor(uint256 quorumNumeratorValue) {\\n _updateQuorumNumerator(quorumNumeratorValue);\\n }\\n\\n /**\\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\\n */\\n function quorumNumerator() public view virtual returns (uint256) {\\n return _quorumNumerator;\\n }\\n\\n /**\\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\\n */\\n function quorumDenominator() public view virtual returns (uint256) {\\n return 100;\\n }\\n\\n /**\\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\\n */\\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - Must be called through a governance proposal.\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\\n _updateQuorumNumerator(newQuorumNumerator);\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\\n require(\\n newQuorumNumerator <= quorumDenominator(),\\n \\\"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\\\"\\n );\\n\\n uint256 oldQuorumNumerator = _quorumNumerator;\\n _quorumNumerator = newQuorumNumerator;\\n\\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\\n }\\n}\\n\",\"keccak256\":\"0xe66d29c0ffd2274de933d80e11d68891f3acc3f078be4560a2b493b7d88dcb7f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Interface of the {Governor} core.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract IGovernor is IERC165 {\\n enum ProposalState {\\n Pending,\\n Active,\\n Canceled,\\n Defeated,\\n Succeeded,\\n Queued,\\n Expired,\\n Executed\\n }\\n\\n /**\\n * @dev Emitted when a proposal is created.\\n */\\n event ProposalCreated(\\n uint256 proposalId,\\n address proposer,\\n address[] targets,\\n uint256[] values,\\n string[] signatures,\\n bytes[] calldatas,\\n uint256 startBlock,\\n uint256 endBlock,\\n string description\\n );\\n\\n /**\\n * @dev Emitted when a proposal is canceled.\\n */\\n event ProposalCanceled(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a proposal is executed.\\n */\\n event ProposalExecuted(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a vote is cast without params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n */\\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\\n\\n /**\\n * @dev Emitted when a vote is cast with params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\\n */\\n event VoteCastWithParams(\\n address indexed voter,\\n uint256 proposalId,\\n uint8 support,\\n uint256 weight,\\n string reason,\\n bytes params\\n );\\n\\n /**\\n * @notice module:core\\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\\n */\\n function name() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \\\"1\\\"\\n */\\n function version() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:voting\\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\\n *\\n * There are 2 standard keys: `support` and `quorum`.\\n *\\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\\n * - `quorum=bravo` means that only For votes are counted towards quorum.\\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\\n *\\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\\n * name that describes the behavior. For example:\\n *\\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\\n *\\n * NOTE: The string can be decoded by the standard\\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\\n * JavaScript class.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Current state of a proposal, following Compound's convention\\n */\\n function state(uint256 proposalId) public view virtual returns (ProposalState);\\n\\n /**\\n * @notice module:core\\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\\n * beginning of the following block.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\\n * during this block.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\\n */\\n function votingDelay() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of blocks, between the vote start and vote ends.\\n *\\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\\n * duration compared to the voting delay.\\n */\\n function votingPeriod() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Minimum number of cast voted required for a proposal to be successful.\\n *\\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\\n */\\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber`.\\n *\\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\\n * multiple), {ERC20Votes} tokens.\\n */\\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockNumber,\\n bytes memory params\\n ) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:voting\\n * @dev Returns whether `account` has cast a vote on `proposalId`.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\\n\\n /**\\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\\n * {IGovernor-votingPeriod} blocks after the voting starts.\\n *\\n * Emits a {ProposalCreated} event.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\\n * deadline to be reached.\\n *\\n * Emits a {ProposalExecuted} event.\\n *\\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Cast a vote\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xa52d593ff06a2353f78fa149da31f2ca94f03d1eff99bde41977fa2fe985a92f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2e53602b96c1bf97c731ed3e2a981b4f85e23a9410a5ebd36e549a4cc93340dc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x2626d8ab3dfdad0fad630c212ad146d59473d0f48b771784c61a7c1dbbea1f3f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Tooling for timepoints, timers and delays\\n */\\nlibrary Timers {\\n struct Timestamp {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(Timestamp storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(Timestamp memory timer) internal view returns (bool) {\\n return timer._deadline > block.timestamp;\\n }\\n\\n function isExpired(Timestamp memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.timestamp;\\n }\\n\\n struct BlockNumber {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(BlockNumber storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(BlockNumber memory timer) internal view returns (bool) {\\n return timer._deadline > block.number;\\n }\\n\\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.number;\\n }\\n}\\n\",\"keccak256\":\"0x29791a62950a7983e02a673639c1a781d1e448691800456c2ce4b99715391b14\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS,\\n InvalidSignatureV // Deprecated in v4.8\\n }\\n\\n function _throwError(RecoverError error) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert(\\\"ECDSA: invalid signature\\\");\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert(\\\"ECDSA: invalid signature 's' value\\\");\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature` or error string. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\\n if (signature.length == 65) {\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n /// @solidity memory-safe-assembly\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n return tryRecover(hash, v, r, s);\\n } else {\\n return (address(0), RecoverError.InvalidSignatureLength);\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, signature);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n *\\n * _Available since v4.2._\\n */\\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature);\\n }\\n\\n return (signer, RecoverError.NoError);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from `s`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", Strings.toString(s.length), s));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Typed Data, created from a\\n * `domainSeparator` and a `structHash`. This produces hash corresponding\\n * to the one signed with the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\\n * JSON-RPC method as part of EIP-712.\\n *\\n * See {recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n }\\n}\\n\",\"keccak256\":\"0x54ee424bfc83ce63b2a918b9a1efb5090a0fb68dbd1de3b10bc667776885dd4f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ECDSA.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n /* solhint-disable var-name-mixedcase */\\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n // invalidate the cached domain separator if the chain id changes.\\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n uint256 private immutable _CACHED_CHAIN_ID;\\n address private immutable _CACHED_THIS;\\n\\n bytes32 private immutable _HASHED_NAME;\\n bytes32 private immutable _HASHED_VERSION;\\n bytes32 private immutable _TYPE_HASH;\\n\\n /* solhint-enable var-name-mixedcase */\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n constructor(string memory name, string memory version) {\\n bytes32 hashedName = keccak256(bytes(name));\\n bytes32 hashedVersion = keccak256(bytes(version));\\n bytes32 typeHash = keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n );\\n _HASHED_NAME = hashedName;\\n _HASHED_VERSION = hashedVersion;\\n _CACHED_CHAIN_ID = block.chainid;\\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n _CACHED_THIS = address(this);\\n _TYPE_HASH = typeHash;\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\\n return _CACHED_DOMAIN_SEPARATOR;\\n } else {\\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n }\\n }\\n\\n function _buildDomainSeparator(\\n bytes32 typeHash,\\n bytes32 nameHash,\\n bytes32 versionHash\\n ) private view returns (bytes32) {\\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\\n }\\n}\\n\",\"keccak256\":\"0x948d8b2d18f38141ec78c5229d770d950ebc781ed3f44cc9e3ccbb9fded5846a\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\\n\\nimport \\\"./EIP712.sol\\\";\\n\",\"keccak256\":\"0xea30c402170bc240354b74e6c6f6a8e5bdb1935d90d168cc58c0654461c6a72b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3546b156d97633f7f8cad536d5454c81d1d604687c02b2eb105fdc33cb962b41\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\\npragma solidity ^0.8.4;\\n\\nimport \\\"../math/SafeCast.sol\\\";\\n\\n/**\\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\\n * the existing queue contents are left in storage.\\n *\\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\\n * used in storage, and not in memory.\\n * ```\\n * DoubleEndedQueue.Bytes32Deque queue;\\n * ```\\n *\\n * _Available since v4.6._\\n */\\nlibrary DoubleEndedQueue {\\n /**\\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\\n */\\n error Empty();\\n\\n /**\\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\\n */\\n error OutOfBounds();\\n\\n /**\\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\\n *\\n * Struct members have an underscore prefix indicating that they are \\\"private\\\" and should not be read or written to\\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\\n * lead to unexpected behavior.\\n *\\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\\n * data[end - 1].\\n */\\n struct Bytes32Deque {\\n int128 _begin;\\n int128 _end;\\n mapping(int128 => bytes32) _data;\\n }\\n\\n /**\\n * @dev Inserts an item at the end of the queue.\\n */\\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 backIndex = deque._end;\\n deque._data[backIndex] = value;\\n unchecked {\\n deque._end = backIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Removes the item at the end of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n value = deque._data[backIndex];\\n delete deque._data[backIndex];\\n deque._end = backIndex;\\n }\\n\\n /**\\n * @dev Inserts an item at the beginning of the queue.\\n */\\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 frontIndex;\\n unchecked {\\n frontIndex = deque._begin - 1;\\n }\\n deque._data[frontIndex] = value;\\n deque._begin = frontIndex;\\n }\\n\\n /**\\n * @dev Removes the item at the beginning of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n value = deque._data[frontIndex];\\n delete deque._data[frontIndex];\\n unchecked {\\n deque._begin = frontIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Returns the item at the beginning of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n return deque._data[frontIndex];\\n }\\n\\n /**\\n * @dev Returns the item at the end of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n return deque._data[backIndex];\\n }\\n\\n /**\\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\\n * `length(deque) - 1`.\\n *\\n * Reverts with `OutOfBounds` if the index is out of bounds.\\n */\\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\\n // int256(deque._begin) is a safe upcast\\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\\n if (idx >= deque._end) revert OutOfBounds();\\n return deque._data[idx];\\n }\\n\\n /**\\n * @dev Resets the queue back to being empty.\\n *\\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\\n * out on potential gas refunds.\\n */\\n function clear(Bytes32Deque storage deque) internal {\\n deque._begin = 0;\\n deque._end = 0;\\n }\\n\\n /**\\n * @dev Returns the number of items in the queue.\\n */\\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\\n // We also assume there are at most int256.max items in the queue.\\n unchecked {\\n return uint256(int256(deque._end) - int256(deque._begin));\\n }\\n }\\n\\n /**\\n * @dev Returns true if the queue is empty.\\n */\\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\\n return deque._end <= deque._begin;\\n }\\n}\\n\",\"keccak256\":\"0x4859ffd6dd69382a1462930c00b6e394007da80e78e510f56930271034737bf2\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x61016060405260026007553480156200001757600080fd5b506040516200329a3803806200329a8339810160408190526200003a91620002ec565b6004816040518060400160405280601481526020017f56656c6f63696d6574657220476f7665726e6f7200000000000000000000000081525080620000846200015e60201b60201c565b815160208084019190912082518383012060e08290526101008190524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81880181905281830187905260608201869052608082019490945230818401528151808203909301835260c00190528051940193909320919290916080523060c05261012052505082516200012a925060009150602084019062000246565b50506001600160a01b031661014052620001448162000179565b5050600680546001600160a01b031916331790556200035a565b6040805180820190915260018152603160f81b602082015290565b6064811115620002015760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a40160405180910390fd5b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b82805462000254906200031e565b90600052602060002090601f016020900481019282620002785760008555620002c3565b82601f106200029357805160ff1916838001178555620002c3565b82800160010185558215620002c3579182015b82811115620002c3578251825591602001919060010190620002a6565b50620002d1929150620002d5565b5090565b5b80821115620002d15760008155600101620002d6565b600060208284031215620002ff57600080fd5b81516001600160a01b03811681146200031757600080fd5b9392505050565b600181811c908216806200033357607f821691505b6020821081036200035457634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e051610100516101205161014051612ed0620003ca600039600081816107df0152818161120f015281816113e40152611a0601526000611b2301526000611b7201526000611b4d01526000611aa601526000611ad001526000611afa0152612ed06000f3fe6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220619141f3666eb3d47b18cb454a5c4e73437ed9eadfb56425659bf6bb30ee8daa64736f6c634300080d0033", + "deployedBytecode": "0x6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220619141f3666eb3d47b18cb454a5c4e73437ed9eadfb56425659bf6bb30ee8daa64736f6c634300080d0033", "devdoc": { "errors": { "Empty()": [ diff --git a/deployments/arbitrumGoerli/GaugeFactory.json b/deployments/arbitrumGoerli/GaugeFactory.json index 455c1568..71387750 100644 --- a/deployments/arbitrumGoerli/GaugeFactory.json +++ b/deployments/arbitrumGoerli/GaugeFactory.json @@ -1,5 +1,5 @@ { - "address": "0x596CAFB654c2281838b570F3801a8288b7B7bE8a", + "address": "0xdEA300B2495790ccc75c6918A302E1952e9c2339", "abi": [ { "inputs": [ @@ -59,28 +59,28 @@ "type": "function" } ], - "transactionHash": "0x0ef11d8a4fe5d29db766f0b627fa7070269253ffd23b330f06a7a91a33aa33c5", + "transactionHash": "0xcbf9cfffdc1928b08a835603cfa19e6e6d7fab2282b5f63487de7a9c948d726d", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x596CAFB654c2281838b570F3801a8288b7B7bE8a", + "contractAddress": "0xdEA300B2495790ccc75c6918A302E1952e9c2339", "transactionIndex": 1, - "gasUsed": "3308285", + "gasUsed": "3308273", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xa8f22b723725bc8dfd117d9cb5e7c686e4f60abb6a7e604fb65cefd7db47795b", - "transactionHash": "0x0ef11d8a4fe5d29db766f0b627fa7070269253ffd23b330f06a7a91a33aa33c5", + "blockHash": "0x8f3ab1d694dd858328ab8b691232273c1361aec6fa132a142ce16fb6e18e1d4b", + "transactionHash": "0xcbf9cfffdc1928b08a835603cfa19e6e6d7fab2282b5f63487de7a9c948d726d", "logs": [], - "blockNumber": 5849128, - "cumulativeGasUsed": "3308285", + "blockNumber": 6069369, + "cumulativeGasUsed": "3308273", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 3, - "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_internal_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_external_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_ve\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isPair\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_gauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/GaugeFactory.sol\":\"GaugeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Gauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\\ncontract Gauge is IGauge {\\n address public immutable stake; // the LP token that needs to be staked for rewards\\n address public immutable _ve; // the ve token used for gauges\\n address public immutable internal_bribe;\\n address public immutable external_bribe;\\n address public immutable voter;\\n\\n uint256 public derivedSupply;\\n mapping(address => uint256) public derivedBalances;\\n\\n bool public isForPair;\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 internal constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(address => uint256)) public lastEarn;\\n mapping(address => mapping(address => uint256))\\n public userRewardPerTokenStored;\\n\\n mapping(address => uint256) public tokenIds;\\n\\n uint256 public totalSupply;\\n mapping(address => uint256) public balanceOf;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n uint256 public fees0;\\n uint256 public fees1;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(\\n address _stake,\\n address _internal_bribe,\\n address _external_bribe,\\n address __ve,\\n address _voter,\\n bool _forPair,\\n address[] memory _allowedRewardTokens\\n ) {\\n stake = _stake;\\n internal_bribe = _internal_bribe;\\n external_bribe = _external_bribe;\\n _ve = __ve;\\n voter = _voter;\\n isForPair = _forPair;\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function claimFees()\\n external\\n lock\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n return _claimFees();\\n }\\n\\n function _claimFees()\\n internal\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n if (!isForPair) {\\n return (0, 0);\\n }\\n (claimed0, claimed1) = IPair(stake).claimFees();\\n if (claimed0 > 0 || claimed1 > 0) {\\n uint256 _fees0 = fees0 + claimed0;\\n uint256 _fees1 = fees1 + claimed1;\\n (address _token0, address _token1) = IPair(stake).tokens();\\n if (\\n _fees0 > IBribe(internal_bribe).left(_token0) &&\\n _fees0 / DURATION > 0\\n ) {\\n fees0 = 0;\\n _safeApprove(_token0, internal_bribe, _fees0);\\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\\n } else {\\n fees0 = _fees0;\\n }\\n if (\\n _fees1 > IBribe(internal_bribe).left(_token1) &&\\n _fees1 / DURATION > 0\\n ) {\\n fees1 = 0;\\n _safeApprove(_token1, internal_bribe, _fees1);\\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\\n } else {\\n fees1 = _fees1;\\n }\\n\\n emit ClaimFees(msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(address account, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(address account, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[account][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[account] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n derivedSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n function getReward(address account, address[] memory tokens) external lock {\\n require(msg.sender == account || msg.sender == voter);\\n _unlocked = 1;\\n IVoter(voter).distribute(address(this));\\n _unlocked = 2;\\n\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], account);\\n lastEarn[tokens[i]][account] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n\\n uint256 _derivedBalance = derivedBalances[account];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(account);\\n derivedBalances[account] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(account, derivedBalances[account]);\\n _writeSupplyCheckpoint();\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (derivedSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / derivedSupply);\\n }\\n\\n function derivedBalance(address account) public view returns (uint256) {\\n return balanceOf[account];\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\\n function earned(address token, address account)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][account],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[account] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[account] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[account][i];\\n Checkpoint memory cp1 = checkpoints[account][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[account][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][account]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n function depositAll(uint256 tokenId) external {\\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\\n }\\n\\n function deposit(uint256 amount, uint256 tokenId) public lock {\\n require(amount > 0);\\n _updateRewardForAllTokens();\\n\\n _safeTransferFrom(stake, msg.sender, address(this), amount);\\n totalSupply += amount;\\n balanceOf[msg.sender] += amount;\\n\\n if (tokenId > 0) {\\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\\n if (tokenIds[msg.sender] == 0) {\\n tokenIds[msg.sender] = tokenId;\\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\\n }\\n require(tokenIds[msg.sender] == tokenId);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, _derivedBalance);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function withdrawAll() external {\\n withdraw(balanceOf[msg.sender]);\\n }\\n\\n function withdraw(uint256 amount) public {\\n uint256 tokenId = 0;\\n if (amount == balanceOf[msg.sender]) {\\n tokenId = tokenIds[msg.sender];\\n }\\n withdrawToken(amount, tokenId);\\n }\\n\\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[msg.sender] -= amount;\\n _safeTransfer(stake, msg.sender, amount);\\n\\n if (tokenId > 0) {\\n require(tokenId == tokenIds[msg.sender]);\\n tokenIds[msg.sender] = 0;\\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(token != stake);\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"rewards tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n _claimFees();\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeApprove(\\n address token,\\n address spender,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x38cc0284dd60d8a1418d9c34e6be84911ca4a1b479dc129f19b9027e4c670e1f\",\"license\":\"MIT\"},\"contracts/factories/GaugeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/Gauge.sol';\\n\\ncontract GaugeFactory is IGaugeFactory {\\n address public last_gauge;\\n\\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\\n return last_gauge;\\n }\\n}\\n\",\"keccak256\":\"0x34f6ac4bdace9ef01d8cffda9b45842efae88b519230c67759b9936aee6acc9b\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50613b19806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea2646970667358221220929baeb85b1bc48821b4e95a725f54f20ab2e3f0c1a3816544d164232d22aa3064736f6c634300080d0033a26469706673582212203721086bab0d5375338b81f026a2a24a718fd4b50955e5f51d88550583d6e94264736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea2646970667358221220929baeb85b1bc48821b4e95a725f54f20ab2e3f0c1a3816544d164232d22aa3064736f6c634300080d0033a26469706673582212203721086bab0d5375338b81f026a2a24a718fd4b50955e5f51d88550583d6e94264736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "d2a2160297444b93438826228d1e185d", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_internal_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_external_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_ve\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isPair\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_gauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/GaugeFactory.sol\":\"GaugeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Gauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\\ncontract Gauge is IGauge {\\n address public immutable stake; // the LP token that needs to be staked for rewards\\n address public immutable _ve; // the ve token used for gauges\\n address public immutable internal_bribe;\\n address public immutable external_bribe;\\n address public immutable voter;\\n\\n uint256 public derivedSupply;\\n mapping(address => uint256) public derivedBalances;\\n\\n bool public isForPair;\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 internal constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(address => uint256)) public lastEarn;\\n mapping(address => mapping(address => uint256))\\n public userRewardPerTokenStored;\\n\\n mapping(address => uint256) public tokenIds;\\n\\n uint256 public totalSupply;\\n mapping(address => uint256) public balanceOf;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n uint256 public fees0;\\n uint256 public fees1;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(\\n address _stake,\\n address _internal_bribe,\\n address _external_bribe,\\n address __ve,\\n address _voter,\\n bool _forPair,\\n address[] memory _allowedRewardTokens\\n ) {\\n stake = _stake;\\n internal_bribe = _internal_bribe;\\n external_bribe = _external_bribe;\\n _ve = __ve;\\n voter = _voter;\\n isForPair = _forPair;\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function claimFees()\\n external\\n lock\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n return _claimFees();\\n }\\n\\n function _claimFees()\\n internal\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n if (!isForPair) {\\n return (0, 0);\\n }\\n (claimed0, claimed1) = IPair(stake).claimFees();\\n if (claimed0 > 0 || claimed1 > 0) {\\n uint256 _fees0 = fees0 + claimed0;\\n uint256 _fees1 = fees1 + claimed1;\\n (address _token0, address _token1) = IPair(stake).tokens();\\n if (\\n _fees0 > IBribe(internal_bribe).left(_token0) &&\\n _fees0 / DURATION > 0\\n ) {\\n fees0 = 0;\\n _safeApprove(_token0, internal_bribe, _fees0);\\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\\n } else {\\n fees0 = _fees0;\\n }\\n if (\\n _fees1 > IBribe(internal_bribe).left(_token1) &&\\n _fees1 / DURATION > 0\\n ) {\\n fees1 = 0;\\n _safeApprove(_token1, internal_bribe, _fees1);\\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\\n } else {\\n fees1 = _fees1;\\n }\\n\\n emit ClaimFees(msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(address account, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(address account, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[account][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[account] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n derivedSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n function getReward(address account, address[] memory tokens) external lock {\\n require(msg.sender == account || msg.sender == voter);\\n _unlocked = 1;\\n IVoter(voter).distribute(address(this));\\n _unlocked = 2;\\n\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], account);\\n lastEarn[tokens[i]][account] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n\\n uint256 _derivedBalance = derivedBalances[account];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(account);\\n derivedBalances[account] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(account, derivedBalances[account]);\\n _writeSupplyCheckpoint();\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (derivedSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / derivedSupply);\\n }\\n\\n function derivedBalance(address account) public view returns (uint256) {\\n return balanceOf[account];\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\\n function earned(address token, address account)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][account],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[account] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[account] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[account][i];\\n Checkpoint memory cp1 = checkpoints[account][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[account][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][account]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n function depositAll(uint256 tokenId) external {\\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\\n }\\n\\n function deposit(uint256 amount, uint256 tokenId) public lock {\\n require(amount > 0);\\n _updateRewardForAllTokens();\\n\\n _safeTransferFrom(stake, msg.sender, address(this), amount);\\n totalSupply += amount;\\n balanceOf[msg.sender] += amount;\\n\\n if (tokenId > 0) {\\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\\n if (tokenIds[msg.sender] == 0) {\\n tokenIds[msg.sender] = tokenId;\\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\\n }\\n require(tokenIds[msg.sender] == tokenId);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, _derivedBalance);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function withdrawAll() external {\\n withdraw(balanceOf[msg.sender]);\\n }\\n\\n function withdraw(uint256 amount) public {\\n uint256 tokenId = 0;\\n if (amount == balanceOf[msg.sender]) {\\n tokenId = tokenIds[msg.sender];\\n }\\n withdrawToken(amount, tokenId);\\n }\\n\\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[msg.sender] -= amount;\\n _safeTransfer(stake, msg.sender, amount);\\n\\n if (tokenId > 0) {\\n require(tokenId == tokenIds[msg.sender]);\\n tokenIds[msg.sender] = 0;\\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(token != stake);\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"rewards tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n _claimFees();\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeApprove(\\n address token,\\n address spender,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x38cc0284dd60d8a1418d9c34e6be84911ca4a1b479dc129f19b9027e4c670e1f\",\"license\":\"MIT\"},\"contracts/factories/GaugeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/Gauge.sol';\\n\\ncontract GaugeFactory is IGaugeFactory {\\n address public last_gauge;\\n\\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\\n return last_gauge;\\n }\\n}\\n\",\"keccak256\":\"0x34f6ac4bdace9ef01d8cffda9b45842efae88b519230c67759b9936aee6acc9b\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50613b19806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea26469706673582212208a3206431587d5e0992bf170e3d9601bbd813d92d440aaedca384edc6b46150364736f6c634300080d0033a2646970667358221220e75dfbd32112b57311df28d130744f2456bb7c2368a2f6dc730071d739644b2064736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea26469706673582212208a3206431587d5e0992bf170e3d9601bbd813d92d440aaedca384edc6b46150364736f6c634300080d0033a2646970667358221220e75dfbd32112b57311df28d130744f2456bb7c2368a2f6dc730071d739644b2064736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/MerkleClaim.json b/deployments/arbitrumGoerli/MerkleClaim.json index 90e70784..d8920384 100644 --- a/deployments/arbitrumGoerli/MerkleClaim.json +++ b/deployments/arbitrumGoerli/MerkleClaim.json @@ -1,5 +1,5 @@ { - "address": "0x1A0F539D3A6096e5C6928b95A651170B339c5FBf", + "address": "0xDD6594d966d9463A7808AF67024E941fB921dB2B", "abi": [ { "inputs": [ @@ -105,31 +105,31 @@ "type": "function" } ], - "transactionHash": "0x289e0c6e8a39e9b3ac929aa2c0b9aa9b313430065d7ec57f21aadd95fdb1ec25", + "transactionHash": "0x0a82585a04a93b1c66412f4c637420cfb75b1c276744694c8e5121252ffef8ec", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x1A0F539D3A6096e5C6928b95A651170B339c5FBf", + "contractAddress": "0xDD6594d966d9463A7808AF67024E941fB921dB2B", "transactionIndex": 1, "gasUsed": "356966", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xe8918a50edda4178b26d2c1881955b3ce0ec4b49d11d04747b7599d4701d542a", - "transactionHash": "0x289e0c6e8a39e9b3ac929aa2c0b9aa9b313430065d7ec57f21aadd95fdb1ec25", + "blockHash": "0x2bd7e64c28fbd006c2f75508801c4ef966c0b9da160c397b003f2311968c554e", + "transactionHash": "0x0a82585a04a93b1c66412f4c637420cfb75b1c276744694c8e5121252ffef8ec", "logs": [], - "blockNumber": 5849272, + "blockNumber": 6069468, "cumulativeGasUsed": "356966", "status": 1, "byzantium": true }, "args": [ - "0x0432f39386A9B1d0339c8Ba0af617b16C86ADA05", + "0x4E13914872BFf7e58f3E231b2687fDd084014999", "0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f" ], - "numDeployments": 3, - "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_flow\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"_merkleRoot\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Claim\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FLOW\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"hasClaimed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\",\"events\":{\"Claim(address,uint256)\":{\"params\":{\"amount\":\"of tokens claimed\",\"to\":\"recipient of claim\"}}},\"kind\":\"dev\",\"methods\":{\"claim(address,uint256,bytes32[])\":{\"params\":{\"amount\":\"of tokens owed to claimee\",\"proof\":\"merkle proof to prove address and amount are in tree\",\"to\":\"address of claimee\"}},\"constructor\":{\"params\":{\"_flow\":\"address\",\"_merkleRoot\":\"of claimees\"}}},\"title\":\"MerkleClaim\",\"version\":1},\"userdoc\":{\"events\":{\"Claim(address,uint256)\":{\"notice\":\"Emitted after a successful token claim\"}},\"kind\":\"user\",\"methods\":{\"FLOW()\":{\"notice\":\"FLOW token to claim\"},\"claim(address,uint256,bytes32[])\":{\"notice\":\"Allows claiming tokens if address is part of merkle tree\"},\"constructor\":{\"notice\":\"Creates a new MerkleClaim contract\"},\"hasClaimed(address)\":{\"notice\":\"Mapping of addresses who have claimed tokens\"},\"merkleRoot()\":{\"notice\":\"ERC20-claimee inclusion root\"}},\"notice\":\"Claims FLOW for members of a merkle tree\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/MerkleClaim.sol\":\"MerkleClaim\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/redeem/MerkleClaim.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity 0.8.13;\\n\\n/// ============ Imports ============\\n\\nimport {IFlow} from \\\"contracts/interfaces/IFlow.sol\\\";\\nimport {MerkleProof} from \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\\\"; // OZ: MerkleProof\\n\\n/// @title MerkleClaim\\n/// @notice Claims FLOW for members of a merkle tree\\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\\ncontract MerkleClaim {\\n /// ============ Immutable storage ============\\n\\n /// @notice FLOW token to claim\\n IFlow public immutable FLOW;\\n /// @notice ERC20-claimee inclusion root\\n bytes32 public immutable merkleRoot;\\n\\n /// ============ Mutable storage ============\\n\\n /// @notice Mapping of addresses who have claimed tokens\\n mapping(address => bool) public hasClaimed;\\n\\n /// ============ Constructor ============\\n\\n /// @notice Creates a new MerkleClaim contract\\n /// @param _flow address\\n /// @param _merkleRoot of claimees\\n constructor(address _flow, bytes32 _merkleRoot) {\\n FLOW = IFlow(_flow);\\n merkleRoot = _merkleRoot;\\n }\\n\\n /// ============ Events ============\\n\\n /// @notice Emitted after a successful token claim\\n /// @param to recipient of claim\\n /// @param amount of tokens claimed\\n event Claim(address indexed to, uint256 amount);\\n\\n /// ============ Functions ============\\n\\n /// @notice Allows claiming tokens if address is part of merkle tree\\n /// @param to address of claimee\\n /// @param amount of tokens owed to claimee\\n /// @param proof merkle proof to prove address and amount are in tree\\n function claim(\\n address to,\\n uint256 amount,\\n bytes32[] calldata proof\\n ) external {\\n // Throw if address has already claimed tokens\\n require(!hasClaimed[to], \\\"ALREADY_CLAIMED\\\");\\n\\n // Verify merkle proof, or revert if not in tree\\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\\n require(isValidLeaf, \\\"NOT_IN_MERKLE\\\");\\n\\n // Set address to claimed\\n hasClaimed[to] = true;\\n\\n // Claim tokens for address\\n require(FLOW.claim(to, amount), \\\"CLAIM_FAILED\\\");\\n\\n // Emit claim event\\n emit Claim(to, amount);\\n }\\n}\\n\",\"keccak256\":\"0xf169ba9559c5c39dc79b2281410b09fd92f200a3b0489b32e28ce08a00a98826\",\"license\":\"AGPL-3.0-only\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev These functions deal with verification of Merkle Tree proofs.\\n *\\n * The tree and the proofs can be generated using our\\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\\n * You will find a quickstart guide in the readme.\\n *\\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\\n * hashing, or use a hash function other than keccak256 for hashing leaves.\\n * This is because the concatenation of a sorted pair of internal nodes in\\n * the merkle tree could be reinterpreted as a leaf value.\\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\\n * against this attack out of the box.\\n */\\nlibrary MerkleProof {\\n /**\\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\\n * defined by `root`. For this, a `proof` must be provided, containing\\n * sibling hashes on the branch from the leaf to the root of the tree. Each\\n * pair of leaves and each pair of pre-images are assumed to be sorted.\\n */\\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProof(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {verify}\\n *\\n * _Available since v4.7._\\n */\\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProofCalldata(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\\n * hash matches the root of the tree. When processing the proof, the pairs\\n * of leafs & pre-images are assumed to be sorted.\\n *\\n * _Available since v4.4._\\n */\\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Calldata version of {processProof}\\n *\\n * _Available since v4.7._\\n */\\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerify(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProof(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {multiProofVerify}\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerifyCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\\n * respectively.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProof(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n /**\\n * @dev Calldata version of {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProofCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\\n }\\n\\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x00, a)\\n mstore(0x20, b)\\n value := keccak256(0x00, 0x40)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcc76dbe53154a5bbd12fdd1613a73f73f3dc7c63d813be36f7ee606f52d6a7b3\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60c060405234801561001057600080fd5b5060405161062638038061062683398101604081905261002f91610045565b6001600160a01b0390911660805260a05261007f565b6000806040838503121561005857600080fd5b82516001600160a01b038116811461006f57600080fd5b6020939093015192949293505050565b60805160a0516105766100b060003960008181605601526101ea0152600081816090015261029601526105766000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633189097b1461008b5780633d13f874146100ca57806373b2e80e146100df575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6100b27f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6100dd6100d836600461043c565b610112565b005b6101026100ed3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea26469706673582212207985f8a8caed236605c9814107a30108b41352a1b3fe5cb8dbfa1e351035101d64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633189097b1461008b5780633d13f874146100ca57806373b2e80e146100df575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6100b27f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6100dd6100d836600461043c565b610112565b005b6101026100ed3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea26469706673582212207985f8a8caed236605c9814107a30108b41352a1b3fe5cb8dbfa1e351035101d64736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "d2a2160297444b93438826228d1e185d", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_flow\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"_merkleRoot\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Claim\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FLOW\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"hasClaimed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\",\"events\":{\"Claim(address,uint256)\":{\"params\":{\"amount\":\"of tokens claimed\",\"to\":\"recipient of claim\"}}},\"kind\":\"dev\",\"methods\":{\"claim(address,uint256,bytes32[])\":{\"params\":{\"amount\":\"of tokens owed to claimee\",\"proof\":\"merkle proof to prove address and amount are in tree\",\"to\":\"address of claimee\"}},\"constructor\":{\"params\":{\"_flow\":\"address\",\"_merkleRoot\":\"of claimees\"}}},\"title\":\"MerkleClaim\",\"version\":1},\"userdoc\":{\"events\":{\"Claim(address,uint256)\":{\"notice\":\"Emitted after a successful token claim\"}},\"kind\":\"user\",\"methods\":{\"FLOW()\":{\"notice\":\"FLOW token to claim\"},\"claim(address,uint256,bytes32[])\":{\"notice\":\"Allows claiming tokens if address is part of merkle tree\"},\"constructor\":{\"notice\":\"Creates a new MerkleClaim contract\"},\"hasClaimed(address)\":{\"notice\":\"Mapping of addresses who have claimed tokens\"},\"merkleRoot()\":{\"notice\":\"ERC20-claimee inclusion root\"}},\"notice\":\"Claims FLOW for members of a merkle tree\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/MerkleClaim.sol\":\"MerkleClaim\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/redeem/MerkleClaim.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity 0.8.13;\\n\\n/// ============ Imports ============\\n\\nimport {IFlow} from \\\"contracts/interfaces/IFlow.sol\\\";\\nimport {MerkleProof} from \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\\\"; // OZ: MerkleProof\\n\\n/// @title MerkleClaim\\n/// @notice Claims FLOW for members of a merkle tree\\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\\ncontract MerkleClaim {\\n /// ============ Immutable storage ============\\n\\n /// @notice FLOW token to claim\\n IFlow public immutable FLOW;\\n /// @notice ERC20-claimee inclusion root\\n bytes32 public immutable merkleRoot;\\n\\n /// ============ Mutable storage ============\\n\\n /// @notice Mapping of addresses who have claimed tokens\\n mapping(address => bool) public hasClaimed;\\n\\n /// ============ Constructor ============\\n\\n /// @notice Creates a new MerkleClaim contract\\n /// @param _flow address\\n /// @param _merkleRoot of claimees\\n constructor(address _flow, bytes32 _merkleRoot) {\\n FLOW = IFlow(_flow);\\n merkleRoot = _merkleRoot;\\n }\\n\\n /// ============ Events ============\\n\\n /// @notice Emitted after a successful token claim\\n /// @param to recipient of claim\\n /// @param amount of tokens claimed\\n event Claim(address indexed to, uint256 amount);\\n\\n /// ============ Functions ============\\n\\n /// @notice Allows claiming tokens if address is part of merkle tree\\n /// @param to address of claimee\\n /// @param amount of tokens owed to claimee\\n /// @param proof merkle proof to prove address and amount are in tree\\n function claim(\\n address to,\\n uint256 amount,\\n bytes32[] calldata proof\\n ) external {\\n // Throw if address has already claimed tokens\\n require(!hasClaimed[to], \\\"ALREADY_CLAIMED\\\");\\n\\n // Verify merkle proof, or revert if not in tree\\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\\n require(isValidLeaf, \\\"NOT_IN_MERKLE\\\");\\n\\n // Set address to claimed\\n hasClaimed[to] = true;\\n\\n // Claim tokens for address\\n require(FLOW.claim(to, amount), \\\"CLAIM_FAILED\\\");\\n\\n // Emit claim event\\n emit Claim(to, amount);\\n }\\n}\\n\",\"keccak256\":\"0xf169ba9559c5c39dc79b2281410b09fd92f200a3b0489b32e28ce08a00a98826\",\"license\":\"AGPL-3.0-only\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev These functions deal with verification of Merkle Tree proofs.\\n *\\n * The tree and the proofs can be generated using our\\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\\n * You will find a quickstart guide in the readme.\\n *\\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\\n * hashing, or use a hash function other than keccak256 for hashing leaves.\\n * This is because the concatenation of a sorted pair of internal nodes in\\n * the merkle tree could be reinterpreted as a leaf value.\\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\\n * against this attack out of the box.\\n */\\nlibrary MerkleProof {\\n /**\\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\\n * defined by `root`. For this, a `proof` must be provided, containing\\n * sibling hashes on the branch from the leaf to the root of the tree. Each\\n * pair of leaves and each pair of pre-images are assumed to be sorted.\\n */\\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProof(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {verify}\\n *\\n * _Available since v4.7._\\n */\\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProofCalldata(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\\n * hash matches the root of the tree. When processing the proof, the pairs\\n * of leafs & pre-images are assumed to be sorted.\\n *\\n * _Available since v4.4._\\n */\\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Calldata version of {processProof}\\n *\\n * _Available since v4.7._\\n */\\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerify(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProof(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {multiProofVerify}\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerifyCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\\n * respectively.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProof(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n /**\\n * @dev Calldata version of {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProofCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\\n }\\n\\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x00, a)\\n mstore(0x20, b)\\n value := keccak256(0x00, 0x40)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcc76dbe53154a5bbd12fdd1613a73f73f3dc7c63d813be36f7ee606f52d6a7b3\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c060405234801561001057600080fd5b5060405161062638038061062683398101604081905261002f91610045565b6001600160a01b0390911660805260a05261007f565b6000806040838503121561005857600080fd5b82516001600160a01b038116811461006f57600080fd5b6020939093015192949293505050565b60805160a0516105766100b060003960008181605601526101ea0152600081816090015261029601526105766000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633189097b1461008b5780633d13f874146100ca57806373b2e80e146100df575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6100b27f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6100dd6100d836600461043c565b610112565b005b6101026100ed3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220735d919fc3ef07f6ea463c63e7979be0343a217a0d43a5a1ef5e61ea8954548e64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633189097b1461008b5780633d13f874146100ca57806373b2e80e146100df575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6100b27f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6100dd6100d836600461043c565b610112565b005b6101026100ed3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220735d919fc3ef07f6ea463c63e7979be0343a217a0d43a5a1ef5e61ea8954548e64736f6c634300080d0033", "devdoc": { "author": "Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)", "events": { diff --git a/deployments/arbitrumGoerli/Minter.json b/deployments/arbitrumGoerli/Minter.json index 921a3438..710027a1 100644 --- a/deployments/arbitrumGoerli/Minter.json +++ b/deployments/arbitrumGoerli/Minter.json @@ -1,5 +1,5 @@ { - "address": "0x83886D8982819B9f1E36e8F134ED3d1AE3eaF9bd", + "address": "0x933348CCa9bA6DAAd71be824844dCd0D22d849f6", "abi": [ { "inputs": [ @@ -324,32 +324,32 @@ "type": "function" } ], - "transactionHash": "0x4354bf457db79ca255447093921e0120a9129a063f8c5d5604c676db1f7db200", + "transactionHash": "0xa3857de90da23bfa903a6460af45cb7edb635213f934a0578b29b4156fb3adf1", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x83886D8982819B9f1E36e8F134ED3d1AE3eaF9bd", + "contractAddress": "0x933348CCa9bA6DAAd71be824844dCd0D22d849f6", "transactionIndex": 1, - "gasUsed": "1199219", + "gasUsed": "1199207", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xff230fc39d91af4258c4a6843926acf7f74e80f8836eb49f6a70d6cab73bb9d6", - "transactionHash": "0x4354bf457db79ca255447093921e0120a9129a063f8c5d5604c676db1f7db200", + "blockHash": "0x4cacb3c4bef18d95064afa2934c5269bdc4b648a8f4b530f407afe517181f950", + "transactionHash": "0xa3857de90da23bfa903a6460af45cb7edb635213f934a0578b29b4156fb3adf1", "logs": [], - "blockNumber": 5849239, - "cumulativeGasUsed": "1199219", + "blockNumber": 6069446, + "cumulativeGasUsed": "1199207", "status": 1, "byzantium": true }, "args": [ - "0xe08A284C791c72E59C9020303b9B70E67bCf1d6C", - "0xF003091B78974ee3F99ec70fC5F42fc9810664EC", - "0xd06A463fD49720629A285E3C8De4310bc103df0a" + "0x04c989FB4768739Fbd62FC1f77D06ae3c1E5eC36", + "0x6d55AFbF1cAf01E0bcA5255bbA730da6fAFD0aF4", + "0xCf24b553f519916664533A862AB100FF8185a0c8" ], - "numDeployments": 3, - "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__voter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__rewards_distributor\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weekly\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_supply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_emission\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_TEAM_RATE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_flow\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_rewards_distributor\",\"outputs\":[{\"internalType\":\"contract IRewardsDistributor\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"contract IVotingEscrow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_voter\",\"outputs\":[{\"internalType\":\"contract IVoter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"active_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"calculate_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minted\",\"type\":\"uint256\"}],\"name\":\"calculate_growth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"claimants\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingTeam\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_teamRate\",\"type\":\"uint256\"}],\"name\":\"setTeamRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"teamRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"update_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Minter.sol\":\"Minter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Minter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IMinter.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\\n\\ncontract Minter is IMinter {\\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\\n uint256 internal constant EMISSION = 990;\\n uint256 internal constant TAIL_EMISSION = 2;\\n uint256 internal constant PRECISION = 1000;\\n IFlow public immutable _flow;\\n IVoter public immutable _voter;\\n IVotingEscrow public immutable _ve;\\n IRewardsDistributor public immutable _rewards_distributor;\\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M FLOW (FLOW has 18 decimals)\\n uint256 public active_period;\\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\\n\\n address internal initializer;\\n address public team;\\n address public pendingTeam;\\n uint256 public teamRate;\\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\\n\\n event Mint(\\n address indexed sender,\\n uint256 weekly,\\n uint256 circulating_supply,\\n uint256 circulating_emission\\n );\\n\\n constructor(\\n address __voter, // the voting & distribution system\\n address __ve, // the ve(3,3) system that will be locked into\\n address __rewards_distributor // the distribution system that ensures users aren't diluted\\n ) {\\n initializer = msg.sender;\\n team = msg.sender;\\n teamRate = 30; // 30 bps = 0.03%\\n _flow = IFlow(IVotingEscrow(__ve).token());\\n _voter = IVoter(__voter);\\n _ve = IVotingEscrow(__ve);\\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\\n }\\n\\n function initialize(\\n address[] memory claimants,\\n uint256[] memory amounts,\\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\\n ) external {\\n require(initializer == msg.sender);\\n _flow.mint(address(this), max);\\n _flow.approve(address(_ve), type(uint256).max);\\n for (uint256 i = 0; i < claimants.length; i++) {\\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\\n }\\n initializer = address(0);\\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\\n }\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team, \\\"not team\\\");\\n pendingTeam = _team;\\n }\\n\\n function acceptTeam() external {\\n require(msg.sender == pendingTeam, \\\"not pending team\\\");\\n team = pendingTeam;\\n }\\n\\n function setTeamRate(uint256 _teamRate) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(_teamRate <= MAX_TEAM_RATE, \\\"rate too high\\\");\\n teamRate = _teamRate;\\n }\\n\\n // calculate circulating supply as total token supply - locked supply\\n function circulating_supply() public view returns (uint256) {\\n return _flow.totalSupply() - _ve.totalSupply();\\n }\\n\\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\\n function calculate_emission() public view returns (uint256) {\\n return (weekly * EMISSION) / PRECISION;\\n }\\n\\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\\n function weekly_emission() public view returns (uint256) {\\n return MathDunks.max(calculate_emission(), circulating_emission());\\n }\\n\\n // calculates tail end (infinity) emissions as 0.2% of total supply\\n function circulating_emission() public view returns (uint256) {\\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\\n }\\n\\n // calculate inflation and adjust ve balances accordingly\\n function calculate_growth(uint256 _minted) public view returns (uint256) {\\n uint256 _veTotal = _ve.totalSupply();\\n uint256 _flowTotal = _flow.totalSupply();\\n return\\n (((((_minted * _veTotal) / _flowTotal) * _veTotal) / _flowTotal) *\\n _veTotal) /\\n _flowTotal /\\n 2;\\n }\\n\\n // update period can only be called once per cycle (1 week)\\n function update_period() external returns (uint256) {\\n uint256 _period = active_period;\\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\\n // only trigger if new week\\n _period = (block.timestamp / WEEK) * WEEK;\\n active_period = _period;\\n weekly = weekly_emission();\\n\\n uint256 _growth = calculate_growth(weekly);\\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\\n (PRECISION - teamRate);\\n uint256 _required = _growth + weekly + _teamEmissions;\\n uint256 _balanceOf = _flow.balanceOf(address(this));\\n if (_balanceOf < _required) {\\n _flow.mint(address(this), _required - _balanceOf);\\n }\\n\\n require(_flow.transfer(team, _teamEmissions));\\n require(_flow.transfer(address(_rewards_distributor), _growth));\\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\\n\\n _flow.approve(address(_voter), weekly);\\n _voter.notifyRewardAmount(weekly);\\n\\n emit Mint(\\n msg.sender,\\n weekly,\\n circulating_supply(),\\n circulating_emission()\\n );\\n }\\n return _period;\\n }\\n}\\n\",\"keccak256\":\"0xc661046dd2b90d93e4f057d2497b137703b4f0c3caccfe846f1a81906a2e1961\",\"license\":\"MIT\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x6101006040526a0c685fa11e01ec6f0000006000553480156200002157600080fd5b506040516200158938038062001589833981016040819052620000449162000156565b60028054336001600160a01b03199182168117909255600380549091169091179055601e60055560408051637e062a3560e11b815290516001600160a01b0384169163fc0c546a9160048083019260209291908290030181865afa158015620000b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d79190620001a0565b6001600160a01b0390811660805283811660a05282811660c052811660e05262093a808062000108816002620001db565b620001149042620001fd565b62000120919062000218565b6200012c9190620001db565b600155506200023b915050565b80516001600160a01b03811681146200015157600080fd5b919050565b6000806000606084860312156200016c57600080fd5b620001778462000139565b9250620001876020850162000139565b9150620001976040850162000139565b90509250925092565b600060208284031215620001b357600080fd5b620001be8262000139565b9392505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620001f857620001f8620001c5565b500290565b60008219821115620002135762000213620001c5565b500190565b6000826200023657634e487b7160e01b600052601260045260246000fd5b500490565b60805160a05160c05160e051611296620002f3600039600081816101d101528181610c3701528181610cde0152610d5101526000818161023a015281816104b30152818161055f01528181610689015261087501526000818161019201528181610e090152610ea301526000818161029d01528181610426015281816104e30152818161070f015281816108f701528181610a5f01528181610ade01528181610ba801528181610c660152610dda01526112966000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c806385170813116100ad578063cfc6c8ff11610071578063cfc6c8ff14610277578063d13996081461027f578063e038c75a14610288578063ed29fc1114610290578063fe75cac51461029857600080fd5b8063851708131461020f57806385f2aef2146102225780638dd598fb146102355780638e01fbfa1461025c578063b5cc143a1461026f57600080fd5b806336d96faf116100f457806336d96faf146101855780633db9b42a1461018d5780634b1cd5da146101cc57806359d46ffc146101f357806378ef7f021461020657600080fd5b806301c8e6fd14610131578063095cf5c61461014c5780631eebae801461016157806326cfc17b146101695780632e8f7b1f14610172575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b61015f61015a366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61015f610180366004610fb8565b610353565b6101396103de565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6004546101b4906001600160a01b031681565b61013960055481565b61015f61021d3660046110a7565b6103f3565b6003546101b4906001600160a01b031681565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b61013961026a366004610fb8565b610684565b61015f6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea2646970667358221220b5102dde2ecb2debf164c245d3462a1f37c037e8bd5c4cbfdac3bfe5a8282da664736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c806385170813116100ad578063cfc6c8ff11610071578063cfc6c8ff14610277578063d13996081461027f578063e038c75a14610288578063ed29fc1114610290578063fe75cac51461029857600080fd5b8063851708131461020f57806385f2aef2146102225780638dd598fb146102355780638e01fbfa1461025c578063b5cc143a1461026f57600080fd5b806336d96faf116100f457806336d96faf146101855780633db9b42a1461018d5780634b1cd5da146101cc57806359d46ffc146101f357806378ef7f021461020657600080fd5b806301c8e6fd14610131578063095cf5c61461014c5780631eebae801461016157806326cfc17b146101695780632e8f7b1f14610172575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b61015f61015a366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61015f610180366004610fb8565b610353565b6101396103de565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6004546101b4906001600160a01b031681565b61013960055481565b61015f61021d3660046110a7565b6103f3565b6003546101b4906001600160a01b031681565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b61013961026a366004610fb8565b610684565b61015f6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea2646970667358221220b5102dde2ecb2debf164c245d3462a1f37c037e8bd5c4cbfdac3bfe5a8282da664736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "d2a2160297444b93438826228d1e185d", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__voter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__rewards_distributor\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weekly\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_supply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_emission\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_TEAM_RATE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_flow\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_rewards_distributor\",\"outputs\":[{\"internalType\":\"contract IRewardsDistributor\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"contract IVotingEscrow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_voter\",\"outputs\":[{\"internalType\":\"contract IVoter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"active_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"calculate_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minted\",\"type\":\"uint256\"}],\"name\":\"calculate_growth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"claimants\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingTeam\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_teamRate\",\"type\":\"uint256\"}],\"name\":\"setTeamRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"teamRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"update_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Minter.sol\":\"Minter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Minter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IMinter.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\\n\\ncontract Minter is IMinter {\\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\\n uint256 internal constant EMISSION = 990;\\n uint256 internal constant TAIL_EMISSION = 2;\\n uint256 internal constant PRECISION = 1000;\\n IFlow public immutable _flow;\\n IVoter public immutable _voter;\\n IVotingEscrow public immutable _ve;\\n IRewardsDistributor public immutable _rewards_distributor;\\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M FLOW (FLOW has 18 decimals)\\n uint256 public active_period;\\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\\n\\n address internal initializer;\\n address public team;\\n address public pendingTeam;\\n uint256 public teamRate;\\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\\n\\n event Mint(\\n address indexed sender,\\n uint256 weekly,\\n uint256 circulating_supply,\\n uint256 circulating_emission\\n );\\n\\n constructor(\\n address __voter, // the voting & distribution system\\n address __ve, // the ve(3,3) system that will be locked into\\n address __rewards_distributor // the distribution system that ensures users aren't diluted\\n ) {\\n initializer = msg.sender;\\n team = msg.sender;\\n teamRate = 30; // 30 bps = 0.03%\\n _flow = IFlow(IVotingEscrow(__ve).token());\\n _voter = IVoter(__voter);\\n _ve = IVotingEscrow(__ve);\\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\\n }\\n\\n function initialize(\\n address[] memory claimants,\\n uint256[] memory amounts,\\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\\n ) external {\\n require(initializer == msg.sender);\\n _flow.mint(address(this), max);\\n _flow.approve(address(_ve), type(uint256).max);\\n for (uint256 i = 0; i < claimants.length; i++) {\\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\\n }\\n initializer = address(0);\\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\\n }\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team, \\\"not team\\\");\\n pendingTeam = _team;\\n }\\n\\n function acceptTeam() external {\\n require(msg.sender == pendingTeam, \\\"not pending team\\\");\\n team = pendingTeam;\\n }\\n\\n function setTeamRate(uint256 _teamRate) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(_teamRate <= MAX_TEAM_RATE, \\\"rate too high\\\");\\n teamRate = _teamRate;\\n }\\n\\n // calculate circulating supply as total token supply - locked supply\\n function circulating_supply() public view returns (uint256) {\\n return _flow.totalSupply() - _ve.totalSupply();\\n }\\n\\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\\n function calculate_emission() public view returns (uint256) {\\n return (weekly * EMISSION) / PRECISION;\\n }\\n\\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\\n function weekly_emission() public view returns (uint256) {\\n return MathDunks.max(calculate_emission(), circulating_emission());\\n }\\n\\n // calculates tail end (infinity) emissions as 0.2% of total supply\\n function circulating_emission() public view returns (uint256) {\\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\\n }\\n\\n // calculate inflation and adjust ve balances accordingly\\n function calculate_growth(uint256 _minted) public view returns (uint256) {\\n uint256 _veTotal = _ve.totalSupply();\\n uint256 _flowTotal = _flow.totalSupply();\\n return\\n (((((_minted * _veTotal) / _flowTotal) * _veTotal) / _flowTotal) *\\n _veTotal) /\\n _flowTotal /\\n 2;\\n }\\n\\n // update period can only be called once per cycle (1 week)\\n function update_period() external returns (uint256) {\\n uint256 _period = active_period;\\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\\n // only trigger if new week\\n _period = (block.timestamp / WEEK) * WEEK;\\n active_period = _period;\\n weekly = weekly_emission();\\n\\n uint256 _growth = calculate_growth(weekly);\\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\\n (PRECISION - teamRate);\\n uint256 _required = _growth + weekly + _teamEmissions;\\n uint256 _balanceOf = _flow.balanceOf(address(this));\\n if (_balanceOf < _required) {\\n _flow.mint(address(this), _required - _balanceOf);\\n }\\n\\n require(_flow.transfer(team, _teamEmissions));\\n require(_flow.transfer(address(_rewards_distributor), _growth));\\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\\n\\n _flow.approve(address(_voter), weekly);\\n _voter.notifyRewardAmount(weekly);\\n\\n emit Mint(\\n msg.sender,\\n weekly,\\n circulating_supply(),\\n circulating_emission()\\n );\\n }\\n return _period;\\n }\\n}\\n\",\"keccak256\":\"0xc661046dd2b90d93e4f057d2497b137703b4f0c3caccfe846f1a81906a2e1961\",\"license\":\"MIT\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x6101006040526a0c685fa11e01ec6f0000006000553480156200002157600080fd5b506040516200158938038062001589833981016040819052620000449162000156565b60028054336001600160a01b03199182168117909255600380549091169091179055601e60055560408051637e062a3560e11b815290516001600160a01b0384169163fc0c546a9160048083019260209291908290030181865afa158015620000b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d79190620001a0565b6001600160a01b0390811660805283811660a05282811660c052811660e05262093a808062000108816002620001db565b620001149042620001fd565b62000120919062000218565b6200012c9190620001db565b600155506200023b915050565b80516001600160a01b03811681146200015157600080fd5b919050565b6000806000606084860312156200016c57600080fd5b620001778462000139565b9250620001876020850162000139565b9150620001976040850162000139565b90509250925092565b600060208284031215620001b357600080fd5b620001be8262000139565b9392505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620001f857620001f8620001c5565b500290565b60008219821115620002135762000213620001c5565b500190565b6000826200023657634e487b7160e01b600052601260045260246000fd5b500490565b60805160a05160c05160e051611296620002f3600039600081816101d101528181610c3701528181610cde0152610d5101526000818161023a015281816104b30152818161055f01528181610689015261087501526000818161019201528181610e090152610ea301526000818161029d01528181610426015281816104e30152818161070f015281816108f701528181610a5f01528181610ade01528181610ba801528181610c660152610dda01526112966000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c806385170813116100ad578063cfc6c8ff11610071578063cfc6c8ff14610277578063d13996081461027f578063e038c75a14610288578063ed29fc1114610290578063fe75cac51461029857600080fd5b8063851708131461020f57806385f2aef2146102225780638dd598fb146102355780638e01fbfa1461025c578063b5cc143a1461026f57600080fd5b806336d96faf116100f457806336d96faf146101855780633db9b42a1461018d5780634b1cd5da146101cc57806359d46ffc146101f357806378ef7f021461020657600080fd5b806301c8e6fd14610131578063095cf5c61461014c5780631eebae801461016157806326cfc17b146101695780632e8f7b1f14610172575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b61015f61015a366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61015f610180366004610fb8565b610353565b6101396103de565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6004546101b4906001600160a01b031681565b61013960055481565b61015f61021d3660046110a7565b6103f3565b6003546101b4906001600160a01b031681565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b61013961026a366004610fb8565b610684565b61015f6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea264697066735822122057707c7ff21f374352214e71e7c225b391feb35beac2e749fd76e72f01a6ba6f64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c806385170813116100ad578063cfc6c8ff11610071578063cfc6c8ff14610277578063d13996081461027f578063e038c75a14610288578063ed29fc1114610290578063fe75cac51461029857600080fd5b8063851708131461020f57806385f2aef2146102225780638dd598fb146102355780638e01fbfa1461025c578063b5cc143a1461026f57600080fd5b806336d96faf116100f457806336d96faf146101855780633db9b42a1461018d5780634b1cd5da146101cc57806359d46ffc146101f357806378ef7f021461020657600080fd5b806301c8e6fd14610131578063095cf5c61461014c5780631eebae801461016157806326cfc17b146101695780632e8f7b1f14610172575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b61015f61015a366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61015f610180366004610fb8565b610353565b6101396103de565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6004546101b4906001600160a01b031681565b61013960055481565b61015f61021d3660046110a7565b6103f3565b6003546101b4906001600160a01b031681565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b61013961026a366004610fb8565b610684565b61015f6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea264697066735822122057707c7ff21f374352214e71e7c225b391feb35beac2e749fd76e72f01a6ba6f64736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/PairFactory.json b/deployments/arbitrumGoerli/PairFactory.json index 4da0cf42..7677391f 100644 --- a/deployments/arbitrumGoerli/PairFactory.json +++ b/deployments/arbitrumGoerli/PairFactory.json @@ -1,5 +1,5 @@ { - "address": "0x32bB8e83F877948Db847BDB6A8DB51d441324c1F", + "address": "0x5c7C6ee91569E2658c3A52f47b35E1AAB7e8e600", "abi": [ { "inputs": [], @@ -383,28 +383,28 @@ "type": "function" } ], - "transactionHash": "0x9c0defb75d082c1c291c4433fe0a4a9fe8c99f66f15355118be6ec20ed56d61d", + "transactionHash": "0x847c09e28a87c4a13b5fb2cc56d188788f105bc0ffc0428c2701093dcb76229d", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x32bB8e83F877948Db847BDB6A8DB51d441324c1F", - "transactionIndex": 4, + "contractAddress": "0x5c7C6ee91569E2658c3A52f47b35E1AAB7e8e600", + "transactionIndex": 1, "gasUsed": "4628154", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x0f7dfa6d40eef900eb285abcc2802de04aa63b6f95a04ea5aad476325268ac66", - "transactionHash": "0x9c0defb75d082c1c291c4433fe0a4a9fe8c99f66f15355118be6ec20ed56d61d", + "blockHash": "0xdb43649995465ade5b3ae9197ef9af2693be7647cac66edd353e9fbf89463298", + "transactionHash": "0x847c09e28a87c4a13b5fb2cc56d188788f105bc0ffc0428c2701093dcb76229d", "logs": [], - "blockNumber": 5849166, - "cumulativeGasUsed": "5463539", + "blockNumber": 6069385, + "cumulativeGasUsed": "4628154", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 3, - "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"PairCreated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_FEE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allPairs\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"allPairsLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"createPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getInitializable\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"name\":\"getPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pairCodeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingFeeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingPauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_feeManager\",\"type\":\"address\"}],\"name\":\"setFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_state\",\"type\":\"bool\"}],\"name\":\"setPause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pauser\",\"type\":\"address\"}],\"name\":\"setPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stableFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"volatileFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/PairFactory.sol\":\"PairFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Pair.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairCallee.sol\\\";\\nimport \\\"contracts/factories/PairFactory.sol\\\";\\nimport \\\"contracts/PairFees.sol\\\";\\n\\n// The base pair of pools, either stable or volatile\\ncontract Pair is IPair {\\n string public name;\\n string public symbol;\\n uint8 public constant decimals = 18;\\n\\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\\n bool public immutable stable;\\n\\n uint256 public totalSupply = 0;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n mapping(address => uint256) public balanceOf;\\n\\n bytes32 internal DOMAIN_SEPARATOR;\\n // keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 internal constant PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n mapping(address => uint256) public nonces;\\n\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n\\n address public immutable token0;\\n address public immutable token1;\\n address public immutable fees;\\n address immutable factory;\\n\\n // Structure to capture time period obervations every 30 minutes, used for local oracles\\n struct Observation {\\n uint256 timestamp;\\n uint256 reserve0Cumulative;\\n uint256 reserve1Cumulative;\\n }\\n\\n // Capture oracle reading every 30 minutes\\n uint256 constant periodSize = 1800;\\n\\n Observation[] public observations;\\n\\n uint256 internal immutable decimals0;\\n uint256 internal immutable decimals1;\\n\\n uint256 public reserve0;\\n uint256 public reserve1;\\n uint256 public blockTimestampLast;\\n\\n uint256 public reserve0CumulativeLast;\\n uint256 public reserve1CumulativeLast;\\n\\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \\\"clean\\\"\\n // this further allows LP holders to easily claim fees for tokens they have/staked\\n uint256 public index0 = 0;\\n uint256 public index1 = 0;\\n\\n // position assigned to each LP to track their current index0 & index1 vs the global position\\n mapping(address => uint256) public supplyIndex0;\\n mapping(address => uint256) public supplyIndex1;\\n\\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\\n mapping(address => uint256) public claimable0;\\n mapping(address => uint256) public claimable1;\\n\\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\\n event Burn(\\n address indexed sender,\\n uint256 amount0,\\n uint256 amount1,\\n address indexed to\\n );\\n event Swap(\\n address indexed sender,\\n uint256 amount0In,\\n uint256 amount1In,\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address indexed to\\n );\\n event Sync(uint256 reserve0, uint256 reserve1);\\n event Claim(\\n address indexed sender,\\n address indexed recipient,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 amount\\n );\\n\\n constructor() {\\n factory = msg.sender;\\n (address _token0, address _token1, bool _stable) = PairFactory(\\n msg.sender\\n ).getInitializable();\\n (token0, token1, stable) = (_token0, _token1, _stable);\\n fees = address(new PairFees(_token0, _token1));\\n if (_stable) {\\n name = string(\\n abi.encodePacked(\\n \\\"StableV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"sAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n } else {\\n name = string(\\n abi.encodePacked(\\n \\\"VolatileV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"vAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n }\\n\\n decimals0 = 10**IERC20(_token0).decimals();\\n decimals1 = 10**IERC20(_token1).decimals();\\n\\n observations.push(Observation(block.timestamp, 0, 0));\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function observationLength() external view returns (uint256) {\\n return observations.length;\\n }\\n\\n function lastObservation() public view returns (Observation memory) {\\n return observations[observations.length - 1];\\n }\\n\\n function metadata()\\n external\\n view\\n returns (\\n uint256 dec0,\\n uint256 dec1,\\n uint256 r0,\\n uint256 r1,\\n bool st,\\n address t0,\\n address t1\\n )\\n {\\n return (\\n decimals0,\\n decimals1,\\n reserve0,\\n reserve1,\\n stable,\\n token0,\\n token1\\n );\\n }\\n\\n function tokens() external view returns (address, address) {\\n return (token0, token1);\\n }\\n\\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\\n _updateFor(msg.sender);\\n\\n claimed0 = claimable0[msg.sender];\\n claimed1 = claimable1[msg.sender];\\n\\n if (claimed0 > 0 || claimed1 > 0) {\\n claimable0[msg.sender] = 0;\\n claimable1[msg.sender] = 0;\\n\\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\\n\\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n // Accrue fees on token0\\n function _update0(uint256 amount) internal {\\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index0 += _ratio;\\n }\\n emit Fees(msg.sender, amount, 0);\\n }\\n\\n // Accrue fees on token1\\n function _update1(uint256 amount) internal {\\n _safeTransfer(token1, fees, amount);\\n uint256 _ratio = (amount * 1e18) / totalSupply;\\n if (_ratio > 0) {\\n index1 += _ratio;\\n }\\n emit Fees(msg.sender, 0, amount);\\n }\\n\\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\\n // Fees are segregated from core funds, so fees can never put liquidity at risk\\n function _updateFor(address recipient) internal {\\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\\n if (_supplied > 0) {\\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\\n uint256 _supplyIndex1 = supplyIndex1[recipient];\\n uint256 _index0 = index0; // get global index0 for accumulated fees\\n uint256 _index1 = index1;\\n supplyIndex0[recipient] = _index0; // update user current position to global position\\n supplyIndex1[recipient] = _index1;\\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\\n uint256 _delta1 = _index1 - _supplyIndex1;\\n if (_delta0 > 0) {\\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\\n claimable0[recipient] += _share;\\n }\\n if (_delta1 > 0) {\\n uint256 _share = (_supplied * _delta1) / 1e18;\\n claimable1[recipient] += _share;\\n }\\n } else {\\n supplyIndex0[recipient] = index0; // new users are set to the default global state\\n supplyIndex1[recipient] = index1;\\n }\\n }\\n\\n function getReserves()\\n public\\n view\\n returns (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n )\\n {\\n _reserve0 = reserve0;\\n _reserve1 = reserve1;\\n _blockTimestampLast = blockTimestampLast;\\n }\\n\\n // update reserves and, on the first call per block, price accumulators\\n function _update(\\n uint256 balance0,\\n uint256 balance1,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal {\\n uint256 blockTimestamp = block.timestamp;\\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\\n reserve0CumulativeLast += _reserve0 * timeElapsed;\\n reserve1CumulativeLast += _reserve1 * timeElapsed;\\n }\\n\\n Observation memory _point = lastObservation();\\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\\n if (timeElapsed > periodSize) {\\n observations.push(\\n Observation(\\n blockTimestamp,\\n reserve0CumulativeLast,\\n reserve1CumulativeLast\\n )\\n );\\n }\\n reserve0 = balance0;\\n reserve1 = balance1;\\n blockTimestampLast = blockTimestamp;\\n emit Sync(reserve0, reserve1);\\n }\\n\\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\\n function currentCumulativePrices()\\n public\\n view\\n returns (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n uint256 blockTimestamp\\n )\\n {\\n blockTimestamp = block.timestamp;\\n reserve0Cumulative = reserve0CumulativeLast;\\n reserve1Cumulative = reserve1CumulativeLast;\\n\\n // if time has elapsed since the last update on the pair, mock the accumulated price values\\n (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n ) = getReserves();\\n if (_blockTimestampLast != blockTimestamp) {\\n // subtraction overflow is desired\\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\\n reserve0Cumulative += _reserve0 * timeElapsed;\\n reserve1Cumulative += _reserve1 * timeElapsed;\\n }\\n }\\n\\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\\n function current(address tokenIn, uint256 amountIn)\\n external\\n view\\n returns (uint256 amountOut)\\n {\\n Observation memory _observation = lastObservation();\\n (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n\\n ) = currentCumulativePrices();\\n if (block.timestamp == _observation.timestamp) {\\n _observation = observations[observations.length - 2];\\n }\\n\\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\\n uint256 _reserve0 = (reserve0Cumulative -\\n _observation.reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (reserve1Cumulative -\\n _observation.reserve1Cumulative) / timeElapsed;\\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n // as per `current`, however allows user configured granularity, up to the full window size\\n function quote(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 granularity\\n ) external view returns (uint256 amountOut) {\\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\\n uint256 priceAverageCumulative;\\n for (uint256 i = 0; i < _prices.length; i++) {\\n priceAverageCumulative += _prices[i];\\n }\\n return priceAverageCumulative / granularity;\\n }\\n\\n // returns a memory set of twap prices\\n function prices(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points\\n ) external view returns (uint256[] memory) {\\n return sample(tokenIn, amountIn, points, 1);\\n }\\n\\n function sample(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points,\\n uint256 window\\n ) public view returns (uint256[] memory) {\\n uint256[] memory _prices = new uint256[](points);\\n\\n uint256 length = observations.length - 1;\\n uint256 i = length - (points * window);\\n uint256 nextIndex = 0;\\n uint256 index = 0;\\n\\n for (; i < length; i += window) {\\n nextIndex = i + window;\\n uint256 timeElapsed = observations[nextIndex].timestamp -\\n observations[i].timestamp;\\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\\n observations[i].reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\\n observations[i].reserve1Cumulative) / timeElapsed;\\n _prices[index] = _getAmountOut(\\n amountIn,\\n tokenIn,\\n _reserve0,\\n _reserve1\\n );\\n // index < length; length cannot overflow\\n unchecked {\\n index = index + 1;\\n }\\n }\\n return _prices;\\n }\\n\\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\\n // standard uniswap v2 implementation\\n function mint(address to) external lock returns (uint256 liquidity) {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\\n uint256 _amount0 = _balance0 - _reserve0;\\n uint256 _amount1 = _balance1 - _reserve1;\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n if (_totalSupply == 0) {\\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\\n } else {\\n liquidity = MathDunks.min(\\n (_amount0 * _totalSupply) / _reserve0,\\n (_amount1 * _totalSupply) / _reserve1\\n );\\n }\\n require(liquidity > 0, \\\"ILM\\\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\\n _mint(to, liquidity);\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Mint(msg.sender, _amount0, _amount1);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n // standard uniswap v2 implementation\\n function burn(address to)\\n external\\n lock\\n returns (uint256 amount0, uint256 amount1)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n (address _token0, address _token1) = (token0, token1);\\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\\n uint256 _liquidity = balanceOf[address(this)];\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\\n require(amount0 > 0 && amount1 > 0, \\\"ILB\\\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\\n _burn(address(this), _liquidity);\\n _safeTransfer(_token0, to, amount0);\\n _safeTransfer(_token1, to, amount1);\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Burn(msg.sender, amount0, amount1, to);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n function swap(\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address to,\\n bytes calldata data\\n ) external lock {\\n require(!PairFactory(factory).isPaused());\\n require(amount0Out > 0 || amount1Out > 0, \\\"IOA\\\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \\\"IL\\\"); // Pair: INSUFFICIENT_LIQUIDITY\\n\\n uint256 _balance0;\\n uint256 _balance1;\\n {\\n // scope for _token{0,1}, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n require(to != _token0 && to != _token1, \\\"IT\\\"); // Pair: INVALID_TO\\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\\n if (data.length > 0)\\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n }\\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\\n ? _balance0 - (_reserve0 - amount0Out)\\n : 0;\\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\\n ? _balance1 - (_reserve1 - amount1Out)\\n : 0;\\n require(amount0In > 0 || amount1In > 0, \\\"IIA\\\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\\n {\\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n if (amount0In > 0)\\n _update0(\\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token0 and move them out of pool\\n if (amount1In > 0)\\n _update1(\\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token1 and move them out of pool\\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \\\"K\\\"); // Pair: K\\n }\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\\n }\\n\\n // force balances to match reserves\\n function skim(address to) external lock {\\n (address _token0, address _token1) = (token0, token1);\\n _safeTransfer(\\n _token0,\\n to,\\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\\n );\\n _safeTransfer(\\n _token1,\\n to,\\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\\n );\\n }\\n\\n // force reserves to match balances\\n function sync() external lock {\\n _update(\\n IERC20(token0).balanceOf(address(this)),\\n IERC20(token1).balanceOf(address(this)),\\n reserve0,\\n reserve1\\n );\\n }\\n\\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\\n 1e18 +\\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\\n 1e18;\\n }\\n\\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (3 * x0 * ((y * y) / 1e18)) /\\n 1e18 +\\n ((((x0 * x0) / 1e18) * x0) / 1e18);\\n }\\n\\n function _get_y(\\n uint256 x0,\\n uint256 xy,\\n uint256 y\\n ) internal pure returns (uint256) {\\n for (uint256 i = 0; i < 255; i++) {\\n uint256 y_prev = y;\\n uint256 k = _f(x0, y);\\n if (k < xy) {\\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\\n y = y + dy;\\n } else {\\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getAmountOut(uint256 amountIn, address tokenIn)\\n external\\n view\\n returns (uint256)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n function _getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal view returns (uint256) {\\n if (stable) {\\n uint256 xy = _k(_reserve0, _reserve1);\\n _reserve0 = (_reserve0 * 1e18) / decimals0;\\n _reserve1 = (_reserve1 * 1e18) / decimals1;\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0\\n ? (amountIn * 1e18) / decimals0\\n : (amountIn * 1e18) / decimals1;\\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\\n } else {\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n return (amountIn * reserveB) / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\\n if (stable) {\\n uint256 _x = (x * 1e18) / decimals0;\\n uint256 _y = (y * 1e18) / decimals1;\\n uint256 _a = (_x * _y) / 1e18;\\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return (_a * _b) / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n\\n function _mint(address dst, uint256 amount) internal {\\n _updateFor(dst); // balances must be updated on mint/burn/transfer\\n totalSupply += amount;\\n balanceOf[dst] += amount;\\n emit Transfer(address(0), dst, amount);\\n }\\n\\n function _burn(address dst, uint256 amount) internal {\\n _updateFor(dst);\\n totalSupply -= amount;\\n balanceOf[dst] -= amount;\\n emit Transfer(dst, address(0), amount);\\n }\\n\\n function approve(address spender, uint256 amount) external returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external {\\n require(deadline >= block.timestamp, \\\"Pair: EXPIRED\\\");\\n DOMAIN_SEPARATOR = keccak256(\\n abi.encode(\\n keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n ),\\n keccak256(bytes(name)),\\n keccak256(bytes(\\\"1\\\")),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR,\\n keccak256(\\n abi.encode(\\n PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n );\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n require(\\n recoveredAddress != address(0) && recoveredAddress == owner,\\n \\\"Pair: INVALID_SIGNATURE\\\"\\n );\\n allowance[owner][spender] = value;\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function transfer(address dst, uint256 amount) external returns (bool) {\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 amount\\n ) external returns (bool) {\\n address spender = msg.sender;\\n uint256 spenderAllowance = allowance[src][spender];\\n\\n if (spender != src && spenderAllowance != type(uint256).max) {\\n uint256 newAllowance = spenderAllowance - amount;\\n allowance[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n function _transferTokens(\\n address src,\\n address dst,\\n uint256 amount\\n ) internal {\\n _updateFor(src); // update fee position for src\\n _updateFor(dst); // update fee position for dst\\n\\n balanceOf[src] -= amount;\\n balanceOf[dst] += amount;\\n\\n emit Transfer(src, dst, amount);\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x4f508747645f4480e0b0f23d952fa9b82af1d9bc60b15b8cd1f542ee136043d1\",\"license\":\"MIT\"},\"contracts/PairFees.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IERC20.sol';\\n\\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\\ncontract PairFees {\\n\\n address internal immutable pair; // The pair it is bonded to\\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\\n\\n constructor(address _token0, address _token1) {\\n pair = msg.sender;\\n token0 = _token0;\\n token1 = _token1;\\n }\\n\\n function _safeTransfer(address token,address to,uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n // Allow the pair to transfer fees to users\\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\\n require(msg.sender == pair);\\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\\n }\\n\\n}\\n\",\"keccak256\":\"0xb772e192bab353f8642e89a95ef4ef0255d1caef08444101d7fe34469c1000ca\",\"license\":\"MIT\"},\"contracts/factories/PairFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/Pair.sol';\\n\\ncontract PairFactory is IPairFactory {\\n\\n bool public isPaused;\\n address public pauser;\\n address public pendingPauser;\\n\\n uint256 public stableFee;\\n uint256 public volatileFee;\\n uint256 public constant MAX_FEE = 5; // 0.05%\\n address public feeManager;\\n address public pendingFeeManager;\\n\\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\\n address[] public allPairs;\\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\\n\\n address internal _temp0;\\n address internal _temp1;\\n bool internal _temp;\\n\\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\\n\\n constructor() {\\n pauser = msg.sender;\\n isPaused = false;\\n feeManager = msg.sender;\\n stableFee = 2; // 0.02%\\n volatileFee = 2;\\n }\\n\\n function allPairsLength() external view returns (uint) {\\n return allPairs.length;\\n }\\n\\n function setPauser(address _pauser) external {\\n require(msg.sender == pauser);\\n pendingPauser = _pauser;\\n }\\n\\n function acceptPauser() external {\\n require(msg.sender == pendingPauser);\\n pauser = pendingPauser;\\n }\\n\\n function setPause(bool _state) external {\\n require(msg.sender == pauser);\\n isPaused = _state;\\n }\\n\\n function setFeeManager(address _feeManager) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n pendingFeeManager = _feeManager;\\n }\\n\\n function acceptFeeManager() external {\\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\\n feeManager = pendingFeeManager;\\n }\\n\\n function setFee(bool _stable, uint256 _fee) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n require(_fee <= MAX_FEE, 'fee too high');\\n require(_fee != 0, 'fee must be nonzero');\\n if (_stable) {\\n stableFee = _fee;\\n } else {\\n volatileFee = _fee;\\n }\\n }\\n\\n function getFee(bool _stable) public view returns(uint256) {\\n return _stable ? stableFee : volatileFee;\\n }\\n\\n function pairCodeHash() external pure returns (bytes32) {\\n return keccak256(type(Pair).creationCode);\\n }\\n\\n function getInitializable() external view returns (address, address, bool) {\\n return (_temp0, _temp1, _temp);\\n }\\n\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\\n (_temp0, _temp1, _temp) = (token0, token1, stable);\\n pair = address(new Pair{salt:salt}());\\n getPair[token0][token1][stable] = pair;\\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\\n allPairs.push(pair);\\n isPair[pair] = true;\\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\\n }\\n}\\n\",\"keccak256\":\"0x9b7984117a5a32188aa9ddf42b6cff024240579ab30f3776f7a201285d813e4f\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairCallee.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairCallee {\\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x3ac2de2c7a08bf59fd1006e4d108b247916369de15fbd048b72ca2b7814023ca\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50600080546001600160a81b03191633610100810260ff1916919091178255600480546001600160a01b0319169091179055600280805560035561519190819061005a90396000f3fe60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea2646970667358221220ce154b3635cf14657eefb7534908f2ecf29803c977257640f38a3f975ef8e6f064736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea2646970667358221220ac6681731d4115b51788d75ee3ed8f52d572455bd0bdc1c79a8f79eb1e44459964736f6c634300080d0033a2646970667358221220316924ccc9676e4b6e71a5db0daf7f5c2096ee7d53ebe473a356330c9381716264736f6c634300080d0033", - "deployedBytecode": "0x60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea2646970667358221220ce154b3635cf14657eefb7534908f2ecf29803c977257640f38a3f975ef8e6f064736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea2646970667358221220ac6681731d4115b51788d75ee3ed8f52d572455bd0bdc1c79a8f79eb1e44459964736f6c634300080d0033a2646970667358221220316924ccc9676e4b6e71a5db0daf7f5c2096ee7d53ebe473a356330c9381716264736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "d2a2160297444b93438826228d1e185d", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"PairCreated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_FEE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allPairs\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"allPairsLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"createPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getInitializable\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"name\":\"getPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pairCodeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingFeeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingPauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_feeManager\",\"type\":\"address\"}],\"name\":\"setFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_state\",\"type\":\"bool\"}],\"name\":\"setPause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pauser\",\"type\":\"address\"}],\"name\":\"setPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stableFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"volatileFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/PairFactory.sol\":\"PairFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Pair.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairCallee.sol\\\";\\nimport \\\"contracts/factories/PairFactory.sol\\\";\\nimport \\\"contracts/PairFees.sol\\\";\\n\\n// The base pair of pools, either stable or volatile\\ncontract Pair is IPair {\\n string public name;\\n string public symbol;\\n uint8 public constant decimals = 18;\\n\\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\\n bool public immutable stable;\\n\\n uint256 public totalSupply = 0;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n mapping(address => uint256) public balanceOf;\\n\\n bytes32 internal DOMAIN_SEPARATOR;\\n // keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 internal constant PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n mapping(address => uint256) public nonces;\\n\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n\\n address public immutable token0;\\n address public immutable token1;\\n address public immutable fees;\\n address immutable factory;\\n\\n // Structure to capture time period obervations every 30 minutes, used for local oracles\\n struct Observation {\\n uint256 timestamp;\\n uint256 reserve0Cumulative;\\n uint256 reserve1Cumulative;\\n }\\n\\n // Capture oracle reading every 30 minutes\\n uint256 constant periodSize = 1800;\\n\\n Observation[] public observations;\\n\\n uint256 internal immutable decimals0;\\n uint256 internal immutable decimals1;\\n\\n uint256 public reserve0;\\n uint256 public reserve1;\\n uint256 public blockTimestampLast;\\n\\n uint256 public reserve0CumulativeLast;\\n uint256 public reserve1CumulativeLast;\\n\\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \\\"clean\\\"\\n // this further allows LP holders to easily claim fees for tokens they have/staked\\n uint256 public index0 = 0;\\n uint256 public index1 = 0;\\n\\n // position assigned to each LP to track their current index0 & index1 vs the global position\\n mapping(address => uint256) public supplyIndex0;\\n mapping(address => uint256) public supplyIndex1;\\n\\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\\n mapping(address => uint256) public claimable0;\\n mapping(address => uint256) public claimable1;\\n\\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\\n event Burn(\\n address indexed sender,\\n uint256 amount0,\\n uint256 amount1,\\n address indexed to\\n );\\n event Swap(\\n address indexed sender,\\n uint256 amount0In,\\n uint256 amount1In,\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address indexed to\\n );\\n event Sync(uint256 reserve0, uint256 reserve1);\\n event Claim(\\n address indexed sender,\\n address indexed recipient,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 amount\\n );\\n\\n constructor() {\\n factory = msg.sender;\\n (address _token0, address _token1, bool _stable) = PairFactory(\\n msg.sender\\n ).getInitializable();\\n (token0, token1, stable) = (_token0, _token1, _stable);\\n fees = address(new PairFees(_token0, _token1));\\n if (_stable) {\\n name = string(\\n abi.encodePacked(\\n \\\"StableV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"sAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n } else {\\n name = string(\\n abi.encodePacked(\\n \\\"VolatileV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"vAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n }\\n\\n decimals0 = 10**IERC20(_token0).decimals();\\n decimals1 = 10**IERC20(_token1).decimals();\\n\\n observations.push(Observation(block.timestamp, 0, 0));\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function observationLength() external view returns (uint256) {\\n return observations.length;\\n }\\n\\n function lastObservation() public view returns (Observation memory) {\\n return observations[observations.length - 1];\\n }\\n\\n function metadata()\\n external\\n view\\n returns (\\n uint256 dec0,\\n uint256 dec1,\\n uint256 r0,\\n uint256 r1,\\n bool st,\\n address t0,\\n address t1\\n )\\n {\\n return (\\n decimals0,\\n decimals1,\\n reserve0,\\n reserve1,\\n stable,\\n token0,\\n token1\\n );\\n }\\n\\n function tokens() external view returns (address, address) {\\n return (token0, token1);\\n }\\n\\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\\n _updateFor(msg.sender);\\n\\n claimed0 = claimable0[msg.sender];\\n claimed1 = claimable1[msg.sender];\\n\\n if (claimed0 > 0 || claimed1 > 0) {\\n claimable0[msg.sender] = 0;\\n claimable1[msg.sender] = 0;\\n\\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\\n\\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n // Accrue fees on token0\\n function _update0(uint256 amount) internal {\\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index0 += _ratio;\\n }\\n emit Fees(msg.sender, amount, 0);\\n }\\n\\n // Accrue fees on token1\\n function _update1(uint256 amount) internal {\\n _safeTransfer(token1, fees, amount);\\n uint256 _ratio = (amount * 1e18) / totalSupply;\\n if (_ratio > 0) {\\n index1 += _ratio;\\n }\\n emit Fees(msg.sender, 0, amount);\\n }\\n\\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\\n // Fees are segregated from core funds, so fees can never put liquidity at risk\\n function _updateFor(address recipient) internal {\\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\\n if (_supplied > 0) {\\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\\n uint256 _supplyIndex1 = supplyIndex1[recipient];\\n uint256 _index0 = index0; // get global index0 for accumulated fees\\n uint256 _index1 = index1;\\n supplyIndex0[recipient] = _index0; // update user current position to global position\\n supplyIndex1[recipient] = _index1;\\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\\n uint256 _delta1 = _index1 - _supplyIndex1;\\n if (_delta0 > 0) {\\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\\n claimable0[recipient] += _share;\\n }\\n if (_delta1 > 0) {\\n uint256 _share = (_supplied * _delta1) / 1e18;\\n claimable1[recipient] += _share;\\n }\\n } else {\\n supplyIndex0[recipient] = index0; // new users are set to the default global state\\n supplyIndex1[recipient] = index1;\\n }\\n }\\n\\n function getReserves()\\n public\\n view\\n returns (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n )\\n {\\n _reserve0 = reserve0;\\n _reserve1 = reserve1;\\n _blockTimestampLast = blockTimestampLast;\\n }\\n\\n // update reserves and, on the first call per block, price accumulators\\n function _update(\\n uint256 balance0,\\n uint256 balance1,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal {\\n uint256 blockTimestamp = block.timestamp;\\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\\n reserve0CumulativeLast += _reserve0 * timeElapsed;\\n reserve1CumulativeLast += _reserve1 * timeElapsed;\\n }\\n\\n Observation memory _point = lastObservation();\\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\\n if (timeElapsed > periodSize) {\\n observations.push(\\n Observation(\\n blockTimestamp,\\n reserve0CumulativeLast,\\n reserve1CumulativeLast\\n )\\n );\\n }\\n reserve0 = balance0;\\n reserve1 = balance1;\\n blockTimestampLast = blockTimestamp;\\n emit Sync(reserve0, reserve1);\\n }\\n\\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\\n function currentCumulativePrices()\\n public\\n view\\n returns (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n uint256 blockTimestamp\\n )\\n {\\n blockTimestamp = block.timestamp;\\n reserve0Cumulative = reserve0CumulativeLast;\\n reserve1Cumulative = reserve1CumulativeLast;\\n\\n // if time has elapsed since the last update on the pair, mock the accumulated price values\\n (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n ) = getReserves();\\n if (_blockTimestampLast != blockTimestamp) {\\n // subtraction overflow is desired\\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\\n reserve0Cumulative += _reserve0 * timeElapsed;\\n reserve1Cumulative += _reserve1 * timeElapsed;\\n }\\n }\\n\\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\\n function current(address tokenIn, uint256 amountIn)\\n external\\n view\\n returns (uint256 amountOut)\\n {\\n Observation memory _observation = lastObservation();\\n (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n\\n ) = currentCumulativePrices();\\n if (block.timestamp == _observation.timestamp) {\\n _observation = observations[observations.length - 2];\\n }\\n\\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\\n uint256 _reserve0 = (reserve0Cumulative -\\n _observation.reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (reserve1Cumulative -\\n _observation.reserve1Cumulative) / timeElapsed;\\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n // as per `current`, however allows user configured granularity, up to the full window size\\n function quote(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 granularity\\n ) external view returns (uint256 amountOut) {\\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\\n uint256 priceAverageCumulative;\\n for (uint256 i = 0; i < _prices.length; i++) {\\n priceAverageCumulative += _prices[i];\\n }\\n return priceAverageCumulative / granularity;\\n }\\n\\n // returns a memory set of twap prices\\n function prices(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points\\n ) external view returns (uint256[] memory) {\\n return sample(tokenIn, amountIn, points, 1);\\n }\\n\\n function sample(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points,\\n uint256 window\\n ) public view returns (uint256[] memory) {\\n uint256[] memory _prices = new uint256[](points);\\n\\n uint256 length = observations.length - 1;\\n uint256 i = length - (points * window);\\n uint256 nextIndex = 0;\\n uint256 index = 0;\\n\\n for (; i < length; i += window) {\\n nextIndex = i + window;\\n uint256 timeElapsed = observations[nextIndex].timestamp -\\n observations[i].timestamp;\\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\\n observations[i].reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\\n observations[i].reserve1Cumulative) / timeElapsed;\\n _prices[index] = _getAmountOut(\\n amountIn,\\n tokenIn,\\n _reserve0,\\n _reserve1\\n );\\n // index < length; length cannot overflow\\n unchecked {\\n index = index + 1;\\n }\\n }\\n return _prices;\\n }\\n\\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\\n // standard uniswap v2 implementation\\n function mint(address to) external lock returns (uint256 liquidity) {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\\n uint256 _amount0 = _balance0 - _reserve0;\\n uint256 _amount1 = _balance1 - _reserve1;\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n if (_totalSupply == 0) {\\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\\n } else {\\n liquidity = MathDunks.min(\\n (_amount0 * _totalSupply) / _reserve0,\\n (_amount1 * _totalSupply) / _reserve1\\n );\\n }\\n require(liquidity > 0, \\\"ILM\\\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\\n _mint(to, liquidity);\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Mint(msg.sender, _amount0, _amount1);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n // standard uniswap v2 implementation\\n function burn(address to)\\n external\\n lock\\n returns (uint256 amount0, uint256 amount1)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n (address _token0, address _token1) = (token0, token1);\\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\\n uint256 _liquidity = balanceOf[address(this)];\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\\n require(amount0 > 0 && amount1 > 0, \\\"ILB\\\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\\n _burn(address(this), _liquidity);\\n _safeTransfer(_token0, to, amount0);\\n _safeTransfer(_token1, to, amount1);\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Burn(msg.sender, amount0, amount1, to);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n function swap(\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address to,\\n bytes calldata data\\n ) external lock {\\n require(!PairFactory(factory).isPaused());\\n require(amount0Out > 0 || amount1Out > 0, \\\"IOA\\\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \\\"IL\\\"); // Pair: INSUFFICIENT_LIQUIDITY\\n\\n uint256 _balance0;\\n uint256 _balance1;\\n {\\n // scope for _token{0,1}, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n require(to != _token0 && to != _token1, \\\"IT\\\"); // Pair: INVALID_TO\\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\\n if (data.length > 0)\\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n }\\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\\n ? _balance0 - (_reserve0 - amount0Out)\\n : 0;\\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\\n ? _balance1 - (_reserve1 - amount1Out)\\n : 0;\\n require(amount0In > 0 || amount1In > 0, \\\"IIA\\\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\\n {\\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n if (amount0In > 0)\\n _update0(\\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token0 and move them out of pool\\n if (amount1In > 0)\\n _update1(\\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token1 and move them out of pool\\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \\\"K\\\"); // Pair: K\\n }\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\\n }\\n\\n // force balances to match reserves\\n function skim(address to) external lock {\\n (address _token0, address _token1) = (token0, token1);\\n _safeTransfer(\\n _token0,\\n to,\\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\\n );\\n _safeTransfer(\\n _token1,\\n to,\\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\\n );\\n }\\n\\n // force reserves to match balances\\n function sync() external lock {\\n _update(\\n IERC20(token0).balanceOf(address(this)),\\n IERC20(token1).balanceOf(address(this)),\\n reserve0,\\n reserve1\\n );\\n }\\n\\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\\n 1e18 +\\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\\n 1e18;\\n }\\n\\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (3 * x0 * ((y * y) / 1e18)) /\\n 1e18 +\\n ((((x0 * x0) / 1e18) * x0) / 1e18);\\n }\\n\\n function _get_y(\\n uint256 x0,\\n uint256 xy,\\n uint256 y\\n ) internal pure returns (uint256) {\\n for (uint256 i = 0; i < 255; i++) {\\n uint256 y_prev = y;\\n uint256 k = _f(x0, y);\\n if (k < xy) {\\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\\n y = y + dy;\\n } else {\\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getAmountOut(uint256 amountIn, address tokenIn)\\n external\\n view\\n returns (uint256)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n function _getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal view returns (uint256) {\\n if (stable) {\\n uint256 xy = _k(_reserve0, _reserve1);\\n _reserve0 = (_reserve0 * 1e18) / decimals0;\\n _reserve1 = (_reserve1 * 1e18) / decimals1;\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0\\n ? (amountIn * 1e18) / decimals0\\n : (amountIn * 1e18) / decimals1;\\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\\n } else {\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n return (amountIn * reserveB) / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\\n if (stable) {\\n uint256 _x = (x * 1e18) / decimals0;\\n uint256 _y = (y * 1e18) / decimals1;\\n uint256 _a = (_x * _y) / 1e18;\\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return (_a * _b) / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n\\n function _mint(address dst, uint256 amount) internal {\\n _updateFor(dst); // balances must be updated on mint/burn/transfer\\n totalSupply += amount;\\n balanceOf[dst] += amount;\\n emit Transfer(address(0), dst, amount);\\n }\\n\\n function _burn(address dst, uint256 amount) internal {\\n _updateFor(dst);\\n totalSupply -= amount;\\n balanceOf[dst] -= amount;\\n emit Transfer(dst, address(0), amount);\\n }\\n\\n function approve(address spender, uint256 amount) external returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external {\\n require(deadline >= block.timestamp, \\\"Pair: EXPIRED\\\");\\n DOMAIN_SEPARATOR = keccak256(\\n abi.encode(\\n keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n ),\\n keccak256(bytes(name)),\\n keccak256(bytes(\\\"1\\\")),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR,\\n keccak256(\\n abi.encode(\\n PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n );\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n require(\\n recoveredAddress != address(0) && recoveredAddress == owner,\\n \\\"Pair: INVALID_SIGNATURE\\\"\\n );\\n allowance[owner][spender] = value;\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function transfer(address dst, uint256 amount) external returns (bool) {\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 amount\\n ) external returns (bool) {\\n address spender = msg.sender;\\n uint256 spenderAllowance = allowance[src][spender];\\n\\n if (spender != src && spenderAllowance != type(uint256).max) {\\n uint256 newAllowance = spenderAllowance - amount;\\n allowance[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n function _transferTokens(\\n address src,\\n address dst,\\n uint256 amount\\n ) internal {\\n _updateFor(src); // update fee position for src\\n _updateFor(dst); // update fee position for dst\\n\\n balanceOf[src] -= amount;\\n balanceOf[dst] += amount;\\n\\n emit Transfer(src, dst, amount);\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x4f508747645f4480e0b0f23d952fa9b82af1d9bc60b15b8cd1f542ee136043d1\",\"license\":\"MIT\"},\"contracts/PairFees.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IERC20.sol';\\n\\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\\ncontract PairFees {\\n\\n address internal immutable pair; // The pair it is bonded to\\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\\n\\n constructor(address _token0, address _token1) {\\n pair = msg.sender;\\n token0 = _token0;\\n token1 = _token1;\\n }\\n\\n function _safeTransfer(address token,address to,uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n // Allow the pair to transfer fees to users\\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\\n require(msg.sender == pair);\\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\\n }\\n\\n}\\n\",\"keccak256\":\"0xb772e192bab353f8642e89a95ef4ef0255d1caef08444101d7fe34469c1000ca\",\"license\":\"MIT\"},\"contracts/factories/PairFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/Pair.sol';\\n\\ncontract PairFactory is IPairFactory {\\n\\n bool public isPaused;\\n address public pauser;\\n address public pendingPauser;\\n\\n uint256 public stableFee;\\n uint256 public volatileFee;\\n uint256 public constant MAX_FEE = 5; // 0.05%\\n address public feeManager;\\n address public pendingFeeManager;\\n\\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\\n address[] public allPairs;\\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\\n\\n address internal _temp0;\\n address internal _temp1;\\n bool internal _temp;\\n\\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\\n\\n constructor() {\\n pauser = msg.sender;\\n isPaused = false;\\n feeManager = msg.sender;\\n stableFee = 2; // 0.02%\\n volatileFee = 2;\\n }\\n\\n function allPairsLength() external view returns (uint) {\\n return allPairs.length;\\n }\\n\\n function setPauser(address _pauser) external {\\n require(msg.sender == pauser);\\n pendingPauser = _pauser;\\n }\\n\\n function acceptPauser() external {\\n require(msg.sender == pendingPauser);\\n pauser = pendingPauser;\\n }\\n\\n function setPause(bool _state) external {\\n require(msg.sender == pauser);\\n isPaused = _state;\\n }\\n\\n function setFeeManager(address _feeManager) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n pendingFeeManager = _feeManager;\\n }\\n\\n function acceptFeeManager() external {\\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\\n feeManager = pendingFeeManager;\\n }\\n\\n function setFee(bool _stable, uint256 _fee) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n require(_fee <= MAX_FEE, 'fee too high');\\n require(_fee != 0, 'fee must be nonzero');\\n if (_stable) {\\n stableFee = _fee;\\n } else {\\n volatileFee = _fee;\\n }\\n }\\n\\n function getFee(bool _stable) public view returns(uint256) {\\n return _stable ? stableFee : volatileFee;\\n }\\n\\n function pairCodeHash() external pure returns (bytes32) {\\n return keccak256(type(Pair).creationCode);\\n }\\n\\n function getInitializable() external view returns (address, address, bool) {\\n return (_temp0, _temp1, _temp);\\n }\\n\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\\n (_temp0, _temp1, _temp) = (token0, token1, stable);\\n pair = address(new Pair{salt:salt}());\\n getPair[token0][token1][stable] = pair;\\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\\n allPairs.push(pair);\\n isPair[pair] = true;\\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\\n }\\n}\\n\",\"keccak256\":\"0x9b7984117a5a32188aa9ddf42b6cff024240579ab30f3776f7a201285d813e4f\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairCallee.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairCallee {\\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x3ac2de2c7a08bf59fd1006e4d108b247916369de15fbd048b72ca2b7814023ca\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50600080546001600160a81b03191633610100810260ff1916919091178255600480546001600160a01b0319169091179055600280805560035561519190819061005a90396000f3fe60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea2646970667358221220ff2c274dfd378ca71906641f0c7f06b25bb815c6c66eae6da4a0e24dbfb4a44664736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea2646970667358221220c10cd0d4059a01c44dcaa3e097beb08044a910ff60f84a22ed835f049e9cc68164736f6c634300080d0033a26469706673582212202a979b2730dcc4e33c282ae10ae03c7a51e1a33f9884927cdce3b275d33e651064736f6c634300080d0033", + "deployedBytecode": "0x60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea2646970667358221220ff2c274dfd378ca71906641f0c7f06b25bb815c6c66eae6da4a0e24dbfb4a44664736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea2646970667358221220c10cd0d4059a01c44dcaa3e097beb08044a910ff60f84a22ed835f049e9cc68164736f6c634300080d0033a26469706673582212202a979b2730dcc4e33c282ae10ae03c7a51e1a33f9884927cdce3b275d33e651064736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/RedemptionReceiver.json b/deployments/arbitrumGoerli/RedemptionReceiver.json index 2da9fbbd..87339e66 100644 --- a/deployments/arbitrumGoerli/RedemptionReceiver.json +++ b/deployments/arbitrumGoerli/RedemptionReceiver.json @@ -1,5 +1,5 @@ { - "address": "0x86E0Da889381Fb86d40D7E870d247C4aFD992cc0", + "address": "0x130809dD1E22C2630E606EE8d59434B6C94a3F1C", "abi": [ { "inputs": [ @@ -323,33 +323,33 @@ "type": "function" } ], - "transactionHash": "0xb6342afd08f27f8a374dabba92721ac4f3eb834d991a5a7969c4f0d86cec9971", + "transactionHash": "0x845732d316e017defcae74f4b923b36723d9082b3532733207fc4840e1c673e0", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x86E0Da889381Fb86d40D7E870d247C4aFD992cc0", + "contractAddress": "0x130809dD1E22C2630E606EE8d59434B6C94a3F1C", "transactionIndex": 1, "gasUsed": "841985", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xd107dacdd5f5bf803ef35e882ef00c8c256aca1f1c0b5b68f9a65a3002e072b4", - "transactionHash": "0xb6342afd08f27f8a374dabba92721ac4f3eb834d991a5a7969c4f0d86cec9971", + "blockHash": "0xe54313be00af1fa1492404c3ce9b17929fe88ee1177aa9ccd3faf679f87cd58a", + "transactionHash": "0x845732d316e017defcae74f4b923b36723d9082b3532733207fc4840e1c673e0", "logs": [], - "blockNumber": 5849258, + "blockNumber": 6069460, "cumulativeGasUsed": "841985", "status": 1, "byzantium": true }, "args": [ "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8", - "0x0432f39386A9B1d0339c8Ba0af617b16C86ADA05", + "0x4E13914872BFf7e58f3E231b2687fDd084014999", 10012, "0x3c2269811836af69497E5F486A85D7316753cf62" ], - "numDeployments": 3, - "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_usdc\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_flow\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"_fantomChainId\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"_endpoint\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fantomSender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableUSDC\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableFLOW\",\"type\":\"uint256\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ELIGIBLE_WEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FLOW\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"USDC\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"toAddressBytes\",\"type\":\"bytes\"}],\"name\":\"addressFromPackedBytes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimLeftovers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endpoint\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomChainId\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_fantomSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableFLOW\",\"type\":\"uint256\"}],\"name\":\"initializeReceiverWith\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"leftoverFLOW\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"srcChainId\",\"type\":\"uint16\"},{\"internalType\":\"bytes\",\"name\":\"srcAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"lzReceive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountWEVE\",\"type\":\"uint256\"}],\"name\":\"previewRedeem\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"shareOfUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shareOfFLOW\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableFLOW\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableUSDC\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemedWEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process This contract is responsible for receiving the LZ message and distributing USDC + FLOW\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/RedemptionReceiver.sol\":\"RedemptionReceiver\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/redeem/RedemptionReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\\\";\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\n\\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\\n/// This contract is responsible for receiving the LZ message and distributing USDC + FLOW\\ncontract RedemptionReceiver is ILayerZeroReceiver {\\n IERC20 public immutable USDC;\\n IFlow public immutable FLOW;\\n\\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\\n address public immutable endpoint;\\n\\n address public team;\\n uint256 public immutable deployed;\\n\\n address public fantomSender;\\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\\n uint256 public redeemedWEVE;\\n uint256 public redeemableUSDC;\\n uint256 public redeemableFLOW;\\n uint256 public leftoverFLOW;\\n\\n constructor(\\n address _usdc,\\n address _flow,\\n uint16 _fantomChainId,\\n address _endpoint\\n ) {\\n require(_fantomChainId == 12 || _fantomChainId == 10012, \\\"CHAIN_ID_NOT_FTM\\\");\\n\\n USDC = IERC20(_usdc);\\n FLOW = IFlow(_flow);\\n\\n fantomChainId = _fantomChainId;\\n endpoint = _endpoint;\\n\\n team = msg.sender;\\n deployed = block.timestamp;\\n }\\n\\n modifier onlyTeam() {\\n require(msg.sender == team, \\\"ONLY_TEAM\\\");\\n _;\\n }\\n\\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableFLOW);\\n\\n function initializeReceiverWith(\\n address _fantomSender,\\n uint256 _redeemableUSDC,\\n uint256 _redeemableFLOW\\n ) external onlyTeam {\\n require(fantomSender == address(0), \\\"ALREADY_INITIALIZED\\\");\\n require(\\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n fantomSender = _fantomSender;\\n redeemableUSDC = _redeemableUSDC;\\n redeemableFLOW = _redeemableFLOW;\\n leftoverFLOW = _redeemableFLOW;\\n\\n emit Initialized(fantomSender, redeemableUSDC, redeemableFLOW);\\n }\\n\\n function setTeam(address _team) external onlyTeam {\\n team = _team;\\n }\\n\\n function previewRedeem(uint256 amountWEVE)\\n public\\n view\\n returns (uint256 shareOfUSDC, uint256 shareOfFLOW)\\n {\\n // pro rata USDC\\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\\n // pro rata FLOW\\n shareOfFLOW = (amountWEVE * redeemableFLOW) / ELIGIBLE_WEVE;\\n }\\n\\n function lzReceive(\\n uint16 srcChainId,\\n bytes memory srcAddress,\\n uint64,\\n bytes memory payload\\n ) external override {\\n require(fantomSender != address(0), \\\"NOT_INITIALIZED\\\");\\n require(\\n msg.sender == endpoint &&\\n srcChainId == fantomChainId &&\\n addressFromPackedBytes(srcAddress) == fantomSender,\\n \\\"UNAUTHORIZED_CALLER\\\"\\n );\\n\\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\\n payload,\\n (address, uint256)\\n );\\n\\n require(\\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\\n \\\"cannot redeem more than eligible\\\"\\n );\\n (uint256 shareOfUSDC, uint256 shareOfFLOW) = previewRedeem(amountWEVE);\\n\\n require(\\n USDC.transfer(redemptionAddress, shareOfUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n leftoverFLOW -= shareOfFLOW; // this will revert if underflows\\n require(\\n FLOW.claim(redemptionAddress, shareOfFLOW),\\n \\\"CLAIM_FAILED\\\"\\n );\\n }\\n\\n function addressFromPackedBytes(bytes memory toAddressBytes)\\n public\\n pure\\n returns (address toAddress)\\n {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n toAddress := mload(add(toAddressBytes, 20))\\n }\\n }\\n\\n function claimLeftovers() external onlyTeam {\\n require(block.timestamp >= deployed + 30 days, \\\"LEFTOVERS_NOT_CLAIMABLE\\\");\\n require(\\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n }\\n}\\n\",\"keccak256\":\"0x582d45a8db937fe4a965056bcbe7d1427f71be66e8071bb1cae76d5f36c6c314\",\"license\":\"MIT\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\nimport \\\"./ILayerZeroUserApplicationConfig.sol\\\";\\n\\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\\n // @param _dstChainId - the destination chain identifier\\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\\n // @param _payload - a custom bytes payload to send to the destination contract\\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\\n\\n // @notice used by the messaging library to publish verified payload\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source contract (as bytes) at the source chain\\n // @param _dstAddress - the address on destination chain\\n // @param _nonce - the unbound message ordering nonce\\n // @param _gasLimit - the gas limit for external contract execution\\n // @param _payload - verified payload to send to the destination contract\\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\\n\\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\\n\\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\\n // @param _srcAddress - the source chain contract address\\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\\n\\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\\n // @param _dstChainId - the destination chain identifier\\n // @param _userApplication - the user app address on this EVM chain\\n // @param _payload - the custom message to send over LayerZero\\n // @param _payInZRO - if false, user app pays the protocol fee in native token\\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\\n\\n // @notice get this Endpoint's immutable source identifier\\n function getChainId() external view returns (uint16);\\n\\n // @notice the interface to retry failed message on this Endpoint destination\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n // @param _payload - the payload to be retried\\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\\n\\n // @notice query if any STORED payload (message blocking) at the endpoint.\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\\n\\n // @notice query if the _libraryAddress is valid for sending msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getSendLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the _libraryAddress is valid for receiving msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the non-reentrancy guard for send() is on\\n // @return true if the guard is on. false otherwise\\n function isSendingPayload() external view returns (bool);\\n\\n // @notice query if the non-reentrancy guard for receive() is on\\n // @return true if the guard is on. false otherwise\\n function isReceivingPayload() external view returns (bool);\\n\\n // @notice get the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _userApplication - the contract address of the user application\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\\n\\n // @notice get the send() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getSendVersion(address _userApplication) external view returns (uint16);\\n\\n // @notice get the lzReceive() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getReceiveVersion(address _userApplication) external view returns (uint16);\\n}\\n\",\"keccak256\":\"0xbc2e0022d4d53d136830aa90037be2ed7a0966f5fd1b409bf5986185984c495f\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroReceiver {\\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\\n // @param _srcChainId - the source endpoint identifier\\n // @param _srcAddress - the source sending contract address from the source chain\\n // @param _nonce - the ordered message nonce\\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\\n}\\n\",\"keccak256\":\"0xd1617e455d90d41556bba636bc440627d301ec481de16ff04fbd520333c3c6f3\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroUserApplicationConfig {\\n // @notice set the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n // @param _config - configuration in the bytes. can encode arbitrary content.\\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\\n\\n // @notice set the send() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setSendVersion(uint16 _version) external;\\n\\n // @notice set the lzReceive() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setReceiveVersion(uint16 _version) external;\\n\\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\\n // @param _srcChainId - the chainId of the source chain\\n // @param _srcAddress - the contract address of the source contract at the source chain\\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\\n}\\n\",\"keccak256\":\"0xdc7e072cf3064081a8edf4a286ca43ddecc24330f2923d96f416f9d3f6538447\",\"license\":\"BUSL-1.1\"}},\"version\":1}", - "bytecode": "0x61012060405234801561001157600080fd5b50604051610f81380380610f81833981016040819052610030916100e2565b8161ffff16600c148061004857508161ffff1661271c145b61008b5760405162461bcd60e51b815260206004820152601060248201526f434841494e5f49445f4e4f545f46544d60801b604482015260640160405180910390fd5b6001600160a01b0393841660805291831660a05261ffff1660c0521660e052600080546001600160a01b03191633179055426101005261013f565b80516001600160a01b03811681146100dd57600080fd5b919050565b600080600080608085870312156100f857600080fd5b610101856100c6565b935061010f602086016100c6565b9250604085015161ffff8116811461012657600080fd5b9150610134606086016100c6565b905092959194509250565b60805160a05160c05160e05161010051610dcd6101b4600039600081816102d601526108c00152600081816101d30152610352015260008181610263015261037c015260008181610163015261059f01526000818161023c015281816104d70152818161078e015261094c0152610dcd6000f3fe608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a408bb4c11610071578063a408bb4c14610298578063aaa8f2ef146102a0578063b8ea6281146102b3578063caccb667146102c8578063f905c15a146102d157600080fd5b80636bfd23a71461021b57806385f2aef21461022457806389a3027114610237578063997a03b71461025e57600080fd5b806347db1a6a116100e957806347db1a6a1461019d5780634cdad506146101a65780635e280f11146101ce57806363b4eb8d146101f557806368ecc6bc1461020857600080fd5b80621d35671461011a578063095cf5c61461012f5780631308db08146101425780633189097b1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60055481565b6040519081526020015b60405180910390f35b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b61014b60035481565b6101b96101b4366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b600154610185906001600160a01b031681565b61012d610216366004610be5565b6106f3565b61014b60025481565b600054610185906001600160a01b031681565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6102857f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101856102c1366004610c1a565b6014015190565b61014b60045481565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea26469706673582212207b71c24b86331eb328782c3cff47b5a9ace7bd87e1419a0421a4319761d8270c64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a408bb4c11610071578063a408bb4c14610298578063aaa8f2ef146102a0578063b8ea6281146102b3578063caccb667146102c8578063f905c15a146102d157600080fd5b80636bfd23a71461021b57806385f2aef21461022457806389a3027114610237578063997a03b71461025e57600080fd5b806347db1a6a116100e957806347db1a6a1461019d5780634cdad506146101a65780635e280f11146101ce57806363b4eb8d146101f557806368ecc6bc1461020857600080fd5b80621d35671461011a578063095cf5c61461012f5780631308db08146101425780633189097b1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60055481565b6040519081526020015b60405180910390f35b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b61014b60035481565b6101b96101b4366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b600154610185906001600160a01b031681565b61012d610216366004610be5565b6106f3565b61014b60025481565b600054610185906001600160a01b031681565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6102857f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101856102c1366004610c1a565b6014015190565b61014b60045481565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea26469706673582212207b71c24b86331eb328782c3cff47b5a9ace7bd87e1419a0421a4319761d8270c64736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "d2a2160297444b93438826228d1e185d", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_usdc\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_flow\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"_fantomChainId\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"_endpoint\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fantomSender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableUSDC\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableFLOW\",\"type\":\"uint256\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ELIGIBLE_WEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FLOW\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"USDC\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"toAddressBytes\",\"type\":\"bytes\"}],\"name\":\"addressFromPackedBytes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimLeftovers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endpoint\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomChainId\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_fantomSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableFLOW\",\"type\":\"uint256\"}],\"name\":\"initializeReceiverWith\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"leftoverFLOW\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"srcChainId\",\"type\":\"uint16\"},{\"internalType\":\"bytes\",\"name\":\"srcAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"lzReceive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountWEVE\",\"type\":\"uint256\"}],\"name\":\"previewRedeem\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"shareOfUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shareOfFLOW\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableFLOW\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableUSDC\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemedWEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process This contract is responsible for receiving the LZ message and distributing USDC + FLOW\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/RedemptionReceiver.sol\":\"RedemptionReceiver\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/redeem/RedemptionReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\\\";\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\n\\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\\n/// This contract is responsible for receiving the LZ message and distributing USDC + FLOW\\ncontract RedemptionReceiver is ILayerZeroReceiver {\\n IERC20 public immutable USDC;\\n IFlow public immutable FLOW;\\n\\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\\n address public immutable endpoint;\\n\\n address public team;\\n uint256 public immutable deployed;\\n\\n address public fantomSender;\\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\\n uint256 public redeemedWEVE;\\n uint256 public redeemableUSDC;\\n uint256 public redeemableFLOW;\\n uint256 public leftoverFLOW;\\n\\n constructor(\\n address _usdc,\\n address _flow,\\n uint16 _fantomChainId,\\n address _endpoint\\n ) {\\n require(_fantomChainId == 12 || _fantomChainId == 10012, \\\"CHAIN_ID_NOT_FTM\\\");\\n\\n USDC = IERC20(_usdc);\\n FLOW = IFlow(_flow);\\n\\n fantomChainId = _fantomChainId;\\n endpoint = _endpoint;\\n\\n team = msg.sender;\\n deployed = block.timestamp;\\n }\\n\\n modifier onlyTeam() {\\n require(msg.sender == team, \\\"ONLY_TEAM\\\");\\n _;\\n }\\n\\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableFLOW);\\n\\n function initializeReceiverWith(\\n address _fantomSender,\\n uint256 _redeemableUSDC,\\n uint256 _redeemableFLOW\\n ) external onlyTeam {\\n require(fantomSender == address(0), \\\"ALREADY_INITIALIZED\\\");\\n require(\\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n fantomSender = _fantomSender;\\n redeemableUSDC = _redeemableUSDC;\\n redeemableFLOW = _redeemableFLOW;\\n leftoverFLOW = _redeemableFLOW;\\n\\n emit Initialized(fantomSender, redeemableUSDC, redeemableFLOW);\\n }\\n\\n function setTeam(address _team) external onlyTeam {\\n team = _team;\\n }\\n\\n function previewRedeem(uint256 amountWEVE)\\n public\\n view\\n returns (uint256 shareOfUSDC, uint256 shareOfFLOW)\\n {\\n // pro rata USDC\\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\\n // pro rata FLOW\\n shareOfFLOW = (amountWEVE * redeemableFLOW) / ELIGIBLE_WEVE;\\n }\\n\\n function lzReceive(\\n uint16 srcChainId,\\n bytes memory srcAddress,\\n uint64,\\n bytes memory payload\\n ) external override {\\n require(fantomSender != address(0), \\\"NOT_INITIALIZED\\\");\\n require(\\n msg.sender == endpoint &&\\n srcChainId == fantomChainId &&\\n addressFromPackedBytes(srcAddress) == fantomSender,\\n \\\"UNAUTHORIZED_CALLER\\\"\\n );\\n\\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\\n payload,\\n (address, uint256)\\n );\\n\\n require(\\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\\n \\\"cannot redeem more than eligible\\\"\\n );\\n (uint256 shareOfUSDC, uint256 shareOfFLOW) = previewRedeem(amountWEVE);\\n\\n require(\\n USDC.transfer(redemptionAddress, shareOfUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n leftoverFLOW -= shareOfFLOW; // this will revert if underflows\\n require(\\n FLOW.claim(redemptionAddress, shareOfFLOW),\\n \\\"CLAIM_FAILED\\\"\\n );\\n }\\n\\n function addressFromPackedBytes(bytes memory toAddressBytes)\\n public\\n pure\\n returns (address toAddress)\\n {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n toAddress := mload(add(toAddressBytes, 20))\\n }\\n }\\n\\n function claimLeftovers() external onlyTeam {\\n require(block.timestamp >= deployed + 30 days, \\\"LEFTOVERS_NOT_CLAIMABLE\\\");\\n require(\\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n }\\n}\\n\",\"keccak256\":\"0x582d45a8db937fe4a965056bcbe7d1427f71be66e8071bb1cae76d5f36c6c314\",\"license\":\"MIT\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\nimport \\\"./ILayerZeroUserApplicationConfig.sol\\\";\\n\\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\\n // @param _dstChainId - the destination chain identifier\\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\\n // @param _payload - a custom bytes payload to send to the destination contract\\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\\n\\n // @notice used by the messaging library to publish verified payload\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source contract (as bytes) at the source chain\\n // @param _dstAddress - the address on destination chain\\n // @param _nonce - the unbound message ordering nonce\\n // @param _gasLimit - the gas limit for external contract execution\\n // @param _payload - verified payload to send to the destination contract\\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\\n\\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\\n\\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\\n // @param _srcAddress - the source chain contract address\\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\\n\\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\\n // @param _dstChainId - the destination chain identifier\\n // @param _userApplication - the user app address on this EVM chain\\n // @param _payload - the custom message to send over LayerZero\\n // @param _payInZRO - if false, user app pays the protocol fee in native token\\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\\n\\n // @notice get this Endpoint's immutable source identifier\\n function getChainId() external view returns (uint16);\\n\\n // @notice the interface to retry failed message on this Endpoint destination\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n // @param _payload - the payload to be retried\\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\\n\\n // @notice query if any STORED payload (message blocking) at the endpoint.\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\\n\\n // @notice query if the _libraryAddress is valid for sending msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getSendLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the _libraryAddress is valid for receiving msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the non-reentrancy guard for send() is on\\n // @return true if the guard is on. false otherwise\\n function isSendingPayload() external view returns (bool);\\n\\n // @notice query if the non-reentrancy guard for receive() is on\\n // @return true if the guard is on. false otherwise\\n function isReceivingPayload() external view returns (bool);\\n\\n // @notice get the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _userApplication - the contract address of the user application\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\\n\\n // @notice get the send() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getSendVersion(address _userApplication) external view returns (uint16);\\n\\n // @notice get the lzReceive() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getReceiveVersion(address _userApplication) external view returns (uint16);\\n}\\n\",\"keccak256\":\"0xbc2e0022d4d53d136830aa90037be2ed7a0966f5fd1b409bf5986185984c495f\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroReceiver {\\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\\n // @param _srcChainId - the source endpoint identifier\\n // @param _srcAddress - the source sending contract address from the source chain\\n // @param _nonce - the ordered message nonce\\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\\n}\\n\",\"keccak256\":\"0xd1617e455d90d41556bba636bc440627d301ec481de16ff04fbd520333c3c6f3\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroUserApplicationConfig {\\n // @notice set the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n // @param _config - configuration in the bytes. can encode arbitrary content.\\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\\n\\n // @notice set the send() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setSendVersion(uint16 _version) external;\\n\\n // @notice set the lzReceive() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setReceiveVersion(uint16 _version) external;\\n\\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\\n // @param _srcChainId - the chainId of the source chain\\n // @param _srcAddress - the contract address of the source contract at the source chain\\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\\n}\\n\",\"keccak256\":\"0xdc7e072cf3064081a8edf4a286ca43ddecc24330f2923d96f416f9d3f6538447\",\"license\":\"BUSL-1.1\"}},\"version\":1}", + "bytecode": "0x61012060405234801561001157600080fd5b50604051610f81380380610f81833981016040819052610030916100e2565b8161ffff16600c148061004857508161ffff1661271c145b61008b5760405162461bcd60e51b815260206004820152601060248201526f434841494e5f49445f4e4f545f46544d60801b604482015260640160405180910390fd5b6001600160a01b0393841660805291831660a05261ffff1660c0521660e052600080546001600160a01b03191633179055426101005261013f565b80516001600160a01b03811681146100dd57600080fd5b919050565b600080600080608085870312156100f857600080fd5b610101856100c6565b935061010f602086016100c6565b9250604085015161ffff8116811461012657600080fd5b9150610134606086016100c6565b905092959194509250565b60805160a05160c05160e05161010051610dcd6101b4600039600081816102d601526108c00152600081816101d30152610352015260008181610263015261037c015260008181610163015261059f01526000818161023c015281816104d70152818161078e015261094c0152610dcd6000f3fe608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a408bb4c11610071578063a408bb4c14610298578063aaa8f2ef146102a0578063b8ea6281146102b3578063caccb667146102c8578063f905c15a146102d157600080fd5b80636bfd23a71461021b57806385f2aef21461022457806389a3027114610237578063997a03b71461025e57600080fd5b806347db1a6a116100e957806347db1a6a1461019d5780634cdad506146101a65780635e280f11146101ce57806363b4eb8d146101f557806368ecc6bc1461020857600080fd5b80621d35671461011a578063095cf5c61461012f5780631308db08146101425780633189097b1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60055481565b6040519081526020015b60405180910390f35b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b61014b60035481565b6101b96101b4366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b600154610185906001600160a01b031681565b61012d610216366004610be5565b6106f3565b61014b60025481565b600054610185906001600160a01b031681565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6102857f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101856102c1366004610c1a565b6014015190565b61014b60045481565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea2646970667358221220a9aafa04aaa7657df3b5764d57c3e104f4a4dc11cc4b9091c82503073c559cb264736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a408bb4c11610071578063a408bb4c14610298578063aaa8f2ef146102a0578063b8ea6281146102b3578063caccb667146102c8578063f905c15a146102d157600080fd5b80636bfd23a71461021b57806385f2aef21461022457806389a3027114610237578063997a03b71461025e57600080fd5b806347db1a6a116100e957806347db1a6a1461019d5780634cdad506146101a65780635e280f11146101ce57806363b4eb8d146101f557806368ecc6bc1461020857600080fd5b80621d35671461011a578063095cf5c61461012f5780631308db08146101425780633189097b1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60055481565b6040519081526020015b60405180910390f35b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b61014b60035481565b6101b96101b4366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b600154610185906001600160a01b031681565b61012d610216366004610be5565b6106f3565b61014b60025481565b600054610185906001600160a01b031681565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6102857f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101856102c1366004610c1a565b6014015190565b61014b60045481565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea2646970667358221220a9aafa04aaa7657df3b5764d57c3e104f4a4dc11cc4b9091c82503073c559cb264736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/RewardsDistributor.json b/deployments/arbitrumGoerli/RewardsDistributor.json index c929eecf..f936ce33 100644 --- a/deployments/arbitrumGoerli/RewardsDistributor.json +++ b/deployments/arbitrumGoerli/RewardsDistributor.json @@ -1,5 +1,5 @@ { - "address": "0xd06A463fD49720629A285E3C8De4310bc103df0a", + "address": "0xCf24b553f519916664533A862AB100FF8185a0c8", "abi": [ { "inputs": [ @@ -351,45 +351,45 @@ "type": "function" } ], - "transactionHash": "0x27c5e1e464a8506a9d266b0632cf37d05f43b0f3a1ebe2adc653e8e0051168bf", + "transactionHash": "0x75066d42d182dea37155901963c580184fcb3e0e902b517cc222b5c4b6ab3a23", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xd06A463fD49720629A285E3C8De4310bc103df0a", + "contractAddress": "0xCf24b553f519916664533A862AB100FF8185a0c8", "transactionIndex": 1, "gasUsed": "1623336", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000080000000020000000000000000000000000000000000000000000000040200000000000002000000000000000000000000000000000000000000020000000000000000000000000000008000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000010000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x524168c7b377927743d8fe0de27e415ee684f569cbe9134c6c42828e382244f4", - "transactionHash": "0x27c5e1e464a8506a9d266b0632cf37d05f43b0f3a1ebe2adc653e8e0051168bf", + "logsBloom": "0x00000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000080000020000000000000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000010000000000040000000000000000000000000000000000000000000000000", + "blockHash": "0x9a71f97bc8bed760d25373911577b73bacdf3ed08c9344833c324f1b56183fc4", + "transactionHash": "0x75066d42d182dea37155901963c580184fcb3e0e902b517cc222b5c4b6ab3a23", "logs": [ { "transactionIndex": 1, - "blockNumber": 5849223, - "transactionHash": "0x27c5e1e464a8506a9d266b0632cf37d05f43b0f3a1ebe2adc653e8e0051168bf", - "address": "0x0432f39386A9B1d0339c8Ba0af617b16C86ADA05", + "blockNumber": 6069419, + "transactionHash": "0x75066d42d182dea37155901963c580184fcb3e0e902b517cc222b5c4b6ab3a23", + "address": "0x4E13914872BFf7e58f3E231b2687fDd084014999", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000d06a463fd49720629a285e3c8de4310bc103df0a", - "0x000000000000000000000000f003091b78974ee3f99ec70fc5f42fc9810664ec" + "0x000000000000000000000000cf24b553f519916664533a862ab100ff8185a0c8", + "0x0000000000000000000000006d55afbf1caf01e0bca5255bba730da6fafd0af4" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "logIndex": 0, - "blockHash": "0x524168c7b377927743d8fe0de27e415ee684f569cbe9134c6c42828e382244f4" + "blockHash": "0x9a71f97bc8bed760d25373911577b73bacdf3ed08c9344833c324f1b56183fc4" } ], - "blockNumber": 5849223, + "blockNumber": 6069419, "cumulativeGasUsed": "1623336", "status": 1, "byzantium": true }, "args": [ - "0xF003091B78974ee3F99ec70fC5F42fc9810664EC" + "0x6d55AFbF1cAf01E0bcA5255bbA730da6fAFD0aF4" ], - "numDeployments": 3, - "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voting_escrow\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"time\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"CheckpointToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"claim_epoch\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"max_epoch\",\"type\":\"uint256\"}],\"name\":\"Claimed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"checkpoint_token\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint_total_supply\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"_tokenIds\",\"type\":\"uint256[]\"}],\"name\":\"claim_many\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_token_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"}],\"name\":\"setDepositor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"start_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"time_cursor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"time_cursor_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token_last_balance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"tokens_per_week\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_epoch_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"ve_for_at\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ve_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voting_escrow\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RewardsDistributor.sol\":\"RewardsDistributor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/*\\n\\n@title Curve Fee Distribution modified for ve(3,3) emissions\\n@author Curve Finance, andrecronje\\n@license MIT\\n\\n*/\\n\\ncontract RewardsDistributor is IRewardsDistributor {\\n event CheckpointToken(uint256 time, uint256 tokens);\\n\\n event Claimed(\\n uint256 tokenId,\\n uint256 amount,\\n uint256 claim_epoch,\\n uint256 max_epoch\\n );\\n\\n uint256 constant WEEK = 7 * 86400;\\n\\n uint256 public start_time;\\n uint256 public time_cursor;\\n mapping(uint256 => uint256) public time_cursor_of;\\n mapping(uint256 => uint256) public user_epoch_of;\\n\\n uint256 public last_token_time;\\n uint256[1000000000000000] public tokens_per_week;\\n\\n address public voting_escrow;\\n address public token;\\n uint256 public token_last_balance;\\n\\n uint256[1000000000000000] public ve_supply;\\n\\n address public depositor;\\n\\n constructor(address _voting_escrow) {\\n uint256 _t = (block.timestamp / WEEK) * WEEK;\\n start_time = _t;\\n last_token_time = _t;\\n time_cursor = _t;\\n address _token = IVotingEscrow(_voting_escrow).token();\\n token = _token;\\n voting_escrow = _voting_escrow;\\n depositor = msg.sender;\\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\\n }\\n\\n function timestamp() external view returns (uint256) {\\n return (block.timestamp / WEEK) * WEEK;\\n }\\n\\n function _checkpoint_token() internal {\\n uint256 token_balance = IERC20(token).balanceOf(address(this));\\n uint256 to_distribute = token_balance - token_last_balance;\\n token_last_balance = token_balance;\\n\\n uint256 t = last_token_time;\\n uint256 since_last = block.timestamp - t;\\n last_token_time = block.timestamp;\\n uint256 this_week = (t / WEEK) * WEEK;\\n uint256 next_week = 0;\\n\\n for (uint256 i = 0; i < 20; i++) {\\n next_week = this_week + WEEK;\\n if (block.timestamp < next_week) {\\n if (since_last == 0 && block.timestamp == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (block.timestamp - t)) /\\n since_last;\\n }\\n break;\\n } else {\\n if (since_last == 0 && next_week == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (next_week - t)) /\\n since_last;\\n }\\n }\\n t = next_week;\\n this_week = next_week;\\n }\\n emit CheckpointToken(block.timestamp, to_distribute);\\n }\\n\\n function checkpoint_token() external {\\n assert(msg.sender == depositor);\\n _checkpoint_token();\\n }\\n\\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\\n internal\\n view\\n returns (uint256)\\n {\\n uint256 _min = 0;\\n uint256 _max = IVotingEscrow(ve).epoch();\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n _mid\\n );\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function _find_timestamp_user_epoch(\\n address ve,\\n uint256 tokenId,\\n uint256 _timestamp,\\n uint256 max_user_epoch\\n ) internal view returns (uint256) {\\n uint256 _min = 0;\\n uint256 _max = max_user_epoch;\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\\n .user_point_history(tokenId, _mid);\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\\n external\\n view\\n returns (uint256)\\n {\\n address ve = voting_escrow;\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _timestamp,\\n max_user_epoch\\n );\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n epoch\\n );\\n return\\n MathDunks.max(\\n uint256(\\n int256(\\n pt.bias -\\n pt.slope *\\n (int128(int256(_timestamp - pt.ts)))\\n )\\n ),\\n 0\\n );\\n }\\n\\n function _checkpoint_total_supply() internal {\\n address ve = voting_escrow;\\n uint256 t = time_cursor;\\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\\n IVotingEscrow(ve).checkpoint();\\n\\n for (uint256 i = 0; i < 20; i++) {\\n if (t > rounded_timestamp) {\\n break;\\n } else {\\n uint256 epoch = _find_timestamp_epoch(ve, t);\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n epoch\\n );\\n int128 dt = 0;\\n if (t > pt.ts) {\\n dt = int128(int256(t - pt.ts));\\n }\\n ve_supply[t] = MathDunks.max(\\n uint256(int256(pt.bias - pt.slope * dt)),\\n 0\\n );\\n }\\n t += WEEK;\\n }\\n time_cursor = t;\\n }\\n\\n function checkpoint_total_supply() external {\\n _checkpoint_total_supply();\\n }\\n\\n function _claim(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\\n user_epoch_of[_tokenId] = user_epoch;\\n time_cursor_of[_tokenId] = week_cursor;\\n\\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\\n\\n return to_distribute;\\n }\\n\\n function _claimable(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal view returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n return to_distribute;\\n }\\n\\n function claimable(uint256 _tokenId) external view returns (uint256) {\\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\\n return _claimable(_tokenId, voting_escrow, _last_token_time);\\n }\\n\\n function claim(uint256 _tokenId) external returns (uint256) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\\n token_last_balance -= amount;\\n }\\n return amount;\\n }\\n\\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n address _voting_escrow = voting_escrow;\\n uint256 total = 0;\\n\\n for (uint256 i = 0; i < _tokenIds.length; i++) {\\n uint256 _tokenId = _tokenIds[i];\\n if (_tokenId == 0) break;\\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\\n total += amount;\\n }\\n }\\n if (total != 0) {\\n token_last_balance -= total;\\n }\\n\\n return true;\\n }\\n\\n // Once off event on contract initialize\\n function setDepositor(address _depositor) external {\\n require(msg.sender == depositor);\\n depositor = _depositor;\\n }\\n}\\n\",\"keccak256\":\"0xc3e7c3c7944974ce250313d2794fbfa3a98786e2040c685dc250c71ff9002829\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b5060405162001b9f38038062001b9f83398101604081905262000034916200019f565b600062093a80620000468142620001d1565b620000529190620001f4565b90508060008190555080600481905550806001819055506000826001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000aa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d091906200019f565b66038d7ea4c6800680546001600160a01b038381166001600160a01b0319928316811790935566038d7ea4c6800580549188169183168217905566071afd498d00088054909216331790915560405163095ea7b360e01b8152600481019190915260001960248201529192509063095ea7b3906044016020604051808303816000875af115801562000166573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200018c919062000222565b6200019657600080fd5b50505062000246565b600060208284031215620001b257600080fd5b81516001600160a01b0381168114620001ca57600080fd5b9392505050565b600082620001ef57634e487b7160e01b600052601260045260246000fd5b500490565b60008160001904831182151516156200021d57634e487b7160e01b600052601160045260246000fd5b500290565b6000602082840312156200023557600080fd5b81518015158114620001ca57600080fd5b61194980620002566000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea2646970667358221220877c3a13c3ebfa895eaa531d7321700f88e3027df204bd9c0bbc82338f0c4de964736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea2646970667358221220877c3a13c3ebfa895eaa531d7321700f88e3027df204bd9c0bbc82338f0c4de964736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "d2a2160297444b93438826228d1e185d", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voting_escrow\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"time\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"CheckpointToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"claim_epoch\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"max_epoch\",\"type\":\"uint256\"}],\"name\":\"Claimed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"checkpoint_token\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint_total_supply\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"_tokenIds\",\"type\":\"uint256[]\"}],\"name\":\"claim_many\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_token_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"}],\"name\":\"setDepositor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"start_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"time_cursor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"time_cursor_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token_last_balance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"tokens_per_week\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_epoch_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"ve_for_at\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ve_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voting_escrow\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RewardsDistributor.sol\":\"RewardsDistributor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/*\\n\\n@title Curve Fee Distribution modified for ve(3,3) emissions\\n@author Curve Finance, andrecronje\\n@license MIT\\n\\n*/\\n\\ncontract RewardsDistributor is IRewardsDistributor {\\n event CheckpointToken(uint256 time, uint256 tokens);\\n\\n event Claimed(\\n uint256 tokenId,\\n uint256 amount,\\n uint256 claim_epoch,\\n uint256 max_epoch\\n );\\n\\n uint256 constant WEEK = 7 * 86400;\\n\\n uint256 public start_time;\\n uint256 public time_cursor;\\n mapping(uint256 => uint256) public time_cursor_of;\\n mapping(uint256 => uint256) public user_epoch_of;\\n\\n uint256 public last_token_time;\\n uint256[1000000000000000] public tokens_per_week;\\n\\n address public voting_escrow;\\n address public token;\\n uint256 public token_last_balance;\\n\\n uint256[1000000000000000] public ve_supply;\\n\\n address public depositor;\\n\\n constructor(address _voting_escrow) {\\n uint256 _t = (block.timestamp / WEEK) * WEEK;\\n start_time = _t;\\n last_token_time = _t;\\n time_cursor = _t;\\n address _token = IVotingEscrow(_voting_escrow).token();\\n token = _token;\\n voting_escrow = _voting_escrow;\\n depositor = msg.sender;\\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\\n }\\n\\n function timestamp() external view returns (uint256) {\\n return (block.timestamp / WEEK) * WEEK;\\n }\\n\\n function _checkpoint_token() internal {\\n uint256 token_balance = IERC20(token).balanceOf(address(this));\\n uint256 to_distribute = token_balance - token_last_balance;\\n token_last_balance = token_balance;\\n\\n uint256 t = last_token_time;\\n uint256 since_last = block.timestamp - t;\\n last_token_time = block.timestamp;\\n uint256 this_week = (t / WEEK) * WEEK;\\n uint256 next_week = 0;\\n\\n for (uint256 i = 0; i < 20; i++) {\\n next_week = this_week + WEEK;\\n if (block.timestamp < next_week) {\\n if (since_last == 0 && block.timestamp == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (block.timestamp - t)) /\\n since_last;\\n }\\n break;\\n } else {\\n if (since_last == 0 && next_week == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (next_week - t)) /\\n since_last;\\n }\\n }\\n t = next_week;\\n this_week = next_week;\\n }\\n emit CheckpointToken(block.timestamp, to_distribute);\\n }\\n\\n function checkpoint_token() external {\\n assert(msg.sender == depositor);\\n _checkpoint_token();\\n }\\n\\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\\n internal\\n view\\n returns (uint256)\\n {\\n uint256 _min = 0;\\n uint256 _max = IVotingEscrow(ve).epoch();\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n _mid\\n );\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function _find_timestamp_user_epoch(\\n address ve,\\n uint256 tokenId,\\n uint256 _timestamp,\\n uint256 max_user_epoch\\n ) internal view returns (uint256) {\\n uint256 _min = 0;\\n uint256 _max = max_user_epoch;\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\\n .user_point_history(tokenId, _mid);\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\\n external\\n view\\n returns (uint256)\\n {\\n address ve = voting_escrow;\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _timestamp,\\n max_user_epoch\\n );\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n epoch\\n );\\n return\\n MathDunks.max(\\n uint256(\\n int256(\\n pt.bias -\\n pt.slope *\\n (int128(int256(_timestamp - pt.ts)))\\n )\\n ),\\n 0\\n );\\n }\\n\\n function _checkpoint_total_supply() internal {\\n address ve = voting_escrow;\\n uint256 t = time_cursor;\\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\\n IVotingEscrow(ve).checkpoint();\\n\\n for (uint256 i = 0; i < 20; i++) {\\n if (t > rounded_timestamp) {\\n break;\\n } else {\\n uint256 epoch = _find_timestamp_epoch(ve, t);\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n epoch\\n );\\n int128 dt = 0;\\n if (t > pt.ts) {\\n dt = int128(int256(t - pt.ts));\\n }\\n ve_supply[t] = MathDunks.max(\\n uint256(int256(pt.bias - pt.slope * dt)),\\n 0\\n );\\n }\\n t += WEEK;\\n }\\n time_cursor = t;\\n }\\n\\n function checkpoint_total_supply() external {\\n _checkpoint_total_supply();\\n }\\n\\n function _claim(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\\n user_epoch_of[_tokenId] = user_epoch;\\n time_cursor_of[_tokenId] = week_cursor;\\n\\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\\n\\n return to_distribute;\\n }\\n\\n function _claimable(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal view returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n return to_distribute;\\n }\\n\\n function claimable(uint256 _tokenId) external view returns (uint256) {\\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\\n return _claimable(_tokenId, voting_escrow, _last_token_time);\\n }\\n\\n function claim(uint256 _tokenId) external returns (uint256) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\\n token_last_balance -= amount;\\n }\\n return amount;\\n }\\n\\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n address _voting_escrow = voting_escrow;\\n uint256 total = 0;\\n\\n for (uint256 i = 0; i < _tokenIds.length; i++) {\\n uint256 _tokenId = _tokenIds[i];\\n if (_tokenId == 0) break;\\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\\n total += amount;\\n }\\n }\\n if (total != 0) {\\n token_last_balance -= total;\\n }\\n\\n return true;\\n }\\n\\n // Once off event on contract initialize\\n function setDepositor(address _depositor) external {\\n require(msg.sender == depositor);\\n depositor = _depositor;\\n }\\n}\\n\",\"keccak256\":\"0xc3e7c3c7944974ce250313d2794fbfa3a98786e2040c685dc250c71ff9002829\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b5060405162001b9f38038062001b9f83398101604081905262000034916200019f565b600062093a80620000468142620001d1565b620000529190620001f4565b90508060008190555080600481905550806001819055506000826001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000aa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d091906200019f565b66038d7ea4c6800680546001600160a01b038381166001600160a01b0319928316811790935566038d7ea4c6800580549188169183168217905566071afd498d00088054909216331790915560405163095ea7b360e01b8152600481019190915260001960248201529192509063095ea7b3906044016020604051808303816000875af115801562000166573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200018c919062000222565b6200019657600080fd5b50505062000246565b600060208284031215620001b257600080fd5b81516001600160a01b0381168114620001ca57600080fd5b9392505050565b600082620001ef57634e487b7160e01b600052601260045260246000fd5b500490565b60008160001904831182151516156200021d57634e487b7160e01b600052601160045260246000fd5b500290565b6000602082840312156200023557600080fd5b81518015158114620001ca57600080fd5b61194980620002566000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea26469706673582212204e4dafd337698280bf8dd6511ad20df90506619fef65a85df15dbb0da22eb0cf64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea26469706673582212204e4dafd337698280bf8dd6511ad20df90506619fef65a85df15dbb0da22eb0cf64736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/Router.json b/deployments/arbitrumGoerli/Router.json index ff838567..708e9018 100644 --- a/deployments/arbitrumGoerli/Router.json +++ b/deployments/arbitrumGoerli/Router.json @@ -1,5 +1,5 @@ { - "address": "0x7620a00A75f7fAE135A7236E79982A98Cfd120e1", + "address": "0x5E88C567F60466cdCA5c9C331090bBB7391fd70a", "abi": [ { "inputs": [ @@ -979,31 +979,31 @@ "type": "receive" } ], - "transactionHash": "0x6a363131580509010713673da815190937e2a41dd72858f82ae4b0ed6a27e9c6", + "transactionHash": "0xab7d722327422765de9bd74c97d5b2cbc7a184525a93f31d154e2677f1e78ea4", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x7620a00A75f7fAE135A7236E79982A98Cfd120e1", + "contractAddress": "0x5E88C567F60466cdCA5c9C331090bBB7391fd70a", "transactionIndex": 1, - "gasUsed": "3145971", + "gasUsed": "3145959", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x4ec5b790e5f67b0ad9c5f3bceb28bd1662399b685b9df03758668f55a983bcd2", - "transactionHash": "0x6a363131580509010713673da815190937e2a41dd72858f82ae4b0ed6a27e9c6", + "blockHash": "0xc714c1597f31846e6778667da3182aadf1a40233d8a2251dee00237bb2e5a0a6", + "transactionHash": "0xab7d722327422765de9bd74c97d5b2cbc7a184525a93f31d154e2677f1e78ea4", "logs": [], - "blockNumber": 5849176, - "cumulativeGasUsed": "3145971", + "blockNumber": 6069390, + "cumulativeGasUsed": "3145959", "status": 1, "byzantium": true }, "args": [ - "0x32bB8e83F877948Db847BDB6A8DB51d441324c1F", + "0x5c7C6ee91569E2658c3A52f47b35E1AAB7e8e600", "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1" ], - "numDeployments": 3, - "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_weth\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"UNSAFE_swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"}],\"name\":\"getAmountsOut\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reserveA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"pairFor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"}],\"name\":\"quoteAddLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"name\":\"quoteRemoveLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityETHWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"}],\"name\":\"sortTokens\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactETHForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForETH\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenFrom\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenTo\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokensSimple\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weth\",\"outputs\":[{\"internalType\":\"contract IWETH\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Router.sol\":\"Router\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Router.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairFactory.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\nimport \\\"contracts/interfaces/IWETH.sol\\\";\\n\\ncontract Router is IRouter {\\n struct route {\\n address from;\\n address to;\\n bool stable;\\n }\\n\\n address public immutable factory;\\n IWETH public immutable weth;\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n bytes32 immutable pairCodeHash;\\n\\n modifier ensure(uint256 deadline) {\\n require(deadline >= block.timestamp, \\\"Router: EXPIRED\\\");\\n _;\\n }\\n\\n constructor(address _factory, address _weth) {\\n factory = _factory;\\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\\n weth = IWETH(_weth);\\n }\\n\\n receive() external payable {\\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\\n }\\n\\n function sortTokens(address tokenA, address tokenB)\\n public\\n pure\\n returns (address token0, address token1)\\n {\\n require(tokenA != tokenB, \\\"Router: IDENTICAL_ADDRESSES\\\");\\n (token0, token1) = tokenA < tokenB\\n ? (tokenA, tokenB)\\n : (tokenB, tokenA);\\n require(token0 != address(0), \\\"Router: ZERO_ADDRESS\\\");\\n }\\n\\n // calculates the CREATE2 address for a pair without making any external calls\\n function pairFor(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (address pair) {\\n (address token0, address token1) = sortTokens(tokenA, tokenB);\\n pair = address(\\n uint160(\\n uint256(\\n keccak256(\\n abi.encodePacked(\\n hex\\\"ff\\\",\\n factory,\\n keccak256(abi.encodePacked(token0, token1, stable)),\\n pairCodeHash // init code hash\\n )\\n )\\n )\\n )\\n );\\n }\\n\\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\\n function quoteLiquidity(\\n uint256 amountA,\\n uint256 reserveA,\\n uint256 reserveB\\n ) internal pure returns (uint256 amountB) {\\n require(amountA > 0, \\\"Router: INSUFFICIENT_AMOUNT\\\");\\n require(reserveA > 0 && reserveB > 0, \\\"Router: INSUFFICIENT_LIQUIDITY\\\");\\n amountB = (amountA * reserveB) / reserveA;\\n }\\n\\n // fetches and sorts the reserves for a pair\\n function getReserves(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (uint256 reserveA, uint256 reserveB) {\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (uint256 reserve0, uint256 reserve1, ) = IPair(\\n pairFor(tokenA, tokenB, stable)\\n ).getReserves();\\n (reserveA, reserveB) = tokenA == token0\\n ? (reserve0, reserve1)\\n : (reserve1, reserve0);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n address tokenOut\\n ) external view returns (uint256 amount, bool stable) {\\n address pair = pairFor(tokenIn, tokenOut, true);\\n uint256 amountStable;\\n uint256 amountVolatile;\\n if (IPairFactory(factory).isPair(pair)) {\\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n pair = pairFor(tokenIn, tokenOut, false);\\n if (IPairFactory(factory).isPair(pair)) {\\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n return\\n amountStable > amountVolatile\\n ? (amountStable, true)\\n : (amountVolatile, false);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountsOut(uint256 amountIn, route[] memory routes)\\n public\\n view\\n returns (uint256[] memory amounts)\\n {\\n require(routes.length >= 1, \\\"Router: INVALID_PATH\\\");\\n amounts = new uint256[](routes.length + 1);\\n amounts[0] = amountIn;\\n for (uint256 i = 0; i < routes.length; i++) {\\n address pair = pairFor(\\n routes[i].from,\\n routes[i].to,\\n routes[i].stable\\n );\\n if (IPairFactory(factory).isPair(pair)) {\\n amounts[i + 1] = IPair(pair).getAmountOut(\\n amounts[i],\\n routes[i].from\\n );\\n }\\n }\\n }\\n\\n function isPair(address pair) external view returns (bool) {\\n return IPairFactory(factory).isPair(pair);\\n }\\n\\n function quoteAddLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired\\n )\\n external\\n view\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n (uint256 reserveA, uint256 reserveB) = (0, 0);\\n uint256 _totalSupply = 0;\\n if (_pair != address(0)) {\\n _totalSupply = IERC20(_pair).totalSupply();\\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\\n }\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n }\\n }\\n }\\n\\n function quoteRemoveLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity\\n ) external view returns (uint256 amountA, uint256 amountB) {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n\\n if (_pair == address(0)) {\\n return (0, 0);\\n }\\n\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n uint256 _totalSupply = IERC20(_pair).totalSupply();\\n\\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\\n }\\n\\n function _addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin\\n ) internal returns (uint256 amountA, uint256 amountB) {\\n require(amountADesired >= amountAMin);\\n require(amountBDesired >= amountBMin);\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n if (_pair == address(0)) {\\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\\n }\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n require(\\n amountBOptimal >= amountBMin,\\n \\\"Router: INSUFFICIENT_B_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n assert(amountAOptimal <= amountADesired);\\n require(\\n amountAOptimal >= amountAMin,\\n \\\"Router: INSUFFICIENT_A_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n }\\n }\\n }\\n\\n function addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n ensure(deadline)\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n (amountA, amountB) = _addLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n amountADesired,\\n amountBDesired,\\n amountAMin,\\n amountBMin\\n );\\n address pair = pairFor(tokenA, tokenB, stable);\\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\\n liquidity = IPair(pair).mint(to);\\n }\\n\\n function addLiquidityETH(\\n address token,\\n bool stable,\\n uint256 amountTokenDesired,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n payable\\n ensure(deadline)\\n returns (\\n uint256 amountToken,\\n uint256 amountETH,\\n uint256 liquidity\\n )\\n {\\n (amountToken, amountETH) = _addLiquidity(\\n token,\\n address(weth),\\n stable,\\n amountTokenDesired,\\n msg.value,\\n amountTokenMin,\\n amountETHMin\\n );\\n address pair = pairFor(token, address(weth), stable);\\n _safeTransferFrom(token, msg.sender, pair, amountToken);\\n weth.deposit{value: amountETH}();\\n assert(weth.transfer(pair, amountETH));\\n liquidity = IPair(pair).mint(to);\\n // refund dust eth, if any\\n if (msg.value > amountETH)\\n _safeTransferETH(msg.sender, msg.value - amountETH);\\n }\\n\\n // **** REMOVE LIQUIDITY ****\\n function removeLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (amountA, amountB) = tokenA == token0\\n ? (amount0, amount1)\\n : (amount1, amount0);\\n require(amountA >= amountAMin, \\\"Router: INSUFFICIENT_A_AMOUNT\\\");\\n require(amountB >= amountBMin, \\\"Router: INSUFFICIENT_B_AMOUNT\\\");\\n }\\n\\n function removeLiquidityETH(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\\n (amountToken, amountETH) = removeLiquidity(\\n token,\\n address(weth),\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n address(this),\\n deadline\\n );\\n _safeTransfer(token, to, amountToken);\\n weth.withdraw(amountETH);\\n _safeTransferETH(to, amountETH);\\n }\\n\\n function removeLiquidityWithPermit(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n {\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(\\n msg.sender,\\n address(this),\\n value,\\n deadline,\\n v,\\n r,\\n s\\n );\\n }\\n\\n (amountA, amountB) = removeLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n liquidity,\\n amountAMin,\\n amountBMin,\\n to,\\n deadline\\n );\\n }\\n\\n function removeLiquidityETHWithPermit(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountToken, uint256 amountETH) {\\n address pair = pairFor(token, address(weth), stable);\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\\n (amountToken, amountETH) = removeLiquidityETH(\\n token,\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n to,\\n deadline\\n );\\n }\\n\\n // **** SWAP ****\\n // requires the initial amount to have already been sent to the first pair\\n function _swap(\\n uint256[] memory amounts,\\n route[] memory routes,\\n address _to\\n ) internal virtual {\\n for (uint256 i = 0; i < routes.length; i++) {\\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\\n uint256 amountOut = amounts[i + 1];\\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\\n ? (uint256(0), amountOut)\\n : (amountOut, uint256(0));\\n address to = i < routes.length - 1\\n ? pairFor(\\n routes[i + 1].from,\\n routes[i + 1].to,\\n routes[i + 1].stable\\n )\\n : _to;\\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\\n amount0Out,\\n amount1Out,\\n to,\\n new bytes(0)\\n );\\n }\\n }\\n\\n function swapExactTokensForTokensSimple(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n address tokenFrom,\\n address tokenTo,\\n bool stable,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n route[] memory routes = new route[](1);\\n routes[0].from = tokenFrom;\\n routes[0].to = tokenTo;\\n routes[0].stable = stable;\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForTokens(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactETHForTokens(\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\\n require(routes[0].from == address(weth), \\\"Router: INVALID_PATH\\\");\\n amounts = getAmountsOut(msg.value, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n weth.deposit{value: amounts[0]}();\\n assert(\\n weth.transfer(\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n )\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForETH(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n require(\\n routes[routes.length - 1].to == address(weth),\\n \\\"Router: INVALID_PATH\\\"\\n );\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, address(this));\\n weth.withdraw(amounts[amounts.length - 1]);\\n _safeTransferETH(to, amounts[amounts.length - 1]);\\n }\\n\\n function UNSAFE_swapExactTokensForTokens(\\n uint256[] memory amounts,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory) {\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n return amounts;\\n }\\n\\n function _safeTransferETH(address to, uint256 value) internal {\\n (bool success, ) = to.call{value: value}(new bytes(0));\\n require(success, \\\"TransferHelper: ETH_TRANSFER_FAILED\\\");\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x3d84c846129d645eec66c37a493bb7fb401a2524497f450eaced155088305ead\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"},\"contracts/interfaces/IWETH.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n function transfer(address to, uint256 value) external returns (bool);\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0x20ad0b3a319a36e3430f0d8512ee3755de8f85a80effe78d06f333f5326ee3d7\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x60e06040523480156200001157600080fd5b50604051620039bc380380620039bc8339810160408190526200003491620000d8565b6001600160a01b038216608081905260408051631355724960e31b81529051639aab9248916004808201926020929091908290030181865afa1580156200007f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000a5919062000110565b60c0526001600160a01b031660a052506200012a565b80516001600160a01b0381168114620000d357600080fd5b919050565b60008060408385031215620000ec57600080fd5b620000f783620000bb565b91506200010760208401620000bb565b90509250929050565b6000602082840312156200012357600080fd5b5051919050565b60805160a05160c0516137c8620001f46000396000610ef901526000818161013e0152818161020b0152818161091901528181610b5801528181610da901528181611470015281816115830152818161161101528181611de901528181611e1f01528181611e5401528181611ee901528181612028015261207801526000818161042d01528181610c3e01528181610ebe015281816111770152818161128b0152818161199601528181611b0a01528181612115015281816126ff01526127a001526137c86000f3fe60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea264697066735822122090d96761dbb6e8825206a0750dfd27f72cd188ce3d6549fa2db5061a5beacc4464736f6c634300080d0033", - "deployedBytecode": "0x60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea264697066735822122090d96761dbb6e8825206a0750dfd27f72cd188ce3d6549fa2db5061a5beacc4464736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "d2a2160297444b93438826228d1e185d", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_weth\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"UNSAFE_swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"}],\"name\":\"getAmountsOut\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reserveA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"pairFor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"}],\"name\":\"quoteAddLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"name\":\"quoteRemoveLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityETHWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"}],\"name\":\"sortTokens\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactETHForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForETH\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenFrom\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenTo\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokensSimple\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weth\",\"outputs\":[{\"internalType\":\"contract IWETH\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Router.sol\":\"Router\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Router.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairFactory.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\nimport \\\"contracts/interfaces/IWETH.sol\\\";\\n\\ncontract Router is IRouter {\\n struct route {\\n address from;\\n address to;\\n bool stable;\\n }\\n\\n address public immutable factory;\\n IWETH public immutable weth;\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n bytes32 immutable pairCodeHash;\\n\\n modifier ensure(uint256 deadline) {\\n require(deadline >= block.timestamp, \\\"Router: EXPIRED\\\");\\n _;\\n }\\n\\n constructor(address _factory, address _weth) {\\n factory = _factory;\\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\\n weth = IWETH(_weth);\\n }\\n\\n receive() external payable {\\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\\n }\\n\\n function sortTokens(address tokenA, address tokenB)\\n public\\n pure\\n returns (address token0, address token1)\\n {\\n require(tokenA != tokenB, \\\"Router: IDENTICAL_ADDRESSES\\\");\\n (token0, token1) = tokenA < tokenB\\n ? (tokenA, tokenB)\\n : (tokenB, tokenA);\\n require(token0 != address(0), \\\"Router: ZERO_ADDRESS\\\");\\n }\\n\\n // calculates the CREATE2 address for a pair without making any external calls\\n function pairFor(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (address pair) {\\n (address token0, address token1) = sortTokens(tokenA, tokenB);\\n pair = address(\\n uint160(\\n uint256(\\n keccak256(\\n abi.encodePacked(\\n hex\\\"ff\\\",\\n factory,\\n keccak256(abi.encodePacked(token0, token1, stable)),\\n pairCodeHash // init code hash\\n )\\n )\\n )\\n )\\n );\\n }\\n\\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\\n function quoteLiquidity(\\n uint256 amountA,\\n uint256 reserveA,\\n uint256 reserveB\\n ) internal pure returns (uint256 amountB) {\\n require(amountA > 0, \\\"Router: INSUFFICIENT_AMOUNT\\\");\\n require(reserveA > 0 && reserveB > 0, \\\"Router: INSUFFICIENT_LIQUIDITY\\\");\\n amountB = (amountA * reserveB) / reserveA;\\n }\\n\\n // fetches and sorts the reserves for a pair\\n function getReserves(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (uint256 reserveA, uint256 reserveB) {\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (uint256 reserve0, uint256 reserve1, ) = IPair(\\n pairFor(tokenA, tokenB, stable)\\n ).getReserves();\\n (reserveA, reserveB) = tokenA == token0\\n ? (reserve0, reserve1)\\n : (reserve1, reserve0);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n address tokenOut\\n ) external view returns (uint256 amount, bool stable) {\\n address pair = pairFor(tokenIn, tokenOut, true);\\n uint256 amountStable;\\n uint256 amountVolatile;\\n if (IPairFactory(factory).isPair(pair)) {\\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n pair = pairFor(tokenIn, tokenOut, false);\\n if (IPairFactory(factory).isPair(pair)) {\\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n return\\n amountStable > amountVolatile\\n ? (amountStable, true)\\n : (amountVolatile, false);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountsOut(uint256 amountIn, route[] memory routes)\\n public\\n view\\n returns (uint256[] memory amounts)\\n {\\n require(routes.length >= 1, \\\"Router: INVALID_PATH\\\");\\n amounts = new uint256[](routes.length + 1);\\n amounts[0] = amountIn;\\n for (uint256 i = 0; i < routes.length; i++) {\\n address pair = pairFor(\\n routes[i].from,\\n routes[i].to,\\n routes[i].stable\\n );\\n if (IPairFactory(factory).isPair(pair)) {\\n amounts[i + 1] = IPair(pair).getAmountOut(\\n amounts[i],\\n routes[i].from\\n );\\n }\\n }\\n }\\n\\n function isPair(address pair) external view returns (bool) {\\n return IPairFactory(factory).isPair(pair);\\n }\\n\\n function quoteAddLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired\\n )\\n external\\n view\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n (uint256 reserveA, uint256 reserveB) = (0, 0);\\n uint256 _totalSupply = 0;\\n if (_pair != address(0)) {\\n _totalSupply = IERC20(_pair).totalSupply();\\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\\n }\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n }\\n }\\n }\\n\\n function quoteRemoveLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity\\n ) external view returns (uint256 amountA, uint256 amountB) {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n\\n if (_pair == address(0)) {\\n return (0, 0);\\n }\\n\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n uint256 _totalSupply = IERC20(_pair).totalSupply();\\n\\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\\n }\\n\\n function _addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin\\n ) internal returns (uint256 amountA, uint256 amountB) {\\n require(amountADesired >= amountAMin);\\n require(amountBDesired >= amountBMin);\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n if (_pair == address(0)) {\\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\\n }\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n require(\\n amountBOptimal >= amountBMin,\\n \\\"Router: INSUFFICIENT_B_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n assert(amountAOptimal <= amountADesired);\\n require(\\n amountAOptimal >= amountAMin,\\n \\\"Router: INSUFFICIENT_A_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n }\\n }\\n }\\n\\n function addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n ensure(deadline)\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n (amountA, amountB) = _addLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n amountADesired,\\n amountBDesired,\\n amountAMin,\\n amountBMin\\n );\\n address pair = pairFor(tokenA, tokenB, stable);\\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\\n liquidity = IPair(pair).mint(to);\\n }\\n\\n function addLiquidityETH(\\n address token,\\n bool stable,\\n uint256 amountTokenDesired,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n payable\\n ensure(deadline)\\n returns (\\n uint256 amountToken,\\n uint256 amountETH,\\n uint256 liquidity\\n )\\n {\\n (amountToken, amountETH) = _addLiquidity(\\n token,\\n address(weth),\\n stable,\\n amountTokenDesired,\\n msg.value,\\n amountTokenMin,\\n amountETHMin\\n );\\n address pair = pairFor(token, address(weth), stable);\\n _safeTransferFrom(token, msg.sender, pair, amountToken);\\n weth.deposit{value: amountETH}();\\n assert(weth.transfer(pair, amountETH));\\n liquidity = IPair(pair).mint(to);\\n // refund dust eth, if any\\n if (msg.value > amountETH)\\n _safeTransferETH(msg.sender, msg.value - amountETH);\\n }\\n\\n // **** REMOVE LIQUIDITY ****\\n function removeLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (amountA, amountB) = tokenA == token0\\n ? (amount0, amount1)\\n : (amount1, amount0);\\n require(amountA >= amountAMin, \\\"Router: INSUFFICIENT_A_AMOUNT\\\");\\n require(amountB >= amountBMin, \\\"Router: INSUFFICIENT_B_AMOUNT\\\");\\n }\\n\\n function removeLiquidityETH(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\\n (amountToken, amountETH) = removeLiquidity(\\n token,\\n address(weth),\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n address(this),\\n deadline\\n );\\n _safeTransfer(token, to, amountToken);\\n weth.withdraw(amountETH);\\n _safeTransferETH(to, amountETH);\\n }\\n\\n function removeLiquidityWithPermit(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n {\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(\\n msg.sender,\\n address(this),\\n value,\\n deadline,\\n v,\\n r,\\n s\\n );\\n }\\n\\n (amountA, amountB) = removeLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n liquidity,\\n amountAMin,\\n amountBMin,\\n to,\\n deadline\\n );\\n }\\n\\n function removeLiquidityETHWithPermit(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountToken, uint256 amountETH) {\\n address pair = pairFor(token, address(weth), stable);\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\\n (amountToken, amountETH) = removeLiquidityETH(\\n token,\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n to,\\n deadline\\n );\\n }\\n\\n // **** SWAP ****\\n // requires the initial amount to have already been sent to the first pair\\n function _swap(\\n uint256[] memory amounts,\\n route[] memory routes,\\n address _to\\n ) internal virtual {\\n for (uint256 i = 0; i < routes.length; i++) {\\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\\n uint256 amountOut = amounts[i + 1];\\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\\n ? (uint256(0), amountOut)\\n : (amountOut, uint256(0));\\n address to = i < routes.length - 1\\n ? pairFor(\\n routes[i + 1].from,\\n routes[i + 1].to,\\n routes[i + 1].stable\\n )\\n : _to;\\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\\n amount0Out,\\n amount1Out,\\n to,\\n new bytes(0)\\n );\\n }\\n }\\n\\n function swapExactTokensForTokensSimple(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n address tokenFrom,\\n address tokenTo,\\n bool stable,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n route[] memory routes = new route[](1);\\n routes[0].from = tokenFrom;\\n routes[0].to = tokenTo;\\n routes[0].stable = stable;\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForTokens(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactETHForTokens(\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\\n require(routes[0].from == address(weth), \\\"Router: INVALID_PATH\\\");\\n amounts = getAmountsOut(msg.value, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n weth.deposit{value: amounts[0]}();\\n assert(\\n weth.transfer(\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n )\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForETH(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n require(\\n routes[routes.length - 1].to == address(weth),\\n \\\"Router: INVALID_PATH\\\"\\n );\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, address(this));\\n weth.withdraw(amounts[amounts.length - 1]);\\n _safeTransferETH(to, amounts[amounts.length - 1]);\\n }\\n\\n function UNSAFE_swapExactTokensForTokens(\\n uint256[] memory amounts,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory) {\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n return amounts;\\n }\\n\\n function _safeTransferETH(address to, uint256 value) internal {\\n (bool success, ) = to.call{value: value}(new bytes(0));\\n require(success, \\\"TransferHelper: ETH_TRANSFER_FAILED\\\");\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x3d84c846129d645eec66c37a493bb7fb401a2524497f450eaced155088305ead\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"},\"contracts/interfaces/IWETH.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n function transfer(address to, uint256 value) external returns (bool);\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0x20ad0b3a319a36e3430f0d8512ee3755de8f85a80effe78d06f333f5326ee3d7\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x60e06040523480156200001157600080fd5b50604051620039bc380380620039bc8339810160408190526200003491620000d8565b6001600160a01b038216608081905260408051631355724960e31b81529051639aab9248916004808201926020929091908290030181865afa1580156200007f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000a5919062000110565b60c0526001600160a01b031660a052506200012a565b80516001600160a01b0381168114620000d357600080fd5b919050565b60008060408385031215620000ec57600080fd5b620000f783620000bb565b91506200010760208401620000bb565b90509250929050565b6000602082840312156200012357600080fd5b5051919050565b60805160a05160c0516137c8620001f46000396000610ef901526000818161013e0152818161020b0152818161091901528181610b5801528181610da901528181611470015281816115830152818161161101528181611de901528181611e1f01528181611e5401528181611ee901528181612028015261207801526000818161042d01528181610c3e01528181610ebe015281816111770152818161128b0152818161199601528181611b0a01528181612115015281816126ff01526127a001526137c86000f3fe60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea264697066735822122046a69c5fee9debde0f2e78a460c20964bd28cb71755b1fff51a930e4072f254664736f6c634300080d0033", + "deployedBytecode": "0x60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea264697066735822122046a69c5fee9debde0f2e78a460c20964bd28cb71755b1fff51a930e4072f254664736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/VeArtProxy.json b/deployments/arbitrumGoerli/VeArtProxy.json index ccc1185c..0d2f8b90 100644 --- a/deployments/arbitrumGoerli/VeArtProxy.json +++ b/deployments/arbitrumGoerli/VeArtProxy.json @@ -1,5 +1,5 @@ { - "address": "0x053238ccA3E4A334D97c424567C9Add44259cd18", + "address": "0x765df7268ed8Ecd71Cb4bcb70751771eD66c9131", "abi": [ { "inputs": [ @@ -36,28 +36,28 @@ "type": "function" } ], - "transactionHash": "0xa1ddf1f3ba03745972958eb09e0dff912cc5efa57b876052dcf64f7e54f32af0", + "transactionHash": "0xd4fa9113f47bad388342b1680bc672d0549aa6d397df52bca1d50616d8c2bf94", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x053238ccA3E4A334D97c424567C9Add44259cd18", + "contractAddress": "0x765df7268ed8Ecd71Cb4bcb70751771eD66c9131", "transactionIndex": 1, "gasUsed": "615440", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xcc29349c8ad111720e036eb710cd2fa2c9079ae1d8a862e98a3aba834e26803f", - "transactionHash": "0xa1ddf1f3ba03745972958eb09e0dff912cc5efa57b876052dcf64f7e54f32af0", + "blockHash": "0x48f98916092a1b24f6033f37fd39fbac17c697447e8995b63b023e8db14625e3", + "transactionHash": "0xd4fa9113f47bad388342b1680bc672d0549aa6d397df52bca1d50616d8c2bf94", "logs": [], - "blockNumber": 5849198, + "blockNumber": 6069402, "cumulativeGasUsed": "615440", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 3, - "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_locked_end\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"_tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"output\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VeArtProxy.sol\":\"VeArtProxy\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\nimport {Base64} from \\\"contracts/libraries/Base64.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\n\\ncontract VeArtProxy is IVeArtProxy {\\n function toString(uint value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT license\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint temp = value;\\n uint digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\\n output = '';\\n output = string(abi.encodePacked(output, \\\"token \\\", toString(_tokenId), ''));\\n output = string(abi.encodePacked(output, \\\"balanceOf \\\", toString(_balanceOf), ''));\\n output = string(abi.encodePacked(output, \\\"locked_end \\\", toString(_locked_end), ''));\\n output = string(abi.encodePacked(output, \\\"value \\\", toString(_value), ''));\\n\\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\\\"name\\\": \\\"lock #', toString(_tokenId), '\\\", \\\"description\\\": \\\"Velocimeter locks, can be used to boost gauge yields, vote on token emission, and receive bribes\\\", \\\"image\\\": \\\"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\\\"}'))));\\n output = string(abi.encodePacked('data:application/json;base64,', json));\\n }\\n}\\n\",\"keccak256\":\"0xc526ae7232c93412d664837d1171f1bf5d231a4ea33bcc7a8d0b4e3fa6a9e227\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/libraries/Base64.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n/// [MIT License]\\n/// @title Base64\\n/// @notice Provides a function for encoding some bytes in base64\\n/// @author Brecht Devos \\nlibrary Base64 {\\n bytes internal constant TABLE = \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\";\\n\\n /// @notice Encodes some bytes to the base64 representation\\n function encode(bytes memory data) internal pure returns (string memory) {\\n uint len = data.length;\\n if (len == 0) return \\\"\\\";\\n\\n // multiply by 4/3 rounded up\\n uint encodedLen = 4 * ((len + 2) / 3);\\n\\n // Add some extra buffer at the end\\n bytes memory result = new bytes(encodedLen + 32);\\n\\n bytes memory table = TABLE;\\n\\n assembly {\\n let tablePtr := add(table, 1)\\n let resultPtr := add(result, 32)\\n\\n for {\\n let i := 0\\n } lt(i, len) {\\n\\n } {\\n i := add(i, 3)\\n let input := and(mload(add(data, i)), 0xffffff)\\n\\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\\n out := shl(224, out)\\n\\n mstore(resultPtr, out)\\n\\n resultPtr := add(resultPtr, 4)\\n }\\n\\n switch mod(len, 3)\\n case 1 {\\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\\n }\\n case 2 {\\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\\n }\\n\\n mstore(result, encodedLen)\\n }\\n\\n return string(result);\\n }\\n}\\n\",\"keccak256\":\"0x55535e1e0a14bbac370fe5f25df23aa88c678b915af53517672130f9a54f7e3e\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50610a2b806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f63696d65746572206c6010918401918201527f6f636b732c2063616e206265207573656420746f20626f6f737420676175676560308201527f207969656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c60508201527f20616e64207265636569766520627269626573222c2022696d616765223a202260708201527f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000609082015283516107718160aa840160208801610435565b61227d60f01b60aa929091019182015260ac01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220e12e7c208efb5910624d3c73f85e2831968bd06a9ade7ff3b401f20786fbb8de64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f63696d65746572206c6010918401918201527f6f636b732c2063616e206265207573656420746f20626f6f737420676175676560308201527f207969656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c60508201527f20616e64207265636569766520627269626573222c2022696d616765223a202260708201527f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000609082015283516107718160aa840160208801610435565b61227d60f01b60aa929091019182015260ac01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220e12e7c208efb5910624d3c73f85e2831968bd06a9ade7ff3b401f20786fbb8de64736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "d2a2160297444b93438826228d1e185d", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_locked_end\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"_tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"output\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VeArtProxy.sol\":\"VeArtProxy\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\nimport {Base64} from \\\"contracts/libraries/Base64.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\n\\ncontract VeArtProxy is IVeArtProxy {\\n function toString(uint value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT license\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint temp = value;\\n uint digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\\n output = '';\\n output = string(abi.encodePacked(output, \\\"token \\\", toString(_tokenId), ''));\\n output = string(abi.encodePacked(output, \\\"balanceOf \\\", toString(_balanceOf), ''));\\n output = string(abi.encodePacked(output, \\\"locked_end \\\", toString(_locked_end), ''));\\n output = string(abi.encodePacked(output, \\\"value \\\", toString(_value), ''));\\n\\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\\\"name\\\": \\\"lock #', toString(_tokenId), '\\\", \\\"description\\\": \\\"Velocimeter locks, can be used to boost gauge yields, vote on token emission, and receive bribes\\\", \\\"image\\\": \\\"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\\\"}'))));\\n output = string(abi.encodePacked('data:application/json;base64,', json));\\n }\\n}\\n\",\"keccak256\":\"0xc526ae7232c93412d664837d1171f1bf5d231a4ea33bcc7a8d0b4e3fa6a9e227\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/libraries/Base64.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n/// [MIT License]\\n/// @title Base64\\n/// @notice Provides a function for encoding some bytes in base64\\n/// @author Brecht Devos \\nlibrary Base64 {\\n bytes internal constant TABLE = \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\";\\n\\n /// @notice Encodes some bytes to the base64 representation\\n function encode(bytes memory data) internal pure returns (string memory) {\\n uint len = data.length;\\n if (len == 0) return \\\"\\\";\\n\\n // multiply by 4/3 rounded up\\n uint encodedLen = 4 * ((len + 2) / 3);\\n\\n // Add some extra buffer at the end\\n bytes memory result = new bytes(encodedLen + 32);\\n\\n bytes memory table = TABLE;\\n\\n assembly {\\n let tablePtr := add(table, 1)\\n let resultPtr := add(result, 32)\\n\\n for {\\n let i := 0\\n } lt(i, len) {\\n\\n } {\\n i := add(i, 3)\\n let input := and(mload(add(data, i)), 0xffffff)\\n\\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\\n out := shl(224, out)\\n\\n mstore(resultPtr, out)\\n\\n resultPtr := add(resultPtr, 4)\\n }\\n\\n switch mod(len, 3)\\n case 1 {\\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\\n }\\n case 2 {\\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\\n }\\n\\n mstore(result, encodedLen)\\n }\\n\\n return string(result);\\n }\\n}\\n\",\"keccak256\":\"0x55535e1e0a14bbac370fe5f25df23aa88c678b915af53517672130f9a54f7e3e\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610a2b806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f63696d65746572206c6010918401918201527f6f636b732c2063616e206265207573656420746f20626f6f737420676175676560308201527f207969656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c60508201527f20616e64207265636569766520627269626573222c2022696d616765223a202260708201527f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000609082015283516107718160aa840160208801610435565b61227d60f01b60aa929091019182015260ac01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212200245977ba7ac6e458e61e7a78ff819f305af12f1712643deedef07226e96ec5b64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f63696d65746572206c6010918401918201527f6f636b732c2063616e206265207573656420746f20626f6f737420676175676560308201527f207969656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c60508201527f20616e64207265636569766520627269626573222c2022696d616765223a202260708201527f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000609082015283516107718160aa840160208801610435565b61227d60f01b60aa929091019182015260ac01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212200245977ba7ac6e458e61e7a78ff819f305af12f1712643deedef07226e96ec5b64736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/VelocimeterLibrary.json b/deployments/arbitrumGoerli/VelocimeterLibrary.json index 66038c4b..29d95353 100644 --- a/deployments/arbitrumGoerli/VelocimeterLibrary.json +++ b/deployments/arbitrumGoerli/VelocimeterLibrary.json @@ -1,5 +1,5 @@ { - "address": "0x142667449d5d6228a9Bd95A52749e3187235a91D", + "address": "0xB0983F8e787A6E8079F722925D81D2C784a52E9E", "abi": [ { "inputs": [ @@ -188,30 +188,30 @@ "type": "function" } ], - "transactionHash": "0x7c6da1ee94ad5cea5213f0141c5b07332199ef1ef219b2aede9969b5f4559cf9", + "transactionHash": "0xa00f5308ea82e068442ac690aab2e1276828215758ff85d72a042442ae06efe3", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x142667449d5d6228a9Bd95A52749e3187235a91D", + "contractAddress": "0xB0983F8e787A6E8079F722925D81D2C784a52E9E", "transactionIndex": 1, "gasUsed": "904028", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xae7b46c7446b0e1d5d86ff3ef4bb2859feac4b1277ded395b0fee98fe3a84778", - "transactionHash": "0x7c6da1ee94ad5cea5213f0141c5b07332199ef1ef219b2aede9969b5f4559cf9", + "blockHash": "0x9c90007e20856d7071d2e06612fcf775ab1e7d31722474d1b0ab38af7e7c14d2", + "transactionHash": "0xa00f5308ea82e068442ac690aab2e1276828215758ff85d72a042442ae06efe3", "logs": [], - "blockNumber": 5849185, + "blockNumber": 6069399, "cumulativeGasUsed": "904028", "status": 1, "byzantium": true }, "args": [ - "0x7620a00A75f7fAE135A7236E79982A98Cfd120e1" + "0x5E88C567F60466cdCA5c9C331090bBB7391fd70a" ], - "numDeployments": 3, - "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getMinimumValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getSample\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VelocimeterLibrary.sol\":\"VelocimeterLibrary\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VelocimeterLibrary.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\n\\ncontract VelocimeterLibrary {\\n IRouter internal immutable router;\\n\\n constructor(address _router) {\\n router = IRouter(_router);\\n }\\n\\n function _f(uint x0, uint y) internal pure returns (uint) {\\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\\n }\\n\\n function _d(uint x0, uint y) internal pure returns (uint) {\\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\\n }\\n\\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\\n for (uint i = 0; i < 255; i++) {\\n uint y_prev = y;\\n uint k = _f(x0, y);\\n if (k < xy) {\\n uint dy = (xy - k)*1e18/_d(x0, y);\\n y = y + dy;\\n } else {\\n uint dy = (k - xy)*1e18/_d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n }\\n\\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return (sample, r0, r1);\\n }\\n\\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\\n if (stable) {\\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\\n _reserve0 = _reserve0 * 1e18 / decimals0;\\n _reserve1 = _reserve1 * 1e18 / decimals1;\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\\n } else {\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n return amountIn * reserveB / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\\n if (stable) {\\n uint _x = x * 1e18 / decimals0;\\n uint _y = y * 1e18 / decimals1;\\n uint _a = (_x * _y) / 1e18;\\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return _a * _b / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n \\n}\\n\",\"keccak256\":\"0x8fa888fd7bda7d3d44a2cc0fd62aeb594c767907f24e7cd390a5fe998d60f388\",\"license\":\"MIT\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"}},\"version\":1}", - "bytecode": "0x60a060405234801561001057600080fd5b5060405161100238038061100283398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051610f626100a06000396000818161010c015281816102730152818161043701526105cb0152610f626000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea2646970667358221220c149725fc6d1c1832794d0b74e88c810171ce1f9cb66ae61e5c1d3478d59b4f064736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea2646970667358221220c149725fc6d1c1832794d0b74e88c810171ce1f9cb66ae61e5c1d3478d59b4f064736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "d2a2160297444b93438826228d1e185d", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getMinimumValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getSample\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VelocimeterLibrary.sol\":\"VelocimeterLibrary\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VelocimeterLibrary.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\n\\ncontract VelocimeterLibrary {\\n IRouter internal immutable router;\\n\\n constructor(address _router) {\\n router = IRouter(_router);\\n }\\n\\n function _f(uint x0, uint y) internal pure returns (uint) {\\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\\n }\\n\\n function _d(uint x0, uint y) internal pure returns (uint) {\\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\\n }\\n\\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\\n for (uint i = 0; i < 255; i++) {\\n uint y_prev = y;\\n uint k = _f(x0, y);\\n if (k < xy) {\\n uint dy = (xy - k)*1e18/_d(x0, y);\\n y = y + dy;\\n } else {\\n uint dy = (k - xy)*1e18/_d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n }\\n\\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return (sample, r0, r1);\\n }\\n\\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\\n if (stable) {\\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\\n _reserve0 = _reserve0 * 1e18 / decimals0;\\n _reserve1 = _reserve1 * 1e18 / decimals1;\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\\n } else {\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n return amountIn * reserveB / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\\n if (stable) {\\n uint _x = x * 1e18 / decimals0;\\n uint _y = y * 1e18 / decimals1;\\n uint _a = (_x * _y) / 1e18;\\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return _a * _b / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n \\n}\\n\",\"keccak256\":\"0x8fa888fd7bda7d3d44a2cc0fd62aeb594c767907f24e7cd390a5fe998d60f388\",\"license\":\"MIT\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"}},\"version\":1}", + "bytecode": "0x60a060405234801561001057600080fd5b5060405161100238038061100283398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051610f626100a06000396000818161010c015281816102730152818161043701526105cb0152610f626000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea2646970667358221220af3305b69464063ea72cd6f5a279509086a4a4891a18d5b72ebe271acc1e08d364736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea2646970667358221220af3305b69464063ea72cd6f5a279509086a4a4891a18d5b72ebe271acc1e08d364736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/Voter.json b/deployments/arbitrumGoerli/Voter.json index 5bc9be5d..413eeafe 100644 --- a/deployments/arbitrumGoerli/Voter.json +++ b/deployments/arbitrumGoerli/Voter.json @@ -1,5 +1,5 @@ { - "address": "0xe08A284C791c72E59C9020303b9B70E67bCf1d6C", + "address": "0x04c989FB4768739Fbd62FC1f77D06ae3c1E5eC36", "abi": [ { "inputs": [ @@ -1141,33 +1141,33 @@ "type": "function" } ], - "transactionHash": "0xcf999bcc29a80f8e010dd7a6cb465ea938e9f5f908506cd9dc563fc8f6c35212", + "transactionHash": "0x3dc77529d2eda4399520704a61c0b112dc589b5282a811c626de39141207eb9c", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xe08A284C791c72E59C9020303b9B70E67bCf1d6C", + "contractAddress": "0x04c989FB4768739Fbd62FC1f77D06ae3c1E5eC36", "transactionIndex": 1, - "gasUsed": "3013820", + "gasUsed": "3013796", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xe86d3d76185a541e47caa4c82a1e06e5dd9c4af11d3fb2c3fc02a1ee3e8f0ee1", - "transactionHash": "0xcf999bcc29a80f8e010dd7a6cb465ea938e9f5f908506cd9dc563fc8f6c35212", + "blockHash": "0xe4a31a974213d9527d10f75839c65c6d302673e5dc4312f1d1d03d136eb75598", + "transactionHash": "0x3dc77529d2eda4399520704a61c0b112dc589b5282a811c626de39141207eb9c", "logs": [], - "blockNumber": 5849232, - "cumulativeGasUsed": "3013820", + "blockNumber": 6069432, + "cumulativeGasUsed": "3013796", "status": 1, "byzantium": true }, "args": [ - "0xF003091B78974ee3F99ec70fC5F42fc9810664EC", - "0x32bB8e83F877948Db847BDB6A8DB51d441324c1F", - "0x596CAFB654c2281838b570F3801a8288b7B7bE8a", - "0x6e724702DfB7bCd31Af55852D67aa6A785aB85e6" + "0x6d55AFbF1cAf01E0bcA5255bbA730da6fAFD0aF4", + "0x5c7C6ee91569E2658c3A52f47b35E1AAB7e8e600", + "0xdEA300B2495790ccc75c6918A302E1952e9c2339", + "0x751B8A4792de90f5c774032f688bcAFA976b78d2" ], - "numDeployments": 3, - "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_gauges\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_bribes\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Abstained\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Attach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Detach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributeReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"internal_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"external_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"name\":\"GaugeCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeKilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeRevived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"reward\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NotifyReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Voted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"whitelister\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"Whitelisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"attachTokenToGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bribefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_bribes\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimBribes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_fees\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"}],\"name\":\"claimRewards\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"detachTokenFromGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"finish\",\"type\":\"uint256\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distributeFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distro\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"emergencyCouncil\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"external_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gaugefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"gauges\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_tokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"internal_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isAlive\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isGauge\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isWhitelisted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"killGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"lastVoted\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"length\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"notifyRewardAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"poke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolForGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"poolVote\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"reset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"reviveGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_council\",\"type\":\"address\"}],\"name\":\"setEmergencyCouncil\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"setGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalWeight\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"updateFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"name\":\"updateForRange\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"updateGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedWeights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"_poolVote\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_weights\",\"type\":\"uint256[]\"}],\"name\":\"vote\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"votes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"weights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"whitelist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Voter.sol\":\"Voter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Voter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/libraries/Math.sol';\\nimport 'contracts/interfaces/IBribe.sol';\\nimport 'contracts/interfaces/IBribeFactory.sol';\\nimport 'contracts/interfaces/IGauge.sol';\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/interfaces/IERC20.sol';\\nimport 'contracts/interfaces/IMinter.sol';\\nimport 'contracts/interfaces/IPair.sol';\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/interfaces/IVoter.sol';\\nimport 'contracts/interfaces/IVotingEscrow.sol';\\n\\ncontract Voter is IVoter {\\n\\n address public immutable _ve; // the ve token that governs these contracts\\n address public immutable factory; // the PairFactory\\n address internal immutable base;\\n address public immutable gaugefactory;\\n address public immutable bribefactory;\\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\\n address public minter;\\n address public governor; // should be set to an IGovernor\\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\\n\\n uint public totalWeight; // total voting weight\\n\\n address[] public pools; // all pools viable for incentives\\n mapping(address => address) public gauges; // pool => gauge\\n mapping(address => address) public poolForGauge; // gauge => pool\\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\\n mapping(address => uint256) public weights; // pool => weight\\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\\n mapping(uint => address[]) public poolVote; // nft => pools\\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\\n mapping(address => bool) public isGauge;\\n mapping(address => bool) public isWhitelisted;\\n mapping(address => bool) public isAlive;\\n\\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\\n event GaugeKilled(address indexed gauge);\\n event GaugeRevived(address indexed gauge);\\n event Voted(address indexed voter, uint tokenId, uint256 weight);\\n event Abstained(uint tokenId, uint256 weight);\\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\\n event Whitelisted(address indexed whitelister, address indexed token);\\n\\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\\n _ve = __ve;\\n factory = _factory;\\n base = IVotingEscrow(__ve).token();\\n gaugefactory = _gauges;\\n bribefactory = _bribes;\\n minter = msg.sender;\\n governor = msg.sender;\\n emergencyCouncil = msg.sender;\\n }\\n\\n // simple re-entrancy check\\n uint internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n modifier onlyNewEpoch(uint _tokenId) {\\n // ensure new epoch since last vote \\n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \\\"TOKEN_ALREADY_VOTED_THIS_EPOCH\\\");\\n _;\\n }\\n\\n function initialize(address[] memory _tokens, address _minter) external {\\n require(msg.sender == minter);\\n for (uint i = 0; i < _tokens.length; i++) {\\n _whitelist(_tokens[i]);\\n }\\n minter = _minter;\\n }\\n\\n function setGovernor(address _governor) public {\\n require(msg.sender == governor);\\n governor = _governor;\\n }\\n\\n function setEmergencyCouncil(address _council) public {\\n require(msg.sender == emergencyCouncil);\\n emergencyCouncil = _council;\\n }\\n\\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n lastVoted[_tokenId] = block.timestamp;\\n _reset(_tokenId);\\n IVotingEscrow(_ve).abstain(_tokenId);\\n }\\n\\n function _reset(uint _tokenId) internal {\\n address[] storage _poolVote = poolVote[_tokenId];\\n uint _poolVoteCnt = _poolVote.length;\\n uint256 _totalWeight = 0;\\n\\n for (uint i = 0; i < _poolVoteCnt; i ++) {\\n address _pool = _poolVote[i];\\n uint256 _votes = votes[_tokenId][_pool];\\n\\n if (_votes != 0) {\\n _updateFor(gauges[_pool]);\\n weights[_pool] -= _votes;\\n votes[_tokenId][_pool] -= _votes;\\n if (_votes > 0) {\\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n _totalWeight += _votes;\\n } else {\\n _totalWeight -= _votes;\\n }\\n emit Abstained(_tokenId, _votes);\\n }\\n }\\n totalWeight -= uint256(_totalWeight);\\n usedWeights[_tokenId] = 0;\\n delete poolVote[_tokenId];\\n }\\n\\n function poke(uint _tokenId) external {\\n address[] memory _poolVote = poolVote[_tokenId];\\n uint _poolCnt = _poolVote.length;\\n uint256[] memory _weights = new uint256[](_poolCnt);\\n\\n for (uint i = 0; i < _poolCnt; i ++) {\\n _weights[i] = votes[_tokenId][_poolVote[i]];\\n }\\n\\n _vote(_tokenId, _poolVote, _weights);\\n }\\n\\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\\n _reset(_tokenId);\\n uint _poolCnt = _poolVote.length;\\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\\n uint256 _totalVoteWeight = 0;\\n uint256 _totalWeight = 0;\\n uint256 _usedWeight = 0;\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n _totalVoteWeight += _weights[i];\\n }\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n address _pool = _poolVote[i];\\n address _gauge = gauges[_pool];\\n\\n if (isGauge[_gauge]) {\\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\\n require(votes[_tokenId][_pool] == 0);\\n require(_poolWeight != 0);\\n _updateFor(_gauge);\\n\\n poolVote[_tokenId].push(_pool);\\n\\n weights[_pool] += _poolWeight;\\n votes[_tokenId][_pool] += _poolWeight;\\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n _usedWeight += _poolWeight;\\n _totalWeight += _poolWeight;\\n emit Voted(msg.sender, _tokenId, _poolWeight);\\n }\\n }\\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\\n totalWeight += uint256(_totalWeight);\\n usedWeights[_tokenId] = uint256(_usedWeight);\\n }\\n\\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n require(_poolVote.length == _weights.length);\\n lastVoted[tokenId] = block.timestamp;\\n _vote(tokenId, _poolVote, _weights);\\n }\\n\\n function whitelist(address _token) public {\\n require(msg.sender == governor);\\n _whitelist(_token);\\n }\\n\\n function _whitelist(address _token) internal {\\n require(!isWhitelisted[_token]);\\n isWhitelisted[_token] = true;\\n emit Whitelisted(msg.sender, _token);\\n }\\n\\n function createGauge(address _pool) external returns (address) {\\n require(gauges[_pool] == address(0x0), \\\"exists\\\");\\n address[] memory allowedRewards = new address[](3);\\n address[] memory internalRewards = new address[](2);\\n bool isPair = IPairFactory(factory).isPair(_pool);\\n address tokenA;\\n address tokenB;\\n\\n if (isPair) {\\n (tokenA, tokenB) = IPair(_pool).tokens();\\n allowedRewards[0] = tokenA;\\n allowedRewards[1] = tokenB;\\n internalRewards[0] = tokenA;\\n internalRewards[1] = tokenB;\\n\\n if (base != tokenA && base != tokenB) {\\n allowedRewards[2] = base;\\n }\\n }\\n\\n if (msg.sender != governor) { // gov can create for any pool, even non-Velocimeter pairs\\n require(isPair, \\\"!_pool\\\");\\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \\\"!whitelisted\\\");\\n }\\n\\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\\n\\n IERC20(base).approve(_gauge, type(uint).max);\\n internal_bribes[_gauge] = _internal_bribe;\\n external_bribes[_gauge] = _external_bribe;\\n gauges[_pool] = _gauge;\\n poolForGauge[_gauge] = _pool;\\n isGauge[_gauge] = true;\\n isAlive[_gauge] = true;\\n _updateFor(_gauge);\\n pools.push(_pool);\\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\\n return _gauge;\\n }\\n\\n function killGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(isAlive[_gauge], \\\"gauge already dead\\\");\\n isAlive[_gauge] = false;\\n claimable[_gauge] = 0;\\n emit GaugeKilled(_gauge);\\n }\\n\\n function reviveGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(!isAlive[_gauge], \\\"gauge already alive\\\");\\n isAlive[_gauge] = true;\\n emit GaugeRevived(_gauge);\\n }\\n\\n function attachTokenToGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\\n emit Attach(account, msg.sender, tokenId);\\n }\\n\\n function emitDeposit(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]);\\n emit Deposit(account, msg.sender, tokenId, amount);\\n }\\n\\n function detachTokenFromGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\\n emit Detach(account, msg.sender, tokenId);\\n }\\n\\n function emitWithdraw(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n emit Withdraw(account, msg.sender, tokenId, amount);\\n }\\n\\n function length() external view returns (uint) {\\n return pools.length;\\n }\\n\\n uint internal index;\\n mapping(address => uint) internal supplyIndex;\\n mapping(address => uint) public claimable;\\n\\n function notifyRewardAmount(uint amount) external {\\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index += _ratio;\\n }\\n emit NotifyReward(msg.sender, base, amount);\\n }\\n\\n function updateFor(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n _updateFor(_gauges[i]);\\n }\\n }\\n\\n function updateForRange(uint start, uint end) public {\\n for (uint i = start; i < end; i++) {\\n _updateFor(gauges[pools[i]]);\\n }\\n }\\n\\n function updateAll() external {\\n updateForRange(0, pools.length);\\n }\\n\\n function updateGauge(address _gauge) external {\\n _updateFor(_gauge);\\n }\\n\\n function _updateFor(address _gauge) internal {\\n address _pool = poolForGauge[_gauge];\\n uint256 _supplied = weights[_pool];\\n if (_supplied > 0) {\\n uint _supplyIndex = supplyIndex[_gauge];\\n uint _index = index; // get global index0 for accumulated distro\\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\\n if (_delta > 0) {\\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\\n if (isAlive[_gauge]) {\\n claimable[_gauge] += _share;\\n }\\n }\\n } else {\\n supplyIndex[_gauge] = index; // new users are set to the default global state\\n }\\n }\\n\\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\\n }\\n }\\n\\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _bribes.length; i++) {\\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _fees.length; i++) {\\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function distributeFees(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n if (IGauge(_gauges[i]).isForPair()){\\n IGauge(_gauges[i]).claimFees();\\n }\\n }\\n }\\n\\n function distribute(address _gauge) public lock {\\n IMinter(minter).update_period();\\n _updateFor(_gauge); // should set claimable to 0 if killed\\n uint _claimable = claimable[_gauge];\\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\\n claimable[_gauge] = 0;\\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\\n emit DistributeReward(msg.sender, _gauge, _claimable);\\n }\\n }\\n\\n function distro() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute(uint start, uint finish) public {\\n for (uint x = start; x < finish; x++) {\\n distribute(gauges[pools[x]]);\\n }\\n }\\n\\n function distribute(address[] memory _gauges) external {\\n for (uint x = 0; x < _gauges.length; x++) {\\n distribute(_gauges[x]);\\n }\\n }\\n\\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x16f98751f0144d1758ecb2bec2062be56c718e18d65f0b948fd2a1404b37e6f8\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x61012060405260016011553480156200001757600080fd5b5060405162003656380380620036568339810160408190526200003a916200011c565b6001600160a01b03808516608081905290841660a05260408051637e062a3560e11b8152905163fc0c546a916004808201926020929091908290030181865afa1580156200008c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b2919062000179565b6001600160a01b0390811660c05291821660e0521661010052505060008054336001600160a01b03199182168117909255600180548216831790556002805490911690911790556200019e565b80516001600160a01b03811681146200011757600080fd5b919050565b600080600080608085870312156200013357600080fd5b6200013e85620000ff565b93506200014e60208601620000ff565b92506200015e60408601620000ff565b91506200016e60608601620000ff565b905092959194509250565b6000602082840312156200018c57600080fd5b6200019782620000ff565b9392505050565b60805160a05160c05160e051610100516133e062000276600039600081816103e701528181611c680152611ce60152600081816104d30152611d79015260008181610b9401528181610c0d01528181610edd01528181610f9901528181611acd01528181611b0601528181611b380152611e5a0152600081816106fc015261192401526000818161058c0152818161092b015281816109d701528181610c9a01528181611069015281816111ea0152818161131a015281816114d901528181611dab015281816125e501526129a801526133e06000f3fe608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea264697066735822122080dd20abddf540a84978cd8d25d18b280221a750a6a97ab6b2ae63e4f085c69a64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea264697066735822122080dd20abddf540a84978cd8d25d18b280221a750a6a97ab6b2ae63e4f085c69a64736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "d2a2160297444b93438826228d1e185d", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_gauges\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_bribes\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Abstained\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Attach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Detach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributeReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"internal_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"external_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"name\":\"GaugeCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeKilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeRevived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"reward\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NotifyReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Voted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"whitelister\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"Whitelisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"attachTokenToGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bribefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_bribes\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimBribes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_fees\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"}],\"name\":\"claimRewards\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"detachTokenFromGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"finish\",\"type\":\"uint256\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distributeFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distro\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"emergencyCouncil\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"external_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gaugefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"gauges\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_tokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"internal_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isAlive\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isGauge\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isWhitelisted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"killGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"lastVoted\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"length\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"notifyRewardAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"poke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolForGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"poolVote\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"reset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"reviveGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_council\",\"type\":\"address\"}],\"name\":\"setEmergencyCouncil\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"setGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalWeight\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"updateFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"name\":\"updateForRange\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"updateGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedWeights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"_poolVote\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_weights\",\"type\":\"uint256[]\"}],\"name\":\"vote\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"votes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"weights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"whitelist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Voter.sol\":\"Voter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Voter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/libraries/Math.sol';\\nimport 'contracts/interfaces/IBribe.sol';\\nimport 'contracts/interfaces/IBribeFactory.sol';\\nimport 'contracts/interfaces/IGauge.sol';\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/interfaces/IERC20.sol';\\nimport 'contracts/interfaces/IMinter.sol';\\nimport 'contracts/interfaces/IPair.sol';\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/interfaces/IVoter.sol';\\nimport 'contracts/interfaces/IVotingEscrow.sol';\\n\\ncontract Voter is IVoter {\\n\\n address public immutable _ve; // the ve token that governs these contracts\\n address public immutable factory; // the PairFactory\\n address internal immutable base;\\n address public immutable gaugefactory;\\n address public immutable bribefactory;\\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\\n address public minter;\\n address public governor; // should be set to an IGovernor\\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\\n\\n uint public totalWeight; // total voting weight\\n\\n address[] public pools; // all pools viable for incentives\\n mapping(address => address) public gauges; // pool => gauge\\n mapping(address => address) public poolForGauge; // gauge => pool\\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\\n mapping(address => uint256) public weights; // pool => weight\\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\\n mapping(uint => address[]) public poolVote; // nft => pools\\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\\n mapping(address => bool) public isGauge;\\n mapping(address => bool) public isWhitelisted;\\n mapping(address => bool) public isAlive;\\n\\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\\n event GaugeKilled(address indexed gauge);\\n event GaugeRevived(address indexed gauge);\\n event Voted(address indexed voter, uint tokenId, uint256 weight);\\n event Abstained(uint tokenId, uint256 weight);\\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\\n event Whitelisted(address indexed whitelister, address indexed token);\\n\\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\\n _ve = __ve;\\n factory = _factory;\\n base = IVotingEscrow(__ve).token();\\n gaugefactory = _gauges;\\n bribefactory = _bribes;\\n minter = msg.sender;\\n governor = msg.sender;\\n emergencyCouncil = msg.sender;\\n }\\n\\n // simple re-entrancy check\\n uint internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n modifier onlyNewEpoch(uint _tokenId) {\\n // ensure new epoch since last vote \\n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \\\"TOKEN_ALREADY_VOTED_THIS_EPOCH\\\");\\n _;\\n }\\n\\n function initialize(address[] memory _tokens, address _minter) external {\\n require(msg.sender == minter);\\n for (uint i = 0; i < _tokens.length; i++) {\\n _whitelist(_tokens[i]);\\n }\\n minter = _minter;\\n }\\n\\n function setGovernor(address _governor) public {\\n require(msg.sender == governor);\\n governor = _governor;\\n }\\n\\n function setEmergencyCouncil(address _council) public {\\n require(msg.sender == emergencyCouncil);\\n emergencyCouncil = _council;\\n }\\n\\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n lastVoted[_tokenId] = block.timestamp;\\n _reset(_tokenId);\\n IVotingEscrow(_ve).abstain(_tokenId);\\n }\\n\\n function _reset(uint _tokenId) internal {\\n address[] storage _poolVote = poolVote[_tokenId];\\n uint _poolVoteCnt = _poolVote.length;\\n uint256 _totalWeight = 0;\\n\\n for (uint i = 0; i < _poolVoteCnt; i ++) {\\n address _pool = _poolVote[i];\\n uint256 _votes = votes[_tokenId][_pool];\\n\\n if (_votes != 0) {\\n _updateFor(gauges[_pool]);\\n weights[_pool] -= _votes;\\n votes[_tokenId][_pool] -= _votes;\\n if (_votes > 0) {\\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n _totalWeight += _votes;\\n } else {\\n _totalWeight -= _votes;\\n }\\n emit Abstained(_tokenId, _votes);\\n }\\n }\\n totalWeight -= uint256(_totalWeight);\\n usedWeights[_tokenId] = 0;\\n delete poolVote[_tokenId];\\n }\\n\\n function poke(uint _tokenId) external {\\n address[] memory _poolVote = poolVote[_tokenId];\\n uint _poolCnt = _poolVote.length;\\n uint256[] memory _weights = new uint256[](_poolCnt);\\n\\n for (uint i = 0; i < _poolCnt; i ++) {\\n _weights[i] = votes[_tokenId][_poolVote[i]];\\n }\\n\\n _vote(_tokenId, _poolVote, _weights);\\n }\\n\\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\\n _reset(_tokenId);\\n uint _poolCnt = _poolVote.length;\\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\\n uint256 _totalVoteWeight = 0;\\n uint256 _totalWeight = 0;\\n uint256 _usedWeight = 0;\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n _totalVoteWeight += _weights[i];\\n }\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n address _pool = _poolVote[i];\\n address _gauge = gauges[_pool];\\n\\n if (isGauge[_gauge]) {\\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\\n require(votes[_tokenId][_pool] == 0);\\n require(_poolWeight != 0);\\n _updateFor(_gauge);\\n\\n poolVote[_tokenId].push(_pool);\\n\\n weights[_pool] += _poolWeight;\\n votes[_tokenId][_pool] += _poolWeight;\\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n _usedWeight += _poolWeight;\\n _totalWeight += _poolWeight;\\n emit Voted(msg.sender, _tokenId, _poolWeight);\\n }\\n }\\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\\n totalWeight += uint256(_totalWeight);\\n usedWeights[_tokenId] = uint256(_usedWeight);\\n }\\n\\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n require(_poolVote.length == _weights.length);\\n lastVoted[tokenId] = block.timestamp;\\n _vote(tokenId, _poolVote, _weights);\\n }\\n\\n function whitelist(address _token) public {\\n require(msg.sender == governor);\\n _whitelist(_token);\\n }\\n\\n function _whitelist(address _token) internal {\\n require(!isWhitelisted[_token]);\\n isWhitelisted[_token] = true;\\n emit Whitelisted(msg.sender, _token);\\n }\\n\\n function createGauge(address _pool) external returns (address) {\\n require(gauges[_pool] == address(0x0), \\\"exists\\\");\\n address[] memory allowedRewards = new address[](3);\\n address[] memory internalRewards = new address[](2);\\n bool isPair = IPairFactory(factory).isPair(_pool);\\n address tokenA;\\n address tokenB;\\n\\n if (isPair) {\\n (tokenA, tokenB) = IPair(_pool).tokens();\\n allowedRewards[0] = tokenA;\\n allowedRewards[1] = tokenB;\\n internalRewards[0] = tokenA;\\n internalRewards[1] = tokenB;\\n\\n if (base != tokenA && base != tokenB) {\\n allowedRewards[2] = base;\\n }\\n }\\n\\n if (msg.sender != governor) { // gov can create for any pool, even non-Velocimeter pairs\\n require(isPair, \\\"!_pool\\\");\\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \\\"!whitelisted\\\");\\n }\\n\\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\\n\\n IERC20(base).approve(_gauge, type(uint).max);\\n internal_bribes[_gauge] = _internal_bribe;\\n external_bribes[_gauge] = _external_bribe;\\n gauges[_pool] = _gauge;\\n poolForGauge[_gauge] = _pool;\\n isGauge[_gauge] = true;\\n isAlive[_gauge] = true;\\n _updateFor(_gauge);\\n pools.push(_pool);\\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\\n return _gauge;\\n }\\n\\n function killGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(isAlive[_gauge], \\\"gauge already dead\\\");\\n isAlive[_gauge] = false;\\n claimable[_gauge] = 0;\\n emit GaugeKilled(_gauge);\\n }\\n\\n function reviveGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(!isAlive[_gauge], \\\"gauge already alive\\\");\\n isAlive[_gauge] = true;\\n emit GaugeRevived(_gauge);\\n }\\n\\n function attachTokenToGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\\n emit Attach(account, msg.sender, tokenId);\\n }\\n\\n function emitDeposit(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]);\\n emit Deposit(account, msg.sender, tokenId, amount);\\n }\\n\\n function detachTokenFromGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\\n emit Detach(account, msg.sender, tokenId);\\n }\\n\\n function emitWithdraw(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n emit Withdraw(account, msg.sender, tokenId, amount);\\n }\\n\\n function length() external view returns (uint) {\\n return pools.length;\\n }\\n\\n uint internal index;\\n mapping(address => uint) internal supplyIndex;\\n mapping(address => uint) public claimable;\\n\\n function notifyRewardAmount(uint amount) external {\\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index += _ratio;\\n }\\n emit NotifyReward(msg.sender, base, amount);\\n }\\n\\n function updateFor(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n _updateFor(_gauges[i]);\\n }\\n }\\n\\n function updateForRange(uint start, uint end) public {\\n for (uint i = start; i < end; i++) {\\n _updateFor(gauges[pools[i]]);\\n }\\n }\\n\\n function updateAll() external {\\n updateForRange(0, pools.length);\\n }\\n\\n function updateGauge(address _gauge) external {\\n _updateFor(_gauge);\\n }\\n\\n function _updateFor(address _gauge) internal {\\n address _pool = poolForGauge[_gauge];\\n uint256 _supplied = weights[_pool];\\n if (_supplied > 0) {\\n uint _supplyIndex = supplyIndex[_gauge];\\n uint _index = index; // get global index0 for accumulated distro\\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\\n if (_delta > 0) {\\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\\n if (isAlive[_gauge]) {\\n claimable[_gauge] += _share;\\n }\\n }\\n } else {\\n supplyIndex[_gauge] = index; // new users are set to the default global state\\n }\\n }\\n\\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\\n }\\n }\\n\\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _bribes.length; i++) {\\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _fees.length; i++) {\\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function distributeFees(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n if (IGauge(_gauges[i]).isForPair()){\\n IGauge(_gauges[i]).claimFees();\\n }\\n }\\n }\\n\\n function distribute(address _gauge) public lock {\\n IMinter(minter).update_period();\\n _updateFor(_gauge); // should set claimable to 0 if killed\\n uint _claimable = claimable[_gauge];\\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\\n claimable[_gauge] = 0;\\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\\n emit DistributeReward(msg.sender, _gauge, _claimable);\\n }\\n }\\n\\n function distro() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute(uint start, uint finish) public {\\n for (uint x = start; x < finish; x++) {\\n distribute(gauges[pools[x]]);\\n }\\n }\\n\\n function distribute(address[] memory _gauges) external {\\n for (uint x = 0; x < _gauges.length; x++) {\\n distribute(_gauges[x]);\\n }\\n }\\n\\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x16f98751f0144d1758ecb2bec2062be56c718e18d65f0b948fd2a1404b37e6f8\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x61012060405260016011553480156200001757600080fd5b5060405162003656380380620036568339810160408190526200003a916200011c565b6001600160a01b03808516608081905290841660a05260408051637e062a3560e11b8152905163fc0c546a916004808201926020929091908290030181865afa1580156200008c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b2919062000179565b6001600160a01b0390811660c05291821660e0521661010052505060008054336001600160a01b03199182168117909255600180548216831790556002805490911690911790556200019e565b80516001600160a01b03811681146200011757600080fd5b919050565b600080600080608085870312156200013357600080fd5b6200013e85620000ff565b93506200014e60208601620000ff565b92506200015e60408601620000ff565b91506200016e60608601620000ff565b905092959194509250565b6000602082840312156200018c57600080fd5b6200019782620000ff565b9392505050565b60805160a05160c05160e051610100516133e062000276600039600081816103e701528181611c680152611ce60152600081816104d30152611d79015260008181610b9401528181610c0d01528181610edd01528181610f9901528181611acd01528181611b0601528181611b380152611e5a0152600081816106fc015261192401526000818161058c0152818161092b015281816109d701528181610c9a01528181611069015281816111ea0152818161131a015281816114d901528181611dab015281816125e501526129a801526133e06000f3fe608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea26469706673582212205e5525f027f33aeaba46aa3ccebb40d0e06be6975265ddae6ddb36ab444278f264736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea26469706673582212205e5525f027f33aeaba46aa3ccebb40d0e06be6975265ddae6ddb36ab444278f264736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/VotingEscrow.json b/deployments/arbitrumGoerli/VotingEscrow.json index 7f28abb4..3982df18 100644 --- a/deployments/arbitrumGoerli/VotingEscrow.json +++ b/deployments/arbitrumGoerli/VotingEscrow.json @@ -1,5 +1,5 @@ { - "address": "0xF003091B78974ee3F99ec70fC5F42fc9810664EC", + "address": "0x6d55AFbF1cAf01E0bcA5255bbA730da6fAFD0aF4", "abi": [ { "inputs": [ @@ -1521,62 +1521,62 @@ "type": "function" } ], - "transactionHash": "0xbff671b0179d6778fbe1940e7cc937755277dac04244840fe289626c2920a82e", + "transactionHash": "0x3270beffcd60bd8139eb66a4fd2befed24efd33fa3ce97ff40823aea884abbce", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xF003091B78974ee3F99ec70fC5F42fc9810664EC", - "transactionIndex": 1, + "contractAddress": "0x6d55AFbF1cAf01E0bcA5255bbA730da6fAFD0aF4", + "transactionIndex": 2, "gasUsed": "4240754", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000400000000000000000008000000000000000000000000000000000000000000000000020080000000000000000800000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000008000000000000000000000000000000000000002000000000000000200000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x7c564810cfa3661e63b5073dcb86f6ac7d77a5010fa76e3a1622c8107f969043", - "transactionHash": "0xbff671b0179d6778fbe1940e7cc937755277dac04244840fe289626c2920a82e", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000020000000000000000000000000000000000000000000020000000000000020000800000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000000000006000000000000000000000000000000000000000020000000000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xb2679ecc240d27e76793e4f63ef24aa1bb2e54562033879ec015874ddc119f35", + "transactionHash": "0x3270beffcd60bd8139eb66a4fd2befed24efd33fa3ce97ff40823aea884abbce", "logs": [ { - "transactionIndex": 1, - "blockNumber": 5849210, - "transactionHash": "0xbff671b0179d6778fbe1940e7cc937755277dac04244840fe289626c2920a82e", - "address": "0xF003091B78974ee3F99ec70fC5F42fc9810664EC", + "transactionIndex": 2, + "blockNumber": 6069407, + "transactionHash": "0x3270beffcd60bd8139eb66a4fd2befed24efd33fa3ce97ff40823aea884abbce", + "address": "0x6d55AFbF1cAf01E0bcA5255bbA730da6fAFD0aF4", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000f003091b78974ee3f99ec70fc5f42fc9810664ec", + "0x0000000000000000000000006d55afbf1caf01e0bca5255bba730da6fafd0af4", "0x0000000000000000000000000000000000000000000000000000000000000000" ], "data": "0x", "logIndex": 0, - "blockHash": "0x7c564810cfa3661e63b5073dcb86f6ac7d77a5010fa76e3a1622c8107f969043" + "blockHash": "0xb2679ecc240d27e76793e4f63ef24aa1bb2e54562033879ec015874ddc119f35" }, { - "transactionIndex": 1, - "blockNumber": 5849210, - "transactionHash": "0xbff671b0179d6778fbe1940e7cc937755277dac04244840fe289626c2920a82e", - "address": "0xF003091B78974ee3F99ec70fC5F42fc9810664EC", + "transactionIndex": 2, + "blockNumber": 6069407, + "transactionHash": "0x3270beffcd60bd8139eb66a4fd2befed24efd33fa3ce97ff40823aea884abbce", + "address": "0x6d55AFbF1cAf01E0bcA5255bbA730da6fAFD0aF4", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x000000000000000000000000f003091b78974ee3f99ec70fc5f42fc9810664ec", + "0x0000000000000000000000006d55afbf1caf01e0bca5255bba730da6fafd0af4", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000" ], "data": "0x", "logIndex": 1, - "blockHash": "0x7c564810cfa3661e63b5073dcb86f6ac7d77a5010fa76e3a1622c8107f969043" + "blockHash": "0xb2679ecc240d27e76793e4f63ef24aa1bb2e54562033879ec015874ddc119f35" } ], - "blockNumber": 5849210, - "cumulativeGasUsed": "4240754", + "blockNumber": 6069407, + "cumulativeGasUsed": "4288479", "status": 1, "byzantium": true }, "args": [ - "0x0432f39386A9B1d0339c8Ba0af617b16C86ADA05", - "0x053238ccA3E4A334D97c424567C9Add44259cd18" + "0x4E13914872BFf7e58f3E231b2687fDd084014999", + "0x765df7268ed8Ecd71Cb4bcb70751771eD66c9131" ], - "numDeployments": 3, - "solcInputHash": "98b870afa86e9d5388a96f4e867892a9", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token_addr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"art_proxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromDelegate\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toDelegate\",\"type\":\"address\"}],\"name\":\"DelegateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"DelegateVotesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"locktime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum VotingEscrow.DepositType\",\"name\":\"deposit_type\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"prevSupply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"supply\",\"type\":\"uint256\"}],\"name\":\"Supply\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DELEGATION_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_DELEGATES\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"abstain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_approved\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"artProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"attach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"attachments\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"balanceOfAtNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_t\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFTAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"block_number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"checkpoints\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"create_lock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"create_lock_for\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"}],\"name\":\"delegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"delegateBySig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"}],\"name\":\"delegates\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"deposit_for\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"detach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastTotalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotesIndex\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"get_last_user_slope\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"increase_amount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"increase_unlock_time\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"isApprovedOrOwner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"locked\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"amount\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"locked__end\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_from\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_to\",\"type\":\"uint256\"}],\"name\":\"merge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"numCheckpoints\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ownership_change\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_proxy\",\"type\":\"address\"}],\"name\":\"setArtProxy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voter\",\"type\":\"address\"}],\"name\":\"setVoter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"slope_changes\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenIndex\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"t\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAtT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_idx\",\"type\":\"uint256\"}],\"name\":\"user_point_history__ts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"voted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"voting\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\",\"details\":\"Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\",\"kind\":\"dev\",\"methods\":{\"approve(address,uint256)\":{\"details\":\"Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address. Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner. Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP) Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"Address to be approved for the given NFT ID.\",\"_tokenId\":\"ID of the token to be approved.\"}},\"balanceOf(address)\":{\"details\":\"Returns the number of NFTs owned by `_owner`. Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\",\"params\":{\"_owner\":\"Address for whom to query the balance.\"}},\"constructor\":{\"params\":{\"token_addr\":\"`FLOW` token address\"}},\"create_lock(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_value\":\"Amount to deposit\"}},\"create_lock_for(uint256,uint256,address)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_to\":\"Address to deposit\",\"_value\":\"Amount to deposit\"}},\"delegate(address)\":{\"params\":{\"delegatee\":\"The address to delegate votes to\"}},\"delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Delegates votes from signer to `delegatee`.\"},\"deposit_for(uint256,uint256)\":{\"details\":\"Anyone (even a smart contract) can deposit for someone else, but cannot extend their locktime and deposit for a brand new user\",\"params\":{\"_tokenId\":\"lock NFT\",\"_value\":\"Amount to add to user's lock\"}},\"getApproved(uint256)\":{\"details\":\"Get the approved address for a single NFT.\",\"params\":{\"_tokenId\":\"ID of the NFT to query the approval of.\"}},\"getVotes(address)\":{\"params\":{\"account\":\"The address to get votes balance\"},\"returns\":{\"_0\":\"The number of current votes for `account`\"}},\"get_last_user_slope(uint256)\":{\"params\":{\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Value of the slope\"}},\"increase_amount(uint256,uint256)\":{\"params\":{\"_value\":\"Amount of tokens to deposit and add to the lock\"}},\"increase_unlock_time(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"New number of seconds until tokens unlock\"}},\"isApprovedForAll(address,address)\":{\"details\":\"Checks if `_operator` is an approved operator for `_owner`.\",\"params\":{\"_operator\":\"The address that acts on behalf of the owner.\",\"_owner\":\"The address that owns the NFTs.\"}},\"locked__end(uint256)\":{\"params\":{\"_tokenId\":\"User NFT\"},\"returns\":{\"_0\":\"Epoch time of the lock end\"}},\"ownerOf(uint256)\":{\"details\":\"Returns the address of the owner of the NFT.\",\"params\":{\"_tokenId\":\"The identifier for an NFT.\"}},\"safeTransferFrom(address,address,uint256)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"safeTransferFrom(address,address,uint256,bytes)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_data\":\"Additional data with no specified format, sent in call to `_to`.\",\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"details\":\"Enables or disables approval for a third party (\\\"operator\\\") to manage all of `msg.sender`'s assets. It also emits the ApprovalForAll event. Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"True if the operators is approved, false to revoke approval.\",\"_operator\":\"Address to add to the set of authorized operators.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Interface identification is specified in ERC-165.\",\"params\":{\"_interfaceID\":\"Id of the interface\"}},\"tokenOfOwnerByIndex(address,uint256)\":{\"details\":\"Get token by index\"},\"tokenURI(uint256)\":{\"details\":\"Returns current token URI metadata\",\"params\":{\"_tokenId\":\"Token ID to fetch URI for.\"}},\"totalSupplyAt(uint256)\":{\"params\":{\"_block\":\"Block to calculate the total voting power at\"},\"returns\":{\"_0\":\"Total voting power at `_block`\"}},\"totalSupplyAtT(uint256)\":{\"details\":\"Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\",\"returns\":{\"_0\":\"Total voting power\"}},\"transferFrom(address,address,uint256)\":{\"details\":\"Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"user_point_history__ts(uint256,uint256)\":{\"params\":{\"_idx\":\"User epoch number\",\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Epoch time of the checkpoint\"}},\"withdraw(uint256)\":{\"details\":\"Only possible if the lock has expired\"}},\"stateVariables\":{\"ERC165_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC165\"},\"ERC721_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721\"},\"ERC721_METADATA_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721Metadata\"},\"_not_entered\":{\"details\":\"reentrancy guard\"},\"idToApprovals\":{\"details\":\"Mapping from NFT ID to approved address.\"},\"idToOwner\":{\"details\":\"Mapping from NFT ID to the address that owns it.\"},\"name\":{\"details\":\"Returns the token collection name.\"},\"ownerToNFTokenCount\":{\"details\":\"Mapping from owner address to count of his tokens.\"},\"ownerToNFTokenIdList\":{\"details\":\"Mapping from owner address to mapping of index to tokenIds\"},\"ownerToOperators\":{\"details\":\"Mapping from owner address to mapping of operator addresses.\"},\"supportedInterfaces\":{\"details\":\"Mapping of interface id to bool about whether or not it's supported\"},\"symbol\":{\"details\":\"Returns the token collection symbol.\"},\"tokenId\":{\"details\":\"Current count of token\"},\"tokenToOwnerIndex\":{\"details\":\"Mapping from NFT ID to index of owner\"}},\"title\":\"Voting Escrow\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DELEGATION_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the delegation struct used by the contract\"},\"DOMAIN_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the contract's domain\"},\"checkpoint()\":{\"notice\":\"Record global data to checkpoint\"},\"checkpoints(address,uint32)\":{\"notice\":\"A record of delegated token checkpoints for each account, by index\"},\"constructor\":{\"notice\":\"Contract constructor\"},\"create_lock(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\"},\"create_lock_for(uint256,uint256,address)\":{\"notice\":\"Deposit `_value` tokens for `_to` and lock for `_lock_duration`\"},\"delegate(address)\":{\"notice\":\"Delegate votes from `msg.sender` to `delegatee`\"},\"delegates(address)\":{\"notice\":\"Overrides the standard `Comp.sol` delegates mapping to return the delegator's own address if they haven't delegated. This avoids having to delegate to oneself.\"},\"deposit_for(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `_tokenId` and add to the lock\"},\"getVotes(address)\":{\"notice\":\"Gets the current votes balance for `account`\"},\"get_last_user_slope(uint256)\":{\"notice\":\"Get the most recently recorded rate of voting power decrease for `_tokenId`\"},\"increase_amount(uint256,uint256)\":{\"notice\":\"Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\"},\"increase_unlock_time(uint256,uint256)\":{\"notice\":\"Extend the unlock time for `_tokenId`\"},\"locked__end(uint256)\":{\"notice\":\"Get timestamp when `_tokenId`'s lock finishes\"},\"nonces(address)\":{\"notice\":\"A record of states for signing / validating signatures\"},\"numCheckpoints(address)\":{\"notice\":\"The number of checkpoints for each account\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"This works even if sender doesn't own any tokens at the time.\"},\"totalSupplyAt(uint256)\":{\"notice\":\"Calculate total voting power at some point in the past\"},\"totalSupplyAtT(uint256)\":{\"notice\":\"Calculate total voting power\"},\"transferFrom(address,address,uint256)\":{\"notice\":\"The caller is responsible to confirm that `_to` is capable of receiving NFTs or else they maybe be permanently lost.\"},\"user_point_history__ts(uint256,uint256)\":{\"notice\":\"Get the timestamp for checkpoint `_idx` for `_tokenId`\"},\"withdraw(uint256)\":{\"notice\":\"Withdraw all tokens for `_tokenId`\"}},\"notice\":\"veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFTVotes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VotingEscrow.sol\":\"VotingEscrow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393030323136323532\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VotingEscrow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IERC721, IERC721Metadata} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {IERC721Receiver} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {IERC20} from \\\"contracts/interfaces/IERC20.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\nimport {IVotingEscrow} from \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/// @title Voting Escrow\\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\\n enum DepositType {\\n DEPOSIT_FOR_TYPE,\\n CREATE_LOCK_TYPE,\\n INCREASE_LOCK_AMOUNT,\\n INCREASE_UNLOCK_TIME,\\n MERGE_TYPE\\n }\\n\\n struct LockedBalance {\\n int128 amount;\\n uint end;\\n }\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint ts;\\n uint blk; // block\\n }\\n /* We cannot really do block numbers per se b/c slope is per time, not per block\\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\\n * What we can do is to extrapolate ***At functions */\\n\\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\\n struct Checkpoint {\\n uint timestamp;\\n uint[] tokenIds;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Deposit(\\n address indexed provider,\\n uint tokenId,\\n uint value,\\n uint indexed locktime,\\n DepositType deposit_type,\\n uint ts\\n );\\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\\n event Supply(uint prevSupply, uint supply);\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n address public immutable token;\\n address public voter;\\n address public team;\\n address public artProxy;\\n\\n mapping(uint => Point) public point_history; // epoch -> unsigned point\\n\\n /// @dev Mapping of interface id to bool about whether or not it's supported\\n mapping(bytes4 => bool) internal supportedInterfaces;\\n\\n /// @dev ERC165 interface ID of ERC165\\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\\n\\n /// @dev ERC165 interface ID of ERC721\\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\\n\\n /// @dev ERC165 interface ID of ERC721Metadata\\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\\n\\n /// @dev Current count of token\\n uint internal tokenId;\\n\\n /// @notice Contract constructor\\n /// @param token_addr `FLOW` token address\\n constructor(address token_addr, address art_proxy) {\\n token = token_addr;\\n voter = msg.sender;\\n team = msg.sender;\\n artProxy = art_proxy;\\n\\n point_history[0].blk = block.number;\\n point_history[0].ts = block.timestamp;\\n\\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\\n\\n // mint-ish\\n emit Transfer(address(0), address(this), tokenId);\\n // burn-ish\\n emit Transfer(address(this), address(0), tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n MODIFIERS\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev reentrancy guard\\n uint8 internal constant _not_entered = 1;\\n uint8 internal constant _entered = 2;\\n uint8 internal _entered_state = 1;\\n modifier nonreentrant() {\\n require(_entered_state == _not_entered);\\n _entered_state = _entered;\\n _;\\n _entered_state = _not_entered;\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string constant public name = \\\"veNFT\\\";\\n string constant public symbol = \\\"veNFT\\\";\\n string constant public version = \\\"1.0.0\\\";\\n uint8 constant public decimals = 18;\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team);\\n team = _team;\\n }\\n\\n function setArtProxy(address _proxy) external {\\n require(msg.sender == team);\\n artProxy = _proxy;\\n }\\n\\n /// @dev Returns current token URI metadata\\n /// @param _tokenId Token ID to fetch URI for.\\n function tokenURI(uint _tokenId) external view returns (string memory) {\\n require(idToOwner[_tokenId] != address(0), \\\"Query for nonexistent token\\\");\\n LockedBalance memory _locked = locked[_tokenId];\\n return IVeArtProxy(artProxy)._tokenURI(\\n _tokenId,\\n _balanceOfNFT(_tokenId, block.timestamp),\\n _locked.end,\\n uint(int256(_locked.amount))\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 BALANCE/OWNER STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to the address that owns it.\\n mapping(uint => address) internal idToOwner;\\n\\n /// @dev Mapping from owner address to count of his tokens.\\n mapping(address => uint) internal ownerToNFTokenCount;\\n\\n /// @dev Returns the address of the owner of the NFT.\\n /// @param _tokenId The identifier for an NFT.\\n function ownerOf(uint _tokenId) public view returns (address) {\\n return idToOwner[_tokenId];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function _balance(address _owner) internal view returns (uint) {\\n return ownerToNFTokenCount[_owner];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function balanceOf(address _owner) external view returns (uint) {\\n return _balance(_owner);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 APPROVAL STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to approved address.\\n mapping(uint => address) internal idToApprovals;\\n\\n /// @dev Mapping from owner address to mapping of operator addresses.\\n mapping(address => mapping(address => bool)) internal ownerToOperators;\\n\\n mapping(uint => uint) public ownership_change;\\n\\n /// @dev Get the approved address for a single NFT.\\n /// @param _tokenId ID of the NFT to query the approval of.\\n function getApproved(uint _tokenId) external view returns (address) {\\n return idToApprovals[_tokenId];\\n }\\n\\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\\n /// @param _owner The address that owns the NFTs.\\n /// @param _operator The address that acts on behalf of the owner.\\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\\n return (ownerToOperators[_owner])[_operator];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\\n /// @param _approved Address to be approved for the given NFT ID.\\n /// @param _tokenId ID of the token to be approved.\\n function approve(address _approved, uint _tokenId) public {\\n address owner = idToOwner[_tokenId];\\n // Throws if `_tokenId` is not a valid NFT\\n require(owner != address(0));\\n // Throws if `_approved` is the current owner\\n require(_approved != owner);\\n // Check requirements\\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\\n require(senderIsOwner || senderIsApprovedForAll);\\n // Set the approval\\n idToApprovals[_tokenId] = _approved;\\n emit Approval(owner, _approved, _tokenId);\\n }\\n\\n /// @dev Enables or disables approval for a third party (\\\"operator\\\") to manage all of\\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\\n /// @notice This works even if sender doesn't own any tokens at the time.\\n /// @param _operator Address to add to the set of authorized operators.\\n /// @param _approved True if the operators is approved, false to revoke approval.\\n function setApprovalForAll(address _operator, bool _approved) external {\\n // Throws if `_operator` is the `msg.sender`\\n assert(_operator != msg.sender);\\n ownerToOperators[msg.sender][_operator] = _approved;\\n emit ApprovalForAll(msg.sender, _operator, _approved);\\n }\\n\\n /* TRANSFER FUNCTIONS */\\n /// @dev Clear an approval of a given address\\n /// Throws if `_owner` is not the current owner.\\n function _clearApproval(address _owner, uint _tokenId) internal {\\n // Throws if `_owner` is not the current owner\\n assert(idToOwner[_tokenId] == _owner);\\n if (idToApprovals[_tokenId] != address(0)) {\\n // Reset approvals\\n idToApprovals[_tokenId] = address(0);\\n }\\n }\\n\\n /// @dev Returns whether the given spender can transfer a given token ID\\n /// @param _spender address of the spender to query\\n /// @param _tokenId uint ID of the token to be transferred\\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\\n address owner = idToOwner[_tokenId];\\n bool spenderIsOwner = owner == _spender;\\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\\n }\\n\\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\\n return _isApprovedOrOwner(_spender, _tokenId);\\n }\\n\\n /// @dev Exeute transfer of a NFT.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_tokenId` is not a valid NFT.\\n function _transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n address _sender\\n ) internal {\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n // Check requirements\\n require(_isApprovedOrOwner(_sender, _tokenId));\\n // Clear approval. Throws if `_from` is not the current owner\\n _clearApproval(_from, _tokenId);\\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\\n _removeTokenFrom(_from, _tokenId);\\n // auto re-delegate\\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\\n // Add NFT\\n _addTokenTo(_to, _tokenId);\\n // Set the block of ownership transfer (for Flash NFT protection)\\n ownership_change[_tokenId] = block.number;\\n // Log the transfer\\n emit Transfer(_from, _to, _tokenId);\\n }\\n\\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\\n /// they maybe be permanently lost.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n safeTransferFrom(_from, _to, _tokenId, \\\"\\\");\\n }\\n\\n function _isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n uint size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n /// @param _data Additional data with no specified format, sent in call to `_to`.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n bytes memory _data\\n ) public {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n\\n if (_isContract(_to)) {\\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\\n revert(\\\"ERC721: ERC721Receiver rejected tokens\\\");\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert('ERC721: transfer to non ERC721Receiver implementer');\\n } else {\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC165 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Interface identification is specified in ERC-165.\\n /// @param _interfaceID Id of the interface\\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\\n return supportedInterfaces[_interfaceID];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from owner address to mapping of index to tokenIds\\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\\n\\n /// @dev Mapping from NFT ID to index of owner\\n mapping(uint => uint) internal tokenToOwnerIndex;\\n\\n /// @dev Get token by index\\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\\n return ownerToNFTokenIdList[_owner][_tokenIndex];\\n }\\n\\n /// @dev Add a NFT to an index mapping to a given address\\n /// @param _to address of the receiver\\n /// @param _tokenId uint ID Of the token to be added\\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\\n uint current_count = _balance(_to);\\n\\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\\n tokenToOwnerIndex[_tokenId] = current_count;\\n }\\n\\n /// @dev Add a NFT to a given address\\n /// Throws if `_tokenId` is owned by someone.\\n function _addTokenTo(address _to, uint _tokenId) internal {\\n // Throws if `_tokenId` is owned by someone\\n assert(idToOwner[_tokenId] == address(0));\\n // Change the owner\\n idToOwner[_tokenId] = _to;\\n // Update owner token index tracking\\n _addTokenToOwnerList(_to, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_to] += 1;\\n }\\n\\n /// @dev Function to mint tokens\\n /// Throws if `_to` is zero address.\\n /// Throws if `_tokenId` is owned by someone.\\n /// @param _to The address that will receive the minted tokens.\\n /// @param _tokenId The token id to mint.\\n /// @return A boolean that indicates if the operation was successful.\\n function _mint(address _to, uint _tokenId) internal returns (bool) {\\n // Throws if `_to` is zero address\\n assert(_to != address(0));\\n // checkpoint for gov\\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\\n // Add NFT. Throws if `_tokenId` is owned by someone\\n _addTokenTo(_to, _tokenId);\\n emit Transfer(address(0), _to, _tokenId);\\n return true;\\n }\\n\\n /// @dev Remove a NFT from an index mapping to a given address\\n /// @param _from address of the sender\\n /// @param _tokenId uint ID Of the token to be removed\\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\\n // Delete\\n uint current_count = _balance(_from) - 1;\\n uint current_index = tokenToOwnerIndex[_tokenId];\\n\\n if (current_count == current_index) {\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n } else {\\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\\n\\n // Add\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[lastTokenId] = current_index;\\n\\n // Delete\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n }\\n }\\n\\n /// @dev Remove a NFT from a given address\\n /// Throws if `_from` is not the current owner.\\n function _removeTokenFrom(address _from, uint _tokenId) internal {\\n // Throws if `_from` is not the current owner\\n assert(idToOwner[_tokenId] == _from);\\n // Change the owner\\n idToOwner[_tokenId] = address(0);\\n // Update owner token index tracking\\n _removeTokenFromOwnerList(_from, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_from] -= 1;\\n }\\n\\n function _burn(uint _tokenId) internal {\\n require(_isApprovedOrOwner(msg.sender, _tokenId), \\\"caller is not owner nor approved\\\");\\n\\n address owner = ownerOf(_tokenId);\\n\\n // Clear approval\\n approve(address(0), _tokenId);\\n // checkpoint for gov\\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\\n // Remove token\\n _removeTokenFrom(msg.sender, _tokenId);\\n emit Transfer(owner, address(0), _tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public user_point_epoch;\\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\\n mapping(uint => LockedBalance) public locked;\\n uint public epoch;\\n mapping(uint => int128) public slope_changes; // time -> signed slope change\\n uint public supply;\\n\\n uint internal constant WEEK = 1 weeks;\\n uint internal constant MAXTIME = 4 * 365 * 86400;\\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\\n uint internal constant MULTIPLIER = 1 ether;\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @return Value of the slope\\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\\n uint uepoch = user_point_epoch[_tokenId];\\n return user_point_history[_tokenId][uepoch].slope;\\n }\\n\\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @param _idx User epoch number\\n /// @return Epoch time of the checkpoint\\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\\n return user_point_history[_tokenId][_idx].ts;\\n }\\n\\n /// @notice Get timestamp when `_tokenId`'s lock finishes\\n /// @param _tokenId User NFT\\n /// @return Epoch time of the lock end\\n function locked__end(uint _tokenId) external view returns (uint) {\\n return locked[_tokenId].end;\\n }\\n\\n /// @notice Record global and per-user data to checkpoint\\n /// @param _tokenId NFT token ID. No user checkpoint if 0\\n /// @param old_locked Pevious locked amount / end lock time for the user\\n /// @param new_locked New locked amount / end lock time for the user\\n function _checkpoint(\\n uint _tokenId,\\n LockedBalance memory old_locked,\\n LockedBalance memory new_locked\\n ) internal {\\n Point memory u_old;\\n Point memory u_new;\\n int128 old_dslope = 0;\\n int128 new_dslope = 0;\\n uint _epoch = epoch;\\n\\n if (_tokenId != 0) {\\n // Calculate slopes and biases\\n // Kept at zero when they have to\\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\\n u_old.slope = old_locked.amount / iMAXTIME;\\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\\n }\\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\\n u_new.slope = new_locked.amount / iMAXTIME;\\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\\n }\\n\\n // Read values of scheduled changes in the slope\\n // old_locked.end can be in the past and in the future\\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\\n old_dslope = slope_changes[old_locked.end];\\n if (new_locked.end != 0) {\\n if (new_locked.end == old_locked.end) {\\n new_dslope = old_dslope;\\n } else {\\n new_dslope = slope_changes[new_locked.end];\\n }\\n }\\n }\\n\\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\\n if (_epoch > 0) {\\n last_point = point_history[_epoch];\\n }\\n uint last_checkpoint = last_point.ts;\\n // initial_last_point is used for extrapolation to calculate block number\\n // (approximately, for *At methods) and save them\\n // as we cannot figure that out exactly from inside the contract\\n Point memory initial_last_point = last_point;\\n uint block_slope = 0; // dblock/dt\\n if (block.timestamp > last_point.ts) {\\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\\n }\\n // If last point is already recorded in this block, slope=0\\n // But that's ok b/c we know the block in such case\\n\\n // Go over weeks to fill history and calculate what the current point is\\n {\\n uint t_i = (last_checkpoint / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n // Hopefully it won't happen that this won't get used in 5 years!\\n // If it does, users will be able to withdraw but vote weight will be broken\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > block.timestamp) {\\n t_i = block.timestamp;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\\n last_point.slope += d_slope;\\n if (last_point.bias < 0) {\\n // This can happen\\n last_point.bias = 0;\\n }\\n if (last_point.slope < 0) {\\n // This cannot happen - just in case\\n last_point.slope = 0;\\n }\\n last_checkpoint = t_i;\\n last_point.ts = t_i;\\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\\n _epoch += 1;\\n if (t_i == block.timestamp) {\\n last_point.blk = block.number;\\n break;\\n } else {\\n point_history[_epoch] = last_point;\\n }\\n }\\n }\\n\\n epoch = _epoch;\\n // Now point_history is filled until t=now\\n\\n if (_tokenId != 0) {\\n // If last point was in this block, the slope change has been applied already\\n // But in such case we have 0 slope(s)\\n last_point.slope += (u_new.slope - u_old.slope);\\n last_point.bias += (u_new.bias - u_old.bias);\\n if (last_point.slope < 0) {\\n last_point.slope = 0;\\n }\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n }\\n\\n // Record the changed point into history\\n point_history[_epoch] = last_point;\\n\\n if (_tokenId != 0) {\\n // Schedule the slope changes (slope is going down)\\n // We subtract new_user_slope from [new_locked.end]\\n // and add old_user_slope to [old_locked.end]\\n if (old_locked.end > block.timestamp) {\\n // old_dslope was - u_old.slope, so we cancel that\\n old_dslope += u_old.slope;\\n if (new_locked.end == old_locked.end) {\\n old_dslope -= u_new.slope; // It was a new deposit, not extension\\n }\\n slope_changes[old_locked.end] = old_dslope;\\n }\\n\\n if (new_locked.end > block.timestamp) {\\n if (new_locked.end > old_locked.end) {\\n new_dslope -= u_new.slope; // old slope disappeared at this point\\n slope_changes[new_locked.end] = new_dslope;\\n }\\n // else: we recorded it already in old_dslope\\n }\\n // Now handle user history\\n uint user_epoch = user_point_epoch[_tokenId] + 1;\\n\\n user_point_epoch[_tokenId] = user_epoch;\\n u_new.ts = block.timestamp;\\n u_new.blk = block.number;\\n user_point_history[_tokenId][user_epoch] = u_new;\\n }\\n }\\n\\n /// @notice Deposit and lock tokens for a user\\n /// @param _tokenId NFT that holds lock\\n /// @param _value Amount to deposit\\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\\n /// @param locked_balance Previous locked amount / timestamp\\n /// @param deposit_type The type of deposit\\n function _deposit_for(\\n uint _tokenId,\\n uint _value,\\n uint unlock_time,\\n LockedBalance memory locked_balance,\\n DepositType deposit_type\\n ) internal {\\n LockedBalance memory _locked = locked_balance;\\n uint supply_before = supply;\\n\\n supply = supply_before + _value;\\n LockedBalance memory old_locked;\\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\\n // Adding to existing lock, or if a lock is expired - creating a new one\\n _locked.amount += int128(int256(_value));\\n if (unlock_time != 0) {\\n _locked.end = unlock_time;\\n }\\n locked[_tokenId] = _locked;\\n\\n // Possibilities:\\n // Both old_locked.end could be current or expired (>/< block.timestamp)\\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\\n // _locked.end > block.timestamp (always)\\n _checkpoint(_tokenId, old_locked, _locked);\\n\\n address from = msg.sender;\\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\\n assert(IERC20(token).transferFrom(from, address(this), _value));\\n }\\n\\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\\n emit Supply(supply_before, supply_before + _value);\\n }\\n\\n function block_number() external view returns (uint) {\\n return block.number;\\n }\\n\\n /// @notice Record global data to checkpoint\\n function checkpoint() external {\\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\\n }\\n\\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\\n /// cannot extend their locktime and deposit for a brand new user\\n /// @param _tokenId lock NFT\\n /// @param _value Amount to add to user's lock\\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n require(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_value > 0); // dev: need non-zero value\\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n ++tokenId;\\n uint _tokenId = tokenId;\\n _mint(_to, _tokenId);\\n\\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\\n return _tokenId;\\n }\\n\\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, msg.sender);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, _to);\\n }\\n\\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\\n /// @param _value Amount of tokens to deposit and add to the lock\\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n assert(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\\n }\\n\\n /// @notice Extend the unlock time for `_tokenId`\\n /// @param _lock_duration New number of seconds until tokens unlock\\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_locked.end > block.timestamp, 'Lock expired');\\n require(_locked.amount > 0, 'Nothing is locked');\\n require(unlock_time > _locked.end, 'Can only increase lock duration');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\\n }\\n\\n /// @notice Withdraw all tokens for `_tokenId`\\n /// @dev Only possible if the lock has expired\\n function withdraw(uint _tokenId) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n require(block.timestamp >= _locked.end, \\\"The lock didn't expire\\\");\\n uint value = uint(int256(_locked.amount));\\n\\n locked[_tokenId] = LockedBalance(0,0);\\n uint supply_before = supply;\\n supply = supply_before - value;\\n\\n // old_locked can have either expired <= timestamp or zero end\\n // _locked has only 0 end\\n // Both can have >= 0 amount\\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\\n\\n assert(IERC20(token).transfer(msg.sender, value));\\n\\n // Burn the NFT\\n _burn(_tokenId);\\n\\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\\n emit Supply(supply_before, supply_before - value);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\\n // They measure the weights for the purpose of voting, so they don't represent\\n // real coins.\\n\\n /// @notice Binary search to estimate timestamp for block number\\n /// @param _block Block to find\\n /// @param max_epoch Don't go beyond this epoch\\n /// @return Approximate timestamp for block\\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\\n // Binary search\\n uint _min = 0;\\n uint _max = max_epoch;\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (point_history[_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n /// @notice Get the current voting power for `_tokenId`\\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\\n /// @param _tokenId NFT for lock\\n /// @param _t Epoch time to return voting power at\\n /// @return User voting power\\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\\n uint _epoch = user_point_epoch[_tokenId];\\n if (_epoch == 0) {\\n return 0;\\n } else {\\n Point memory last_point = user_point_history[_tokenId][_epoch];\\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(int256(last_point.bias));\\n }\\n }\\n\\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\\n if (ownership_change[_tokenId] == block.number) return 0;\\n return _balanceOfNFT(_tokenId, block.timestamp);\\n }\\n\\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\\n return _balanceOfNFT(_tokenId, _t);\\n }\\n\\n /// @notice Measure voting power of `_tokenId` at block height `_block`\\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\\n /// @param _tokenId User's wallet NFT\\n /// @param _block Block to calculate the voting power at\\n /// @return Voting power\\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\\n // Copying and pasting totalSupply code because Vyper cannot pass by\\n // reference yet\\n assert(_block <= block.number);\\n\\n // Binary search\\n uint _min = 0;\\n uint _max = user_point_epoch[_tokenId];\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (user_point_history[_tokenId][_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n\\n Point memory upoint = user_point_history[_tokenId][_min];\\n\\n uint max_epoch = epoch;\\n uint _epoch = _find_block_epoch(_block, max_epoch);\\n Point memory point_0 = point_history[_epoch];\\n uint d_block = 0;\\n uint d_t = 0;\\n if (_epoch < max_epoch) {\\n Point memory point_1 = point_history[_epoch + 1];\\n d_block = point_1.blk - point_0.blk;\\n d_t = point_1.ts - point_0.ts;\\n } else {\\n d_block = block.number - point_0.blk;\\n d_t = block.timestamp - point_0.ts;\\n }\\n uint block_time = point_0.ts;\\n if (d_block != 0) {\\n block_time += (d_t * (_block - point_0.blk)) / d_block;\\n }\\n\\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\\n if (upoint.bias >= 0) {\\n return uint(uint128(upoint.bias));\\n } else {\\n return 0;\\n }\\n }\\n\\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\\n return _balanceOfAtNFT(_tokenId, _block);\\n }\\n\\n /// @notice Calculate total voting power at some point in the past\\n /// @param _block Block to calculate the total voting power at\\n /// @return Total voting power at `_block`\\n function totalSupplyAt(uint _block) external view returns (uint) {\\n assert(_block <= block.number);\\n uint _epoch = epoch;\\n uint target_epoch = _find_block_epoch(_block, _epoch);\\n\\n Point memory point = point_history[target_epoch];\\n uint dt = 0;\\n if (target_epoch < _epoch) {\\n Point memory point_next = point_history[target_epoch + 1];\\n if (point.blk != point_next.blk) {\\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\\n }\\n } else {\\n if (point.blk != block.number) {\\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\\n }\\n }\\n // Now dt contains info on how far are we beyond point\\n return _supply_at(point, point.ts + dt);\\n }\\n /// @notice Calculate total voting power at some point in the past\\n /// @param point The point (bias/slope) to start search from\\n /// @param t Time to calculate the total voting power at\\n /// @return Total voting power at that time\\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\\n Point memory last_point = point;\\n uint t_i = (last_point.ts / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > t) {\\n t_i = t;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\\n if (t_i == t) {\\n break;\\n }\\n last_point.slope += d_slope;\\n last_point.ts = t_i;\\n }\\n\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(uint128(last_point.bias));\\n }\\n\\n function totalSupply() external view returns (uint) {\\n return totalSupplyAtT(block.timestamp);\\n }\\n\\n /// @notice Calculate total voting power\\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\\n /// @return Total voting power\\n function totalSupplyAtT(uint t) public view returns (uint) {\\n uint _epoch = epoch;\\n Point memory last_point = point_history[_epoch];\\n return _supply_at(last_point, t);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public attachments;\\n mapping(uint => bool) public voted;\\n\\n function setVoter(address _voter) external {\\n require(msg.sender == voter);\\n voter = _voter;\\n }\\n\\n function voting(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = true;\\n }\\n\\n function abstain(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = false;\\n }\\n\\n function attach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] + 1;\\n }\\n\\n function detach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] - 1;\\n }\\n\\n function merge(uint _from, uint _to) external {\\n require(attachments[_from] == 0 && !voted[_from], \\\"attached\\\");\\n require(_from != _to);\\n require(_isApprovedOrOwner(msg.sender, _from));\\n require(_isApprovedOrOwner(msg.sender, _to));\\n\\n LockedBalance memory _locked0 = locked[_from];\\n LockedBalance memory _locked1 = locked[_to];\\n uint value0 = uint(int256(_locked0.amount));\\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\\n\\n locked[_from] = LockedBalance(0, 0);\\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\\n _burn(_from);\\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of each accounts delegate\\n mapping(address => address) private _delegates;\\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\\n\\n /// @notice A record of delegated token checkpoints for each account, by index\\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint32) public numCheckpoints;\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping(address => uint) public nonces;\\n\\n /**\\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\\n * the delegator's own address if they haven't delegated.\\n * This avoids having to delegate to oneself.\\n */\\n function delegates(address delegator) public view returns (address) {\\n address current = _delegates[delegator];\\n return current == address(0) ? delegator : current;\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getVotes(address account) external view returns (uint) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n votes = votes + _balanceOfNFT(tId, block.timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint storage cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPastVotes(address account, uint timestamp)\\n public\\n view\\n returns (uint)\\n {\\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\\n // Sum votes\\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n // Use the provided input timestamp here to get the right decay\\n votes = votes + _balanceOfNFT(tId, timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\\n return totalSupplyAtT(timestamp);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _moveTokenDelegates(\\n address srcRep,\\n address dstRep,\\n uint _tokenId\\n ) internal {\\n if (srcRep != dstRep && _tokenId > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except _tokenId\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (tId != _tokenId) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n // All the same plus _tokenId\\n require(\\n dstRepOld.length + 1 <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n dstRepNew.push(_tokenId);\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _findWhatCheckpointToWrite(address account)\\n internal\\n view\\n returns (uint32)\\n {\\n uint _timestamp = block.timestamp;\\n uint32 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n return _nCheckPoints - 1;\\n } else {\\n return _nCheckPoints;\\n }\\n }\\n\\n function _moveAllDelegates(\\n address owner,\\n address srcRep,\\n address dstRep\\n ) internal {\\n // You can only redelegate what you own\\n if (srcRep != dstRep) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except what owner owns\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (idToOwner[tId] != owner) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n uint ownerTokenCount = ownerToNFTokenCount[owner];\\n require(\\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n // All the same\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n // Plus all that's owned\\n for (uint i = 0; i < ownerTokenCount; i++) {\\n uint tId = ownerToNFTokenIdList[owner][i];\\n dstRepNew.push(tId);\\n }\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\\n address currentDelegate = delegates(delegator);\\n\\n _delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n _moveAllDelegates(delegator, currentDelegate, delegatee);\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n if (delegatee == address(0)) delegatee = msg.sender;\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n function delegateBySig(\\n address delegatee,\\n uint nonce,\\n uint expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public {\\n bytes32 domainSeparator = keccak256(\\n abi.encode(\\n DOMAIN_TYPEHASH,\\n keccak256(bytes(name)),\\n keccak256(bytes(version)),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 structHash = keccak256(\\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash)\\n );\\n address signatory = ecrecover(digest, v, r, s);\\n require(\\n signatory != address(0),\\n \\\"VotingEscrow::delegateBySig: invalid signature\\\"\\n );\\n require(\\n nonce == nonces[signatory]++,\\n \\\"VotingEscrow::delegateBySig: invalid nonce\\\"\\n );\\n require(\\n block.timestamp <= expiry,\\n \\\"VotingEscrow::delegateBySig: signature expired\\\"\\n );\\n return _delegate(signatory, delegatee);\\n }\\n}\\n\",\"keccak256\":\"0x7109ed9d84b5504fe5d4c73d5a10997a0b73f2f4d45813ce5e161997d405fd73\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x41bbb2c41036ca64b2f6c9e973e8cfaa113ebc42af86702cd0d267f915a7e886\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60a06040526006805460ff191660011790553480156200001e57600080fd5b5060405162004a1c38038062004a1c8339810160408190526200004191620001b8565b6001600160a01b0382811660805260008054336001600160a01b031991821681178355600180548316909117815560028054909216938516939093179055437f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f0155427f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f005560046020527f9fe05126d2d9ecf60592e254dead906a4b2e492f36cca727682c38e9008c6ac1805460ff1990811684179091557f4267c0a6fd96b7a87f183ee8744f24d011423cd0e0142b3f563f183d8d9a456b8054821684179055635b5e139f60e01b82527e24030bcf4927897dffe721c2d8dda4bfd8910861687c42b03a463b43b04147805490911690921790915560055460405190913091600080516020620049fc833981519152908290a46005546040516000903090600080516020620049fc833981519152908390a45050620001f0565b80516001600160a01b0381168114620001b357600080fd5b919050565b60008060408385031215620001cc57600080fd5b620001d7836200019b565b9150620001e7602084016200019b565b90509250929050565b6080516147e26200021a60003960008181610b220152818161101801526133b501526147e26000f3fe608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea2646970667358221220e191f45ee9b9ddd82838199fcaf044fa9ba45ffb29c39aba72aeb1c4753b392e64736f6c634300080d0033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea2646970667358221220e191f45ee9b9ddd82838199fcaf044fa9ba45ffb29c39aba72aeb1c4753b392e64736f6c634300080d0033", + "numDeployments": 1, + "solcInputHash": "d2a2160297444b93438826228d1e185d", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token_addr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"art_proxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromDelegate\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toDelegate\",\"type\":\"address\"}],\"name\":\"DelegateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"DelegateVotesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"locktime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum VotingEscrow.DepositType\",\"name\":\"deposit_type\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"prevSupply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"supply\",\"type\":\"uint256\"}],\"name\":\"Supply\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DELEGATION_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_DELEGATES\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"abstain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_approved\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"artProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"attach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"attachments\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"balanceOfAtNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_t\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFTAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"block_number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"checkpoints\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"create_lock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"create_lock_for\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"}],\"name\":\"delegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"delegateBySig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"}],\"name\":\"delegates\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"deposit_for\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"detach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastTotalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotesIndex\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"get_last_user_slope\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"increase_amount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"increase_unlock_time\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"isApprovedOrOwner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"locked\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"amount\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"locked__end\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_from\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_to\",\"type\":\"uint256\"}],\"name\":\"merge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"numCheckpoints\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ownership_change\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_proxy\",\"type\":\"address\"}],\"name\":\"setArtProxy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voter\",\"type\":\"address\"}],\"name\":\"setVoter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"slope_changes\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenIndex\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"t\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAtT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_idx\",\"type\":\"uint256\"}],\"name\":\"user_point_history__ts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"voted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"voting\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\",\"details\":\"Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\",\"kind\":\"dev\",\"methods\":{\"approve(address,uint256)\":{\"details\":\"Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address. Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner. Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP) Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"Address to be approved for the given NFT ID.\",\"_tokenId\":\"ID of the token to be approved.\"}},\"balanceOf(address)\":{\"details\":\"Returns the number of NFTs owned by `_owner`. Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\",\"params\":{\"_owner\":\"Address for whom to query the balance.\"}},\"constructor\":{\"params\":{\"token_addr\":\"`FLOW` token address\"}},\"create_lock(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_value\":\"Amount to deposit\"}},\"create_lock_for(uint256,uint256,address)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_to\":\"Address to deposit\",\"_value\":\"Amount to deposit\"}},\"delegate(address)\":{\"params\":{\"delegatee\":\"The address to delegate votes to\"}},\"delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Delegates votes from signer to `delegatee`.\"},\"deposit_for(uint256,uint256)\":{\"details\":\"Anyone (even a smart contract) can deposit for someone else, but cannot extend their locktime and deposit for a brand new user\",\"params\":{\"_tokenId\":\"lock NFT\",\"_value\":\"Amount to add to user's lock\"}},\"getApproved(uint256)\":{\"details\":\"Get the approved address for a single NFT.\",\"params\":{\"_tokenId\":\"ID of the NFT to query the approval of.\"}},\"getVotes(address)\":{\"params\":{\"account\":\"The address to get votes balance\"},\"returns\":{\"_0\":\"The number of current votes for `account`\"}},\"get_last_user_slope(uint256)\":{\"params\":{\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Value of the slope\"}},\"increase_amount(uint256,uint256)\":{\"params\":{\"_value\":\"Amount of tokens to deposit and add to the lock\"}},\"increase_unlock_time(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"New number of seconds until tokens unlock\"}},\"isApprovedForAll(address,address)\":{\"details\":\"Checks if `_operator` is an approved operator for `_owner`.\",\"params\":{\"_operator\":\"The address that acts on behalf of the owner.\",\"_owner\":\"The address that owns the NFTs.\"}},\"locked__end(uint256)\":{\"params\":{\"_tokenId\":\"User NFT\"},\"returns\":{\"_0\":\"Epoch time of the lock end\"}},\"ownerOf(uint256)\":{\"details\":\"Returns the address of the owner of the NFT.\",\"params\":{\"_tokenId\":\"The identifier for an NFT.\"}},\"safeTransferFrom(address,address,uint256)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"safeTransferFrom(address,address,uint256,bytes)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_data\":\"Additional data with no specified format, sent in call to `_to`.\",\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"details\":\"Enables or disables approval for a third party (\\\"operator\\\") to manage all of `msg.sender`'s assets. It also emits the ApprovalForAll event. Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"True if the operators is approved, false to revoke approval.\",\"_operator\":\"Address to add to the set of authorized operators.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Interface identification is specified in ERC-165.\",\"params\":{\"_interfaceID\":\"Id of the interface\"}},\"tokenOfOwnerByIndex(address,uint256)\":{\"details\":\"Get token by index\"},\"tokenURI(uint256)\":{\"details\":\"Returns current token URI metadata\",\"params\":{\"_tokenId\":\"Token ID to fetch URI for.\"}},\"totalSupplyAt(uint256)\":{\"params\":{\"_block\":\"Block to calculate the total voting power at\"},\"returns\":{\"_0\":\"Total voting power at `_block`\"}},\"totalSupplyAtT(uint256)\":{\"details\":\"Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\",\"returns\":{\"_0\":\"Total voting power\"}},\"transferFrom(address,address,uint256)\":{\"details\":\"Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"user_point_history__ts(uint256,uint256)\":{\"params\":{\"_idx\":\"User epoch number\",\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Epoch time of the checkpoint\"}},\"withdraw(uint256)\":{\"details\":\"Only possible if the lock has expired\"}},\"stateVariables\":{\"ERC165_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC165\"},\"ERC721_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721\"},\"ERC721_METADATA_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721Metadata\"},\"_not_entered\":{\"details\":\"reentrancy guard\"},\"idToApprovals\":{\"details\":\"Mapping from NFT ID to approved address.\"},\"idToOwner\":{\"details\":\"Mapping from NFT ID to the address that owns it.\"},\"name\":{\"details\":\"Returns the token collection name.\"},\"ownerToNFTokenCount\":{\"details\":\"Mapping from owner address to count of his tokens.\"},\"ownerToNFTokenIdList\":{\"details\":\"Mapping from owner address to mapping of index to tokenIds\"},\"ownerToOperators\":{\"details\":\"Mapping from owner address to mapping of operator addresses.\"},\"supportedInterfaces\":{\"details\":\"Mapping of interface id to bool about whether or not it's supported\"},\"symbol\":{\"details\":\"Returns the token collection symbol.\"},\"tokenId\":{\"details\":\"Current count of token\"},\"tokenToOwnerIndex\":{\"details\":\"Mapping from NFT ID to index of owner\"}},\"title\":\"Voting Escrow\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DELEGATION_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the delegation struct used by the contract\"},\"DOMAIN_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the contract's domain\"},\"checkpoint()\":{\"notice\":\"Record global data to checkpoint\"},\"checkpoints(address,uint32)\":{\"notice\":\"A record of delegated token checkpoints for each account, by index\"},\"constructor\":{\"notice\":\"Contract constructor\"},\"create_lock(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\"},\"create_lock_for(uint256,uint256,address)\":{\"notice\":\"Deposit `_value` tokens for `_to` and lock for `_lock_duration`\"},\"delegate(address)\":{\"notice\":\"Delegate votes from `msg.sender` to `delegatee`\"},\"delegates(address)\":{\"notice\":\"Overrides the standard `Comp.sol` delegates mapping to return the delegator's own address if they haven't delegated. This avoids having to delegate to oneself.\"},\"deposit_for(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `_tokenId` and add to the lock\"},\"getVotes(address)\":{\"notice\":\"Gets the current votes balance for `account`\"},\"get_last_user_slope(uint256)\":{\"notice\":\"Get the most recently recorded rate of voting power decrease for `_tokenId`\"},\"increase_amount(uint256,uint256)\":{\"notice\":\"Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\"},\"increase_unlock_time(uint256,uint256)\":{\"notice\":\"Extend the unlock time for `_tokenId`\"},\"locked__end(uint256)\":{\"notice\":\"Get timestamp when `_tokenId`'s lock finishes\"},\"nonces(address)\":{\"notice\":\"A record of states for signing / validating signatures\"},\"numCheckpoints(address)\":{\"notice\":\"The number of checkpoints for each account\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"This works even if sender doesn't own any tokens at the time.\"},\"totalSupplyAt(uint256)\":{\"notice\":\"Calculate total voting power at some point in the past\"},\"totalSupplyAtT(uint256)\":{\"notice\":\"Calculate total voting power\"},\"transferFrom(address,address,uint256)\":{\"notice\":\"The caller is responsible to confirm that `_to` is capable of receiving NFTs or else they maybe be permanently lost.\"},\"user_point_history__ts(uint256,uint256)\":{\"notice\":\"Get the timestamp for checkpoint `_idx` for `_tokenId`\"},\"withdraw(uint256)\":{\"notice\":\"Withdraw all tokens for `_tokenId`\"}},\"notice\":\"veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFTVotes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VotingEscrow.sol\":\"VotingEscrow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VotingEscrow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IERC721, IERC721Metadata} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {IERC721Receiver} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {IERC20} from \\\"contracts/interfaces/IERC20.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\nimport {IVotingEscrow} from \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/// @title Voting Escrow\\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\\n enum DepositType {\\n DEPOSIT_FOR_TYPE,\\n CREATE_LOCK_TYPE,\\n INCREASE_LOCK_AMOUNT,\\n INCREASE_UNLOCK_TIME,\\n MERGE_TYPE\\n }\\n\\n struct LockedBalance {\\n int128 amount;\\n uint end;\\n }\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint ts;\\n uint blk; // block\\n }\\n /* We cannot really do block numbers per se b/c slope is per time, not per block\\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\\n * What we can do is to extrapolate ***At functions */\\n\\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\\n struct Checkpoint {\\n uint timestamp;\\n uint[] tokenIds;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Deposit(\\n address indexed provider,\\n uint tokenId,\\n uint value,\\n uint indexed locktime,\\n DepositType deposit_type,\\n uint ts\\n );\\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\\n event Supply(uint prevSupply, uint supply);\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n address public immutable token;\\n address public voter;\\n address public team;\\n address public artProxy;\\n\\n mapping(uint => Point) public point_history; // epoch -> unsigned point\\n\\n /// @dev Mapping of interface id to bool about whether or not it's supported\\n mapping(bytes4 => bool) internal supportedInterfaces;\\n\\n /// @dev ERC165 interface ID of ERC165\\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\\n\\n /// @dev ERC165 interface ID of ERC721\\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\\n\\n /// @dev ERC165 interface ID of ERC721Metadata\\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\\n\\n /// @dev Current count of token\\n uint internal tokenId;\\n\\n /// @notice Contract constructor\\n /// @param token_addr `FLOW` token address\\n constructor(address token_addr, address art_proxy) {\\n token = token_addr;\\n voter = msg.sender;\\n team = msg.sender;\\n artProxy = art_proxy;\\n\\n point_history[0].blk = block.number;\\n point_history[0].ts = block.timestamp;\\n\\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\\n\\n // mint-ish\\n emit Transfer(address(0), address(this), tokenId);\\n // burn-ish\\n emit Transfer(address(this), address(0), tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n MODIFIERS\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev reentrancy guard\\n uint8 internal constant _not_entered = 1;\\n uint8 internal constant _entered = 2;\\n uint8 internal _entered_state = 1;\\n modifier nonreentrant() {\\n require(_entered_state == _not_entered);\\n _entered_state = _entered;\\n _;\\n _entered_state = _not_entered;\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string constant public name = \\\"veNFT\\\";\\n string constant public symbol = \\\"veNFT\\\";\\n string constant public version = \\\"1.0.0\\\";\\n uint8 constant public decimals = 18;\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team);\\n team = _team;\\n }\\n\\n function setArtProxy(address _proxy) external {\\n require(msg.sender == team);\\n artProxy = _proxy;\\n }\\n\\n /// @dev Returns current token URI metadata\\n /// @param _tokenId Token ID to fetch URI for.\\n function tokenURI(uint _tokenId) external view returns (string memory) {\\n require(idToOwner[_tokenId] != address(0), \\\"Query for nonexistent token\\\");\\n LockedBalance memory _locked = locked[_tokenId];\\n return IVeArtProxy(artProxy)._tokenURI(\\n _tokenId,\\n _balanceOfNFT(_tokenId, block.timestamp),\\n _locked.end,\\n uint(int256(_locked.amount))\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 BALANCE/OWNER STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to the address that owns it.\\n mapping(uint => address) internal idToOwner;\\n\\n /// @dev Mapping from owner address to count of his tokens.\\n mapping(address => uint) internal ownerToNFTokenCount;\\n\\n /// @dev Returns the address of the owner of the NFT.\\n /// @param _tokenId The identifier for an NFT.\\n function ownerOf(uint _tokenId) public view returns (address) {\\n return idToOwner[_tokenId];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function _balance(address _owner) internal view returns (uint) {\\n return ownerToNFTokenCount[_owner];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function balanceOf(address _owner) external view returns (uint) {\\n return _balance(_owner);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 APPROVAL STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to approved address.\\n mapping(uint => address) internal idToApprovals;\\n\\n /// @dev Mapping from owner address to mapping of operator addresses.\\n mapping(address => mapping(address => bool)) internal ownerToOperators;\\n\\n mapping(uint => uint) public ownership_change;\\n\\n /// @dev Get the approved address for a single NFT.\\n /// @param _tokenId ID of the NFT to query the approval of.\\n function getApproved(uint _tokenId) external view returns (address) {\\n return idToApprovals[_tokenId];\\n }\\n\\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\\n /// @param _owner The address that owns the NFTs.\\n /// @param _operator The address that acts on behalf of the owner.\\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\\n return (ownerToOperators[_owner])[_operator];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\\n /// @param _approved Address to be approved for the given NFT ID.\\n /// @param _tokenId ID of the token to be approved.\\n function approve(address _approved, uint _tokenId) public {\\n address owner = idToOwner[_tokenId];\\n // Throws if `_tokenId` is not a valid NFT\\n require(owner != address(0));\\n // Throws if `_approved` is the current owner\\n require(_approved != owner);\\n // Check requirements\\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\\n require(senderIsOwner || senderIsApprovedForAll);\\n // Set the approval\\n idToApprovals[_tokenId] = _approved;\\n emit Approval(owner, _approved, _tokenId);\\n }\\n\\n /// @dev Enables or disables approval for a third party (\\\"operator\\\") to manage all of\\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\\n /// @notice This works even if sender doesn't own any tokens at the time.\\n /// @param _operator Address to add to the set of authorized operators.\\n /// @param _approved True if the operators is approved, false to revoke approval.\\n function setApprovalForAll(address _operator, bool _approved) external {\\n // Throws if `_operator` is the `msg.sender`\\n assert(_operator != msg.sender);\\n ownerToOperators[msg.sender][_operator] = _approved;\\n emit ApprovalForAll(msg.sender, _operator, _approved);\\n }\\n\\n /* TRANSFER FUNCTIONS */\\n /// @dev Clear an approval of a given address\\n /// Throws if `_owner` is not the current owner.\\n function _clearApproval(address _owner, uint _tokenId) internal {\\n // Throws if `_owner` is not the current owner\\n assert(idToOwner[_tokenId] == _owner);\\n if (idToApprovals[_tokenId] != address(0)) {\\n // Reset approvals\\n idToApprovals[_tokenId] = address(0);\\n }\\n }\\n\\n /// @dev Returns whether the given spender can transfer a given token ID\\n /// @param _spender address of the spender to query\\n /// @param _tokenId uint ID of the token to be transferred\\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\\n address owner = idToOwner[_tokenId];\\n bool spenderIsOwner = owner == _spender;\\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\\n }\\n\\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\\n return _isApprovedOrOwner(_spender, _tokenId);\\n }\\n\\n /// @dev Exeute transfer of a NFT.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_tokenId` is not a valid NFT.\\n function _transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n address _sender\\n ) internal {\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n // Check requirements\\n require(_isApprovedOrOwner(_sender, _tokenId));\\n // Clear approval. Throws if `_from` is not the current owner\\n _clearApproval(_from, _tokenId);\\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\\n _removeTokenFrom(_from, _tokenId);\\n // auto re-delegate\\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\\n // Add NFT\\n _addTokenTo(_to, _tokenId);\\n // Set the block of ownership transfer (for Flash NFT protection)\\n ownership_change[_tokenId] = block.number;\\n // Log the transfer\\n emit Transfer(_from, _to, _tokenId);\\n }\\n\\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\\n /// they maybe be permanently lost.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n safeTransferFrom(_from, _to, _tokenId, \\\"\\\");\\n }\\n\\n function _isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n uint size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n /// @param _data Additional data with no specified format, sent in call to `_to`.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n bytes memory _data\\n ) public {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n\\n if (_isContract(_to)) {\\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\\n revert(\\\"ERC721: ERC721Receiver rejected tokens\\\");\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert('ERC721: transfer to non ERC721Receiver implementer');\\n } else {\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC165 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Interface identification is specified in ERC-165.\\n /// @param _interfaceID Id of the interface\\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\\n return supportedInterfaces[_interfaceID];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from owner address to mapping of index to tokenIds\\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\\n\\n /// @dev Mapping from NFT ID to index of owner\\n mapping(uint => uint) internal tokenToOwnerIndex;\\n\\n /// @dev Get token by index\\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\\n return ownerToNFTokenIdList[_owner][_tokenIndex];\\n }\\n\\n /// @dev Add a NFT to an index mapping to a given address\\n /// @param _to address of the receiver\\n /// @param _tokenId uint ID Of the token to be added\\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\\n uint current_count = _balance(_to);\\n\\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\\n tokenToOwnerIndex[_tokenId] = current_count;\\n }\\n\\n /// @dev Add a NFT to a given address\\n /// Throws if `_tokenId` is owned by someone.\\n function _addTokenTo(address _to, uint _tokenId) internal {\\n // Throws if `_tokenId` is owned by someone\\n assert(idToOwner[_tokenId] == address(0));\\n // Change the owner\\n idToOwner[_tokenId] = _to;\\n // Update owner token index tracking\\n _addTokenToOwnerList(_to, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_to] += 1;\\n }\\n\\n /// @dev Function to mint tokens\\n /// Throws if `_to` is zero address.\\n /// Throws if `_tokenId` is owned by someone.\\n /// @param _to The address that will receive the minted tokens.\\n /// @param _tokenId The token id to mint.\\n /// @return A boolean that indicates if the operation was successful.\\n function _mint(address _to, uint _tokenId) internal returns (bool) {\\n // Throws if `_to` is zero address\\n assert(_to != address(0));\\n // checkpoint for gov\\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\\n // Add NFT. Throws if `_tokenId` is owned by someone\\n _addTokenTo(_to, _tokenId);\\n emit Transfer(address(0), _to, _tokenId);\\n return true;\\n }\\n\\n /// @dev Remove a NFT from an index mapping to a given address\\n /// @param _from address of the sender\\n /// @param _tokenId uint ID Of the token to be removed\\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\\n // Delete\\n uint current_count = _balance(_from) - 1;\\n uint current_index = tokenToOwnerIndex[_tokenId];\\n\\n if (current_count == current_index) {\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n } else {\\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\\n\\n // Add\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[lastTokenId] = current_index;\\n\\n // Delete\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n }\\n }\\n\\n /// @dev Remove a NFT from a given address\\n /// Throws if `_from` is not the current owner.\\n function _removeTokenFrom(address _from, uint _tokenId) internal {\\n // Throws if `_from` is not the current owner\\n assert(idToOwner[_tokenId] == _from);\\n // Change the owner\\n idToOwner[_tokenId] = address(0);\\n // Update owner token index tracking\\n _removeTokenFromOwnerList(_from, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_from] -= 1;\\n }\\n\\n function _burn(uint _tokenId) internal {\\n require(_isApprovedOrOwner(msg.sender, _tokenId), \\\"caller is not owner nor approved\\\");\\n\\n address owner = ownerOf(_tokenId);\\n\\n // Clear approval\\n approve(address(0), _tokenId);\\n // checkpoint for gov\\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\\n // Remove token\\n _removeTokenFrom(msg.sender, _tokenId);\\n emit Transfer(owner, address(0), _tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public user_point_epoch;\\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\\n mapping(uint => LockedBalance) public locked;\\n uint public epoch;\\n mapping(uint => int128) public slope_changes; // time -> signed slope change\\n uint public supply;\\n\\n uint internal constant WEEK = 1 weeks;\\n uint internal constant MAXTIME = 4 * 365 * 86400;\\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\\n uint internal constant MULTIPLIER = 1 ether;\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @return Value of the slope\\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\\n uint uepoch = user_point_epoch[_tokenId];\\n return user_point_history[_tokenId][uepoch].slope;\\n }\\n\\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @param _idx User epoch number\\n /// @return Epoch time of the checkpoint\\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\\n return user_point_history[_tokenId][_idx].ts;\\n }\\n\\n /// @notice Get timestamp when `_tokenId`'s lock finishes\\n /// @param _tokenId User NFT\\n /// @return Epoch time of the lock end\\n function locked__end(uint _tokenId) external view returns (uint) {\\n return locked[_tokenId].end;\\n }\\n\\n /// @notice Record global and per-user data to checkpoint\\n /// @param _tokenId NFT token ID. No user checkpoint if 0\\n /// @param old_locked Pevious locked amount / end lock time for the user\\n /// @param new_locked New locked amount / end lock time for the user\\n function _checkpoint(\\n uint _tokenId,\\n LockedBalance memory old_locked,\\n LockedBalance memory new_locked\\n ) internal {\\n Point memory u_old;\\n Point memory u_new;\\n int128 old_dslope = 0;\\n int128 new_dslope = 0;\\n uint _epoch = epoch;\\n\\n if (_tokenId != 0) {\\n // Calculate slopes and biases\\n // Kept at zero when they have to\\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\\n u_old.slope = old_locked.amount / iMAXTIME;\\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\\n }\\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\\n u_new.slope = new_locked.amount / iMAXTIME;\\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\\n }\\n\\n // Read values of scheduled changes in the slope\\n // old_locked.end can be in the past and in the future\\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\\n old_dslope = slope_changes[old_locked.end];\\n if (new_locked.end != 0) {\\n if (new_locked.end == old_locked.end) {\\n new_dslope = old_dslope;\\n } else {\\n new_dslope = slope_changes[new_locked.end];\\n }\\n }\\n }\\n\\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\\n if (_epoch > 0) {\\n last_point = point_history[_epoch];\\n }\\n uint last_checkpoint = last_point.ts;\\n // initial_last_point is used for extrapolation to calculate block number\\n // (approximately, for *At methods) and save them\\n // as we cannot figure that out exactly from inside the contract\\n Point memory initial_last_point = last_point;\\n uint block_slope = 0; // dblock/dt\\n if (block.timestamp > last_point.ts) {\\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\\n }\\n // If last point is already recorded in this block, slope=0\\n // But that's ok b/c we know the block in such case\\n\\n // Go over weeks to fill history and calculate what the current point is\\n {\\n uint t_i = (last_checkpoint / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n // Hopefully it won't happen that this won't get used in 5 years!\\n // If it does, users will be able to withdraw but vote weight will be broken\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > block.timestamp) {\\n t_i = block.timestamp;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\\n last_point.slope += d_slope;\\n if (last_point.bias < 0) {\\n // This can happen\\n last_point.bias = 0;\\n }\\n if (last_point.slope < 0) {\\n // This cannot happen - just in case\\n last_point.slope = 0;\\n }\\n last_checkpoint = t_i;\\n last_point.ts = t_i;\\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\\n _epoch += 1;\\n if (t_i == block.timestamp) {\\n last_point.blk = block.number;\\n break;\\n } else {\\n point_history[_epoch] = last_point;\\n }\\n }\\n }\\n\\n epoch = _epoch;\\n // Now point_history is filled until t=now\\n\\n if (_tokenId != 0) {\\n // If last point was in this block, the slope change has been applied already\\n // But in such case we have 0 slope(s)\\n last_point.slope += (u_new.slope - u_old.slope);\\n last_point.bias += (u_new.bias - u_old.bias);\\n if (last_point.slope < 0) {\\n last_point.slope = 0;\\n }\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n }\\n\\n // Record the changed point into history\\n point_history[_epoch] = last_point;\\n\\n if (_tokenId != 0) {\\n // Schedule the slope changes (slope is going down)\\n // We subtract new_user_slope from [new_locked.end]\\n // and add old_user_slope to [old_locked.end]\\n if (old_locked.end > block.timestamp) {\\n // old_dslope was - u_old.slope, so we cancel that\\n old_dslope += u_old.slope;\\n if (new_locked.end == old_locked.end) {\\n old_dslope -= u_new.slope; // It was a new deposit, not extension\\n }\\n slope_changes[old_locked.end] = old_dslope;\\n }\\n\\n if (new_locked.end > block.timestamp) {\\n if (new_locked.end > old_locked.end) {\\n new_dslope -= u_new.slope; // old slope disappeared at this point\\n slope_changes[new_locked.end] = new_dslope;\\n }\\n // else: we recorded it already in old_dslope\\n }\\n // Now handle user history\\n uint user_epoch = user_point_epoch[_tokenId] + 1;\\n\\n user_point_epoch[_tokenId] = user_epoch;\\n u_new.ts = block.timestamp;\\n u_new.blk = block.number;\\n user_point_history[_tokenId][user_epoch] = u_new;\\n }\\n }\\n\\n /// @notice Deposit and lock tokens for a user\\n /// @param _tokenId NFT that holds lock\\n /// @param _value Amount to deposit\\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\\n /// @param locked_balance Previous locked amount / timestamp\\n /// @param deposit_type The type of deposit\\n function _deposit_for(\\n uint _tokenId,\\n uint _value,\\n uint unlock_time,\\n LockedBalance memory locked_balance,\\n DepositType deposit_type\\n ) internal {\\n LockedBalance memory _locked = locked_balance;\\n uint supply_before = supply;\\n\\n supply = supply_before + _value;\\n LockedBalance memory old_locked;\\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\\n // Adding to existing lock, or if a lock is expired - creating a new one\\n _locked.amount += int128(int256(_value));\\n if (unlock_time != 0) {\\n _locked.end = unlock_time;\\n }\\n locked[_tokenId] = _locked;\\n\\n // Possibilities:\\n // Both old_locked.end could be current or expired (>/< block.timestamp)\\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\\n // _locked.end > block.timestamp (always)\\n _checkpoint(_tokenId, old_locked, _locked);\\n\\n address from = msg.sender;\\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\\n assert(IERC20(token).transferFrom(from, address(this), _value));\\n }\\n\\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\\n emit Supply(supply_before, supply_before + _value);\\n }\\n\\n function block_number() external view returns (uint) {\\n return block.number;\\n }\\n\\n /// @notice Record global data to checkpoint\\n function checkpoint() external {\\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\\n }\\n\\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\\n /// cannot extend their locktime and deposit for a brand new user\\n /// @param _tokenId lock NFT\\n /// @param _value Amount to add to user's lock\\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n require(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_value > 0); // dev: need non-zero value\\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n ++tokenId;\\n uint _tokenId = tokenId;\\n _mint(_to, _tokenId);\\n\\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\\n return _tokenId;\\n }\\n\\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, msg.sender);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, _to);\\n }\\n\\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\\n /// @param _value Amount of tokens to deposit and add to the lock\\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n assert(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\\n }\\n\\n /// @notice Extend the unlock time for `_tokenId`\\n /// @param _lock_duration New number of seconds until tokens unlock\\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_locked.end > block.timestamp, 'Lock expired');\\n require(_locked.amount > 0, 'Nothing is locked');\\n require(unlock_time > _locked.end, 'Can only increase lock duration');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\\n }\\n\\n /// @notice Withdraw all tokens for `_tokenId`\\n /// @dev Only possible if the lock has expired\\n function withdraw(uint _tokenId) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n require(block.timestamp >= _locked.end, \\\"The lock didn't expire\\\");\\n uint value = uint(int256(_locked.amount));\\n\\n locked[_tokenId] = LockedBalance(0,0);\\n uint supply_before = supply;\\n supply = supply_before - value;\\n\\n // old_locked can have either expired <= timestamp or zero end\\n // _locked has only 0 end\\n // Both can have >= 0 amount\\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\\n\\n assert(IERC20(token).transfer(msg.sender, value));\\n\\n // Burn the NFT\\n _burn(_tokenId);\\n\\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\\n emit Supply(supply_before, supply_before - value);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\\n // They measure the weights for the purpose of voting, so they don't represent\\n // real coins.\\n\\n /// @notice Binary search to estimate timestamp for block number\\n /// @param _block Block to find\\n /// @param max_epoch Don't go beyond this epoch\\n /// @return Approximate timestamp for block\\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\\n // Binary search\\n uint _min = 0;\\n uint _max = max_epoch;\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (point_history[_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n /// @notice Get the current voting power for `_tokenId`\\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\\n /// @param _tokenId NFT for lock\\n /// @param _t Epoch time to return voting power at\\n /// @return User voting power\\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\\n uint _epoch = user_point_epoch[_tokenId];\\n if (_epoch == 0) {\\n return 0;\\n } else {\\n Point memory last_point = user_point_history[_tokenId][_epoch];\\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(int256(last_point.bias));\\n }\\n }\\n\\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\\n if (ownership_change[_tokenId] == block.number) return 0;\\n return _balanceOfNFT(_tokenId, block.timestamp);\\n }\\n\\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\\n return _balanceOfNFT(_tokenId, _t);\\n }\\n\\n /// @notice Measure voting power of `_tokenId` at block height `_block`\\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\\n /// @param _tokenId User's wallet NFT\\n /// @param _block Block to calculate the voting power at\\n /// @return Voting power\\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\\n // Copying and pasting totalSupply code because Vyper cannot pass by\\n // reference yet\\n assert(_block <= block.number);\\n\\n // Binary search\\n uint _min = 0;\\n uint _max = user_point_epoch[_tokenId];\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (user_point_history[_tokenId][_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n\\n Point memory upoint = user_point_history[_tokenId][_min];\\n\\n uint max_epoch = epoch;\\n uint _epoch = _find_block_epoch(_block, max_epoch);\\n Point memory point_0 = point_history[_epoch];\\n uint d_block = 0;\\n uint d_t = 0;\\n if (_epoch < max_epoch) {\\n Point memory point_1 = point_history[_epoch + 1];\\n d_block = point_1.blk - point_0.blk;\\n d_t = point_1.ts - point_0.ts;\\n } else {\\n d_block = block.number - point_0.blk;\\n d_t = block.timestamp - point_0.ts;\\n }\\n uint block_time = point_0.ts;\\n if (d_block != 0) {\\n block_time += (d_t * (_block - point_0.blk)) / d_block;\\n }\\n\\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\\n if (upoint.bias >= 0) {\\n return uint(uint128(upoint.bias));\\n } else {\\n return 0;\\n }\\n }\\n\\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\\n return _balanceOfAtNFT(_tokenId, _block);\\n }\\n\\n /// @notice Calculate total voting power at some point in the past\\n /// @param _block Block to calculate the total voting power at\\n /// @return Total voting power at `_block`\\n function totalSupplyAt(uint _block) external view returns (uint) {\\n assert(_block <= block.number);\\n uint _epoch = epoch;\\n uint target_epoch = _find_block_epoch(_block, _epoch);\\n\\n Point memory point = point_history[target_epoch];\\n uint dt = 0;\\n if (target_epoch < _epoch) {\\n Point memory point_next = point_history[target_epoch + 1];\\n if (point.blk != point_next.blk) {\\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\\n }\\n } else {\\n if (point.blk != block.number) {\\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\\n }\\n }\\n // Now dt contains info on how far are we beyond point\\n return _supply_at(point, point.ts + dt);\\n }\\n /// @notice Calculate total voting power at some point in the past\\n /// @param point The point (bias/slope) to start search from\\n /// @param t Time to calculate the total voting power at\\n /// @return Total voting power at that time\\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\\n Point memory last_point = point;\\n uint t_i = (last_point.ts / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > t) {\\n t_i = t;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\\n if (t_i == t) {\\n break;\\n }\\n last_point.slope += d_slope;\\n last_point.ts = t_i;\\n }\\n\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(uint128(last_point.bias));\\n }\\n\\n function totalSupply() external view returns (uint) {\\n return totalSupplyAtT(block.timestamp);\\n }\\n\\n /// @notice Calculate total voting power\\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\\n /// @return Total voting power\\n function totalSupplyAtT(uint t) public view returns (uint) {\\n uint _epoch = epoch;\\n Point memory last_point = point_history[_epoch];\\n return _supply_at(last_point, t);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public attachments;\\n mapping(uint => bool) public voted;\\n\\n function setVoter(address _voter) external {\\n require(msg.sender == voter);\\n voter = _voter;\\n }\\n\\n function voting(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = true;\\n }\\n\\n function abstain(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = false;\\n }\\n\\n function attach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] + 1;\\n }\\n\\n function detach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] - 1;\\n }\\n\\n function merge(uint _from, uint _to) external {\\n require(attachments[_from] == 0 && !voted[_from], \\\"attached\\\");\\n require(_from != _to);\\n require(_isApprovedOrOwner(msg.sender, _from));\\n require(_isApprovedOrOwner(msg.sender, _to));\\n\\n LockedBalance memory _locked0 = locked[_from];\\n LockedBalance memory _locked1 = locked[_to];\\n uint value0 = uint(int256(_locked0.amount));\\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\\n\\n locked[_from] = LockedBalance(0, 0);\\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\\n _burn(_from);\\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of each accounts delegate\\n mapping(address => address) private _delegates;\\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\\n\\n /// @notice A record of delegated token checkpoints for each account, by index\\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint32) public numCheckpoints;\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping(address => uint) public nonces;\\n\\n /**\\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\\n * the delegator's own address if they haven't delegated.\\n * This avoids having to delegate to oneself.\\n */\\n function delegates(address delegator) public view returns (address) {\\n address current = _delegates[delegator];\\n return current == address(0) ? delegator : current;\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getVotes(address account) external view returns (uint) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n votes = votes + _balanceOfNFT(tId, block.timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint storage cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPastVotes(address account, uint timestamp)\\n public\\n view\\n returns (uint)\\n {\\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\\n // Sum votes\\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n // Use the provided input timestamp here to get the right decay\\n votes = votes + _balanceOfNFT(tId, timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\\n return totalSupplyAtT(timestamp);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _moveTokenDelegates(\\n address srcRep,\\n address dstRep,\\n uint _tokenId\\n ) internal {\\n if (srcRep != dstRep && _tokenId > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except _tokenId\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (tId != _tokenId) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n // All the same plus _tokenId\\n require(\\n dstRepOld.length + 1 <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n dstRepNew.push(_tokenId);\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _findWhatCheckpointToWrite(address account)\\n internal\\n view\\n returns (uint32)\\n {\\n uint _timestamp = block.timestamp;\\n uint32 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n return _nCheckPoints - 1;\\n } else {\\n return _nCheckPoints;\\n }\\n }\\n\\n function _moveAllDelegates(\\n address owner,\\n address srcRep,\\n address dstRep\\n ) internal {\\n // You can only redelegate what you own\\n if (srcRep != dstRep) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except what owner owns\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (idToOwner[tId] != owner) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n uint ownerTokenCount = ownerToNFTokenCount[owner];\\n require(\\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n // All the same\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n // Plus all that's owned\\n for (uint i = 0; i < ownerTokenCount; i++) {\\n uint tId = ownerToNFTokenIdList[owner][i];\\n dstRepNew.push(tId);\\n }\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\\n address currentDelegate = delegates(delegator);\\n\\n _delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n _moveAllDelegates(delegator, currentDelegate, delegatee);\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n if (delegatee == address(0)) delegatee = msg.sender;\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n function delegateBySig(\\n address delegatee,\\n uint nonce,\\n uint expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public {\\n bytes32 domainSeparator = keccak256(\\n abi.encode(\\n DOMAIN_TYPEHASH,\\n keccak256(bytes(name)),\\n keccak256(bytes(version)),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 structHash = keccak256(\\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash)\\n );\\n address signatory = ecrecover(digest, v, r, s);\\n require(\\n signatory != address(0),\\n \\\"VotingEscrow::delegateBySig: invalid signature\\\"\\n );\\n require(\\n nonce == nonces[signatory]++,\\n \\\"VotingEscrow::delegateBySig: invalid nonce\\\"\\n );\\n require(\\n block.timestamp <= expiry,\\n \\\"VotingEscrow::delegateBySig: signature expired\\\"\\n );\\n return _delegate(signatory, delegatee);\\n }\\n}\\n\",\"keccak256\":\"0x7109ed9d84b5504fe5d4c73d5a10997a0b73f2f4d45813ce5e161997d405fd73\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x41bbb2c41036ca64b2f6c9e973e8cfaa113ebc42af86702cd0d267f915a7e886\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a06040526006805460ff191660011790553480156200001e57600080fd5b5060405162004a1c38038062004a1c8339810160408190526200004191620001b8565b6001600160a01b0382811660805260008054336001600160a01b031991821681178355600180548316909117815560028054909216938516939093179055437f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f0155427f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f005560046020527f9fe05126d2d9ecf60592e254dead906a4b2e492f36cca727682c38e9008c6ac1805460ff1990811684179091557f4267c0a6fd96b7a87f183ee8744f24d011423cd0e0142b3f563f183d8d9a456b8054821684179055635b5e139f60e01b82527e24030bcf4927897dffe721c2d8dda4bfd8910861687c42b03a463b43b04147805490911690921790915560055460405190913091600080516020620049fc833981519152908290a46005546040516000903090600080516020620049fc833981519152908390a45050620001f0565b80516001600160a01b0381168114620001b357600080fd5b919050565b60008060408385031215620001cc57600080fd5b620001d7836200019b565b9150620001e7602084016200019b565b90509250929050565b6080516147e26200021a60003960008181610b220152818161101801526133b501526147e26000f3fe608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea264697066735822122098b1358028f64f409b693ae89fbabe991f348f6d1fe6dea27f8f63e0a686c2fd64736f6c634300080d0033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea264697066735822122098b1358028f64f409b693ae89fbabe991f348f6d1fe6dea27f8f63e0a686c2fd64736f6c634300080d0033", "devdoc": { "author": "Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)", "details": "Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).", diff --git a/deployments/arbitrumGoerli/solcInputs/5e3bd610e528b3bcf2b3d4c538d2d553.json b/deployments/arbitrumGoerli/solcInputs/5e3bd610e528b3bcf2b3d4c538d2d553.json deleted file mode 100644 index e4e82ece..00000000 --- a/deployments/arbitrumGoerli/solcInputs/5e3bd610e528b3bcf2b3d4c538d2d553.json +++ /dev/null @@ -1,238 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/ExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/factories/BribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n\n// if this imports int and ext bribe why is the the gauge factory asking for those address as if they are deployed to an address.\n" - }, - "contracts/factories/GaugeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" - }, - "contracts/factories/PairFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" - }, - "contracts/factories/WrappedExternalBribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" - }, - "contracts/Flow.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IFlow.sol\";\n\ncontract Flow is IFlow {\n\n string public constant name = \"Velocimeter\";\n string public constant symbol = \"FLOW\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" - }, - "contracts/FlowGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract FlowGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velocimeter Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" - }, - "contracts/Gauge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/governance/L2Governor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" - }, - "contracts/governance/L2GovernorCountingSimple.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" - }, - "contracts/governance/L2GovernorVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" - }, - "contracts/governance/L2GovernorVotesQuorumFraction.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" - }, - "contracts/interfaces/IBribe.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IBribeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IERC20.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" - }, - "contracts/interfaces/IFlow.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IFlow {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" - }, - "contracts/interfaces/IGauge.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" - }, - "contracts/interfaces/IGaugeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IMinter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" - }, - "contracts/interfaces/IPair.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IPairCallee.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" - }, - "contracts/interfaces/IPairFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" - }, - "contracts/interfaces/IRewardsDistributor.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" - }, - "contracts/interfaces/IRouter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" - }, - "contracts/interfaces/IVeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" - }, - "contracts/interfaces/IVoter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" - }, - "contracts/interfaces/IVotingEscrow.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" - }, - "contracts/interfaces/IWETH.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" - }, - "contracts/InternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/libraries/Base64.sol": { - "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" - }, - "contracts/libraries/Math.sol": { - "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" - }, - "contracts/Minter.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IFlow.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IFlow public immutable _flow;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M FLOW (FLOW has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _flow = IFlow(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _flow.mint(address(this), max);\n _flow.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _flow.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _flowTotal = _flow.totalSupply();\n return\n (((((_minted * _veTotal) / _flowTotal) * _veTotal) / _flowTotal) *\n _veTotal) /\n _flowTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _flow.balanceOf(address(this));\n if (_balanceOf < _required) {\n _flow.mint(address(this), _required - _balanceOf);\n }\n\n require(_flow.transfer(team, _teamEmissions));\n require(_flow.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _flow.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" - }, - "contracts/Pair.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/PairFees.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" - }, - "contracts/redeem/MerkleClaim.sol": { - "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IFlow} from \"contracts/interfaces/IFlow.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims FLOW for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice FLOW token to claim\n IFlow public immutable FLOW;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _flow address\n /// @param _merkleRoot of claimees\n constructor(address _flow, bytes32 _merkleRoot) {\n FLOW = IFlow(_flow);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(FLOW.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" - }, - "contracts/redeem/RedemptionReceiver.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IFlow.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + FLOW\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IFlow public immutable FLOW;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableFLOW;\n uint256 public leftoverFLOW;\n\n constructor(\n address _usdc,\n address _flow,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n FLOW = IFlow(_flow);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableFLOW);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableFLOW\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableFLOW = _redeemableFLOW;\n leftoverFLOW = _redeemableFLOW;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableFLOW);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfFLOW)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata FLOW\n shareOfFLOW = (amountWEVE * redeemableFLOW) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfFLOW) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverFLOW -= shareOfFLOW; // this will revert if underflows\n require(\n FLOW.claim(redemptionAddress, shareOfFLOW),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" - }, - "contracts/redeem/RedemptionSender.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" - }, - "contracts/RewardsDistributor.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" - }, - "contracts/Router.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velocimeter locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" - }, - "contracts/VelocimeterLibrary.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelocimeterLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" - }, - "contracts/Voter.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velocimeter pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VotingEscrow.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `FLOW` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" - }, - "contracts/WrappedExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - }, - "metadata": { - "useLiteralContent": true - }, - "libraries": { - "": { - "__CACHE_BREAKER__": "0x0000000000000031363734383938323035393133" - } - } - } -} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/98b870afa86e9d5388a96f4e867892a9.json b/deployments/arbitrumGoerli/solcInputs/98b870afa86e9d5388a96f4e867892a9.json deleted file mode 100644 index bc1c3ae0..00000000 --- a/deployments/arbitrumGoerli/solcInputs/98b870afa86e9d5388a96f4e867892a9.json +++ /dev/null @@ -1,238 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/ExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/factories/BribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport 'contracts/InternalBribe.sol';\nimport 'contracts/ExternalBribe.sol';\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\n return last_external_bribe;\n }\n}\n\n// if this imports int and ext bribe why is the the gauge factory asking for those address as if they are deployed to an address.\n" - }, - "contracts/factories/GaugeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" - }, - "contracts/factories/PairFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" - }, - "contracts/factories/WrappedExternalBribeFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" - }, - "contracts/Flow.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IFlow.sol\";\n\ncontract Flow is IFlow {\n\n string public constant name = \"Velocimeter\";\n string public constant symbol = \"FLOW\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" - }, - "contracts/FlowGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract FlowGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velocimeter Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" - }, - "contracts/Gauge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/governance/L2Governor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" - }, - "contracts/governance/L2GovernorCountingSimple.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" - }, - "contracts/governance/L2GovernorVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" - }, - "contracts/governance/L2GovernorVotesQuorumFraction.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" - }, - "contracts/interfaces/IBribe.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IBribeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IERC20.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" - }, - "contracts/interfaces/IFlow.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IFlow {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" - }, - "contracts/interfaces/IGauge.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" - }, - "contracts/interfaces/IGaugeFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" - }, - "contracts/interfaces/IMinter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" - }, - "contracts/interfaces/IPair.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" - }, - "contracts/interfaces/IPairCallee.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" - }, - "contracts/interfaces/IPairFactory.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" - }, - "contracts/interfaces/IRewardsDistributor.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" - }, - "contracts/interfaces/IRouter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" - }, - "contracts/interfaces/IVeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" - }, - "contracts/interfaces/IVoter.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" - }, - "contracts/interfaces/IVotingEscrow.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" - }, - "contracts/interfaces/IWETH.sol": { - "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" - }, - "contracts/InternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/libraries/Base64.sol": { - "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" - }, - "contracts/libraries/Math.sol": { - "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" - }, - "contracts/Minter.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IFlow.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IFlow public immutable _flow;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M FLOW (FLOW has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _flow = IFlow(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _flow.mint(address(this), max);\n _flow.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _flow.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _flowTotal = _flow.totalSupply();\n return\n (((((_minted * _veTotal) / _flowTotal) * _veTotal) / _flowTotal) *\n _veTotal) /\n _flowTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _flow.balanceOf(address(this));\n if (_balanceOf < _required) {\n _flow.mint(address(this), _required - _balanceOf);\n }\n\n require(_flow.transfer(team, _teamEmissions));\n require(_flow.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _flow.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" - }, - "contracts/Pair.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/PairFees.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" - }, - "contracts/redeem/MerkleClaim.sol": { - "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IFlow} from \"contracts/interfaces/IFlow.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims FLOW for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice FLOW token to claim\n IFlow public immutable FLOW;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _flow address\n /// @param _merkleRoot of claimees\n constructor(address _flow, bytes32 _merkleRoot) {\n FLOW = IFlow(_flow);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(FLOW.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" - }, - "contracts/redeem/RedemptionReceiver.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IFlow.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + FLOW\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IFlow public immutable FLOW;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableFLOW;\n uint256 public leftoverFLOW;\n\n constructor(\n address _usdc,\n address _flow,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n FLOW = IFlow(_flow);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableFLOW);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableFLOW\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableFLOW = _redeemableFLOW;\n leftoverFLOW = _redeemableFLOW;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableFLOW);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfFLOW)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata FLOW\n shareOfFLOW = (amountWEVE * redeemableFLOW) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfFLOW) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverFLOW -= shareOfFLOW; // this will revert if underflows\n require(\n FLOW.claim(redemptionAddress, shareOfFLOW),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" - }, - "contracts/redeem/RedemptionSender.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" - }, - "contracts/RewardsDistributor.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" - }, - "contracts/Router.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VeArtProxy.sol": { - "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velocimeter locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" - }, - "contracts/VelocimeterLibrary.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelocimeterLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" - }, - "contracts/Voter.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velocimeter pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "contracts/VotingEscrow.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `FLOW` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" - }, - "contracts/WrappedExternalBribe.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" - }, - "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { - "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" - }, - "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - }, - "metadata": { - "useLiteralContent": true - }, - "libraries": { - "": { - "__CACHE_BREAKER__": "0x0000000000000031363734393030323136323532" - } - } - } -} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/539b862778415c77e4d39b17addb6c5e.json b/deployments/arbitrumGoerli/solcInputs/d2a2160297444b93438826228d1e185d.json similarity index 99% rename from deployments/arbitrumGoerli/solcInputs/539b862778415c77e4d39b17addb6c5e.json rename to deployments/arbitrumGoerli/solcInputs/d2a2160297444b93438826228d1e185d.json index 41c1d6e5..b1e2fb90 100644 --- a/deployments/arbitrumGoerli/solcInputs/539b862778415c77e4d39b17addb6c5e.json +++ b/deployments/arbitrumGoerli/solcInputs/d2a2160297444b93438826228d1e185d.json @@ -231,7 +231,7 @@ }, "libraries": { "": { - "__CACHE_BREAKER__": "0x0000000000000031363734393030303739343537" + "__CACHE_BREAKER__": "0x0000000000000031363734393838363334363530" } } } diff --git a/dist/deploy/00_velo.d.ts b/dist/deploy/00_velo.d.ts index d4011bce..2255cecc 100644 --- a/dist/deploy/00_velo.d.ts +++ b/dist/deploy/00_velo.d.ts @@ -1,3 +1,3 @@ -import { DeployFunction } from 'hardhat-deploy/types' -declare const func: DeployFunction -export default func +import { DeployFunction } from 'hardhat-deploy/types'; +declare const func: DeployFunction; +export default func; diff --git a/dist/deploy/00_velo.js b/dist/deploy/00_velo.js index e5b7d4cb..1e786acb 100644 --- a/dist/deploy/00_velo.js +++ b/dist/deploy/00_velo.js @@ -1,16 +1,16 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); const func = async function (hre) { - const { deployments, getNamedAccounts } = hre - const { deploy } = deployments - const { deployer } = await getNamedAccounts() - await deploy('Flow', { - from: deployer, - args: [], - log: true, - skipIfAlreadyDeployed: false - }) -} -exports.default = func -func.tags = ['Flow'] -func.id = 'flow' + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + await deploy('Flow', { + from: deployer, + args: [], + log: true, + skipIfAlreadyDeployed: false + }); +}; +exports.default = func; +func.tags = ['Flow']; +func.id = 'flow'; diff --git a/dist/deploy/01_gaugeFactory.d.ts b/dist/deploy/01_gaugeFactory.d.ts index 68b368bb..2255cecc 100644 --- a/dist/deploy/01_gaugeFactory.d.ts +++ b/dist/deploy/01_gaugeFactory.d.ts @@ -1,3 +1,3 @@ -import { DeployFunction } from "hardhat-deploy/types"; +import { DeployFunction } from 'hardhat-deploy/types'; declare const func: DeployFunction; export default func; diff --git a/dist/deploy/01_gaugeFactory.js b/dist/deploy/01_gaugeFactory.js index d930ff1a..950278e1 100644 --- a/dist/deploy/01_gaugeFactory.js +++ b/dist/deploy/01_gaugeFactory.js @@ -1,16 +1,16 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); const func = async function (hre) { - const { deployments, getNamedAccounts } = hre - const { deploy } = deployments - const { deployer } = await getNamedAccounts() - await deploy('GaugeFactory', { - from: deployer, - args: [], - log: true, - skipIfAlreadyDeployed: false - }) -} -exports.default = func -func.tags = ['GaugeFactory'] -func.id = 'gaugeFactory' + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + await deploy('GaugeFactory', { + from: deployer, + args: [], + log: true, + skipIfAlreadyDeployed: false + }); +}; +exports.default = func; +func.tags = ['GaugeFactory']; +func.id = 'gaugeFactory'; diff --git a/dist/deploy/02_bribeFactory.d.ts b/dist/deploy/02_bribeFactory.d.ts index 68b368bb..2255cecc 100644 --- a/dist/deploy/02_bribeFactory.d.ts +++ b/dist/deploy/02_bribeFactory.d.ts @@ -1,3 +1,3 @@ -import { DeployFunction } from "hardhat-deploy/types"; +import { DeployFunction } from 'hardhat-deploy/types'; declare const func: DeployFunction; export default func; diff --git a/dist/deploy/02_bribeFactory.js b/dist/deploy/02_bribeFactory.js index 930c9c81..e551ecd2 100644 --- a/dist/deploy/02_bribeFactory.js +++ b/dist/deploy/02_bribeFactory.js @@ -1,16 +1,16 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); const func = async function (hre) { - const { deployments, getNamedAccounts } = hre - const { deploy } = deployments - const { deployer } = await getNamedAccounts() - await deploy('BribeFactory', { - from: deployer, - args: [], - log: true, - skipIfAlreadyDeployed: false - }) -} -exports.default = func -func.tags = ['BribeFactory'] -func.id = 'bribeFactory' + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + await deploy('BribeFactory', { + from: deployer, + args: [], + log: true, + skipIfAlreadyDeployed: false + }); +}; +exports.default = func; +func.tags = ['BribeFactory']; +func.id = 'bribeFactory'; diff --git a/dist/deploy/04_pairFactory.d.ts b/dist/deploy/04_pairFactory.d.ts index 68b368bb..2255cecc 100644 --- a/dist/deploy/04_pairFactory.d.ts +++ b/dist/deploy/04_pairFactory.d.ts @@ -1,3 +1,3 @@ -import { DeployFunction } from "hardhat-deploy/types"; +import { DeployFunction } from 'hardhat-deploy/types'; declare const func: DeployFunction; export default func; diff --git a/dist/deploy/04_pairFactory.js b/dist/deploy/04_pairFactory.js index 38d019b0..da9eea4a 100644 --- a/dist/deploy/04_pairFactory.js +++ b/dist/deploy/04_pairFactory.js @@ -1,16 +1,16 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); const func = async function (hre) { - const { deployments, getNamedAccounts } = hre - const { deploy } = deployments - const { deployer } = await getNamedAccounts() - await deploy('PairFactory', { - from: deployer, - args: [], - log: true, - skipIfAlreadyDeployed: false - }) -} -exports.default = func -func.tags = ['PairFactory'] -func.id = 'pairFactory' + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + await deploy('PairFactory', { + from: deployer, + args: [], + log: true, + skipIfAlreadyDeployed: false + }); +}; +exports.default = func; +func.tags = ['PairFactory']; +func.id = 'pairFactory'; diff --git a/dist/deploy/05_router.d.ts b/dist/deploy/05_router.d.ts index 68b368bb..2255cecc 100644 --- a/dist/deploy/05_router.d.ts +++ b/dist/deploy/05_router.d.ts @@ -1,3 +1,3 @@ -import { DeployFunction } from "hardhat-deploy/types"; +import { DeployFunction } from 'hardhat-deploy/types'; declare const func: DeployFunction; export default func; diff --git a/dist/deploy/05_router.js b/dist/deploy/05_router.js index d794e0dd..ad7b5da0 100644 --- a/dist/deploy/05_router.js +++ b/dist/deploy/05_router.js @@ -1,26 +1,22 @@ -'use strict' -var __importDefault = - (this && this.__importDefault) || - function (mod) { - return mod && mod.__esModule ? mod : { default: mod } - } -Object.defineProperty(exports, '__esModule', { value: true }) -const arbTestnetConfig_1 = __importDefault( - require('../tasks/deploy/constants/arbConfig') -) -const ARB_TEST_CONFIG = arbTestnetConfig_1.default +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const arbConfig_1 = __importDefault(require("../tasks/deploy/constants/arbConfig")); +const ARB_TEST_CONFIG = arbConfig_1.default; const func = async function (hre) { - const { deployments, getNamedAccounts } = hre - const { deploy } = deployments - const { deployer } = await getNamedAccounts() - const pairFactory = await deployments.get('PairFactory') - await deploy('Router', { - from: deployer, - args: [pairFactory.address, ARB_TEST_CONFIG.WETH], - log: true, - skipIfAlreadyDeployed: false - }) -} -exports.default = func -func.tags = ['Router'] -func.id = 'router' + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + const pairFactory = await deployments.get('PairFactory'); + await deploy('Router', { + from: deployer, + args: [pairFactory.address, ARB_TEST_CONFIG.WETH], + log: true, + skipIfAlreadyDeployed: false + }); +}; +exports.default = func; +func.tags = ['Router']; +func.id = 'router'; diff --git a/dist/deploy/06_library.d.ts b/dist/deploy/06_library.d.ts index 68b368bb..2255cecc 100644 --- a/dist/deploy/06_library.d.ts +++ b/dist/deploy/06_library.d.ts @@ -1,3 +1,3 @@ -import { DeployFunction } from "hardhat-deploy/types"; +import { DeployFunction } from 'hardhat-deploy/types'; declare const func: DeployFunction; export default func; diff --git a/dist/deploy/06_library.js b/dist/deploy/06_library.js index 536855d7..040d5615 100644 --- a/dist/deploy/06_library.js +++ b/dist/deploy/06_library.js @@ -1,17 +1,17 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); const func = async function (hre) { - const { deployments, getNamedAccounts } = hre - const { deploy } = deployments - const { deployer } = await getNamedAccounts() - const router = await deployments.get('Router') - await deploy('VelocimeterLibrary', { - from: deployer, - args: [router.address], - log: true, - skipIfAlreadyDeployed: false - }) -} -exports.default = func -func.tags = ['VelocimeterLibrary'] -func.id = 'velodromeLibrary' + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + const router = await deployments.get('Router'); + await deploy('VelocimeterLibrary', { + from: deployer, + args: [router.address], + log: true, + skipIfAlreadyDeployed: false + }); +}; +exports.default = func; +func.tags = ['VelocimeterLibrary']; +func.id = 'velocimeterLibrary'; diff --git a/dist/deploy/07_veArtProxy.d.ts b/dist/deploy/07_veArtProxy.d.ts index 68b368bb..2255cecc 100644 --- a/dist/deploy/07_veArtProxy.d.ts +++ b/dist/deploy/07_veArtProxy.d.ts @@ -1,3 +1,3 @@ -import { DeployFunction } from "hardhat-deploy/types"; +import { DeployFunction } from 'hardhat-deploy/types'; declare const func: DeployFunction; export default func; diff --git a/dist/deploy/07_veArtProxy.js b/dist/deploy/07_veArtProxy.js index 46ed538b..bc6cfdef 100644 --- a/dist/deploy/07_veArtProxy.js +++ b/dist/deploy/07_veArtProxy.js @@ -1,16 +1,16 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); const func = async function (hre) { - const { deployments, getNamedAccounts } = hre - const { deploy } = deployments - const { deployer } = await getNamedAccounts() - await deploy('VeArtProxy', { - from: deployer, - args: [], - log: true, - skipIfAlreadyDeployed: false - }) -} -exports.default = func -func.tags = ['VeArtProxy'] -func.id = 'veArtProxy' + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + await deploy('VeArtProxy', { + from: deployer, + args: [], + log: true, + skipIfAlreadyDeployed: false + }); +}; +exports.default = func; +func.tags = ['VeArtProxy']; +func.id = 'veArtProxy'; diff --git a/dist/deploy/08_votingEscrow.d.ts b/dist/deploy/08_votingEscrow.d.ts index 68b368bb..2255cecc 100644 --- a/dist/deploy/08_votingEscrow.d.ts +++ b/dist/deploy/08_votingEscrow.d.ts @@ -1,3 +1,3 @@ -import { DeployFunction } from "hardhat-deploy/types"; +import { DeployFunction } from 'hardhat-deploy/types'; declare const func: DeployFunction; export default func; diff --git a/dist/deploy/08_votingEscrow.js b/dist/deploy/08_votingEscrow.js index 6033cd1a..17a5120d 100644 --- a/dist/deploy/08_votingEscrow.js +++ b/dist/deploy/08_votingEscrow.js @@ -1,18 +1,18 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); const func = async function (hre) { - const { deployments, getNamedAccounts } = hre - const { deploy } = deployments - const { deployer } = await getNamedAccounts() - const flow = await deployments.get('Flow') - const veArtProxy = await deployments.get('VeArtProxy') - await deploy('VotingEscrow', { - from: deployer, - args: [flow.address, veArtProxy.address], - log: true, - skipIfAlreadyDeployed: false - }) -} -exports.default = func -func.tags = ['VotingEscrow'] -func.id = 'votingEscrow' + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + const flow = await deployments.get('Flow'); + const veArtProxy = await deployments.get('VeArtProxy'); + await deploy('VotingEscrow', { + from: deployer, + args: [flow.address, veArtProxy.address], + log: true, + skipIfAlreadyDeployed: false + }); +}; +exports.default = func; +func.tags = ['VotingEscrow']; +func.id = 'votingEscrow'; diff --git a/dist/deploy/09_rewardsDist.d.ts b/dist/deploy/09_rewardsDist.d.ts index 68b368bb..2255cecc 100644 --- a/dist/deploy/09_rewardsDist.d.ts +++ b/dist/deploy/09_rewardsDist.d.ts @@ -1,3 +1,3 @@ -import { DeployFunction } from "hardhat-deploy/types"; +import { DeployFunction } from 'hardhat-deploy/types'; declare const func: DeployFunction; export default func; diff --git a/dist/deploy/09_rewardsDist.js b/dist/deploy/09_rewardsDist.js index c41fcb9b..9a3f90bb 100644 --- a/dist/deploy/09_rewardsDist.js +++ b/dist/deploy/09_rewardsDist.js @@ -1,17 +1,17 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); const func = async function (hre) { - const { deployments, getNamedAccounts } = hre - const { deploy } = deployments - const { deployer } = await getNamedAccounts() - const escrow = await deployments.get('VotingEscrow') - await deploy('RewardsDistributor', { - from: deployer, - args: [escrow.address], - log: true, - skipIfAlreadyDeployed: false - }) -} -exports.default = func -func.tags = ['RewardsDistributor'] -func.id = 'rewardsDistributor' + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + const escrow = await deployments.get('VotingEscrow'); + await deploy('RewardsDistributor', { + from: deployer, + args: [escrow.address], + log: true, + skipIfAlreadyDeployed: false + }); +}; +exports.default = func; +func.tags = ['RewardsDistributor']; +func.id = 'rewardsDistributor'; diff --git a/dist/deploy/10_voter.d.ts b/dist/deploy/10_voter.d.ts index 68b368bb..2255cecc 100644 --- a/dist/deploy/10_voter.d.ts +++ b/dist/deploy/10_voter.d.ts @@ -1,3 +1,3 @@ -import { DeployFunction } from "hardhat-deploy/types"; +import { DeployFunction } from 'hardhat-deploy/types'; declare const func: DeployFunction; export default func; diff --git a/dist/deploy/10_voter.js b/dist/deploy/10_voter.js index ec3d36ba..b223fd45 100644 --- a/dist/deploy/10_voter.js +++ b/dist/deploy/10_voter.js @@ -1,25 +1,25 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); const func = async function (hre) { - const { deployments, getNamedAccounts } = hre - const { deploy } = deployments - const { deployer } = await getNamedAccounts() - const escrow = await deployments.get('VotingEscrow') - const pairFactory = await deployments.get('PairFactory') - const gaugeFactory = await deployments.get('GaugeFactory') - const bribeFactory = await deployments.get('BribeFactory') - await deploy('Voter', { - from: deployer, - args: [ - escrow.address, - pairFactory.address, - gaugeFactory.address, - bribeFactory.address - ], - log: true, - skipIfAlreadyDeployed: false - }) -} -exports.default = func -func.tags = ['Voter'] -func.id = 'voter' + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + const escrow = await deployments.get('VotingEscrow'); + const pairFactory = await deployments.get('PairFactory'); + const gaugeFactory = await deployments.get('GaugeFactory'); + const bribeFactory = await deployments.get('BribeFactory'); + await deploy('Voter', { + from: deployer, + args: [ + escrow.address, + pairFactory.address, + gaugeFactory.address, + bribeFactory.address + ], + log: true, + skipIfAlreadyDeployed: false + }); +}; +exports.default = func; +func.tags = ['Voter']; +func.id = 'voter'; diff --git a/dist/deploy/11_minter.d.ts b/dist/deploy/11_minter.d.ts index 68b368bb..2255cecc 100644 --- a/dist/deploy/11_minter.d.ts +++ b/dist/deploy/11_minter.d.ts @@ -1,3 +1,3 @@ -import { DeployFunction } from "hardhat-deploy/types"; +import { DeployFunction } from 'hardhat-deploy/types'; declare const func: DeployFunction; export default func; diff --git a/dist/deploy/11_minter.js b/dist/deploy/11_minter.js index 4f5bddd7..6fe5830e 100644 --- a/dist/deploy/11_minter.js +++ b/dist/deploy/11_minter.js @@ -1,19 +1,19 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); const func = async function (hre) { - const { deployments, getNamedAccounts } = hre - const { deploy } = deployments - const { deployer } = await getNamedAccounts() - const escrow = await deployments.get('VotingEscrow') - const voter = await deployments.get('Voter') - const dist = await deployments.get('RewardsDistributor') - await deploy('Minter', { - from: deployer, - args: [voter.address, escrow.address, dist.address], - log: true, - skipIfAlreadyDeployed: false - }) -} -exports.default = func -func.tags = ['Minter'] -func.id = 'minter' + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + const escrow = await deployments.get('VotingEscrow'); + const voter = await deployments.get('Voter'); + const dist = await deployments.get('RewardsDistributor'); + await deploy('Minter', { + from: deployer, + args: [voter.address, escrow.address, dist.address], + log: true, + skipIfAlreadyDeployed: false + }); +}; +exports.default = func; +func.tags = ['Minter']; +func.id = 'minter'; diff --git a/dist/deploy/12_veloGovernor.d.ts b/dist/deploy/12_veloGovernor.d.ts index 68b368bb..2255cecc 100644 --- a/dist/deploy/12_veloGovernor.d.ts +++ b/dist/deploy/12_veloGovernor.d.ts @@ -1,3 +1,3 @@ -import { DeployFunction } from "hardhat-deploy/types"; +import { DeployFunction } from 'hardhat-deploy/types'; declare const func: DeployFunction; export default func; diff --git a/dist/deploy/12_veloGovernor.js b/dist/deploy/12_veloGovernor.js index e5e1293f..6eb7091b 100644 --- a/dist/deploy/12_veloGovernor.js +++ b/dist/deploy/12_veloGovernor.js @@ -1,17 +1,17 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); const func = async function (hre) { - const { deployments, getNamedAccounts } = hre - const { deploy } = deployments - const { deployer } = await getNamedAccounts() - const escrow = await deployments.get('VotingEscrow') - await deploy('FlowGovernor', { - from: deployer, - args: [escrow.address], - log: true, - skipIfAlreadyDeployed: false - }) -} -exports.default = func -func.tags = ['FlowGovernor'] -func.id = 'FlowGovernor' + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + const escrow = await deployments.get('VotingEscrow'); + await deploy('FlowGovernor', { + from: deployer, + args: [escrow.address], + log: true, + skipIfAlreadyDeployed: false + }); +}; +exports.default = func; +func.tags = ['FlowGovernor']; +func.id = 'FlowGovernor'; diff --git a/dist/deploy/13_redemptionReceiver.d.ts b/dist/deploy/13_redemptionReceiver.d.ts index 68b368bb..2255cecc 100644 --- a/dist/deploy/13_redemptionReceiver.d.ts +++ b/dist/deploy/13_redemptionReceiver.d.ts @@ -1,3 +1,3 @@ -import { DeployFunction } from "hardhat-deploy/types"; +import { DeployFunction } from 'hardhat-deploy/types'; declare const func: DeployFunction; export default func; diff --git a/dist/deploy/13_redemptionReceiver.js b/dist/deploy/13_redemptionReceiver.js index 9860c1de..8af8beaf 100644 --- a/dist/deploy/13_redemptionReceiver.js +++ b/dist/deploy/13_redemptionReceiver.js @@ -1,35 +1,29 @@ -'use strict' -var __importDefault = - (this && this.__importDefault) || - function (mod) { - return mod && mod.__esModule ? mod : { default: mod } - } -Object.defineProperty(exports, '__esModule', { value: true }) -const arbTestnetConfig_1 = __importDefault( - require('../tasks/deploy/constants/arbConfig') -) -const testFantomConfig_1 = __importDefault( - require('../tasks/deploy/constants/testFantomConfig') -) -const ARB_TEST_CONFIG = arbTestnetConfig_1.default -const FTM_CONFIG = testFantomConfig_1.default +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const arbConfig_1 = __importDefault(require("../tasks/deploy/constants/arbConfig")); +const testFantomConfig_1 = __importDefault(require("../tasks/deploy/constants/testFantomConfig")); +const ARB_TEST_CONFIG = arbConfig_1.default; +const FTM_CONFIG = testFantomConfig_1.default; const func = async function (hre) { - const { deployments, getNamedAccounts } = hre - const { deploy } = deployments - const { deployer } = await getNamedAccounts() - const flow = await deployments.get('Flow') - await deploy('RedemptionReceiver', { - from: deployer, - args: [ - ARB_TEST_CONFIG.USDC, - flow.address, - FTM_CONFIG.lzChainId, - ARB_TEST_CONFIG.lzEndpoint - ], - log: true, - skipIfAlreadyDeployed: false - }) -} -exports.default = func -func.tags = ['RedemptionReceiver'] -func.id = 'redemptionReceiver' + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + const flow = await deployments.get('Flow'); + await deploy('RedemptionReceiver', { + from: deployer, + args: [ + ARB_TEST_CONFIG.USDC, + flow.address, + FTM_CONFIG.lzChainId, + ARB_TEST_CONFIG.lzEndpoint + ], + log: true, + skipIfAlreadyDeployed: false + }); +}; +exports.default = func; +func.tags = ['RedemptionReceiver']; +func.id = 'redemptionReceiver'; diff --git a/dist/deploy/14_merkleClaim.d.ts b/dist/deploy/14_merkleClaim.d.ts index 68b368bb..2255cecc 100644 --- a/dist/deploy/14_merkleClaim.d.ts +++ b/dist/deploy/14_merkleClaim.d.ts @@ -1,3 +1,3 @@ -import { DeployFunction } from "hardhat-deploy/types"; +import { DeployFunction } from 'hardhat-deploy/types'; declare const func: DeployFunction; export default func; diff --git a/dist/deploy/14_merkleClaim.js b/dist/deploy/14_merkleClaim.js index 8fab7147..392dbea4 100644 --- a/dist/deploy/14_merkleClaim.js +++ b/dist/deploy/14_merkleClaim.js @@ -1,26 +1,23 @@ -'use strict' -var __importDefault = - (this && this.__importDefault) || - function (mod) { - return mod && mod.__esModule ? mod : { default: mod } - } -Object.defineProperty(exports, '__esModule', { value: true }) -const arbTestnetConfig_1 = __importDefault( - require('../tasks/deploy/constants/arbConfig') -) -const ARB_TEST_CONFIG = arbTestnetConfig_1.default +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +//import arbTestnetConfig from '../tasks/deploy/constants/arbTestnetConfig' +const arbConfig_1 = __importDefault(require("../tasks/deploy/constants/arbConfig")); +const ARB_TEST_CONFIG = arbConfig_1.default; const func = async function (hre) { - const { deployments, getNamedAccounts } = hre - const { deploy } = deployments - const { deployer } = await getNamedAccounts() - const flow = await deployments.get('Flow') - await deploy('MerkleClaim', { - from: deployer, - args: [flow.address, ARB_TEST_CONFIG.merkleRoot], - log: true, - skipIfAlreadyDeployed: false - }) -} -exports.default = func -func.tags = ['MerkleClaim'] -func.id = 'merkleClaim' + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + const flow = await deployments.get('Flow'); + await deploy('MerkleClaim', { + from: deployer, + args: [flow.address, ARB_TEST_CONFIG.merkleRoot], + log: true, + skipIfAlreadyDeployed: false + }); +}; +exports.default = func; +func.tags = ['MerkleClaim']; +func.id = 'merkleClaim'; diff --git a/dist/deploy/15_init.d.ts b/dist/deploy/15_init.d.ts index 68b368bb..2255cecc 100644 --- a/dist/deploy/15_init.d.ts +++ b/dist/deploy/15_init.d.ts @@ -1,3 +1,3 @@ -import { DeployFunction } from "hardhat-deploy/types"; +import { DeployFunction } from 'hardhat-deploy/types'; declare const func: DeployFunction; export default func; diff --git a/dist/deploy/15_init.js b/dist/deploy/15_init.js index c50722e7..07bf7f26 100644 --- a/dist/deploy/15_init.js +++ b/dist/deploy/15_init.js @@ -1,60 +1,55 @@ -'use strict' -var __importDefault = - (this && this.__importDefault) || - function (mod) { - return mod && mod.__esModule ? mod : { default: mod } - } -Object.defineProperty(exports, '__esModule', { value: true }) -const arbTestnetConfig_1 = __importDefault( - require('../tasks/deploy/constants/arbConfig') // update to arbConfig -) -const ARB_TEST_CONFIG = arbTestnetConfig_1.default +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const arbConfig_1 = __importDefault(require("../tasks/deploy/constants/arbConfig")); +const ARB_TEST_CONFIG = arbConfig_1.default; const func = async function (hre) { - const { deployments, ethers } = hre - const flow = await ethers.getContract('Flow') - const pairFactory = await ethers.getContract('PairFactory') - const escrow = await ethers.getContract('VotingEscrow') - const voter = await ethers.getContract('Voter') - const distributor = await ethers.getContract('RewardsDistributor') - const governor = await ethers.getContract('FlowGovernor') - const minter = await ethers.getContract('Minter') - const receiver = await ethers.getContract('RedemptionReceiver') - const claim = await deployments.get('MerkleClaim') - // Initialize - await flow.initialMint(ARB_TEST_CONFIG.teamEOA) - console.log('Initial minted') - await flow.setRedemptionReceiver(receiver.address) - console.log('RedemptionReceiver set') - await flow.setMerkleClaim(claim.address) - console.log('MerkleClaim set') - await flow.setMinter(minter.address) - console.log('Minter set') - await pairFactory.setPauser(ARB_TEST_CONFIG.teamMultisig) - console.log('Pauser set') - await escrow.setVoter(voter.address) - console.log( - 'Voter set', - 'voter address: ', - voter.address, - 'escrow address: ', - escrow.address - ) - await escrow.setTeam(ARB_TEST_CONFIG.teamMultisig) - console.log('Team set for escrow') - await voter.setGovernor(ARB_TEST_CONFIG.teamMultisig) - console.log('Governor set') - await voter.setEmergencyCouncil(ARB_TEST_CONFIG.teamMultisig) - console.log('Emergency Council set') - await distributor.setDepositor(minter.address) - console.log('Depositor set') - await receiver.setTeam(ARB_TEST_CONFIG.teamMultisig) - console.log('Team set for receiver') - await governor.setTeam(ARB_TEST_CONFIG.teamMultisig) - console.log('Team set for governor') - await minter.setTeam(ARB_TEST_CONFIG.teamMultisig) - console.log('Team set for minter') - return true -} -exports.default = func -func.tags = ['Init'] -func.id = 'init' + const { deployments, ethers } = hre; + const flow = await ethers.getContract('Flow'); + const pairFactory = await ethers.getContract('PairFactory'); + const escrow = await ethers.getContract('VotingEscrow'); + const voter = await ethers.getContract('Voter'); + const distributor = await ethers.getContract('RewardsDistributor'); + const governor = await ethers.getContract('FlowGovernor'); + const minter = await ethers.getContract('Minter'); + const receiver = await ethers.getContract('RedemptionReceiver'); + const claim = await deployments.get('MerkleClaim'); + // Initialize + await flow.initialMint(ARB_TEST_CONFIG.teamEOA); + console.log('Initial minted'); + await flow.setRedemptionReceiver(receiver.address); + console.log('RedemptionReceiver set'); + await flow.setMerkleClaim(claim.address); + console.log('MerkleClaim set'); + await flow.setMinter(minter.address); + console.log('Minter set'); + await pairFactory.setPauser(ARB_TEST_CONFIG.teamMultisig); + console.log('Pauser set'); + await escrow.setVoter(voter.address); + console.log('Voter set', 'voter address: ', voter.address, 'escrow address: ', escrow.address); + await escrow.setTeam(ARB_TEST_CONFIG.teamMultisig); + console.log('Team set for escrow'); + await voter.setGovernor(ARB_TEST_CONFIG.teamMultisig); + console.log('Governor set'); + await voter.setEmergencyCouncil(ARB_TEST_CONFIG.teamMultisig); + console.log('Emergency Council set'); + await distributor.setDepositor(minter.address); + console.log('Depositor set'); + await receiver.setTeam(ARB_TEST_CONFIG.teamMultisig); + console.log('Team set for receiver'); + await governor.setTeam(ARB_TEST_CONFIG.teamMultisig); + console.log('Team set for governor'); + await minter.setTeam(ARB_TEST_CONFIG.teamMultisig); + console.log('Team set for minter'); + await minter.initialize(ARB_TEST_CONFIG.partnerAddrs, ARB_TEST_CONFIG.partnerAmts, ARB_TEST_CONFIG.partnerMax); + // create pair + // provide liq + // etc etc + // see forge tests for more details + return true; +}; +exports.default = func; +func.tags = ['init_deploy']; +func.id = 'init_deploy'; diff --git a/dist/deploy/16_whitelist.d.ts b/dist/deploy/16_whitelist.d.ts index 68b368bb..2255cecc 100644 --- a/dist/deploy/16_whitelist.d.ts +++ b/dist/deploy/16_whitelist.d.ts @@ -1,3 +1,3 @@ -import { DeployFunction } from "hardhat-deploy/types"; +import { DeployFunction } from 'hardhat-deploy/types'; declare const func: DeployFunction; export default func; diff --git a/dist/deploy/16_whitelist.js b/dist/deploy/16_whitelist.js index b1a40644..913fd425 100644 --- a/dist/deploy/16_whitelist.js +++ b/dist/deploy/16_whitelist.js @@ -1,26 +1,22 @@ -'use strict' -var __importDefault = - (this && this.__importDefault) || - function (mod) { - return mod && mod.__esModule ? mod : { default: mod } - } -Object.defineProperty(exports, '__esModule', { value: true }) -const arbTestnetConfig_1 = __importDefault( - require('../tasks/deploy/constants/arbConfig') -) -const ARB_TEST_CONFIG = arbTestnetConfig_1.default +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const arbConfig_1 = __importDefault(require("../tasks/deploy/constants/arbConfig")); +const ARB_TEST_CONFIG = arbConfig_1.default; const func = async function (hre) { - const { ethers } = hre - const flow = await ethers.getContract('Flow') - const voter = await ethers.getContract('Voter') - const minter = await ethers.getContract('Minter') - // Whitelist - const nativeToken = [flow.address] - const tokenWhitelist = nativeToken.concat(ARB_TEST_CONFIG.tokenWhitelist) - await voter.initialize(tokenWhitelist, minter.address) - console.log('Whitelist set') - return true -} -exports.default = func -func.tags = ['whitelist'] -func.id = 'whitelist' + const { ethers } = hre; + const flow = await ethers.getContract('Flow'); + const voter = await ethers.getContract('Voter'); + const minter = await ethers.getContract('Minter'); + // Whitelist + const nativeToken = [flow.address]; + const tokenWhitelist = nativeToken.concat(ARB_TEST_CONFIG.tokenWhitelist); + await voter.initialize(tokenWhitelist, minter.address); + console.log('Whitelist set'); + return true; +}; +exports.default = func; +func.tags = ['whitelist']; +func.id = 'whitelist'; diff --git a/dist/deploy/17_dist.d.ts b/dist/deploy/17_dist.d.ts index 68b368bb..2255cecc 100644 --- a/dist/deploy/17_dist.d.ts +++ b/dist/deploy/17_dist.d.ts @@ -1,3 +1,3 @@ -import { DeployFunction } from "hardhat-deploy/types"; +import { DeployFunction } from 'hardhat-deploy/types'; declare const func: DeployFunction; export default func; diff --git a/dist/deploy/17_dist.js b/dist/deploy/17_dist.js index f0a62e23..456f8b5f 100644 --- a/dist/deploy/17_dist.js +++ b/dist/deploy/17_dist.js @@ -1,27 +1,54 @@ -'use strict' -var __importDefault = - (this && this.__importDefault) || - function (mod) { - return mod && mod.__esModule ? mod : { default: mod } - } -Object.defineProperty(exports, '__esModule', { value: true }) -const arbTestnetConfig_1 = __importDefault( - require('../tasks/deploy/constants/arbConfig') -) -const ARB_TEST_CONFIG = arbTestnetConfig_1.default +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const arbConfig_1 = __importDefault(require("../tasks/deploy/constants/arbConfig")); +const ARB_TEST_CONFIG = arbConfig_1.default; const func = async function (hre) { - const { ethers } = hre - const minter = await ethers.getContract('Minter') - // Initial veVELO distro this is already done by now in init... - // await minter.initialize( - // ARB_TEST_CONFIG.partnerAddrs, - // ARB_TEST_CONFIG.partnerAmts, - // ARB_TEST_CONFIG.partnerMax - // ) this is inside of dist and it does not run apparently... - console.log('veVELO distributed') - console.log('Arbitrum Goerli Velocimeter Instruments deployed') - return true -} -exports.default = func -func.tags = ['initial_dist'] -func.id = 'initial_dist' + const { ethers } = hre; + const minter = await ethers.getContract('Minter'); + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + const flow = await deployments.get('Flow'); + // Initial veVELO distro // this is not inside dist lets see if its being used for deploys?? + // await minter.initialize( + // ARB_TEST_CONFIG.partnerAddrs, + // ARB_TEST_CONFIG.partnerAmts, + // ARB_TEST_CONFIG.partnerMax + // ) + console.log('veVELO distributed'); + // + console.log('Arbitrum Goerli Velocimeter Instruments deployed'); + return true; + // Initialize + console.log('deployer', deployer); + // await flow.initialMint(ARB_CONFIG.teamEOA) + // console.log('Initial minted') + // await flow.setRedemptionReceiver(receiver.address) + // console.log('RedemptionReceiver set') + // await flow.setMerkleClaim(claim.address) + // console.log('MerkleClaim set') + // await flow.setMinter(minter.address) + // console.log('Minter set') + // await pairFactory.setPauser(ARB_CONFIG.teamMultisig) + // console.log('Pauser set') + // await escrow.setVoter(voter.address) + // console.log('Voter set') + // await escrow.setTeam(ARB_CONFIG.teamMultisig) + // console.log('Team set for escrow') + // await voter.setGovernor(ARB_CONFIG.teamMultisig) + // console.log('Governor set') + // await voter.setEmergencyCouncil(ARB_CONFIG.teamMultisig) + // console.log('Emergency Council set') + // await distributor.setDepositor(minter.address) + // console.log('Depositor set') + // await receiver.setTeam(ARB_CONFIG.teamMultisig) + // console.log('Team set for receiver') + // await governor.setTeam(ARB_CONFIG.teamMultisig) + // console.log('Team set for governor') +}; +exports.default = func; +func.tags = ['initial_dist']; +func.id = 'initial_dist'; diff --git a/dist/hardhat.config.d.ts b/dist/hardhat.config.d.ts index fcac00df..69885bae 100644 --- a/dist/hardhat.config.d.ts +++ b/dist/hardhat.config.d.ts @@ -1,11 +1,13 @@ -import "@nomiclabs/hardhat-ethers"; -import "@nomiclabs/hardhat-etherscan"; -import "@nomiclabs/hardhat-waffle"; -import "@typechain/hardhat"; -import "hardhat-preprocessor"; -import "hardhat-abi-exporter"; -import "hardhat-deploy"; -import { HardhatUserConfig } from "hardhat/config"; -import "./checkEnv"; +import '@nomiclabs/hardhat-ethers'; +import '@nomiclabs/hardhat-etherscan'; +import '@nomiclabs/hardhat-waffle'; +import '@typechain/hardhat'; +import 'hardhat-preprocessor'; +import 'hardhat-abi-exporter'; +import 'hardhat-deploy'; +import { HardhatUserConfig } from 'hardhat/config'; +import './tasks/accounts'; +import './tasks/deploy'; +import './checkEnv'; declare const config: HardhatUserConfig; export default config; diff --git a/dist/hardhat.config.js b/dist/hardhat.config.js index da26b4ea..6711990e 100644 --- a/dist/hardhat.config.js +++ b/dist/hardhat.config.js @@ -1,109 +1,110 @@ -'use strict' -var __importDefault = - (this && this.__importDefault) || - function (mod) { - return mod && mod.__esModule ? mod : { default: mod } - } -Object.defineProperty(exports, '__esModule', { value: true }) -require('@nomiclabs/hardhat-ethers') -require('@nomiclabs/hardhat-etherscan') -require('@nomiclabs/hardhat-waffle') -require('@typechain/hardhat') -require('hardhat-preprocessor') -require('hardhat-abi-exporter') -require('hardhat-deploy') -const fs_1 = __importDefault(require('fs')) -const path_1 = require('path') -const dotenv_1 = require('dotenv') -;(0, dotenv_1.config)({ path: (0, path_1.resolve)(__dirname, './.env') }) -require('./checkEnv') +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +require("@nomiclabs/hardhat-ethers"); +require("@nomiclabs/hardhat-etherscan"); +require("@nomiclabs/hardhat-waffle"); +require("@typechain/hardhat"); +require("hardhat-preprocessor"); +require("hardhat-abi-exporter"); +require("hardhat-deploy"); +const dotenv_1 = require("dotenv"); +const fs_1 = __importDefault(require("fs")); +const path_1 = require("path"); +require("./tasks/accounts"); +require("./tasks/deploy"); +(0, dotenv_1.config)({ path: (0, path_1.resolve)(__dirname, './.env') }); +require("./checkEnv"); const remappings = fs_1.default - .readFileSync('remappings.txt', 'utf8') - .split('\n') - .filter(Boolean) - .map(line => line.trim().split('=')) + .readFileSync('remappings.txt', 'utf8') + .split('\n') + .filter(Boolean) + .map(line => line.trim().split('=')); const config = { - networks: { - hardhat: { - initialBaseFeePerGas: 0, - forking: { - url: `https://arb-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY}`, - blockNumber: 16051852 - } - }, - opera: { - url: 'https://rpc.fantom.network', - accounts: [process.env.PRIVATE_KEY] - }, - arbitrum: { - url: `https://arb-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY}`, - accounts: [process.env.PRIVATE_KEY], - chainId: 42161, - saveDeployments: true, - verify: { - etherscan: { - apiUrl: 'https://api.arbiscan.io/api' + networks: { + hardhat: { + initialBaseFeePerGas: 0, + forking: { + url: `https://arb-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY}`, + blockNumber: 16051852 + } + }, + opera: { + url: 'https://rpc.fantom.network', + accounts: [process.env.PRIVATE_KEY] + }, + arbitrumOne: { + url: `https://arb-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY}`, + accounts: [process.env.PRIVATE_KEY], + chainId: 42161, + saveDeployments: true, + verify: { + etherscan: { + apiUrl: 'https://api.arbiscan.io', + apiKey: process.env.ARB_SCAN_API_KEY + } + } + }, + arbitrumGoerli: { + url: `https://arb-goerli.g.alchemy.com/v2/${process.env.ALCHEMY_GOERLI_ARBITRUM_API_KEY}`, + accounts: [process.env.PRIVATE_KEY], + chainId: 421613, + saveDeployments: true, + // deploy: ['dist/deploy/'], + verify: { + etherscan: { + apiUrl: 'https://api-goerli.arbiscan.io', + apiKey: process.env.ARB_SCAN_API_KEY + } + } } - } + // ftmTestnet: { + // url: 'https://rpc.testnet.fantom.network', + // accounts: [process.env.PRIVATE_KEY!] + // }, + // optimisticEthereum: { + // url: 'https://mainnet.optimism.io', + // accounts: [process.env.PRIVATE_KEY!] + // } }, - arbitrumGoerli: { - url: `https://arb-goerli.g.alchemy.com/v2/${process.env.ALCHEMY_GOERLI_ARBITRUM_API_KEY}`, - accounts: [process.env.PRIVATE_KEY], - chainId: 421613, - saveDeployments: false, - verify: { - etherscan: { - apiUrl: 'https://api-goerli.arbiscan.io/', - apiKey: process.env.ARB_SCAN_API_KEY + solidity: { + version: '0.8.13', + settings: { + optimizer: { + enabled: true, + runs: 200 + } } - } }, - ftmTestnet: { - url: 'https://rpc.testnet.fantom.network', - accounts: [process.env.PRIVATE_KEY] + namedAccounts: { + deployer: 0 }, - optimisticEthereum: { - url: 'https://mainnet.optimism.io', - accounts: [process.env.PRIVATE_KEY] - } - }, - solidity: { - version: '0.8.13', - settings: { - optimizer: { - enabled: true, - runs: 200 - } - } - }, - namedAccounts: { - deployer: 0 - }, - // This fully resolves paths for imports in the ./lib directory for Hardhat - preprocess: { - eachLine: hre => ({ - transform: line => { - if (!line.match(/^\s*import /i)) { - return line - } - const remapping = remappings.find(([find]) => line.match('"' + find)) - if (!remapping) { - return line + // This fully resolves paths for imports in the ./lib directory for Hardhat + preprocess: { + eachLine: hre => ({ + transform: (line) => { + if (!line.match(/^\s*import /i)) { + return line; + } + const remapping = remappings.find(([find]) => line.match('"' + find)); + if (!remapping) { + return line; + } + const [find, replace] = remapping; + return line.replace('"' + find, '"' + replace); + } + }) + }, + etherscan: { + apiKey: { + // opera: process.env.FTM_SCAN_API_KEY!, + // ftmTestnet: process.env.FTM_SCAN_API_KEY!, + // optimisticEthereum: process.env.OP_SCAN_API_KEY!, + arbitrumOne: process.env.ARB_SCAN_API_KEY, + arbitrumGoerli: process.env.ARB_SCAN_API_KEY } - const [find, replace] = remapping - return line.replace('"' + find, '"' + replace) - } - }) - }, - etherscan: { - apiKey: { - opera: process.env.FTM_SCAN_API_KEY, - ftmTestnet: process.env.FTM_SCAN_API_KEY, - optimisticEthereum: process.env.OP_SCAN_API_KEY, - - arbitrum: process.env.ARB_SCAN_API_KEY, - arbitrumGoerli: process.env.ARB_SCAN_API_KEY } - } -} -exports.default = config +}; +exports.default = config; diff --git a/dist/tasks/accounts.d.ts b/dist/tasks/accounts.d.ts new file mode 100644 index 00000000..cb0ff5c3 --- /dev/null +++ b/dist/tasks/accounts.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/tasks/accounts.js b/dist/tasks/accounts.js new file mode 100644 index 00000000..672ed06b --- /dev/null +++ b/dist/tasks/accounts.js @@ -0,0 +1,9 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const config_1 = require("hardhat/config"); +(0, config_1.task)('accounts', 'Prints the list of accounts', async (_taskArgs, hre) => { + const accounts = await hre.ethers.getSigners(); + for (const account of accounts) { + console.log(await account.getAddress()); + } +}); diff --git a/dist/tasks/deploy/arb.js b/dist/tasks/deploy/arb.js index c112e8a5..e9180518 100644 --- a/dist/tasks/deploy/arb.js +++ b/dist/tasks/deploy/arb.js @@ -1,187 +1,121 @@ -'use strict' -var __importDefault = - (this && this.__importDefault) || - function (mod) { - return mod && mod.__esModule ? mod : { default: mod } - } -Object.defineProperty(exports, '__esModule', { value: true }) -const config_1 = require('hardhat/config') -const arbConfig_1 = __importDefault(require('./constants/arbConfig')) -const arbTestnetConfig_1 = __importDefault(require('./constants/arbConfig')) -const fantomConfig_1 = __importDefault(require('./constants/fantomConfig')) -const testFantomConfig_1 = __importDefault( - require('./constants/testFantomConfig') -) -;(0, config_1.task)('deploy:arb', 'Deploys Arbitrum contracts').setAction( - async function (taskArguments, { ethers }) { - const mainnet = true - const ARB_CONFIG = mainnet - ? arbConfig_1.default - : arbTestnetConfig_1.default - const FTM_CONFIG = mainnet - ? fantomConfig_1.default - : testFantomConfig_1.default - console.log( - 'ALCHEMY_MAINNET_ARBITRUM_API_KEY: ', - process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY - ) +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const config_1 = require("hardhat/config"); +const arbConfig_1 = __importDefault(require("./constants/arbConfig")); +const arbConfig_2 = __importDefault(require("./constants/arbConfig")); +const fantomConfig_1 = __importDefault(require("./constants/fantomConfig")); +const testFantomConfig_1 = __importDefault(require("./constants/testFantomConfig")); +(0, config_1.task)('deploy:arb', 'Deploys Arbitrum contracts').setAction(async function (taskArguments, { ethers }) { + const mainnet = true; + const ARB_CONFIG = mainnet ? arbConfig_1.default : arbConfig_2.default; + const FTM_CONFIG = mainnet ? fantomConfig_1.default : testFantomConfig_1.default; + console.log('ALCHEMY_MAINNET_ARBITRUM_API_KEY: ', process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY); // Load - const [ - Flow, - GaugeFactory, - BribeFactory, - PairFactory, - Router, - Library, - VeArtProxy, - VotingEscrow, - RewardsDistributor, - Voter, - Minter, - VeloGovernor, - RedemptionReceiver, - MerkleClaim - ] = await Promise.all([ - ethers.getContractFactory('Flow'), - ethers.getContractFactory('GaugeFactory'), - ethers.getContractFactory('BribeFactory'), - ethers.getContractFactory('PairFactory'), - ethers.getContractFactory('Router'), - ethers.getContractFactory('VelocimeterLibrary'), - ethers.getContractFactory('VeArtProxy'), - ethers.getContractFactory('VotingEscrow'), - ethers.getContractFactory('RewardsDistributor'), - ethers.getContractFactory('Voter'), - ethers.getContractFactory('Minter'), - ethers.getContractFactory('VeloGovernor'), - ethers.getContractFactory('RedemptionReceiver'), - ethers.getContractFactory('MerkleClaim') - ]) - const flow = await Flow.deploy() - await flow.deployed() - console.log('Flow deployed to dunks: ', flow.address) - const gaugeFactory = await GaugeFactory.deploy() - await gaugeFactory.deployed() - console.log('GaugeFactory deployed to: ', gaugeFactory.address) - const bribeFactory = await BribeFactory.deploy() - await bribeFactory.deployed() - console.log('BribeFactory deployed to: ', bribeFactory.address) - const pairFactory = await PairFactory.deploy() - await pairFactory.deployed() - console.log('PairFactory deployed to: ', pairFactory.address) - const router = await Router.deploy(pairFactory.address, ARB_CONFIG.WETH) - await router.deployed() - console.log('Router deployed to: ', router.address) - console.log('Args: ', pairFactory.address, ARB_CONFIG.WETH, '\n') - const library = await Library.deploy(router.address) - await library.deployed() - console.log('VelocimeterLibrary deployed to: ', library.address) - console.log('Args: ', router.address, '\n') - const artProxy = await VeArtProxy.deploy() - await artProxy.deployed() - console.log('VeArtProxy deployed to: ', artProxy.address) - const escrow = await VotingEscrow.deploy(flow.address, artProxy.address) - await escrow.deployed() - console.log('VotingEscrow deployed to: ', escrow.address) - console.log('Args: ', flow.address, artProxy.address, '\n') - const distributor = await RewardsDistributor.deploy(escrow.address) - await distributor.deployed() - console.log('RewardsDistributor deployed to: ', distributor.address) - console.log('Args: ', escrow.address, '\n') - const voter = await Voter.deploy( - escrow.address, - pairFactory.address, - gaugeFactory.address, - bribeFactory.address - ) - await voter.deployed() - console.log('Voter deployed to: ', voter.address) - console.log( - 'Args: ', - escrow.address, - pairFactory.address, - gaugeFactory.address, - bribeFactory.address, - '\n' - ) - const minter = await Minter.deploy( - voter.address, - escrow.address, - distributor.address - ) - await minter.deployed() - console.log('Minter deployed to: ', minter.address) - console.log( - 'Args: ', - voter.address, - escrow.address, - distributor.address, - '\n' - ) - const receiver = await RedemptionReceiver.deploy( - ARB_CONFIG.USDC, - flow.address, - FTM_CONFIG.lzChainId, - ARB_CONFIG.lzEndpoint - ) - await receiver.deployed() - console.log('RedemptionReceiver deployed to: ', receiver.address) - console.log( - 'Args: ', - ARB_CONFIG.USDC, - flow.address, - FTM_CONFIG.lzChainId, - ARB_CONFIG.lzEndpoint, - '\n' - ) - const governor = await VeloGovernor.deploy(escrow.address) - await governor.deployed() - console.log('VeloGovernor deployed to: ', governor.address) - console.log('Args: ', escrow.address, '\n') + const [Flow, GaugeFactory, BribeFactory, PairFactory, Router, Library, VeArtProxy, VotingEscrow, RewardsDistributor, Voter, Minter, FlowGovernor, RedemptionReceiver, MerkleClaim] = await Promise.all([ + ethers.getContractFactory('Flow'), + ethers.getContractFactory('GaugeFactory'), + ethers.getContractFactory('BribeFactory'), + ethers.getContractFactory('PairFactory'), + ethers.getContractFactory('Router'), + ethers.getContractFactory('VelocimeterLibrary'), + ethers.getContractFactory('VeArtProxy'), + ethers.getContractFactory('VotingEscrow'), + ethers.getContractFactory('RewardsDistributor'), + ethers.getContractFactory('Voter'), + ethers.getContractFactory('Minter'), + ethers.getContractFactory('FlowGovernor'), + ethers.getContractFactory('RedemptionReceiver'), + ethers.getContractFactory('MerkleClaim') + ]); + const flow = await Flow.deploy(); + await flow.deployed(); + console.log('Flow deployed to dunks: ', flow.address); + const gaugeFactory = await GaugeFactory.deploy(); + await gaugeFactory.deployed(); + console.log('GaugeFactory deployed to: ', gaugeFactory.address); + const bribeFactory = await BribeFactory.deploy(); + await bribeFactory.deployed(); + console.log('BribeFactory deployed to: ', bribeFactory.address); + const pairFactory = await PairFactory.deploy(); + await pairFactory.deployed(); + console.log('PairFactory deployed to: ', pairFactory.address); + const router = await Router.deploy(pairFactory.address, ARB_CONFIG.WETH); + await router.deployed(); + console.log('Router deployed to: ', router.address); + console.log('Args: ', pairFactory.address, ARB_CONFIG.WETH, '\n'); + const library = await Library.deploy(router.address); + await library.deployed(); + console.log('VelocimeterLibrary deployed to: ', library.address); + console.log('Args: ', router.address, '\n'); + const artProxy = await VeArtProxy.deploy(); + await artProxy.deployed(); + console.log('VeArtProxy deployed to: ', artProxy.address); + const escrow = await VotingEscrow.deploy(flow.address, artProxy.address); + await escrow.deployed(); + console.log('VotingEscrow deployed to: ', escrow.address); + console.log('Args: ', flow.address, artProxy.address, '\n'); + const distributor = await RewardsDistributor.deploy(escrow.address); + await distributor.deployed(); + console.log('RewardsDistributor deployed to: ', distributor.address); + console.log('Args: ', escrow.address, '\n'); + const voter = await Voter.deploy(escrow.address, pairFactory.address, gaugeFactory.address, bribeFactory.address); + await voter.deployed(); + console.log('Voter deployed to: ', voter.address); + console.log('Args: ', escrow.address, pairFactory.address, gaugeFactory.address, bribeFactory.address, '\n'); + const minter = await Minter.deploy(voter.address, escrow.address, distributor.address); + await minter.deployed(); + console.log('Minter deployed to: ', minter.address); + console.log('Args: ', voter.address, escrow.address, distributor.address, '\n'); + const receiver = await RedemptionReceiver.deploy(ARB_CONFIG.USDC, flow.address, FTM_CONFIG.lzChainId, ARB_CONFIG.lzEndpoint); + await receiver.deployed(); + console.log('RedemptionReceiver deployed to: ', receiver.address); + console.log('Args: ', ARB_CONFIG.USDC, flow.address, FTM_CONFIG.lzChainId, ARB_CONFIG.lzEndpoint, '\n'); + const governor = await FlowGovernor.deploy(escrow.address); + await governor.deployed(); + console.log('FlowGovernor deployed to: ', governor.address); + console.log('Args: ', escrow.address, '\n'); // Airdrop - const claim = await MerkleClaim.deploy(flow.address, ARB_CONFIG.merkleRoot) - await claim.deployed() - console.log('MerkleClaim deployed to: ', claim.address) - console.log('Args: ', flow.address, ARB_CONFIG.merkleRoot, '\n') + const claim = await MerkleClaim.deploy(flow.address, ARB_CONFIG.merkleRoot); + await claim.deployed(); + console.log('MerkleClaim deployed to: ', claim.address); + console.log('Args: ', flow.address, ARB_CONFIG.merkleRoot, '\n'); // Initialize - await flow.initialMint(ARB_CONFIG.teamEOA) - console.log('Initial minted') - await flow.setRedemptionReceiver(receiver.address) - console.log('RedemptionReceiver set') - await flow.setMerkleClaim(claim.address) - console.log('MerkleClaim set') - await flow.setMinter(minter.address) - console.log('Minter set') - await pairFactory.setPauser(ARB_CONFIG.teamMultisig) - console.log('Pauser set') - await escrow.setVoter(voter.address) - console.log('Voter set') - await escrow.setTeam(ARB_CONFIG.teamMultisig) - console.log('Team set for escrow') - await voter.setGovernor(ARB_CONFIG.teamMultisig) - console.log('Governor set') - await voter.setEmergencyCouncil(ARB_CONFIG.teamMultisig) - console.log('Emergency Council set') - await distributor.setDepositor(minter.address) - console.log('Depositor set') - await receiver.setTeam(ARB_CONFIG.teamMultisig) - console.log('Team set for receiver') - await governor.setTeam(ARB_CONFIG.teamMultisig) - console.log('Team set for governor') + await flow.initialMint(ARB_CONFIG.teamEOA); + console.log('Initial minted'); + await flow.setRedemptionReceiver(receiver.address); + console.log('RedemptionReceiver set'); + await flow.setMerkleClaim(claim.address); + console.log('MerkleClaim set'); + await flow.setMinter(minter.address); + console.log('Minter set'); + await pairFactory.setPauser(ARB_CONFIG.teamMultisig); + console.log('Pauser set'); + await escrow.setVoter(voter.address); + console.log('Voter set'); + await escrow.setTeam(ARB_CONFIG.teamMultisig); + console.log('Team set for escrow'); + await voter.setGovernor(ARB_CONFIG.teamMultisig); + console.log('Governor set'); + await voter.setEmergencyCouncil(ARB_CONFIG.teamMultisig); + console.log('Emergency Council set'); + await distributor.setDepositor(minter.address); + console.log('Depositor set'); + await receiver.setTeam(ARB_CONFIG.teamMultisig); + console.log('Team set for receiver'); + await governor.setTeam(ARB_CONFIG.teamMultisig); + console.log('Team set for governor'); // Whitelist - const nativeToken = [flow.address] - const tokenWhitelist = nativeToken.concat(ARB_CONFIG.tokenWhitelist) - await voter.initialize(tokenWhitelist, minter.address) - console.log('Whitelist set') + const nativeToken = [flow.address]; + const tokenWhitelist = nativeToken.concat(ARB_CONFIG.tokenWhitelist); + await voter.initialize(tokenWhitelist, minter.address); + console.log('Whitelist set'); // Initial veVELO distro - await minter.initialize( - ARB_CONFIG.partnerAddrs, - ARB_CONFIG.partnerAmts, - ARB_CONFIG.partnerMax - ) - console.log('veVELO distributed') - await minter.setTeam(ARB_CONFIG.teamMultisig) - console.log('Team set for minter') - console.log('Arbitrum contracts deployed') - } -) + await minter.initialize(ARB_CONFIG.partnerAddrs, ARB_CONFIG.partnerAmts, ARB_CONFIG.partnerMax); + console.log('veVELO distributed'); + await minter.setTeam(ARB_CONFIG.teamMultisig); + console.log('Team set for minter'); + console.log('Arbitrum contracts deployed'); +}); diff --git a/dist/tasks/deploy/arbHardhat.js b/dist/tasks/deploy/arbHardhat.js index e1a36a5f..5c7d171f 100644 --- a/dist/tasks/deploy/arbHardhat.js +++ b/dist/tasks/deploy/arbHardhat.js @@ -1,188 +1,121 @@ -'use strict' -var __importDefault = - (this && this.__importDefault) || - function (mod) { - return mod && mod.__esModule ? mod : { default: mod } - } -Object.defineProperty(exports, '__esModule', { value: true }) -const config_1 = require('hardhat/config') -const arbConfig_1 = __importDefault(require('./constants/arbConfig')) -const arbHardhatConfig_1 = __importDefault( - require('./constants/arbHardhatConfig') -) -const fantomConfig_1 = __importDefault(require('./constants/fantomConfig')) -const testFantomConfig_1 = __importDefault( - require('./constants/testFantomConfig') -) -;(0, config_1.task)( - 'deploy:arbHardhat', - 'Deploys Arbitrum forked chain contracts' -).setAction(async function (taskArguments, { ethers }) { - const mainnet = false - const ARB_CONFIG = mainnet ? arbConfig_1.default : arbHardhatConfig_1.default - const FTM_CONFIG = mainnet - ? fantomConfig_1.default - : testFantomConfig_1.default - console.log( - 'ALCHEMY_MAINNET_ARBITRUM_API_KEY: ', - process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY - ) - // Load - const [ - Flow, - GaugeFactory, - BribeFactory, - PairFactory, - Router, - Library, - VeArtProxy, - VotingEscrow, - RewardsDistributor, - Voter, - Minter, - FlowGovernor, - RedemptionReceiver, - MerkleClaim - ] = await Promise.all([ - ethers.getContractFactory('Flow'), - ethers.getContractFactory('GaugeFactory'), - ethers.getContractFactory('BribeFactory'), - ethers.getContractFactory('PairFactory'), - ethers.getContractFactory('Router'), - ethers.getContractFactory('VelocimeterLibrary'), - ethers.getContractFactory('VeArtProxy'), - ethers.getContractFactory('VotingEscrow'), - ethers.getContractFactory('RewardsDistributor'), - ethers.getContractFactory('Voter'), - ethers.getContractFactory('Minter'), - ethers.getContractFactory('FlowGovernor'), - ethers.getContractFactory('RedemptionReceiver'), - ethers.getContractFactory('MerkleClaim') - ]) - const flow = await Flow.deploy() - await flow.deployed() - console.log('Flow deployed to dunks: ', flow.address) - const gaugeFactory = await GaugeFactory.deploy() - await gaugeFactory.deployed() - console.log('GaugeFactory deployed to: ', gaugeFactory.address) - const bribeFactory = await BribeFactory.deploy() - await bribeFactory.deployed() - console.log('BribeFactory deployed to: ', bribeFactory.address) - const pairFactory = await PairFactory.deploy() - await pairFactory.deployed() - console.log('PairFactory deployed to: ', pairFactory.address) - const router = await Router.deploy(pairFactory.address, ARB_CONFIG.WETH) - await router.deployed() - console.log('Router deployed to: ', router.address) - console.log('Args: ', pairFactory.address, ARB_CONFIG.WETH, '\n') - const library = await Library.deploy(router.address) - await library.deployed() - console.log('VelocimeterLibrary deployed to: ', library.address) - console.log('Args: ', router.address, '\n') - const artProxy = await VeArtProxy.deploy() - await artProxy.deployed() - console.log('VeArtProxy deployed to: ', artProxy.address) - const escrow = await VotingEscrow.deploy(flow.address, artProxy.address) - await escrow.deployed() - console.log('VotingEscrow deployed to: ', escrow.address) - console.log('Args: ', flow.address, artProxy.address, '\n') - const distributor = await RewardsDistributor.deploy(escrow.address) - await distributor.deployed() - console.log('RewardsDistributor deployed to: ', distributor.address) - console.log('Args: ', escrow.address, '\n') - const voter = await Voter.deploy( - escrow.address, - pairFactory.address, - gaugeFactory.address, - bribeFactory.address - ) - await voter.deployed() - console.log('Voter deployed to: ', voter.address) - console.log( - 'Args: ', - escrow.address, - pairFactory.address, - gaugeFactory.address, - bribeFactory.address, - '\n' - ) - const minter = await Minter.deploy( - voter.address, - escrow.address, - distributor.address - ) - await minter.deployed() - console.log('Minter deployed to: ', minter.address) - console.log( - 'Args: ', - voter.address, - escrow.address, - distributor.address, - '\n' - ) - const receiver = await RedemptionReceiver.deploy( - ARB_CONFIG.USDC, - flow.address, - FTM_CONFIG.lzChainId, - ARB_CONFIG.lzEndpoint - ) - await receiver.deployed() - console.log('RedemptionReceiver deployed to: ', receiver.address) - console.log( - 'Args: ', - ARB_CONFIG.USDC, - flow.address, - FTM_CONFIG.lzChainId, - ARB_CONFIG.lzEndpoint, - '\n' - ) - const governor = await FlowGovernor.deploy(escrow.address) - await governor.deployed() - console.log('FlowGovernor deployed to: ', governor.address) - console.log('Args: ', escrow.address, '\n') - // Airdrop - const claim = await MerkleClaim.deploy(flow.address, ARB_CONFIG.merkleRoot) - await claim.deployed() - console.log('MerkleClaim deployed to: ', claim.address) - console.log('Args: ', flow.address, ARB_CONFIG.merkleRoot, '\n') - // Initialize - await flow.initialMint(ARB_CONFIG.teamEOA) - console.log('Initial minted') - await flow.setRedemptionReceiver(receiver.address) - console.log('RedemptionReceiver set') - await flow.setMerkleClaim(claim.address) - console.log('MerkleClaim set') - await flow.setMinter(minter.address) - console.log('Minter set') - await pairFactory.setPauser(ARB_CONFIG.teamMultisig) - console.log('Pauser set') - await escrow.setVoter(voter.address) - console.log('Voter set') - await escrow.setTeam(ARB_CONFIG.teamMultisig) - console.log('Team set for escrow') - await voter.setGovernor(ARB_CONFIG.teamMultisig) - console.log('Governor set') - await voter.setEmergencyCouncil(ARB_CONFIG.teamMultisig) - console.log('Emergency Council set') - await distributor.setDepositor(minter.address) - console.log('Depositor set') - await receiver.setTeam(ARB_CONFIG.teamMultisig) - console.log('Team set for receiver') - await governor.setTeam(ARB_CONFIG.teamMultisig) - console.log('Team set for governor') - // Whitelist - const nativeToken = [flow.address] - const tokenWhitelist = nativeToken.concat(ARB_CONFIG.tokenWhitelist) - await voter.initialize(tokenWhitelist, minter.address) - console.log('Whitelist set') - // Initial veVELO distro - await minter.initialize( - ARB_CONFIG.partnerAddrs, - ARB_CONFIG.partnerAmts, - ARB_CONFIG.partnerMax - ) - console.log('veVELO distributed') - await minter.setTeam(ARB_CONFIG.teamMultisig) - console.log('Team set for minter') - console.log('Arbitrum Forked Chain contracts deployed') -}) +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const config_1 = require("hardhat/config"); +const arbConfig_1 = __importDefault(require("./constants/arbConfig")); +const arbHardhatConfig_1 = __importDefault(require("./constants/arbHardhatConfig")); +const fantomConfig_1 = __importDefault(require("./constants/fantomConfig")); +const testFantomConfig_1 = __importDefault(require("./constants/testFantomConfig")); +(0, config_1.task)('deploy:arbHardhat', 'Deploys Arbitrum forked chain contracts').setAction(async function (taskArguments, { ethers }) { + const mainnet = false; + const ARB_CONFIG = mainnet ? arbConfig_1.default : arbHardhatConfig_1.default; + const FTM_CONFIG = mainnet ? fantomConfig_1.default : testFantomConfig_1.default; + console.log('ALCHEMY_MAINNET_ARBITRUM_API_KEY: ', process.env.ALCHEMY_MAINNET_ARBITRUM_API_KEY); + // Load + const [Flow, GaugeFactory, BribeFactory, PairFactory, Router, Library, VeArtProxy, VotingEscrow, RewardsDistributor, Voter, Minter, FlowGovernor, RedemptionReceiver, MerkleClaim] = await Promise.all([ + ethers.getContractFactory('Flow'), + ethers.getContractFactory('GaugeFactory'), + ethers.getContractFactory('BribeFactory'), + ethers.getContractFactory('PairFactory'), + ethers.getContractFactory('Router'), + ethers.getContractFactory('VelocimeterLibrary'), + ethers.getContractFactory('VeArtProxy'), + ethers.getContractFactory('VotingEscrow'), + ethers.getContractFactory('RewardsDistributor'), + ethers.getContractFactory('Voter'), + ethers.getContractFactory('Minter'), + ethers.getContractFactory('FlowGovernor'), + ethers.getContractFactory('RedemptionReceiver'), + ethers.getContractFactory('MerkleClaim') + ]); + const flow = await Flow.deploy(); + await flow.deployed(); + console.log('Flow deployed to dunks: ', flow.address); + const gaugeFactory = await GaugeFactory.deploy(); + await gaugeFactory.deployed(); + console.log('GaugeFactory deployed to: ', gaugeFactory.address); + const bribeFactory = await BribeFactory.deploy(); + await bribeFactory.deployed(); + console.log('BribeFactory deployed to: ', bribeFactory.address); + const pairFactory = await PairFactory.deploy(); + await pairFactory.deployed(); + console.log('PairFactory deployed to: ', pairFactory.address); + const router = await Router.deploy(pairFactory.address, ARB_CONFIG.WETH); + await router.deployed(); + console.log('Router deployed to: ', router.address); + console.log('Args: ', pairFactory.address, ARB_CONFIG.WETH, '\n'); + const library = await Library.deploy(router.address); + await library.deployed(); + console.log('VelocimeterLibrary deployed to: ', library.address); + console.log('Args: ', router.address, '\n'); + const artProxy = await VeArtProxy.deploy(); + await artProxy.deployed(); + console.log('VeArtProxy deployed to: ', artProxy.address); + const escrow = await VotingEscrow.deploy(flow.address, artProxy.address); + await escrow.deployed(); + console.log('VotingEscrow deployed to: ', escrow.address); + console.log('Args: ', flow.address, artProxy.address, '\n'); + const distributor = await RewardsDistributor.deploy(escrow.address); + await distributor.deployed(); + console.log('RewardsDistributor deployed to: ', distributor.address); + console.log('Args: ', escrow.address, '\n'); + const voter = await Voter.deploy(escrow.address, pairFactory.address, gaugeFactory.address, bribeFactory.address); + await voter.deployed(); + console.log('Voter deployed to: ', voter.address); + console.log('Args: ', escrow.address, pairFactory.address, gaugeFactory.address, bribeFactory.address, '\n'); + const minter = await Minter.deploy(voter.address, escrow.address, distributor.address); + await minter.deployed(); + console.log('Minter deployed to: ', minter.address); + console.log('Args: ', voter.address, escrow.address, distributor.address, '\n'); + const receiver = await RedemptionReceiver.deploy(ARB_CONFIG.USDC, flow.address, FTM_CONFIG.lzChainId, ARB_CONFIG.lzEndpoint); + await receiver.deployed(); + console.log('RedemptionReceiver deployed to: ', receiver.address); + console.log('Args: ', ARB_CONFIG.USDC, flow.address, FTM_CONFIG.lzChainId, ARB_CONFIG.lzEndpoint, '\n'); + const governor = await FlowGovernor.deploy(escrow.address); + await governor.deployed(); + console.log('FlowGovernor deployed to: ', governor.address); + console.log('Args: ', escrow.address, '\n'); + // Airdrop + const claim = await MerkleClaim.deploy(flow.address, ARB_CONFIG.merkleRoot); + await claim.deployed(); + console.log('MerkleClaim deployed to: ', claim.address); + console.log('Args: ', flow.address, ARB_CONFIG.merkleRoot, '\n'); + // Initialize + await flow.initialMint(ARB_CONFIG.teamEOA); + console.log('Initial minted'); + await flow.setRedemptionReceiver(receiver.address); + console.log('RedemptionReceiver set'); + await flow.setMerkleClaim(claim.address); + console.log('MerkleClaim set'); + await flow.setMinter(minter.address); + console.log('Minter set'); + await pairFactory.setPauser(ARB_CONFIG.teamMultisig); + console.log('Pauser set'); + await escrow.setVoter(voter.address); + console.log('Voter set'); + await escrow.setTeam(ARB_CONFIG.teamMultisig); + console.log('Team set for escrow'); + await voter.setGovernor(ARB_CONFIG.teamMultisig); + console.log('Governor set'); + await voter.setEmergencyCouncil(ARB_CONFIG.teamMultisig); + console.log('Emergency Council set'); + await distributor.setDepositor(minter.address); + console.log('Depositor set'); + await receiver.setTeam(ARB_CONFIG.teamMultisig); + console.log('Team set for receiver'); + await governor.setTeam(ARB_CONFIG.teamMultisig); + console.log('Team set for governor'); + // Whitelist + const nativeToken = [flow.address]; + const tokenWhitelist = nativeToken.concat(ARB_CONFIG.tokenWhitelist); + await voter.initialize(tokenWhitelist, minter.address); + console.log('Whitelist set'); + // Initial veVELO distro + await minter.initialize(ARB_CONFIG.partnerAddrs, ARB_CONFIG.partnerAmts, ARB_CONFIG.partnerMax); + console.log('veVELO distributed'); + await minter.setTeam(ARB_CONFIG.teamMultisig); + console.log('Team set for minter'); + console.log('Arbitrum Forked Chain contracts deployed'); +}); diff --git a/dist/tasks/deploy/arbTest.js b/dist/tasks/deploy/arbTest.js index 89c6b544..ba696388 100644 --- a/dist/tasks/deploy/arbTest.js +++ b/dist/tasks/deploy/arbTest.js @@ -1,61 +1,35 @@ -'use strict' -var __importDefault = - (this && this.__importDefault) || - function (mod) { - return mod && mod.__esModule ? mod : { default: mod } - } -Object.defineProperty(exports, '__esModule', { value: true }) -const config_1 = require('hardhat/config') -var fs = require('fs') -const optimismConfig_1 = __importDefault(require('./constants/optimismConfig')) -const testOptimismConfig_1 = __importDefault( - require('./constants/testOptimismConfig') -) -const fantomConfig_1 = __importDefault(require('./constants/fantomConfig')) -const testFantomConfig_1 = __importDefault( - require('./constants/testFantomConfig') -) -;(0, config_1.task)('deploy:arbTest', 'Deploys Optimism contracts').setAction( - async function (taskArguments, { ethers }) { - const mainnet = false - const OP_CONFIG = mainnet - ? optimismConfig_1.default - : testOptimismConfig_1.default - const FTM_CONFIG = mainnet - ? fantomConfig_1.default - : testFantomConfig_1.default +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const config_1 = require("hardhat/config"); +var fs = require('fs'); +const optimismConfig_1 = __importDefault(require("./constants/optimismConfig")); +const testOptimismConfig_1 = __importDefault(require("./constants/testOptimismConfig")); +const fantomConfig_1 = __importDefault(require("./constants/fantomConfig")); +const testFantomConfig_1 = __importDefault(require("./constants/testFantomConfig")); +(0, config_1.task)('deploy:arbTest', 'Deploys Optimism contracts').setAction(async function (taskArguments, { ethers }) { + const mainnet = false; + const OP_CONFIG = mainnet ? optimismConfig_1.default : testOptimismConfig_1.default; + const FTM_CONFIG = mainnet ? fantomConfig_1.default : testFantomConfig_1.default; // Load - const [ - Flow, - GaugeFactory, - BribeFactory, - PairFactory, - Router, - Library, - VeArtProxy, - VotingEscrow, - RewardsDistributor, - Voter, - Minter, - FlowGovernor, - RedemptionReceiver, - MerkleClaim - ] = await Promise.all([ - ethers.getContractFactory('Flow'), - ethers.getContractFactory('GaugeFactory'), - ethers.getContractFactory('BribeFactory'), - ethers.getContractFactory('PairFactory'), - ethers.getContractFactory('Router'), - ethers.getContractFactory('VelocimeterLibrary'), - ethers.getContractFactory('VeArtProxy'), - ethers.getContractFactory('VotingEscrow'), - ethers.getContractFactory('RewardsDistributor'), - ethers.getContractFactory('Voter'), - ethers.getContractFactory('Minter'), - ethers.getContractFactory('FlowGovernor'), - ethers.getContractFactory('RedemptionReceiver'), - ethers.getContractFactory('MerkleClaim') - ]) + const [Flow, GaugeFactory, BribeFactory, PairFactory, Router, Library, VeArtProxy, VotingEscrow, RewardsDistributor, Voter, Minter, FlowGovernor, RedemptionReceiver, MerkleClaim] = await Promise.all([ + ethers.getContractFactory('Flow'), + ethers.getContractFactory('GaugeFactory'), + ethers.getContractFactory('BribeFactory'), + ethers.getContractFactory('PairFactory'), + ethers.getContractFactory('Router'), + ethers.getContractFactory('VelocimeterLibrary'), + ethers.getContractFactory('VeArtProxy'), + ethers.getContractFactory('VotingEscrow'), + ethers.getContractFactory('RewardsDistributor'), + ethers.getContractFactory('Voter'), + ethers.getContractFactory('Minter'), + ethers.getContractFactory('FlowGovernor'), + ethers.getContractFactory('RedemptionReceiver'), + ethers.getContractFactory('MerkleClaim') + ]); //WIP wait for 5 block transactions to ensure deployment before verifying // https://stackoverflow.com/questions/72916701/hardhat-compile-deploy-and-verify-in-a-single-script // https://github.com/profullstackdeveloper/contract-deploy-verify-hardhat @@ -68,34 +42,35 @@ const testFantomConfig_1 = __importDefault( // constructorArguments: [arg1, arg2, arg3] // }) // WIP ^^ - const flow = await Flow.deploy() - await flow.deployed() - console.log('Flow deployed to: ', flow.address) + const flow = await Flow.deploy(); + await flow.deployed(); + console.log('Flow deployed to: ', flow.address); await hre.run('verify:verify', { - address: flow.address, - contract: 'contracts/Flow.sol:Flow', - constructorArguments: [] - }) - await flow.deployed() - const name = await flow.name() - console.log('dunksname: ', name) + address: flow.address, + contract: 'contracts/Flow.sol:Flow', + constructorArguments: [] + }); + await flow.deployed(); + const name = await flow.name(); + console.log('dunksname: ', name); const temp1 = { - [name]: flow.address - } - const json1 = JSON.stringify(temp1) - console.log('result of json is ', json1) + [name]: flow.address + }; + const json1 = JSON.stringify(temp1); + console.log('result of json is ', json1); fs.writeFileSync('contracts/deployments/veloAddress.json', json1, err => { - if (err) { - console.log('ERROR! while creating file: ', err) - } else { - console.log('result is ', json1) - } - }) + if (err) { + console.log('ERROR! while creating file: ', err); + } + else { + console.log('result is ', json1); + } + }); // repeat for gauge factory // update all the things... - const gaugeFactory = await GaugeFactory.deploy() - await gaugeFactory.deployed() - console.log('GaugeFactory deployed to: ', gaugeFactory.address) + const gaugeFactory = await GaugeFactory.deploy(); + await gaugeFactory.deployed(); + console.log('GaugeFactory deployed to: ', gaugeFactory.address); // await hre.run('verify:verify', { // address: gaugeFactory.address, // contract: 'contracts/factories/GaugeFactory.sol:GaugeFactory', //Filename.sol:ClassName @@ -116,131 +91,86 @@ const testFantomConfig_1 = __importDefault( // console.log('result is ', json) // } // }) - const bribeFactory = await BribeFactory.deploy() - await bribeFactory.deployed() - console.log('BribeFactory deployed to: ', bribeFactory.address) - const pairFactory = await PairFactory.deploy() - await pairFactory.deployed() - console.log('PairFactory deployed to: ', pairFactory.address) - const router = await Router.deploy(pairFactory.address, OP_CONFIG.WETH) - await router.deployed() - console.log('Router deployed to: ', router.address) - console.log('Args: ', pairFactory.address, OP_CONFIG.WETH, '\n') - const library = await Library.deploy(router.address) - await library.deployed() - console.log('VelocimeterLibrary deployed to: ', library.address) - console.log('Args: ', router.address, '\n') - const artProxy = await VeArtProxy.deploy() - await artProxy.deployed() - console.log('VeArtProxy deployed to: ', artProxy.address) - const escrow = await VotingEscrow.deploy(flow.address, artProxy.address) - await escrow.deployed() - console.log('VotingEscrow deployed to: ', escrow.address) - console.log('Args: ', flow.address, artProxy.address, '\n') - const distributor = await RewardsDistributor.deploy(escrow.address) - await distributor.deployed() - console.log('RewardsDistributor deployed to: ', distributor.address) - console.log('Args: ', escrow.address, '\n') - const voter = await Voter.deploy( - escrow.address, - pairFactory.address, - gaugeFactory.address, - bribeFactory.address - ) - await voter.deployed() - console.log('Voter deployed to: ', voter.address) - console.log( - 'Args: ', - escrow.address, - pairFactory.address, - gaugeFactory.address, - bribeFactory.address, - '\n' - ) - const minter = await Minter.deploy( - voter.address, - escrow.address, - distributor.address - ) - await minter.deployed() - console.log('Minter deployed to: ', minter.address) - console.log( - 'Args: ', - voter.address, - escrow.address, - distributor.address, - '\n' - ) - const receiver = await RedemptionReceiver.deploy( - OP_CONFIG.USDC, - flow.address, - FTM_CONFIG.lzChainId, - OP_CONFIG.lzEndpoint - ) - await receiver.deployed() - console.log('RedemptionReceiver deployed to: ', receiver.address) - console.log( - 'Args: ', - OP_CONFIG.USDC, - flow.address, - FTM_CONFIG.lzChainId, - OP_CONFIG.lzEndpoint, - '\n' - ) - const governor = await FlowGovernor.deploy(escrow.address) - await governor.deployed() - console.log('FlowGovernor deployed to: ', governor.address) - console.log('Args: ', escrow.address, '\n') + const bribeFactory = await BribeFactory.deploy(); + await bribeFactory.deployed(); + console.log('BribeFactory deployed to: ', bribeFactory.address); + const pairFactory = await PairFactory.deploy(); + await pairFactory.deployed(); + console.log('PairFactory deployed to: ', pairFactory.address); + const router = await Router.deploy(pairFactory.address, OP_CONFIG.WETH); + await router.deployed(); + console.log('Router deployed to: ', router.address); + console.log('Args: ', pairFactory.address, OP_CONFIG.WETH, '\n'); + const library = await Library.deploy(router.address); + await library.deployed(); + console.log('VelocimeterLibrary deployed to: ', library.address); + console.log('Args: ', router.address, '\n'); + const artProxy = await VeArtProxy.deploy(); + await artProxy.deployed(); + console.log('VeArtProxy deployed to: ', artProxy.address); + const escrow = await VotingEscrow.deploy(flow.address, artProxy.address); + await escrow.deployed(); + console.log('VotingEscrow deployed to: ', escrow.address); + console.log('Args: ', flow.address, artProxy.address, '\n'); + const distributor = await RewardsDistributor.deploy(escrow.address); + await distributor.deployed(); + console.log('RewardsDistributor deployed to: ', distributor.address); + console.log('Args: ', escrow.address, '\n'); + const voter = await Voter.deploy(escrow.address, pairFactory.address, gaugeFactory.address, bribeFactory.address); + await voter.deployed(); + console.log('Voter deployed to: ', voter.address); + console.log('Args: ', escrow.address, pairFactory.address, gaugeFactory.address, bribeFactory.address, '\n'); + const minter = await Minter.deploy(voter.address, escrow.address, distributor.address); + await minter.deployed(); + console.log('Minter deployed to: ', minter.address); + console.log('Args: ', voter.address, escrow.address, distributor.address, '\n'); + const receiver = await RedemptionReceiver.deploy(OP_CONFIG.USDC, flow.address, FTM_CONFIG.lzChainId, OP_CONFIG.lzEndpoint); + await receiver.deployed(); + console.log('RedemptionReceiver deployed to: ', receiver.address); + console.log('Args: ', OP_CONFIG.USDC, flow.address, FTM_CONFIG.lzChainId, OP_CONFIG.lzEndpoint, '\n'); + const governor = await FlowGovernor.deploy(escrow.address); + await governor.deployed(); + console.log('FlowGovernor deployed to: ', governor.address); + console.log('Args: ', escrow.address, '\n'); // Airdrop // const claim = await MerkleClaim.deploy(flow.address, OP_CONFIG.merkleRoot) // await claim.deployed() // console.log('MerkleClaim deployed to: ', claim.address) // console.log('Args: ', flow.address, OP_CONFIG.merkleRoot, '\n') // Initialize - await flow.initialMint(OP_CONFIG.teamEOA) - console.log('Initial minted') - await flow.setRedemptionReceiver(receiver.address) - console.log('RedemptionReceiver set') + await flow.initialMint(OP_CONFIG.teamEOA); + console.log('Initial minted'); + await flow.setRedemptionReceiver(receiver.address); + console.log('RedemptionReceiver set'); // await flow.setMerkleClaim(claim.address) // console.log('MerkleClaim set') - await flow.setMinter(minter.address) - console.log('Minter set') - await pairFactory.setPauser(OP_CONFIG.teamMultisig) - console.log('Pauser set') - await escrow.setVoter(voter.address) - console.log( - 'Voter set', - 'voter address: ', - voter.address, - 'escrow address: ', - escrow.address - ) - await escrow.setTeam(OP_CONFIG.teamMultisig) - console.log('Team set for escrow') - await voter.setGovernor(OP_CONFIG.teamMultisig) - console.log('Governor set') - await voter.setEmergencyCouncil(OP_CONFIG.teamMultisig) - console.log('Emergency Council set') - await distributor.setDepositor(minter.address) - console.log('Depositor set') - await receiver.setTeam(OP_CONFIG.teamMultisig) - console.log('Team set for receiver') - await governor.setTeam(OP_CONFIG.teamMultisig) - console.log('Team set for governor') + await flow.setMinter(minter.address); + console.log('Minter set'); + await pairFactory.setPauser(OP_CONFIG.teamMultisig); + console.log('Pauser set'); + await escrow.setVoter(voter.address); + console.log('Voter set', 'voter address: ', voter.address, 'escrow address: ', escrow.address); + await escrow.setTeam(OP_CONFIG.teamMultisig); + console.log('Team set for escrow'); + await voter.setGovernor(OP_CONFIG.teamMultisig); + console.log('Governor set'); + await voter.setEmergencyCouncil(OP_CONFIG.teamMultisig); + console.log('Emergency Council set'); + await distributor.setDepositor(minter.address); + console.log('Depositor set'); + await receiver.setTeam(OP_CONFIG.teamMultisig); + console.log('Team set for receiver'); + await governor.setTeam(OP_CONFIG.teamMultisig); + console.log('Team set for governor'); // Whitelist - const nativeToken = [flow.address] - const tokenWhitelist = nativeToken.concat(OP_CONFIG.tokenWhitelist) - await voter.initialize(tokenWhitelist, minter.address) - console.log('Whitelist set') + const nativeToken = [flow.address]; + const tokenWhitelist = nativeToken.concat(OP_CONFIG.tokenWhitelist); + await voter.initialize(tokenWhitelist, minter.address); + console.log('Whitelist set'); // Initial veVELO distro - await minter.initialize( - OP_CONFIG.partnerAddrs, - OP_CONFIG.partnerAmts, - OP_CONFIG.partnerMax - ) - console.log('veVELO distributed') - await minter.setTeam(OP_CONFIG.teamMultisig) - console.log('Team set for minter') - console.log('Arbitrum Goerli Velocimeter Instruments deployed') - } -) + await minter.initialize(OP_CONFIG.partnerAddrs, OP_CONFIG.partnerAmts, OP_CONFIG.partnerMax); + console.log('veVELO distributed'); + await minter.setTeam(OP_CONFIG.teamMultisig); + console.log('Team set for minter'); + console.log('Arbitrum Goerli Velocimeter Instruments deployed'); +}); diff --git a/dist/tasks/deploy/constants/arbConfig.d.ts b/dist/tasks/deploy/constants/arbConfig.d.ts index 232c2572..f9f4fb8b 100644 --- a/dist/tasks/deploy/constants/arbConfig.d.ts +++ b/dist/tasks/deploy/constants/arbConfig.d.ts @@ -6,6 +6,16 @@ declare const arbConfig: { USDC: string; teamEOA: string; teamMultisig: string; + coolie: string; + dunks: string; + ceazor: string; + faeflow: string; + wtck: string; + torbik: string; + arbitrumTeam: string; + velodromeMultisig: string; + anton: string; + andre: string; emergencyCouncil: string; merkleRoot: string; tokenWhitelist: string[]; diff --git a/dist/tasks/deploy/constants/arbConfig.js b/dist/tasks/deploy/constants/arbConfig.js index 0da093d6..d6cccb6e 100644 --- a/dist/tasks/deploy/constants/arbConfig.js +++ b/dist/tasks/deploy/constants/arbConfig.js @@ -4,26 +4,32 @@ const ethers_1 = require('ethers') const TOKEN_DECIMALS = ethers_1.ethers.BigNumber.from('10').pow( ethers_1.ethers.BigNumber.from('18') ) - -const MILLION = ethers_1.ethers.BigNumber.from('1').pow( +const MILLION = ethers_1.ethers.BigNumber.from('10').pow( ethers_1.ethers.BigNumber.from('6') ) -const FOUR_MILLION = ethers_1.ethers.BigNumber.from('4') +console.log(MILLION) +const HALF_MILLION = ethers_1.ethers.BigNumber.from('.5') .mul(MILLION) - .mul(TOKEN_DECIMALS) + .mul(TOKEN_DECIMALS) // not sure if we can do this?? const TWO_MILLION = ethers_1.ethers.BigNumber.from('2') .mul(MILLION) .mul(TOKEN_DECIMALS) +const FOUR_MILLION = ethers_1.ethers.BigNumber.from('4') + .mul(MILLION) + .mul(TOKEN_DECIMALS) const TEN_MILLION = ethers_1.ethers.BigNumber.from('10') .mul(MILLION) .mul(TOKEN_DECIMALS) -const TWELVE_MILLION = ethers_1.ethers.BigNumber.from('12') +const TWELEVE_MILLION = ethers_1.ethers.BigNumber.from('12') + .mul(MILLION) + .mul(TOKEN_DECIMALS) +const TWENTY_MILLION = ethers_1.ethers.BigNumber.from('20') .mul(MILLION) .mul(TOKEN_DECIMALS) const SIXTY_MILLION = ethers_1.ethers.BigNumber.from('60') .mul(MILLION) .mul(TOKEN_DECIMALS) -const PARTNER_MAX = ethers_1.ethers.BigNumber.from('78') +const PARTNER_MAX = ethers_1.ethers.BigNumber.from('90') // It will literally mint this many tokens so be careful with it.. .mul(MILLION) .mul(TOKEN_DECIMALS) const TEAM_MULTISIG = '0x16ec7CD5E35682B751d0c77c41A4e6a1A3E2DE01' @@ -32,6 +38,13 @@ const arbitrumTeam = TEAM_MULTISIG const velodromeMultisig = TEAM_MULTISIG const anton = TEAM_MULTISIG const andre = TEAM_MULTISIG +const coolie = '0x03B88DacB7c21B54cEfEcC297D981E5b721A9dF1' +const ceazor = '0x3c5Aac016EF2F178e8699D6208796A2D67557fe2' +const wtck = '0x78e801136F77805239A7F533521A7a5570F572C8' +const t0rb1k = '0x0b776552c1Aef1Dc33005DD25AcDA22493b6615d' +const dunks = '0x069e85D4F1010DD961897dC8C095FBB5FF297434' +const faeflow = '0x069e85D4F1010DD961897dC8C095FBB5FF297434' +//edit this one or the other one?? const arbConfig = { // Chain const lzChainId: 110, @@ -39,142 +52,154 @@ const arbConfig = { // Tokens WETH: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', USDC: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', - // Addresses teamEOA: TEAM_EOA, teamMultisig: TEAM_MULTISIG, - coolie: 0x03b88dacb7c21b54cefecc297d981e5b721a9df1, + coolie: TEAM_EOA, dunks: '0x069e85D4F1010DD961897dC8C095FBB5FF297434', ceazor: '0x3c5Aac016EF2F178e8699D6208796A2D67557fe2', - faeflow: TEAM_EOA, //update + faeflow: TEAM_EOA, wtck: TEAM_EOA, torbik: TEAM_EOA, - velodromeMultisig: TEAM_EOA, arbitrumTeam: TEAM_MULTISIG, velodromeMultisig: TEAM_MULTISIG, anton: TEAM_MULTISIG, andre: TEAM_MULTISIG, - emergencyCouncil: '0xcC2D01030eC2cd187346F70bFc483F24488C32E8', merkleRoot: '0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f', tokenWhitelist: [ // '0x4200000000000000000000000000000000000042', // OP - '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', // WETH updated - '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', // USDC updated but do we want to whitelist it? - '0x17FC002b466eEc40DaE837Fc4bE5c67993ddBd6F', // FRAX updated - '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', // DAI + '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', + '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', + '0x17FC002b466eEc40DaE837Fc4bE5c67993ddBd6F', + '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', // '0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9', // sUSD not sure on this one - '0x10663b695b8f75647bD3FF0ff609e16D35BbD1eC', // AGG + '0x10663b695b8f75647bD3FF0ff609e16D35BbD1eC', '0xb96B904ba83DdEeCE47CAADa8B40EE6936D92091' //CRE8R - // '0x8aE125E8653821E851F12A49F7765db9a9ce7384', // DOLA // '0x10010078a54396F62c96dF8532dc2B4847d47ED3', // HND - // '0xc40F949F8a4e094D1b49a23ea9241D289B7b2819' // LUSD ], + // partnerAddrs: [ + // TEAM_MULTISIG, // 1 Protocol owned NFT 64m + // '0x069e85D4F1010DD961897dC8C095FBB5FF297434', // 2 dunks + // '0x3c5Aac016EF2F178e8699D6208796A2D67557fe2', // 3 ceazor + // '0x03B88DacB7c21B54cEfEcC297D981E5b721A9dF1', // 4coolie + // '0xf78da0B8Ae888C318e1A19415d593729A61Ac0c3', // 5 faeflow, + // '0x78e801136F77805239A7F533521A7a5570F572C8', // 6 wtck, + // '0x0b776552c1Aef1Dc33005DD25AcDA22493b6615d', // 7 torbik, + // velodromeMultisig, // 8 should we split this up? + // anton, // 9 half % + // andre, // 10 half % + // arbitrumTeam, // 11 minimum 1% could be more if they help us + // TEAM_MULTISIG, // 12 + // TEAM_MULTISIG, // 13 + // TEAM_MULTISIG, // 14 + // TEAM_MULTISIG, // 15 + // TEAM_MULTISIG, // 16 + // TEAM_MULTISIG, // 17 + // TEAM_MULTISIG, // 18 + // TEAM_MULTISIG, // 19 + // TEAM_MULTISIG, // 20 + // TEAM_MULTISIG, // 21 + // TEAM_MULTISIG, // 22 + // TEAM_MULTISIG, // 23 + // TEAM_MULTISIG, // 24 + // TEAM_MULTISIG, // 25 + // TEAM_MULTISIG, // 26 + // TEAM_MULTISIG, // 27 + // TEAM_MULTISIG, // 28 + // TEAM_MULTISIG, // 29 + // TEAM_MULTISIG, // 30 + // TEAM_MULTISIG, // 31 + // TEAM_MULTISIG, // 32 + // TEAM_MULTISIG, // 33 + // TEAM_MULTISIG, // 34 + // TEAM_MULTISIG, // 35 + // TEAM_MULTISIG, // 36 + // TEAM_MULTISIG, // 37 + // TEAM_MULTISIG, // 38 + // TEAM_MULTISIG, // 39 + // TEAM_MULTISIG, // 40 + // TEAM_MULTISIG, // 41 + // TEAM_MULTISIG, // 42 + // TEAM_MULTISIG, // 43 + // TEAM_MULTISIG, // 44 + // TEAM_MULTISIG, // 45 + // TEAM_MULTISIG, // 46 + // TEAM_MULTISIG, // 47 + // TEAM_MULTISIG, // 48 + // TEAM_MULTISIG // 38 x protcol / partner NFTs # 49 + // ], + // partnerAmts: [ + // SIXTY_MILLION, // 60 million for protcol owned NFT 15% #1 + // TWO_MILLION, // dunks presale 2 + // TWO_MILLION, // ceazor presale 3 + // FOUR_MILLION, // team veFLOW 1% 4 + // FOUR_MILLION, // team veFLOW 1% 5 + // FOUR_MILLION, // team veFLOW 1% 6 + // FOUR_MILLION, // team veFLOW 1% 7 + // FOUR_MILLION, // team veFLOW 1% 8 + // FOUR_MILLION, // team veFLOW 1% 9 + // FOUR_MILLION, // 10 tribute to velodrome (need to get their arb address DO NOT USE MULTISIG FROM OP) + // FOUR_MILLION, //11 + // FOUR_MILLION, // 12 + // FOUR_MILLION, // 13 + // FOUR_MILLION, // 14 + // FOUR_MILLION, // 15 + // FOUR_MILLION, // 16 + // FOUR_MILLION, // 17 + // FOUR_MILLION, // 18 + // FOUR_MILLION, // 19 + // FOUR_MILLION, // 20 + // FOUR_MILLION, // 21 + // FOUR_MILLION, // 22 + // FOUR_MILLION, // 23 + // FOUR_MILLION, // 24 + // FOUR_MILLION, // 25 + // FOUR_MILLION, // 26 + // FOUR_MILLION, // 27 + // FOUR_MILLION, // 28 + // FOUR_MILLION, // 29 + // FOUR_MILLION, // 30 + // FOUR_MILLION, // 31 + // FOUR_MILLION, // 32 + // FOUR_MILLION, // 33 + // FOUR_MILLION, // 34 + // FOUR_MILLION, // 35 + // FOUR_MILLION, // 36 + // FOUR_MILLION, // 37 + // FOUR_MILLION, // 38 + // FOUR_MILLION, // 39 + // FOUR_MILLION, // 40 + // FOUR_MILLION, // 41 + // FOUR_MILLION, // 42 + // FOUR_MILLION, // 43 + // FOUR_MILLION, // 44 + // FOUR_MILLION, // 45 + // FOUR_MILLION, // 46 + // FOUR_MILLION, // 47 + // FOUR_MILLION, // 48 + // FOUR_MILLION // 1% to each partner x 38 partners # 49 + // ], partnerAddrs: [ - TEAM_MULTISIG, // 1 Protocol owned NFT 64m - '0x069e85D4F1010DD961897dC8C095FBB5FF297434', // 2 dunks - '0x3c5Aac016EF2F178e8699D6208796A2D67557fe2', // 3 ceazor - '0x03B88DacB7c21B54cEfEcC297D981E5b721A9dF1', // 4coolie - - '0xf78da0B8Ae888C318e1A19415d593729A61Ac0c3', // 5 faeflow, - '0x78e801136F77805239A7F533521A7a5570F572C8', // 6 wtck, - '0x0b776552c1Aef1Dc33005DD25AcDA22493b6615d', // 7 torbik, - velodromeMultisig, // 8 should we split this up? - anton, // 9 half % - andre, // 10 half % - arbitrumTeam, // 11 minimum 1% could be more if they help us - TEAM_MULTISIG, // 12 - TEAM_MULTISIG, // 13 - TEAM_MULTISIG, // 14 - TEAM_MULTISIG, // 15 - TEAM_MULTISIG, // 16 - TEAM_MULTISIG, // 17 - TEAM_MULTISIG, // 18 - TEAM_MULTISIG, // 19 - TEAM_MULTISIG, // 20 - TEAM_MULTISIG, // 21 - TEAM_MULTISIG, // 22 - TEAM_MULTISIG, // 23 - TEAM_MULTISIG, // 24 - TEAM_MULTISIG, // 25 - TEAM_MULTISIG, // 26 - TEAM_MULTISIG, // 27 - TEAM_MULTISIG, // 28 - TEAM_MULTISIG, // 29 - TEAM_MULTISIG, // 30 - TEAM_MULTISIG, // 31 - TEAM_MULTISIG, // 32 - TEAM_MULTISIG, // 33 - TEAM_MULTISIG, // 34 - TEAM_MULTISIG, // 35 - TEAM_MULTISIG, // 36 - TEAM_MULTISIG, // 37 - TEAM_MULTISIG, // 38 - TEAM_MULTISIG, // 39 - TEAM_MULTISIG, // 40 - TEAM_MULTISIG, // 41 - TEAM_MULTISIG, // 42 - TEAM_MULTISIG, // 43 - TEAM_MULTISIG, // 44 - TEAM_MULTISIG, // 45 - TEAM_MULTISIG, // 46 - TEAM_MULTISIG, // 47 - TEAM_MULTISIG, // 48 - TEAM_MULTISIG // 38 x protcol / partner NFTs # 49 + TEAM_MULTISIG, + '0x069e85D4F1010DD961897dC8C095FBB5FF297434', + coolie, + ceazor, + '0xf78da0B8Ae888C318e1A19415d593729A61Ac0c3', + '0x78e801136F77805239A7F533521A7a5570F572C8', + '0x0b776552c1Aef1Dc33005DD25AcDA22493b6615d' ], partnerAmts: [ - SIXTY_MILLION, // 60 million for protcol owned NFT 15% #1 - TWO_MILLION, // dunks presale 2 - TWO_MILLION, // ceazor presale 3 - FOUR_MILLION, // team veFLOW 1% 4 - FOUR_MILLION, // team veFLOW 1% 5 - FOUR_MILLION, // team veFLOW 1% 6 - FOUR_MILLION, // team veFLOW 1% 7 - FOUR_MILLION, // team veFLOW 1% 8 - FOUR_MILLION, // team veFLOW 1% 9 - FOUR_MILLION, // 10 tribute to velodrome (need to get their arb address DO NOT USE MULTISIG FROM OP) - FOUR_MILLION, //11 - FOUR_MILLION, // 12 - FOUR_MILLION, // 13 - FOUR_MILLION, // 14 - FOUR_MILLION, // 15 - FOUR_MILLION, // 16 - FOUR_MILLION, // 17 - FOUR_MILLION, // 18 - FOUR_MILLION, // 19 - FOUR_MILLION, // 20 - FOUR_MILLION, // 21 - FOUR_MILLION, // 22 - FOUR_MILLION, // 23 - FOUR_MILLION, // 24 - FOUR_MILLION, // 25 - FOUR_MILLION, // 26 - FOUR_MILLION, // 27 - FOUR_MILLION, // 28 - FOUR_MILLION, // 29 - FOUR_MILLION, // 30 - FOUR_MILLION, // 31 - FOUR_MILLION, // 32 - FOUR_MILLION, // 33 - FOUR_MILLION, // 34 - FOUR_MILLION, // 35 - FOUR_MILLION, // 36 - FOUR_MILLION, // 37 - FOUR_MILLION, // 38 - FOUR_MILLION, // 39 - FOUR_MILLION, // 40 - FOUR_MILLION, // 41 - FOUR_MILLION, // 42 - FOUR_MILLION, // 43 - FOUR_MILLION, // 44 - FOUR_MILLION, // 45 - FOUR_MILLION, // 46 - FOUR_MILLION, // 47 - FOUR_MILLION, // 48 - FOUR_MILLION // 1% to each partner x 38 partners # 49 + SIXTY_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION ], partnerMax: PARTNER_MAX } diff --git a/dist/tasks/deploy/constants/arbHardhatConfig.js b/dist/tasks/deploy/constants/arbHardhatConfig.js index de543984..f5d5c409 100644 --- a/dist/tasks/deploy/constants/arbHardhatConfig.js +++ b/dist/tasks/deploy/constants/arbHardhatConfig.js @@ -16,14 +16,15 @@ const arbHardhatConfig = { lzChainId: 110, lzEndpoint: '0x3c2269811836af69497E5F486A85D7316753cf62', // Tokens - WETH: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', + WETH: '0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83', USDC: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', // Addresses teamEOA: TEAM_EOA, teamMultisig: TEAM_MULTISIG, - emergencyCouncil: '0xcC2D01030eC2cd187346F70bFc483F24488C32E8', + emergencyCouncil: '0x069e85D4F1010DD961897dC8C095FBB5FF297434', merkleRoot: '0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f', tokenWhitelist: [ + // todo update whitelist with actual goerli tokens '0x4200000000000000000000000000000000000042', '0x4200000000000000000000000000000000000006', '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', diff --git a/dist/tasks/deploy/constants/arbTestnetConfig.d.ts b/dist/tasks/deploy/constants/arbTestnetConfig.d.ts new file mode 100644 index 00000000..5d2c6776 --- /dev/null +++ b/dist/tasks/deploy/constants/arbTestnetConfig.d.ts @@ -0,0 +1,16 @@ +import { ethers } from 'ethers'; +declare const arbHardhatConfig: { + lzChainId: number; + lzEndpoint: string; + WETH: string; + USDC: string; + teamEOA: string; + teamMultisig: string; + emergencyCouncil: string; + merkleRoot: string; + tokenWhitelist: string[]; + partnerAddrs: string[]; + partnerAmts: ethers.BigNumber[]; + partnerMax: ethers.BigNumber; +}; +export default arbHardhatConfig; diff --git a/dist/tasks/deploy/constants/arbTestnetConfig.js b/dist/tasks/deploy/constants/arbTestnetConfig.js index f7e6aabb..f5d5c409 100644 --- a/dist/tasks/deploy/constants/arbTestnetConfig.js +++ b/dist/tasks/deploy/constants/arbTestnetConfig.js @@ -1,93 +1,83 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) -const ethers_1 = require('ethers') -const TOKEN_DECIMALS = ethers_1.ethers.BigNumber.from('10').pow( - ethers_1.ethers.BigNumber.from('18') -) -const MILLION = ethers_1.ethers.BigNumber.from('10').pow( - ethers_1.ethers.BigNumber.from('6') -) -const FOUR_MILLION = ethers_1.ethers.BigNumber.from('4') - .mul(MILLION) - .mul(TOKEN_DECIMALS) -const TEN_MILLION = ethers_1.ethers.BigNumber.from('10') - .mul(MILLION) - .mul(TOKEN_DECIMALS) +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const ethers_1 = require("ethers"); +const TOKEN_DECIMALS = ethers_1.ethers.BigNumber.from('10').pow(ethers_1.ethers.BigNumber.from('18')); +const MILLION = ethers_1.ethers.BigNumber.from('10').pow(ethers_1.ethers.BigNumber.from('6')); +const FOUR_MILLION = ethers_1.ethers.BigNumber.from('4').mul(MILLION).mul(TOKEN_DECIMALS); +const TEN_MILLION = ethers_1.ethers.BigNumber.from('10').mul(MILLION).mul(TOKEN_DECIMALS); const TWENTY_MILLION = ethers_1.ethers.BigNumber.from('20') - .mul(MILLION) - .mul(TOKEN_DECIMALS) -const PARTNER_MAX = ethers_1.ethers.BigNumber.from('78') - .mul(MILLION) - .mul(TOKEN_DECIMALS) -const TEAM_MULTISIG = '0x069e85D4F1010DD961897dC8C095FBB5FF297434' -const TEAM_EOA = '0x069e85D4F1010DD961897dC8C095FBB5FF297434' + .mul(MILLION) + .mul(TOKEN_DECIMALS); +const PARTNER_MAX = ethers_1.ethers.BigNumber.from('78').mul(MILLION).mul(TOKEN_DECIMALS); +const TEAM_MULTISIG = '0x069e85D4F1010DD961897dC8C095FBB5FF297434'; +const TEAM_EOA = '0x069e85D4F1010DD961897dC8C095FBB5FF297434'; const arbHardhatConfig = { - // Chain const - lzChainId: 110, - lzEndpoint: '0x3c2269811836af69497E5F486A85D7316753cf62', - // Tokens - WETH: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', - USDC: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', - // Addresses - teamEOA: TEAM_EOA, - teamMultisig: TEAM_MULTISIG, - emergencyCouncil: '0xcC2D01030eC2cd187346F70bFc483F24488C32E8', - merkleRoot: - '0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f', - tokenWhitelist: [ - '0x4200000000000000000000000000000000000042', - '0x4200000000000000000000000000000000000006', - '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', - '0x2E3D870790dC77A83DD1d18184Acc7439A53f475', - '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', - '0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9', - '0x217D47011b23BB961eB6D93cA9945B7501a5BB11', - '0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb', - '0x67CCEA5bb16181E7b4109c9c2143c24a1c2205Be', - '0x9e1028F5F1D5eDE59748FFceE5532509976840E0', - '0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4', - '0xCB8FA9a76b8e203D8C3797bF438d8FB81Ea3326A', - '0x3E29D3A9316dAB217754d13b28646B76607c5f04', - '0x8aE125E8653821E851F12A49F7765db9a9ce7384', - '0x10010078a54396F62c96dF8532dc2B4847d47ED3', - // "", // BTRFLY -- N/A - // "", // pxVELO -- N/A - '0xc40F949F8a4e094D1b49a23ea9241D289B7b2819' // LUSD - // "", // wstETH -- N/A - // "", // HOP -- N/A - ], - partnerAddrs: [ - TEAM_EOA, - '0x4a84675512949f81EBFEAAcC6C00D03eDd329de5', - TEAM_EOA, - '0xa283139017a2f5BAdE8d8e25412C600055D318F8', - '0xDcf664d0f76E99eaA2DBD569474d0E75dC899FCD', - '0x489863b61C625a15C74FB4C21486baCb4A3937AB', - '0x641f26c67A5D0829Ae61019131093B6a7c7d18a3', - '0xC224bf25Dcc99236F00843c7D8C4194abE8AA94a', - '0xB6DACAE4eF97b4817d54df8e005269f509f803f9', - TEAM_EOA, - TEAM_EOA, - '0x0dF840dCbf1229262A4125C1fc559bd338eC9491', - '0x2E33A660742e813aD948fB9f7d682FE461E5fbf3', - '0xd2D4e9024D8C90aB52032a9F1e0d92D4cE20191B' // LUSD - ], - partnerAmts: [ - TEN_MILLION, - TWENTY_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION - ], - partnerMax: PARTNER_MAX -} -exports.default = arbHardhatConfig + // Chain const + lzChainId: 110, + lzEndpoint: '0x3c2269811836af69497E5F486A85D7316753cf62', + // Tokens + WETH: '0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83', + USDC: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', + // Addresses + teamEOA: TEAM_EOA, + teamMultisig: TEAM_MULTISIG, + emergencyCouncil: '0x069e85D4F1010DD961897dC8C095FBB5FF297434', + merkleRoot: '0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f', + tokenWhitelist: [ + // todo update whitelist with actual goerli tokens + '0x4200000000000000000000000000000000000042', + '0x4200000000000000000000000000000000000006', + '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', + '0x2E3D870790dC77A83DD1d18184Acc7439A53f475', + '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', + '0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9', + '0x217D47011b23BB961eB6D93cA9945B7501a5BB11', + '0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb', + '0x67CCEA5bb16181E7b4109c9c2143c24a1c2205Be', + '0x9e1028F5F1D5eDE59748FFceE5532509976840E0', + '0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4', + '0xCB8FA9a76b8e203D8C3797bF438d8FB81Ea3326A', + '0x3E29D3A9316dAB217754d13b28646B76607c5f04', + '0x8aE125E8653821E851F12A49F7765db9a9ce7384', + '0x10010078a54396F62c96dF8532dc2B4847d47ED3', + // "", // BTRFLY -- N/A + // "", // pxVELO -- N/A + '0xc40F949F8a4e094D1b49a23ea9241D289B7b2819' // LUSD + // "", // wstETH -- N/A + // "", // HOP -- N/A + ], + partnerAddrs: [ + TEAM_EOA, + '0x4a84675512949f81EBFEAAcC6C00D03eDd329de5', + TEAM_EOA, + '0xa283139017a2f5BAdE8d8e25412C600055D318F8', + '0xDcf664d0f76E99eaA2DBD569474d0E75dC899FCD', + '0x489863b61C625a15C74FB4C21486baCb4A3937AB', + '0x641f26c67A5D0829Ae61019131093B6a7c7d18a3', + '0xC224bf25Dcc99236F00843c7D8C4194abE8AA94a', + '0xB6DACAE4eF97b4817d54df8e005269f509f803f9', + TEAM_EOA, + TEAM_EOA, + '0x0dF840dCbf1229262A4125C1fc559bd338eC9491', + '0x2E33A660742e813aD948fB9f7d682FE461E5fbf3', + '0xd2D4e9024D8C90aB52032a9F1e0d92D4cE20191B' // LUSD + ], + partnerAmts: [ + TEN_MILLION, + TWENTY_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION + ], + partnerMax: PARTNER_MAX +}; +exports.default = arbHardhatConfig; diff --git a/dist/tasks/deploy/init.js b/dist/tasks/deploy/init.js index cf29a79a..c23f753f 100644 --- a/dist/tasks/deploy/init.js +++ b/dist/tasks/deploy/init.js @@ -1,4 +1,4 @@ -'use strict' +"use strict"; // The tasks in this file should be called by the multisig // CURRENTLY OUTDATED // import { task } from "hardhat/config"; diff --git a/dist/tasks/deploy/op.js b/dist/tasks/deploy/op.js index e9a6fb01..1276b7ee 100644 --- a/dist/tasks/deploy/op.js +++ b/dist/tasks/deploy/op.js @@ -1,185 +1,120 @@ -'use strict' -var __importDefault = - (this && this.__importDefault) || - function (mod) { - return mod && mod.__esModule ? mod : { default: mod } - } -Object.defineProperty(exports, '__esModule', { value: true }) -const config_1 = require('hardhat/config') -const optimismConfig_1 = __importDefault(require('./constants/optimismConfig')) -const testOptimismConfig_1 = __importDefault( - require('./constants/testOptimismConfig') -) -const fantomConfig_1 = __importDefault(require('./constants/fantomConfig')) -const testFantomConfig_1 = __importDefault( - require('./constants/testFantomConfig') -) -;(0, config_1.task)('deploy:op', 'Deploys Optimism contracts').setAction( - async function (taskArguments, { ethers }) { - const mainnet = false - const OP_CONFIG = mainnet - ? optimismConfig_1.default - : testOptimismConfig_1.default - const FTM_CONFIG = mainnet - ? fantomConfig_1.default - : testFantomConfig_1.default +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const config_1 = require("hardhat/config"); +const optimismConfig_1 = __importDefault(require("./constants/optimismConfig")); +const testOptimismConfig_1 = __importDefault(require("./constants/testOptimismConfig")); +const fantomConfig_1 = __importDefault(require("./constants/fantomConfig")); +const testFantomConfig_1 = __importDefault(require("./constants/testFantomConfig")); +(0, config_1.task)('deploy:op', 'Deploys Optimism contracts').setAction(async function (taskArguments, { ethers }) { + const mainnet = false; + const OP_CONFIG = mainnet ? optimismConfig_1.default : testOptimismConfig_1.default; + const FTM_CONFIG = mainnet ? fantomConfig_1.default : testFantomConfig_1.default; // Load - const [ - Flow, - GaugeFactory, - BribeFactory, - PairFactory, - Router, - Library, - VeArtProxy, - VotingEscrow, - RewardsDistributor, - Voter, - Minter, - FlowGovernor, - RedemptionReceiver, - MerkleClaim - ] = await Promise.all([ - ethers.getContractFactory('Flow'), - ethers.getContractFactory('GaugeFactory'), - ethers.getContractFactory('BribeFactory'), - ethers.getContractFactory('PairFactory'), - ethers.getContractFactory('Router'), - ethers.getContractFactory('VelocimeterLibrary'), - ethers.getContractFactory('VeArtProxy'), - ethers.getContractFactory('VotingEscrow'), - ethers.getContractFactory('RewardsDistributor'), - ethers.getContractFactory('Voter'), - ethers.getContractFactory('Minter'), - ethers.getContractFactory('FlowGovernor'), - ethers.getContractFactory('RedemptionReceiver'), - ethers.getContractFactory('MerkleClaim') - ]) - const flow = await Flow.deploy() - await flow.deployed() - console.log('Flow deployed to: ', flow.address) - const gaugeFactory = await GaugeFactory.deploy() - await gaugeFactory.deployed() - console.log('GaugeFactory deployed to: ', gaugeFactory.address) - const bribeFactory = await BribeFactory.deploy() - await bribeFactory.deployed() - console.log('BribeFactory deployed to: ', bribeFactory.address) - const pairFactory = await PairFactory.deploy() - await pairFactory.deployed() - console.log('PairFactory deployed to: ', pairFactory.address) - const router = await Router.deploy(pairFactory.address, OP_CONFIG.WETH) - await router.deployed() - console.log('Router deployed to: ', router.address) - console.log('Args: ', pairFactory.address, OP_CONFIG.WETH, '\n') - const library = await Library.deploy(router.address) - await library.deployed() - console.log('VelocimeterLibrary deployed to: ', library.address) - console.log('Args: ', router.address, '\n') - const artProxy = await VeArtProxy.deploy() - await artProxy.deployed() - console.log('VeArtProxy deployed to: ', artProxy.address) - const escrow = await VotingEscrow.deploy(flow.address, artProxy.address) - await escrow.deployed() - console.log('VotingEscrow deployed to: ', escrow.address) - console.log('Args: ', flow.address, artProxy.address, '\n') - const distributor = await RewardsDistributor.deploy(escrow.address) - await distributor.deployed() - console.log('RewardsDistributor deployed to: ', distributor.address) - console.log('Args: ', escrow.address, '\n') - const voter = await Voter.deploy( - escrow.address, - pairFactory.address, - gaugeFactory.address, - bribeFactory.address - ) - await voter.deployed() - console.log('Voter deployed to: ', voter.address) - console.log( - 'Args: ', - escrow.address, - pairFactory.address, - gaugeFactory.address, - bribeFactory.address, - '\n' - ) - const minter = await Minter.deploy( - voter.address, - escrow.address, - distributor.address - ) - await minter.deployed() - console.log('Minter deployed to: ', minter.address) - console.log( - 'Args: ', - voter.address, - escrow.address, - distributor.address, - '\n' - ) - const receiver = await RedemptionReceiver.deploy( - OP_CONFIG.USDC, - flow.address, - FTM_CONFIG.lzChainId, - OP_CONFIG.lzEndpoint - ) - await receiver.deployed() - console.log('RedemptionReceiver deployed to: ', receiver.address) - console.log( - 'Args: ', - OP_CONFIG.USDC, - flow.address, - FTM_CONFIG.lzChainId, - OP_CONFIG.lzEndpoint, - '\n' - ) - const governor = await FlowGovernor.deploy(escrow.address) - await governor.deployed() - console.log('FlowGovernor deployed to: ', governor.address) - console.log('Args: ', escrow.address, '\n') + const [Flow, GaugeFactory, BribeFactory, PairFactory, Router, Library, VeArtProxy, VotingEscrow, RewardsDistributor, Voter, Minter, FlowGovernor, RedemptionReceiver, MerkleClaim] = await Promise.all([ + ethers.getContractFactory('Flow'), + ethers.getContractFactory('GaugeFactory'), + ethers.getContractFactory('BribeFactory'), + ethers.getContractFactory('PairFactory'), + ethers.getContractFactory('Router'), + ethers.getContractFactory('VelocimeterLibrary'), + ethers.getContractFactory('VeArtProxy'), + ethers.getContractFactory('VotingEscrow'), + ethers.getContractFactory('RewardsDistributor'), + ethers.getContractFactory('Voter'), + ethers.getContractFactory('Minter'), + ethers.getContractFactory('FlowGovernor'), + ethers.getContractFactory('RedemptionReceiver'), + ethers.getContractFactory('MerkleClaim') + ]); + const flow = await Flow.deploy(); + await flow.deployed(); + console.log('Flow deployed to: ', flow.address); + const gaugeFactory = await GaugeFactory.deploy(); + await gaugeFactory.deployed(); + console.log('GaugeFactory deployed to: ', gaugeFactory.address); + const bribeFactory = await BribeFactory.deploy(); + await bribeFactory.deployed(); + console.log('BribeFactory deployed to: ', bribeFactory.address); + const pairFactory = await PairFactory.deploy(); + await pairFactory.deployed(); + console.log('PairFactory deployed to: ', pairFactory.address); + const router = await Router.deploy(pairFactory.address, OP_CONFIG.WETH); + await router.deployed(); + console.log('Router deployed to: ', router.address); + console.log('Args: ', pairFactory.address, OP_CONFIG.WETH, '\n'); + const library = await Library.deploy(router.address); + await library.deployed(); + console.log('VelocimeterLibrary deployed to: ', library.address); + console.log('Args: ', router.address, '\n'); + const artProxy = await VeArtProxy.deploy(); + await artProxy.deployed(); + console.log('VeArtProxy deployed to: ', artProxy.address); + const escrow = await VotingEscrow.deploy(flow.address, artProxy.address); + await escrow.deployed(); + console.log('VotingEscrow deployed to: ', escrow.address); + console.log('Args: ', flow.address, artProxy.address, '\n'); + const distributor = await RewardsDistributor.deploy(escrow.address); + await distributor.deployed(); + console.log('RewardsDistributor deployed to: ', distributor.address); + console.log('Args: ', escrow.address, '\n'); + const voter = await Voter.deploy(escrow.address, pairFactory.address, gaugeFactory.address, bribeFactory.address); + await voter.deployed(); + console.log('Voter deployed to: ', voter.address); + console.log('Args: ', escrow.address, pairFactory.address, gaugeFactory.address, bribeFactory.address, '\n'); + const minter = await Minter.deploy(voter.address, escrow.address, distributor.address); + await minter.deployed(); + console.log('Minter deployed to: ', minter.address); + console.log('Args: ', voter.address, escrow.address, distributor.address, '\n'); + const receiver = await RedemptionReceiver.deploy(OP_CONFIG.USDC, flow.address, FTM_CONFIG.lzChainId, OP_CONFIG.lzEndpoint); + await receiver.deployed(); + console.log('RedemptionReceiver deployed to: ', receiver.address); + console.log('Args: ', OP_CONFIG.USDC, flow.address, FTM_CONFIG.lzChainId, OP_CONFIG.lzEndpoint, '\n'); + const governor = await FlowGovernor.deploy(escrow.address); + await governor.deployed(); + console.log('FlowGovernor deployed to: ', governor.address); + console.log('Args: ', escrow.address, '\n'); // Airdrop - const claim = await MerkleClaim.deploy(flow.address, OP_CONFIG.merkleRoot) - await claim.deployed() - console.log('MerkleClaim deployed to: ', claim.address) - console.log('Args: ', flow.address, OP_CONFIG.merkleRoot, '\n') + const claim = await MerkleClaim.deploy(flow.address, OP_CONFIG.merkleRoot); + await claim.deployed(); + console.log('MerkleClaim deployed to: ', claim.address); + console.log('Args: ', flow.address, OP_CONFIG.merkleRoot, '\n'); // Initialize - await flow.initialMint(OP_CONFIG.teamEOA) - console.log('Initial minted') - await flow.setRedemptionReceiver(receiver.address) - console.log('RedemptionReceiver set') - await flow.setMerkleClaim(claim.address) - console.log('MerkleClaim set') - await flow.setMinter(minter.address) - console.log('Minter set') - await pairFactory.setPauser(OP_CONFIG.teamMultisig) - console.log('Pauser set') - await escrow.setVoter(voter.address) - console.log('Voter set') - await escrow.setTeam(OP_CONFIG.teamMultisig) - console.log('Team set for escrow') - await voter.setGovernor(OP_CONFIG.teamMultisig) - console.log('Governor set') - await voter.setEmergencyCouncil(OP_CONFIG.teamMultisig) - console.log('Emergency Council set') - await distributor.setDepositor(minter.address) - console.log('Depositor set') - await receiver.setTeam(OP_CONFIG.teamMultisig) - console.log('Team set for receiver') - await governor.setTeam(OP_CONFIG.teamMultisig) - console.log('Team set for governor') + await flow.initialMint(OP_CONFIG.teamEOA); + console.log('Initial minted'); + await flow.setRedemptionReceiver(receiver.address); + console.log('RedemptionReceiver set'); + await flow.setMerkleClaim(claim.address); + console.log('MerkleClaim set'); + await flow.setMinter(minter.address); + console.log('Minter set'); + await pairFactory.setPauser(OP_CONFIG.teamMultisig); + console.log('Pauser set'); + await escrow.setVoter(voter.address); + console.log('Voter set'); + await escrow.setTeam(OP_CONFIG.teamMultisig); + console.log('Team set for escrow'); + await voter.setGovernor(OP_CONFIG.teamMultisig); + console.log('Governor set'); + await voter.setEmergencyCouncil(OP_CONFIG.teamMultisig); + console.log('Emergency Council set'); + await distributor.setDepositor(minter.address); + console.log('Depositor set'); + await receiver.setTeam(OP_CONFIG.teamMultisig); + console.log('Team set for receiver'); + await governor.setTeam(OP_CONFIG.teamMultisig); + console.log('Team set for governor'); // Whitelist - const nativeToken = [flow.address] - const tokenWhitelist = nativeToken.concat(OP_CONFIG.tokenWhitelist) - await voter.initialize(tokenWhitelist, minter.address) - console.log('Whitelist set') + const nativeToken = [flow.address]; + const tokenWhitelist = nativeToken.concat(OP_CONFIG.tokenWhitelist); + await voter.initialize(tokenWhitelist, minter.address); + console.log('Whitelist set'); // Initial veVELO distro - await minter.initialize( - OP_CONFIG.partnerAddrs, - OP_CONFIG.partnerAmts, - OP_CONFIG.partnerMax - ) - console.log('veVELO distributed') - await minter.setTeam(OP_CONFIG.teamMultisig) - console.log('Team set for minter') - console.log('Optimism contracts deployed') - } -) + await minter.initialize(OP_CONFIG.partnerAddrs, OP_CONFIG.partnerAmts, OP_CONFIG.partnerMax); + console.log('veVELO distributed'); + await minter.setTeam(OP_CONFIG.teamMultisig); + console.log('Team set for minter'); + console.log('Optimism contracts deployed'); +}); diff --git a/tasks/deploy/constants/arbConfig.ts b/tasks/deploy/constants/arbConfig.ts index bb89c779..42812379 100644 --- a/tasks/deploy/constants/arbConfig.ts +++ b/tasks/deploy/constants/arbConfig.ts @@ -3,7 +3,14 @@ import { ethers } from 'ethers' const TOKEN_DECIMALS = ethers.BigNumber.from('10').pow( ethers.BigNumber.from('18') ) + const MILLION = ethers.BigNumber.from('10').pow(ethers.BigNumber.from('6')) +console.log('million', MILLION) + +// const HALF_MILLION = ethers.BigNumber.from('.5') +// .mul(MILLION) +// .mul(TOKEN_DECIMALS) +const ONE_MILLION = ethers.BigNumber.from('1').mul(MILLION).mul(TOKEN_DECIMALS) const TWO_MILLION = ethers.BigNumber.from('2').mul(MILLION).mul(TOKEN_DECIMALS) const FOUR_MILLION = ethers.BigNumber.from('4').mul(MILLION).mul(TOKEN_DECIMALS) const TEN_MILLION = ethers.BigNumber.from('10').mul(MILLION).mul(TOKEN_DECIMALS) @@ -16,7 +23,7 @@ const TWENTY_MILLION = ethers.BigNumber.from('20') const SIXTY_MILLION = ethers.BigNumber.from('60') .mul(MILLION) .mul(TOKEN_DECIMALS) -const PARTNER_MAX = ethers.BigNumber.from('9000') +const PARTNER_MAX = ethers.BigNumber.from('600') // It will literally mint this many tokens so be careful with it.. .mul(MILLION) .mul(TOKEN_DECIMALS) @@ -26,6 +33,14 @@ const arbitrumTeam = TEAM_MULTISIG const velodromeMultisig = TEAM_MULTISIG const anton = TEAM_MULTISIG const andre = TEAM_MULTISIG +const coolie = '0x03B88DacB7c21B54cEfEcC297D981E5b721A9dF1' +const ceazor = '0x3c5Aac016EF2F178e8699D6208796A2D67557fe2' +const wtck = '0x78e801136F77805239A7F533521A7a5570F572C8' +const t0rb1k = '0x0b776552c1Aef1Dc33005DD25AcDA22493b6615d' +const dunks = '0x069e85D4F1010DD961897dC8C095FBB5FF297434' +const faeflow = '0x397A7EC90bb4f0e89Ffd2Fb3269a3ef295d4f84A' + +//edit this one or the other one?? const arbConfig = { // Chain const @@ -36,15 +51,45 @@ const arbConfig = { WETH: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', USDC: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', + // partnerAddrs: [ + // TEAM_MULTISIG // 1 Protocol owned NFT 64m + // // dunks, // 2 + // // dunks, //3 + // // coolie, //4 + // // ceazor, //5 + // // ceazor, // 6 + // // faeflow, // 7 faeflow, + // // wtck, // 8 wtck, + // // t0rb1k // 9 torbik, + // // dunks, // 10 + // // dunks // 11 + // ], + // partnerAmts: [ + // SIXTY_MILLION // 60 million for protcol owned NFT 15% #1 + // // FOUR_MILLION, // 2 + // // FOUR_MILLION, // 3 + // // FOUR_MILLION, //4 + // // FOUR_MILLION, //5 + // // FOUR_MILLION, //6 + // // FOUR_MILLION, //7 + // // FOUR_MILLION, // 8 1% + // // FOUR_MILLION // 9 1% + // // MILLION, // 10 1/4 % + // // MILLION // 11 + // ], + partnerAddrs: [TEAM_MULTISIG, dunks, t0rb1k, dunks, t0rb1k, dunks, t0rb1k], + partnerAmts: [SIXTY_MILLION, FOUR_MILLION, FOUR_MILLION, ONE_MILLION], // MILLION Mint 0.001 WTF pls halp + partnerMax: PARTNER_MAX, + // Addresses teamEOA: TEAM_EOA, teamMultisig: TEAM_MULTISIG, coolie: TEAM_EOA, dunks: '0x069e85D4F1010DD961897dC8C095FBB5FF297434', ceazor: '0x3c5Aac016EF2F178e8699D6208796A2D67557fe2', - faeflow: TEAM_EOA, //update - wtck: TEAM_EOA, - torbik: TEAM_EOA, + faeflow: '', //update + wtck: '0x78e801136F77805239A7F533521A7a5570F572C8', + torbik: '0x0b776552c1Aef1Dc33005DD25AcDA22493b6615d', arbitrumTeam: TEAM_MULTISIG, velodromeMultisig: TEAM_MULTISIG, @@ -69,7 +114,7 @@ const arbConfig = { // '0x10010078a54396F62c96dF8532dc2B4847d47ED3', // HND // '0xc40F949F8a4e094D1b49a23ea9241D289B7b2819' // LUSD - ], + ] // partnerAddrs: [ // TEAM_MULTISIG, // 1 Protocol owned NFT 64m // '0x069e85D4F1010DD961897dC8C095FBB5FF297434', // 2 dunks @@ -173,13 +218,6 @@ const arbConfig = { // FOUR_MILLION, // 48 // FOUR_MILLION // 1% to each partner x 38 partners # 49 // ], - partnerAddrs: [ - TEAM_MULTISIG // 1 Protocol owned NFT 64m - ], - partnerAmts: [ - SIXTY_MILLION // 60 million for protcol owned NFT 15% #1 - ], - partnerMax: PARTNER_MAX } export default arbConfig From 716d8ccac87fcdef257e589dc46bae91bd824d87 Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Mon, 30 Jan 2023 21:50:48 +1100 Subject: [PATCH 26/43] m --- contracts/ExternalBribeV.sol | 0 contracts/Minter.sol | 6 +- contracts/WrappedExternalBribeV.sol | 0 contracts/factories/BribeFactory.sol | 24 +- contracts/routerV.sol | 0 deploy/18_wrappedBribeFactory.ts | 25 ++ deployments/arbitrumGoerli/BribeFactory.json | 26 +- deployments/arbitrumGoerli/Flow.json | 54 ++-- deployments/arbitrumGoerli/FlowGovernor.json | 98 +++---- deployments/arbitrumGoerli/GaugeFactory.json | 28 +- deployments/arbitrumGoerli/MerkleClaim.json | 26 +- deployments/arbitrumGoerli/Minter.json | 44 ++-- deployments/arbitrumGoerli/PairFactory.json | 52 ++-- .../arbitrumGoerli/RedemptionReceiver.json | 36 +-- .../arbitrumGoerli/RewardsDistributor.json | 64 ++--- deployments/arbitrumGoerli/Router.json | 28 +- deployments/arbitrumGoerli/VeArtProxy.json | 28 +- .../arbitrumGoerli/VelocimeterLibrary.json | 24 +- deployments/arbitrumGoerli/Voter.json | 76 +++--- deployments/arbitrumGoerli/VotingEscrow.json | 162 ++++++------ .../WrappedExternalBribeFactory.json | 148 +++++++++++ .../6e27611a2cedd773c4cc6e46935e6392.json | 247 ++++++++++++++++++ .../WrappedExternalBribeFactory.json | 148 +++++++++++ .../4e21824d68c90a2d8601cfb8f8d80414.json | 247 ++++++++++++++++++ package.json | 3 +- tasks/deploy/constants/arbConfig.ts | 38 +-- 26 files changed, 1232 insertions(+), 400 deletions(-) create mode 100644 contracts/ExternalBribeV.sol create mode 100644 contracts/WrappedExternalBribeV.sol create mode 100644 contracts/routerV.sol create mode 100644 deploy/18_wrappedBribeFactory.ts create mode 100644 deployments/arbitrumGoerli/WrappedExternalBribeFactory.json create mode 100644 deployments/arbitrumGoerli/solcInputs/6e27611a2cedd773c4cc6e46935e6392.json create mode 100644 deployments/arbitrumOne/WrappedExternalBribeFactory.json create mode 100644 deployments/arbitrumOne/solcInputs/4e21824d68c90a2d8601cfb8f8d80414.json diff --git a/contracts/ExternalBribeV.sol b/contracts/ExternalBribeV.sol new file mode 100644 index 00000000..e69de29b diff --git a/contracts/Minter.sol b/contracts/Minter.sol index 37ba78c1..b701d2ac 100644 --- a/contracts/Minter.sol +++ b/contracts/Minter.sol @@ -43,7 +43,7 @@ contract Minter is IMinter { ) { initializer = msg.sender; team = msg.sender; - teamRate = 30; // 30 bps = 0.03% + teamRate = 30; // 30 bps = 3% _flow = IFlow(IVotingEscrow(__ve).token()); _voter = IVoter(__voter); _ve = IVotingEscrow(__ve); @@ -52,8 +52,8 @@ contract Minter is IMinter { } function initialize( - address[] memory claimants, - uint256[] memory amounts, + address[] memory claimants, // partnerAddrs + uint256[] memory amounts, // partnerAmounts uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m ) external { require(initializer == msg.sender); diff --git a/contracts/WrappedExternalBribeV.sol b/contracts/WrappedExternalBribeV.sol new file mode 100644 index 00000000..e69de29b diff --git a/contracts/factories/BribeFactory.sol b/contracts/factories/BribeFactory.sol index 6e19c8ed..84758461 100644 --- a/contracts/factories/BribeFactory.sol +++ b/contracts/factories/BribeFactory.sol @@ -2,22 +2,30 @@ pragma solidity 0.8.13; import "contracts/interfaces/IBribeFactory.sol"; -import 'contracts/InternalBribe.sol'; -import 'contracts/ExternalBribe.sol'; +import "contracts/InternalBribe.sol"; +import "contracts/ExternalBribe.sol"; contract BribeFactory is IBribeFactory { address public last_internal_bribe; address public last_external_bribe; - function createInternalBribe(address[] memory allowedRewards) external returns (address) { - last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards)); + function createInternalBribe(address[] memory allowedRewards) + external + returns (address) + { + last_internal_bribe = address( + new InternalBribe(msg.sender, allowedRewards) + ); return last_internal_bribe; } - function createExternalBribe(address[] memory allowedRewards) external returns (address) { - last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards)); + function createExternalBribe(address[] memory allowedRewards) + external + returns (address) + { + last_external_bribe = address( + new ExternalBribe(msg.sender, allowedRewards) + ); return last_external_bribe; } } - -// if this imports int and ext bribe why is the the gauge factory asking for those address as if they are deployed to an address. diff --git a/contracts/routerV.sol b/contracts/routerV.sol new file mode 100644 index 00000000..e69de29b diff --git a/deploy/18_wrappedBribeFactory.ts b/deploy/18_wrappedBribeFactory.ts new file mode 100644 index 00000000..27cb64fe --- /dev/null +++ b/deploy/18_wrappedBribeFactory.ts @@ -0,0 +1,25 @@ +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments + + const { deployer } = await getNamedAccounts() + + // const escrow = await deployments.get('VotingEscrow') + // const pairFactory = await deployments.get('PairFactory') + // const gaugeFactory = await deployments.get('GaugeFactory') + // const bribeFactory = await deployments.get('BribeFactory') + const voter = await deployments.get('Voter') + + await deploy('WrappedExternalBribeFactory', { + from: deployer, + args: [voter.address], + log: true, + skipIfAlreadyDeployed: false + }) +} +export default func +func.tags = ['WrappedExternalBribeFactory'] +func.id = 'wrapped-external-bribe-factory' diff --git a/deployments/arbitrumGoerli/BribeFactory.json b/deployments/arbitrumGoerli/BribeFactory.json index 9a162864..c2c76ef9 100644 --- a/deployments/arbitrumGoerli/BribeFactory.json +++ b/deployments/arbitrumGoerli/BribeFactory.json @@ -1,5 +1,5 @@ { - "address": "0x751B8A4792de90f5c774032f688bcAFA976b78d2", + "address": "0xb506F3C710Dbb31177A128d73bDA1D99b90512F2", "abi": [ { "inputs": [ @@ -66,28 +66,28 @@ "type": "function" } ], - "transactionHash": "0x185ad5311989350078ddf3d8ce0f922179054a69f7b6049aa302f25133264b4c", + "transactionHash": "0x76a367f2e00261a614c72434d880ef766013a1903b13708e8f4e128d02fe699c", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x751B8A4792de90f5c774032f688bcAFA976b78d2", + "contractAddress": "0xb506F3C710Dbb31177A128d73bDA1D99b90512F2", "transactionIndex": 1, "gasUsed": "4288879", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xb1a2062a3985eacaefa187ab3b044c2fc8e97d6686037cc22f6fb856c480e9fb", - "transactionHash": "0x185ad5311989350078ddf3d8ce0f922179054a69f7b6049aa302f25133264b4c", + "blockHash": "0xb7b011797f137749c567c8e5322baff5538d1f5ffc0756a97207d81517f636bc", + "transactionHash": "0x76a367f2e00261a614c72434d880ef766013a1903b13708e8f4e128d02fe699c", "logs": [], - "blockNumber": 6069377, + "blockNumber": 6188425, "cumulativeGasUsed": "4288879", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "d2a2160297444b93438826228d1e185d", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createExternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createInternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_external_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_internal_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/BribeFactory.sol\":\"BribeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/ExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract ExternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve; // \\u5929\\u4f7f\\u306e\\u305f\\u307e\\u3054\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balanceOf;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n _prevSupply = supplyCheckpoints[\\n getPriorSupplyIndex(_nextEpochStart + DURATION)\\n ].supply;\\n prevRewards.balanceOf =\\n (cp0.balanceOf *\\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (block.timestamp > _lastEpochEnd) {\\n reward +=\\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\\n }\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0xfe1e53dea8a63ce448c5856a740ed73038ad29a9dcd0f2a2752049b146bb4eb0\",\"license\":\"MIT\"},\"contracts/InternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract InternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve;\\n\\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 public constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n mapping(address => mapping(uint256 => uint256))\\n public userRewardPerTokenStored;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (totalSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / totalSupply);\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\\n _startTimestamp = endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][tokenId],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][tokenId]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n require(isReward[token]);\\n\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2dc302de5dfd95018d1fba7a3a1916d2c1fcf32859d19d38648767f13422a694\",\"license\":\"MIT\"},\"contracts/factories/BribeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IBribeFactory.sol\\\";\\nimport 'contracts/InternalBribe.sol';\\nimport 'contracts/ExternalBribe.sol';\\n\\ncontract BribeFactory is IBribeFactory {\\n address public last_internal_bribe;\\n address public last_external_bribe;\\n\\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\\n return last_internal_bribe;\\n }\\n\\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\\n return last_external_bribe;\\n }\\n}\\n\\n// if this imports int and ext bribe why is the the gauge factory asking for those address as if they are deployed to an address.\\n\",\"keccak256\":\"0xd107fb5a520bae9b655bec4ad2eb11d598e74d0eeda0db547e2526a907dea7ec\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50614cca806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea26469706673582212205d5f561dc89344ce077e473fa6486d4404842add0024fedd5dd3b8d9b8c5096d64736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea26469706673582212209ae9b4f7cd05b4da457b63c0edae414d9a4c62879112ebdb5df9717dd23782d964736f6c634300080d0033a26469706673582212206095c7527ab4fbf61bbea631cc41141117e8abc6109d19e5a7eef414f0a2e86864736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea26469706673582212205d5f561dc89344ce077e473fa6486d4404842add0024fedd5dd3b8d9b8c5096d64736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea26469706673582212209ae9b4f7cd05b4da457b63c0edae414d9a4c62879112ebdb5df9717dd23782d964736f6c634300080d0033a26469706673582212206095c7527ab4fbf61bbea631cc41141117e8abc6109d19e5a7eef414f0a2e86864736f6c634300080d0033", + "numDeployments": 2, + "solcInputHash": "6e27611a2cedd773c4cc6e46935e6392", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createExternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createInternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_external_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_internal_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/BribeFactory.sol\":\"BribeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735303535373437363232\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/ExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract ExternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve; // \\u5929\\u4f7f\\u306e\\u305f\\u307e\\u3054\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balanceOf;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n _prevSupply = supplyCheckpoints[\\n getPriorSupplyIndex(_nextEpochStart + DURATION)\\n ].supply;\\n prevRewards.balanceOf =\\n (cp0.balanceOf *\\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (block.timestamp > _lastEpochEnd) {\\n reward +=\\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\\n }\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0xfe1e53dea8a63ce448c5856a740ed73038ad29a9dcd0f2a2752049b146bb4eb0\",\"license\":\"MIT\"},\"contracts/InternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract InternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve;\\n\\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 public constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n mapping(address => mapping(uint256 => uint256))\\n public userRewardPerTokenStored;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (totalSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / totalSupply);\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\\n _startTimestamp = endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][tokenId],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][tokenId]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n require(isReward[token]);\\n\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2dc302de5dfd95018d1fba7a3a1916d2c1fcf32859d19d38648767f13422a694\",\"license\":\"MIT\"},\"contracts/factories/BribeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IBribeFactory.sol\\\";\\nimport \\\"contracts/InternalBribe.sol\\\";\\nimport \\\"contracts/ExternalBribe.sol\\\";\\n\\ncontract BribeFactory is IBribeFactory {\\n address public last_internal_bribe;\\n address public last_external_bribe;\\n\\n function createInternalBribe(address[] memory allowedRewards)\\n external\\n returns (address)\\n {\\n last_internal_bribe = address(\\n new InternalBribe(msg.sender, allowedRewards)\\n );\\n return last_internal_bribe;\\n }\\n\\n function createExternalBribe(address[] memory allowedRewards)\\n external\\n returns (address)\\n {\\n last_external_bribe = address(\\n new ExternalBribe(msg.sender, allowedRewards)\\n );\\n return last_external_bribe;\\n }\\n}\\n\",\"keccak256\":\"0x8c40b8537b65c9a412a22d707e5a160bf2310c128705dcb0a80f968bc072c39f\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50614cca806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea2646970667358221220383f07a90fe1a92e1da7513e8f9df872d48db6ba27fa4bc2e0e6bb377385872064736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea26469706673582212207aa931c0c0446e52574c00658c2b3661d4f63c19467623d92411d03cd043077e64736f6c634300080d0033a264697066735822122055532663d1925328f3156e07450d20b425b9dac3c261c39496133e0852d03cad64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea2646970667358221220383f07a90fe1a92e1da7513e8f9df872d48db6ba27fa4bc2e0e6bb377385872064736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea26469706673582212207aa931c0c0446e52574c00658c2b3661d4f63c19467623d92411d03cd043077e64736f6c634300080d0033a264697066735822122055532663d1925328f3156e07450d20b425b9dac3c261c39496133e0852d03cad64736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, @@ -101,7 +101,7 @@ "storageLayout": { "storage": [ { - "astId": 21321, + "astId": 21323, "contract": "contracts/factories/BribeFactory.sol:BribeFactory", "label": "last_internal_bribe", "offset": 0, @@ -109,7 +109,7 @@ "type": "t_address" }, { - "astId": 21323, + "astId": 21325, "contract": "contracts/factories/BribeFactory.sol:BribeFactory", "label": "last_external_bribe", "offset": 0, diff --git a/deployments/arbitrumGoerli/Flow.json b/deployments/arbitrumGoerli/Flow.json index fd78a140..edc5fc55 100644 --- a/deployments/arbitrumGoerli/Flow.json +++ b/deployments/arbitrumGoerli/Flow.json @@ -1,5 +1,5 @@ { - "address": "0x4E13914872BFf7e58f3E231b2687fDd084014999", + "address": "0x49E4eA802DdF4CAF7C699782a80DeefdC03Dcb4B", "abi": [ { "inputs": [], @@ -381,43 +381,43 @@ "type": "function" } ], - "transactionHash": "0xaf60f3962ca09f925c640003d31a2aad7f667c470c0522811e6454723e43bfc4", + "transactionHash": "0x8162d4143bba22a7aa330be80d18f4f89ae72a86d155b63a65f646aea577e48b", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x4E13914872BFf7e58f3E231b2687fDd084014999", - "transactionIndex": 2, + "contractAddress": "0x49E4eA802DdF4CAF7C699782a80DeefdC03Dcb4B", + "transactionIndex": 1, "gasUsed": "537302", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000008100000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000010000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000002000000000000000000000000000000000000000000000000000020000000000000000040000000080000000000000000000000000000000000000000", - "blockHash": "0x1beedb944f7dc34a5fa26ab9e94b3a870d2c9af1dee43f8a5a69d240201566cd", - "transactionHash": "0xaf60f3962ca09f925c640003d31a2aad7f667c470c0522811e6454723e43bfc4", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000080000000000000000000000400000000000000000000000000000000000000080000000000000000000000000000008000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000010000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000002000000000000000000000000000000000000000000000000000020000000000000000000000000080000000000000000000000000000000000000000", + "blockHash": "0x78f094f17222191c24acaaf18d4c8bc0a3ffb69d577bcc665f27a2d805a3afb3", + "transactionHash": "0x8162d4143bba22a7aa330be80d18f4f89ae72a86d155b63a65f646aea577e48b", "logs": [ { - "transactionIndex": 2, - "blockNumber": 6069358, - "transactionHash": "0xaf60f3962ca09f925c640003d31a2aad7f667c470c0522811e6454723e43bfc4", - "address": "0x4E13914872BFf7e58f3E231b2687fDd084014999", + "transactionIndex": 1, + "blockNumber": 6188400, + "transactionHash": "0x8162d4143bba22a7aa330be80d18f4f89ae72a86d155b63a65f646aea577e48b", + "address": "0x49E4eA802DdF4CAF7C699782a80DeefdC03Dcb4B", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x00000000000000000000000053f3b51fd7f327e1ec4e6eaa3a049149cb2acad2" ], "data": "0x0000000000000000000000000000000000000000000000000000000000000000", - "logIndex": 11, - "blockHash": "0x1beedb944f7dc34a5fa26ab9e94b3a870d2c9af1dee43f8a5a69d240201566cd" + "logIndex": 0, + "blockHash": "0x78f094f17222191c24acaaf18d4c8bc0a3ffb69d577bcc665f27a2d805a3afb3" } ], - "blockNumber": 6069358, - "cumulativeGasUsed": "1022147", + "blockNumber": 6188400, + "cumulativeGasUsed": "537302", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "d2a2160297444b93438826228d1e185d", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"initialMint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialMinted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleClaim\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redemptionReceiver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_merkleClaim\",\"type\":\"address\"}],\"name\":\"setMerkleClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"setMinter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_receiver\",\"type\":\"address\"}],\"name\":\"setRedemptionReceiver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Flow.sol\":\"Flow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Flow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\n\\ncontract Flow is IFlow {\\n\\n string public constant name = \\\"Velocimeter\\\";\\n string public constant symbol = \\\"FLOW\\\";\\n uint8 public constant decimals = 18;\\n uint public totalSupply = 0;\\n\\n mapping(address => uint) public balanceOf;\\n mapping(address => mapping(address => uint)) public allowance;\\n\\n bool public initialMinted;\\n address public minter;\\n address public redemptionReceiver;\\n address public merkleClaim;\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n\\n constructor() {\\n minter = msg.sender;\\n _mint(msg.sender, 0);\\n }\\n\\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\\n function setMinter(address _minter) external {\\n require(msg.sender == minter);\\n minter = _minter;\\n }\\n\\n function setRedemptionReceiver(address _receiver) external {\\n require(msg.sender == minter);\\n redemptionReceiver = _receiver;\\n }\\n\\n function setMerkleClaim(address _merkleClaim) external {\\n require(msg.sender == minter);\\n merkleClaim = _merkleClaim;\\n }\\n\\n // Initial mint: total 82M\\n // 4M for \\\"Genesis\\\" pools\\n // 30M for liquid team allocation (40M excl init veNFT)\\n // 48M for future partners\\n function initialMint(address _recipient) external {\\n require(msg.sender == minter && !initialMinted);\\n initialMinted = true;\\n _mint(_recipient, 82 * 1e6 * 1e18);\\n }\\n\\n function approve(address _spender, uint _value) external returns (bool) {\\n allowance[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n function _mint(address _to, uint _amount) internal returns (bool) {\\n totalSupply += _amount;\\n unchecked {\\n balanceOf[_to] += _amount;\\n }\\n emit Transfer(address(0x0), _to, _amount);\\n return true;\\n }\\n\\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\\n balanceOf[_from] -= _value;\\n unchecked {\\n balanceOf[_to] += _value;\\n }\\n emit Transfer(_from, _to, _value);\\n return true;\\n }\\n\\n function transfer(address _to, uint _value) external returns (bool) {\\n return _transfer(msg.sender, _to, _value);\\n }\\n\\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\\n uint allowed_from = allowance[_from][msg.sender];\\n if (allowed_from != type(uint).max) {\\n allowance[_from][msg.sender] -= _value;\\n }\\n return _transfer(_from, _to, _value);\\n }\\n\\n function mint(address account, uint amount) external returns (bool) {\\n require(msg.sender == minter);\\n _mint(account, amount);\\n return true;\\n }\\n\\n function claim(address account, uint amount) external returns (bool) {\\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\\n _mint(account, amount);\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xe98c291786f74c8f02edb3673870ba99d6b9adac299bbe42f1df42c740d737ac\",\"license\":\"MIT\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"}},\"version\":1}", - "bytecode": "0x60806040526000805534801561001457600080fd5b5060038054610100600160a81b0319163361010081029190911790915561003c906000610042565b506100d9565b60008160008082825461005591906100b3565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a350600192915050565b600082198211156100d457634e487b7160e01b600052601160045260246000fd5b500190565b61082e806100e86000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ae578063dd62ed3e146102c1578063e752c44a146102ec578063ec676a25146102ff578063fca3b5aa1461031257600080fd5b806395d89b4114610243578063a9059cbb14610266578063aad3ec9614610279578063c268f9ba1461028c578063ca1c4de9146102a157600080fd5b806323b872dd116100f457806323b872dd146101d0578063313ce567146101e357806340c10f19146101fd5780635e05fe501461021057806370a082311461022357600080fd5b806306fdde03146101265780630754617214610166578063095ea7b31461019657806318160ddd146101b9575b600080fd5b6101506040518060400160405280600b81526020016a2b32b637b1b4b6b2ba32b960a91b81525081565b60405161015d919061068e565b60405180910390f35b60035461017e9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015d565b6101a96101a43660046106ff565b610325565b604051901515815260200161015d565b6101c260005481565b60405190815260200161015d565b6101a96101de366004610729565b610391565b6101eb601281565b60405160ff909116815260200161015d565b6101a961020b3660046106ff565b61040b565b60045461017e906001600160a01b031681565b6101c2610231366004610765565b60016020526000908152604090205481565b61015060405180604001604052806004815260200163464c4f5760e01b81525081565b6101a96102743660046106ff565b61043e565b6101a96102873660046106ff565b610452565b61029f61029a366004610765565b610481565b005b6003546101a99060ff1681565b61029f6102bc366004610765565b6104d2565b6101c26102cf366004610780565b600260209081526000928352604080842090915290825290205481565b60055461017e906001600160a01b031681565b61029f61030d366004610765565b610510565b61029f610320366004610765565b61054e565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103809086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f7576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103f19084906107c9565b90915550505b610402858585610592565b95945050505050565b60035460009061010090046001600160a01b0316331461042a57600080fd5b6104348383610629565b5060019392505050565b600061044b338484610592565b9392505050565b6004546000906001600160a01b031633148061047857506005546001600160a01b031633145b61042a57600080fd5b60035461010090046001600160a01b0316331480156104a3575060035460ff16155b6104ac57600080fd5b6003805460ff191660011790556104ce816a43d42ce83da41d92000000610629565b5050565b60035461010090046001600160a01b031633146104ee57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052c57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056a57600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105bc9084906107c9565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106179086815260200190565b60405180910390a35060019392505050565b60008160008082825461063c91906107e0565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610380565b600060208083528351808285015260005b818110156106bb5785810183015185820160400152820161069f565b818111156106cd576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106fa57600080fd5b919050565b6000806040838503121561071257600080fd5b61071b836106e3565b946020939093013593505050565b60008060006060848603121561073e57600080fd5b610747846106e3565b9250610755602085016106e3565b9150604084013590509250925092565b60006020828403121561077757600080fd5b61044b826106e3565b6000806040838503121561079357600080fd5b61079c836106e3565b91506107aa602084016106e3565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107db576107db6107b3565b500390565b600082198211156107f3576107f36107b3565b50019056fea2646970667358221220f8b02598ef222bea887cc1b8774b7a707d0d5af2989efc0c337c134d268c958864736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ae578063dd62ed3e146102c1578063e752c44a146102ec578063ec676a25146102ff578063fca3b5aa1461031257600080fd5b806395d89b4114610243578063a9059cbb14610266578063aad3ec9614610279578063c268f9ba1461028c578063ca1c4de9146102a157600080fd5b806323b872dd116100f457806323b872dd146101d0578063313ce567146101e357806340c10f19146101fd5780635e05fe501461021057806370a082311461022357600080fd5b806306fdde03146101265780630754617214610166578063095ea7b31461019657806318160ddd146101b9575b600080fd5b6101506040518060400160405280600b81526020016a2b32b637b1b4b6b2ba32b960a91b81525081565b60405161015d919061068e565b60405180910390f35b60035461017e9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015d565b6101a96101a43660046106ff565b610325565b604051901515815260200161015d565b6101c260005481565b60405190815260200161015d565b6101a96101de366004610729565b610391565b6101eb601281565b60405160ff909116815260200161015d565b6101a961020b3660046106ff565b61040b565b60045461017e906001600160a01b031681565b6101c2610231366004610765565b60016020526000908152604090205481565b61015060405180604001604052806004815260200163464c4f5760e01b81525081565b6101a96102743660046106ff565b61043e565b6101a96102873660046106ff565b610452565b61029f61029a366004610765565b610481565b005b6003546101a99060ff1681565b61029f6102bc366004610765565b6104d2565b6101c26102cf366004610780565b600260209081526000928352604080842090915290825290205481565b60055461017e906001600160a01b031681565b61029f61030d366004610765565b610510565b61029f610320366004610765565b61054e565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103809086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f7576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103f19084906107c9565b90915550505b610402858585610592565b95945050505050565b60035460009061010090046001600160a01b0316331461042a57600080fd5b6104348383610629565b5060019392505050565b600061044b338484610592565b9392505050565b6004546000906001600160a01b031633148061047857506005546001600160a01b031633145b61042a57600080fd5b60035461010090046001600160a01b0316331480156104a3575060035460ff16155b6104ac57600080fd5b6003805460ff191660011790556104ce816a43d42ce83da41d92000000610629565b5050565b60035461010090046001600160a01b031633146104ee57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052c57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056a57600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105bc9084906107c9565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106179086815260200190565b60405180910390a35060019392505050565b60008160008082825461063c91906107e0565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610380565b600060208083528351808285015260005b818110156106bb5785810183015185820160400152820161069f565b818111156106cd576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106fa57600080fd5b919050565b6000806040838503121561071257600080fd5b61071b836106e3565b946020939093013593505050565b60008060006060848603121561073e57600080fd5b610747846106e3565b9250610755602085016106e3565b9150604084013590509250925092565b60006020828403121561077757600080fd5b61044b826106e3565b6000806040838503121561079357600080fd5b61079c836106e3565b91506107aa602084016106e3565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107db576107db6107b3565b500390565b600082198211156107f3576107f36107b3565b50019056fea2646970667358221220f8b02598ef222bea887cc1b8774b7a707d0d5af2989efc0c337c134d268c958864736f6c634300080d0033", + "numDeployments": 2, + "solcInputHash": "6e27611a2cedd773c4cc6e46935e6392", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"initialMint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialMinted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleClaim\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redemptionReceiver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_merkleClaim\",\"type\":\"address\"}],\"name\":\"setMerkleClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"setMinter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_receiver\",\"type\":\"address\"}],\"name\":\"setRedemptionReceiver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Flow.sol\":\"Flow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735303535373437363232\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Flow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\n\\ncontract Flow is IFlow {\\n\\n string public constant name = \\\"Velocimeter\\\";\\n string public constant symbol = \\\"FLOW\\\";\\n uint8 public constant decimals = 18;\\n uint public totalSupply = 0;\\n\\n mapping(address => uint) public balanceOf;\\n mapping(address => mapping(address => uint)) public allowance;\\n\\n bool public initialMinted;\\n address public minter;\\n address public redemptionReceiver;\\n address public merkleClaim;\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n\\n constructor() {\\n minter = msg.sender;\\n _mint(msg.sender, 0);\\n }\\n\\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\\n function setMinter(address _minter) external {\\n require(msg.sender == minter);\\n minter = _minter;\\n }\\n\\n function setRedemptionReceiver(address _receiver) external {\\n require(msg.sender == minter);\\n redemptionReceiver = _receiver;\\n }\\n\\n function setMerkleClaim(address _merkleClaim) external {\\n require(msg.sender == minter);\\n merkleClaim = _merkleClaim;\\n }\\n\\n // Initial mint: total 82M\\n // 4M for \\\"Genesis\\\" pools\\n // 30M for liquid team allocation (40M excl init veNFT)\\n // 48M for future partners\\n function initialMint(address _recipient) external {\\n require(msg.sender == minter && !initialMinted);\\n initialMinted = true;\\n _mint(_recipient, 82 * 1e6 * 1e18);\\n }\\n\\n function approve(address _spender, uint _value) external returns (bool) {\\n allowance[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n function _mint(address _to, uint _amount) internal returns (bool) {\\n totalSupply += _amount;\\n unchecked {\\n balanceOf[_to] += _amount;\\n }\\n emit Transfer(address(0x0), _to, _amount);\\n return true;\\n }\\n\\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\\n balanceOf[_from] -= _value;\\n unchecked {\\n balanceOf[_to] += _value;\\n }\\n emit Transfer(_from, _to, _value);\\n return true;\\n }\\n\\n function transfer(address _to, uint _value) external returns (bool) {\\n return _transfer(msg.sender, _to, _value);\\n }\\n\\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\\n uint allowed_from = allowance[_from][msg.sender];\\n if (allowed_from != type(uint).max) {\\n allowance[_from][msg.sender] -= _value;\\n }\\n return _transfer(_from, _to, _value);\\n }\\n\\n function mint(address account, uint amount) external returns (bool) {\\n require(msg.sender == minter);\\n _mint(account, amount);\\n return true;\\n }\\n\\n function claim(address account, uint amount) external returns (bool) {\\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\\n _mint(account, amount);\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xe98c291786f74c8f02edb3673870ba99d6b9adac299bbe42f1df42c740d737ac\",\"license\":\"MIT\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"}},\"version\":1}", + "bytecode": "0x60806040526000805534801561001457600080fd5b5060038054610100600160a81b0319163361010081029190911790915561003c906000610042565b506100d9565b60008160008082825461005591906100b3565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a350600192915050565b600082198211156100d457634e487b7160e01b600052601160045260246000fd5b500190565b61082e806100e86000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ae578063dd62ed3e146102c1578063e752c44a146102ec578063ec676a25146102ff578063fca3b5aa1461031257600080fd5b806395d89b4114610243578063a9059cbb14610266578063aad3ec9614610279578063c268f9ba1461028c578063ca1c4de9146102a157600080fd5b806323b872dd116100f457806323b872dd146101d0578063313ce567146101e357806340c10f19146101fd5780635e05fe501461021057806370a082311461022357600080fd5b806306fdde03146101265780630754617214610166578063095ea7b31461019657806318160ddd146101b9575b600080fd5b6101506040518060400160405280600b81526020016a2b32b637b1b4b6b2ba32b960a91b81525081565b60405161015d919061068e565b60405180910390f35b60035461017e9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015d565b6101a96101a43660046106ff565b610325565b604051901515815260200161015d565b6101c260005481565b60405190815260200161015d565b6101a96101de366004610729565b610391565b6101eb601281565b60405160ff909116815260200161015d565b6101a961020b3660046106ff565b61040b565b60045461017e906001600160a01b031681565b6101c2610231366004610765565b60016020526000908152604090205481565b61015060405180604001604052806004815260200163464c4f5760e01b81525081565b6101a96102743660046106ff565b61043e565b6101a96102873660046106ff565b610452565b61029f61029a366004610765565b610481565b005b6003546101a99060ff1681565b61029f6102bc366004610765565b6104d2565b6101c26102cf366004610780565b600260209081526000928352604080842090915290825290205481565b60055461017e906001600160a01b031681565b61029f61030d366004610765565b610510565b61029f610320366004610765565b61054e565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103809086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f7576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103f19084906107c9565b90915550505b610402858585610592565b95945050505050565b60035460009061010090046001600160a01b0316331461042a57600080fd5b6104348383610629565b5060019392505050565b600061044b338484610592565b9392505050565b6004546000906001600160a01b031633148061047857506005546001600160a01b031633145b61042a57600080fd5b60035461010090046001600160a01b0316331480156104a3575060035460ff16155b6104ac57600080fd5b6003805460ff191660011790556104ce816a43d42ce83da41d92000000610629565b5050565b60035461010090046001600160a01b031633146104ee57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052c57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056a57600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105bc9084906107c9565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106179086815260200190565b60405180910390a35060019392505050565b60008160008082825461063c91906107e0565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610380565b600060208083528351808285015260005b818110156106bb5785810183015185820160400152820161069f565b818111156106cd576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106fa57600080fd5b919050565b6000806040838503121561071257600080fd5b61071b836106e3565b946020939093013593505050565b60008060006060848603121561073e57600080fd5b610747846106e3565b9250610755602085016106e3565b9150604084013590509250925092565b60006020828403121561077757600080fd5b61044b826106e3565b6000806040838503121561079357600080fd5b61079c836106e3565b91506107aa602084016106e3565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107db576107db6107b3565b500390565b600082198211156107f3576107f36107b3565b50019056fea26469706673582212201feb195c14efa3bcf6edce815fd11c1f178ad8461ca1fd2e95583b7e4ddd295564736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ae578063dd62ed3e146102c1578063e752c44a146102ec578063ec676a25146102ff578063fca3b5aa1461031257600080fd5b806395d89b4114610243578063a9059cbb14610266578063aad3ec9614610279578063c268f9ba1461028c578063ca1c4de9146102a157600080fd5b806323b872dd116100f457806323b872dd146101d0578063313ce567146101e357806340c10f19146101fd5780635e05fe501461021057806370a082311461022357600080fd5b806306fdde03146101265780630754617214610166578063095ea7b31461019657806318160ddd146101b9575b600080fd5b6101506040518060400160405280600b81526020016a2b32b637b1b4b6b2ba32b960a91b81525081565b60405161015d919061068e565b60405180910390f35b60035461017e9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015d565b6101a96101a43660046106ff565b610325565b604051901515815260200161015d565b6101c260005481565b60405190815260200161015d565b6101a96101de366004610729565b610391565b6101eb601281565b60405160ff909116815260200161015d565b6101a961020b3660046106ff565b61040b565b60045461017e906001600160a01b031681565b6101c2610231366004610765565b60016020526000908152604090205481565b61015060405180604001604052806004815260200163464c4f5760e01b81525081565b6101a96102743660046106ff565b61043e565b6101a96102873660046106ff565b610452565b61029f61029a366004610765565b610481565b005b6003546101a99060ff1681565b61029f6102bc366004610765565b6104d2565b6101c26102cf366004610780565b600260209081526000928352604080842090915290825290205481565b60055461017e906001600160a01b031681565b61029f61030d366004610765565b610510565b61029f610320366004610765565b61054e565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103809086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f7576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103f19084906107c9565b90915550505b610402858585610592565b95945050505050565b60035460009061010090046001600160a01b0316331461042a57600080fd5b6104348383610629565b5060019392505050565b600061044b338484610592565b9392505050565b6004546000906001600160a01b031633148061047857506005546001600160a01b031633145b61042a57600080fd5b60035461010090046001600160a01b0316331480156104a3575060035460ff16155b6104ac57600080fd5b6003805460ff191660011790556104ce816a43d42ce83da41d92000000610629565b5050565b60035461010090046001600160a01b031633146104ee57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052c57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056a57600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105bc9084906107c9565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106179086815260200190565b60405180910390a35060019392505050565b60008160008082825461063c91906107e0565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610380565b600060208083528351808285015260005b818110156106bb5785810183015185820160400152820161069f565b818111156106cd576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106fa57600080fd5b919050565b6000806040838503121561071257600080fd5b61071b836106e3565b946020939093013593505050565b60008060006060848603121561073e57600080fd5b610747846106e3565b9250610755602085016106e3565b9150604084013590509250925092565b60006020828403121561077757600080fd5b61044b826106e3565b6000806040838503121561079357600080fd5b61079c836106e3565b91506107aa602084016106e3565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107db576107db6107b3565b500390565b600082198211156107f3576107f36107b3565b50019056fea26469706673582212201feb195c14efa3bcf6edce815fd11c1f178ad8461ca1fd2e95583b7e4ddd295564736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, @@ -431,7 +431,7 @@ "storageLayout": { "storage": [ { - "astId": 1342, + "astId": 1343, "contract": "contracts/Flow.sol:Flow", "label": "totalSupply", "offset": 0, @@ -439,7 +439,7 @@ "type": "t_uint256" }, { - "astId": 1346, + "astId": 1347, "contract": "contracts/Flow.sol:Flow", "label": "balanceOf", "offset": 0, @@ -447,7 +447,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1352, + "astId": 1353, "contract": "contracts/Flow.sol:Flow", "label": "allowance", "offset": 0, @@ -455,7 +455,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 1354, + "astId": 1355, "contract": "contracts/Flow.sol:Flow", "label": "initialMinted", "offset": 0, @@ -463,7 +463,7 @@ "type": "t_bool" }, { - "astId": 1356, + "astId": 1357, "contract": "contracts/Flow.sol:Flow", "label": "minter", "offset": 1, @@ -471,7 +471,7 @@ "type": "t_address" }, { - "astId": 1358, + "astId": 1359, "contract": "contracts/Flow.sol:Flow", "label": "redemptionReceiver", "offset": 0, @@ -479,7 +479,7 @@ "type": "t_address" }, { - "astId": 1360, + "astId": 1361, "contract": "contracts/Flow.sol:Flow", "label": "merkleClaim", "offset": 0, diff --git a/deployments/arbitrumGoerli/FlowGovernor.json b/deployments/arbitrumGoerli/FlowGovernor.json index 5bd87a17..feb4820c 100644 --- a/deployments/arbitrumGoerli/FlowGovernor.json +++ b/deployments/arbitrumGoerli/FlowGovernor.json @@ -1,5 +1,5 @@ { - "address": "0x4C80ebcC6942543c83dA9cbD9aab41994307909c", + "address": "0x89b3ba263B34F95118cE4ed8Fb8A417Fc406ab61", "abi": [ { "inputs": [ @@ -1055,43 +1055,43 @@ "type": "receive" } ], - "transactionHash": "0x5890f42548404912dc7a781bf48dfc717a9ee7fedcc2031802bc667f57427d43", + "transactionHash": "0xcbe7f6b35db978e40a7e9a27c31152cc21533bd56987ef3cd6dece199dce59a0", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x4C80ebcC6942543c83dA9cbD9aab41994307909c", + "contractAddress": "0x89b3ba263B34F95118cE4ed8Fb8A417Fc406ab61", "transactionIndex": 1, "gasUsed": "2742890", - "logsBloom": "0x00000000000000000100000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x273df698ce46e21bb47c3fdaf3912c203104a6061471ed97193c8f892d851671", - "transactionHash": "0x5890f42548404912dc7a781bf48dfc717a9ee7fedcc2031802bc667f57427d43", + "logsBloom": "0x00000000000000000100000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000004000000000040000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xa0007d324cd128170d9c0150a633357d987c4063f5166568e6ff1daf28aa8472", + "transactionHash": "0xcbe7f6b35db978e40a7e9a27c31152cc21533bd56987ef3cd6dece199dce59a0", "logs": [ { "transactionIndex": 1, - "blockNumber": 6069454, - "transactionHash": "0x5890f42548404912dc7a781bf48dfc717a9ee7fedcc2031802bc667f57427d43", - "address": "0x4C80ebcC6942543c83dA9cbD9aab41994307909c", + "blockNumber": 6188476, + "transactionHash": "0xcbe7f6b35db978e40a7e9a27c31152cc21533bd56987ef3cd6dece199dce59a0", + "address": "0x89b3ba263B34F95118cE4ed8Fb8A417Fc406ab61", "topics": [ "0x0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997" ], "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004", "logIndex": 0, - "blockHash": "0x273df698ce46e21bb47c3fdaf3912c203104a6061471ed97193c8f892d851671" + "blockHash": "0xa0007d324cd128170d9c0150a633357d987c4063f5166568e6ff1daf28aa8472" } ], - "blockNumber": 6069454, + "blockNumber": 6188476, "cumulativeGasUsed": "2742890", "status": 1, "byzantium": true }, "args": [ - "0x6d55AFbF1cAf01E0bcA5255bbA730da6fAFD0aF4" + "0x38c8250FF6bD87812eDc5aAee577836c2B3c2aE6" ], - "numDeployments": 1, - "solcInputHash": "d2a2160297444b93438826228d1e185d", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"_ve\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"Empty\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"proposer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"string[]\",\"name\":\"signatures\",\"type\":\"string[]\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"ProposalCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldQuorumNumerator\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"QuorumNumeratorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"VoteCast\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"VoteCastWithParams\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"COUNTING_MODE\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EXTENDED_BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_PROPOSAL_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROPOSAL_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"}],\"name\":\"castVote\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"castVoteWithReason\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"castVoteWithReasonAndParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteWithReasonAndParamsBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"execute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"getVotesWithParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasVoted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"hashProposal\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalDeadline\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalSnapshot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"againstVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"forVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"abstainVotes\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"propose\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"quorum\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumDenominator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"}],\"name\":\"setProposalNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTeam\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"state\",\"outputs\":[{\"internalType\":\"enum IGovernor.ProposalState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"updateQuorumNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"Empty()\":[{\"details\":\"An operation (e.g. {front}) couldn't be completed due to the queue being empty.\"}]},\"kind\":\"dev\",\"methods\":{\"COUNTING_MODE()\":{\"details\":\"See {IGovernor-COUNTING_MODE}.\"},\"castVote(uint256,uint8)\":{\"details\":\"See {IGovernor-castVote}.\"},\"castVoteBySig(uint256,uint8,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteBySig}.\"},\"castVoteWithReason(uint256,uint8,string)\":{\"details\":\"See {IGovernor-castVoteWithReason}.\"},\"castVoteWithReasonAndParams(uint256,uint8,string,bytes)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParams}.\"},\"castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParamsBySig}.\"},\"execute(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-execute}.\"},\"getVotes(address,uint256)\":{\"details\":\"See {IGovernor-getVotes}.\"},\"getVotesWithParams(address,uint256,bytes)\":{\"details\":\"See {IGovernor-getVotesWithParams}.\"},\"hasVoted(uint256,address)\":{\"details\":\"See {IGovernor-hasVoted}.\"},\"hashProposal(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-hashProposal}. The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in advance, before the proposal is submitted. Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the same proposal (with same operation and same description) will have the same id if submitted on multiple governors across multiple networks. This also means that in order to execute the same operation twice (on the same governor) the proposer will have to change the description in order to avoid proposal id conflicts.\"},\"name()\":{\"details\":\"See {IGovernor-name}.\"},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155BatchReceived}.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155Received}.\"},\"onERC721Received(address,address,uint256,bytes)\":{\"details\":\"See {IERC721Receiver-onERC721Received}.\"},\"proposalDeadline(uint256)\":{\"details\":\"See {IGovernor-proposalDeadline}.\"},\"proposalSnapshot(uint256)\":{\"details\":\"See {IGovernor-proposalSnapshot}.\"},\"proposalThreshold()\":{\"details\":\"Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\"},\"proposalVotes(uint256)\":{\"details\":\"Accessor to the internal vote counts.\"},\"propose(address[],uint256[],bytes[],string)\":{\"details\":\"See {IGovernor-propose}.\"},\"quorum(uint256)\":{\"details\":\"Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\"},\"quorumDenominator()\":{\"details\":\"Returns the quorum denominator. Defaults to 100, but may be overridden.\"},\"quorumNumerator()\":{\"details\":\"Returns the current quorum numerator. See {quorumDenominator}.\"},\"relay(address,uint256,bytes)\":{\"details\":\"Relays a transaction or function call to an arbitrary target. In cases where the governance executor is some contract other than the governor itself, like when using a timelock, this function can be invoked in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake. Note that if the executor is simply the governor itself, use of `relay` is redundant.\"},\"state(uint256)\":{\"details\":\"See {IGovernor-state}.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"updateQuorumNumerator(uint256)\":{\"details\":\"Changes the quorum numerator. Emits a {QuorumNumeratorUpdated} event. Requirements: - Must be called through a governance proposal. - New numerator must be smaller or equal to the denominator.\"},\"version()\":{\"details\":\"See {IGovernor-version}.\"},\"votingDelay()\":{\"details\":\"Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\"},\"votingPeriod()\":{\"details\":\"Delay, in number of blocks, between the vote start and vote ends. NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting duration compared to the voting delay.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"votingDelay()\":{\"notice\":\"module:user-config\"},\"votingPeriod()\":{\"notice\":\"module:user-config\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/FlowGovernor.sol\":\"FlowGovernor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/FlowGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IGovernor} from \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\nimport {L2GovernorCountingSimple} from \\\"contracts/governance/L2GovernorCountingSimple.sol\\\";\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\nimport {L2GovernorVotesQuorumFraction} from \\\"contracts/governance/L2GovernorVotesQuorumFraction.sol\\\";\\n\\ncontract FlowGovernor is\\n L2Governor,\\n L2GovernorCountingSimple,\\n L2GovernorVotes,\\n L2GovernorVotesQuorumFraction\\n{\\n address public team;\\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\\n uint256 public proposalNumerator = 2; // start at 0.02%\\n\\n constructor(IVotes _ve)\\n L2Governor(\\\"Velocimeter Governor\\\")\\n L2GovernorVotes(_ve)\\n L2GovernorVotesQuorumFraction(4) // 4%\\n {\\n team = msg.sender;\\n }\\n\\n function votingDelay() public pure override(IGovernor) returns (uint256) {\\n return 15 minutes; // 1 block\\n }\\n\\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\\n return 1 weeks;\\n }\\n\\n function setTeam(address newTeam) external {\\n require(msg.sender == team, \\\"not team\\\");\\n team = newTeam;\\n }\\n\\n function setProposalNumerator(uint256 numerator) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \\\"numerator too high\\\");\\n proposalNumerator = numerator;\\n }\\n\\n function proposalThreshold()\\n public\\n view\\n override(L2Governor)\\n returns (uint256)\\n {\\n return\\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\\n PROPOSAL_DENOMINATOR;\\n }\\n}\\n\",\"keccak256\":\"0xbf02f2fa1b0179b06bba2274ce6720c31ba3783f899502567cc25a093b27edb6\",\"license\":\"MIT\"},\"contracts/governance/L2Governor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Address.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Context.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\\n *\\n * @dev Core of the governance system, designed to be extended though various modules.\\n *\\n * This contract is abstract and requires several function to be implemented in various modules:\\n *\\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\\n * - A voting module must implement {_getVotes}\\n * - Additionanly, the {votingPeriod} must also be implemented\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\\n using SafeCast for uint256;\\n using Timers for Timers.Timestamp;\\n\\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\\\"Ballot(uint256 proposalId,uint8 support)\\\");\\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\\n keccak256(\\\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\\\");\\n\\n struct ProposalCore {\\n Timers.Timestamp voteStart;\\n Timers.Timestamp voteEnd;\\n bool executed;\\n bool canceled;\\n }\\n\\n string private _name;\\n\\n mapping(uint256 => ProposalCore) private _proposals;\\n\\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\\n\\n /**\\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\\n * parameter setters in {GovernorSettings} are protected using this modifier.\\n *\\n * The governance executing address may be different from the Governor's own address, for example it could be a\\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\\n * for example, additional timelock proposers are not able to change governance parameters without going through the\\n * governance protocol (since v4.6).\\n */\\n modifier onlyGovernance() {\\n require(_msgSender() == _executor(), \\\"Governor: onlyGovernance\\\");\\n if (_executor() != address(this)) {\\n bytes32 msgDataHash = keccak256(_msgData());\\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\\n while (_governanceCall.popFront() != msgDataHash) {}\\n }\\n _;\\n }\\n\\n /**\\n * @dev Sets the value for {name} and {version}\\n */\\n constructor(string memory name_) EIP712(name_, version()) {\\n _name = name_;\\n }\\n\\n /**\\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\\n */\\n receive() external payable virtual {\\n require(_executor() == address(this));\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\\n // include the castVoteWithReasonAndParams() function as standard\\n return\\n interfaceId ==\\n (type(IGovernor).interfaceId ^\\n this.castVoteWithReasonAndParams.selector ^\\n this.castVoteWithReasonAndParamsBySig.selector ^\\n this.getVotesWithParams.selector) ||\\n interfaceId == type(IGovernor).interfaceId ||\\n interfaceId == type(IERC1155Receiver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IGovernor-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IGovernor-version}.\\n */\\n function version() public view virtual override returns (string memory) {\\n return \\\"1\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hashProposal}.\\n *\\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\\n * advance, before the proposal is submitted.\\n *\\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual override returns (uint256) {\\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\\n }\\n\\n /**\\n * @dev See {IGovernor-state}.\\n */\\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n\\n if (proposal.executed) {\\n return ProposalState.Executed;\\n }\\n\\n if (proposal.canceled) {\\n return ProposalState.Canceled;\\n }\\n\\n uint256 start = proposalSnapshot(proposalId);\\n\\n if (start == 0) {\\n revert(\\\"Governor: unknown proposal id\\\");\\n }\\n\\n if (start >= block.timestamp) {\\n return ProposalState.Pending;\\n }\\n\\n uint256 deadline = proposalDeadline(proposalId);\\n\\n if (deadline >= block.timestamp) {\\n return ProposalState.Active;\\n }\\n\\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\\n return ProposalState.Succeeded;\\n } else {\\n return ProposalState.Defeated;\\n }\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalSnapshot}.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteStart.getDeadline();\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalDeadline}.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteEnd.getDeadline();\\n }\\n\\n /**\\n * @dev Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\\n */\\n function proposalThreshold() public view virtual returns (uint256) {\\n return 0;\\n }\\n\\n /**\\n * @dev Amount of votes already cast passes the threshold limit.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Is the proposal successful or not.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) internal view virtual returns (uint256);\\n\\n /**\\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\\n *\\n * Note: Support is generic and can represent various things depending on the voting system used.\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory params\\n ) internal virtual;\\n\\n /**\\n * @dev Default additional encoded parameters used by castVote methods that don't include them\\n *\\n * Note: Should be overridden by specific implementations to use an appropriate value, the\\n * meaning of the additional params, in the context of that implementation\\n */\\n function _defaultParams() internal view virtual returns (bytes memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-propose}.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual override returns (uint256) {\\n require(\\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\\n \\\"Governor: proposer votes below proposal threshold\\\"\\n );\\n\\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\\n\\n require(targets.length == values.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length == calldatas.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length > 0, \\\"Governor: empty proposal\\\");\\n\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(proposal.voteStart.isUnset(), \\\"Governor: proposal already exists\\\");\\n\\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\\n uint64 deadline = start + votingPeriod().toUint64();\\n\\n proposal.voteStart.setDeadline(start);\\n proposal.voteEnd.setDeadline(deadline);\\n\\n emit ProposalCreated(\\n proposalId,\\n _msgSender(),\\n targets,\\n values,\\n new string[](targets.length),\\n calldatas,\\n start,\\n deadline,\\n description\\n );\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-execute}.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual override returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n\\n ProposalState status = state(proposalId);\\n require(\\n status == ProposalState.Succeeded || status == ProposalState.Queued,\\n \\\"Governor: proposal not successful\\\"\\n );\\n _proposals[proposalId].executed = true;\\n\\n emit ProposalExecuted(proposalId);\\n\\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\\n _execute(proposalId, targets, values, calldatas, descriptionHash);\\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\\n */\\n function _execute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n string memory errorMessage = \\\"Governor: call reverted without message\\\";\\n for (uint256 i = 0; i < targets.length; ++i) {\\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\\n Address.verifyCallResult(success, returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Hook before execution is triggered.\\n */\\n function _beforeExecute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory, /* values */\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n for (uint256 i = 0; i < targets.length; ++i) {\\n if (targets[i] == address(this)) {\\n _governanceCall.pushBack(keccak256(calldatas[i]));\\n }\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook after execution is triggered.\\n */\\n function _afterExecute(\\n uint256, /* proposalId */\\n address[] memory, /* targets */\\n uint256[] memory, /* values */\\n bytes[] memory, /* calldatas */\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n if (!_governanceCall.empty()) {\\n _governanceCall.clear();\\n }\\n }\\n }\\n\\n /**\\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\\n * canceled to allow distinguishing it from executed proposals.\\n *\\n * Emits a {IGovernor-ProposalCanceled} event.\\n */\\n function _cancel(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) internal virtual returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n ProposalState status = state(proposalId);\\n\\n require(\\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\\n \\\"Governor: proposal not active\\\"\\n );\\n _proposals[proposalId].canceled = true;\\n\\n emit ProposalCanceled(proposalId);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotes}.\\n */\\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, _defaultParams());\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotesWithParams}.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVote}.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReason}.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteBySig}.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\\n v,\\n r,\\n s\\n );\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(\\n keccak256(\\n abi.encode(\\n EXTENDED_BALLOT_TYPEHASH,\\n proposalId,\\n support,\\n keccak256(bytes(reason)),\\n keccak256(params)\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason\\n ) internal virtual returns (uint256) {\\n return _castVote(proposalId, account, support, reason, _defaultParams());\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason,\\n bytes memory params\\n ) internal virtual returns (uint256) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(state(proposalId) == ProposalState.Active, \\\"Governor: vote not currently active\\\");\\n\\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\\n _countVote(proposalId, account, support, weight, params);\\n\\n if (params.length == 0) {\\n emit VoteCast(account, proposalId, support, weight, reason);\\n } else {\\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\\n }\\n\\n return weight;\\n }\\n\\n /**\\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\\n */\\n function relay(\\n address target,\\n uint256 value,\\n bytes calldata data\\n ) external virtual onlyGovernance {\\n Address.functionCallWithValue(target, data, value);\\n }\\n\\n /**\\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\\n * through another contract such as a timelock.\\n */\\n function _executor() internal view virtual returns (address) {\\n return address(this);\\n }\\n\\n /**\\n * @dev See {IERC721Receiver-onERC721Received}.\\n */\\n function onERC721Received(\\n address,\\n address,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155Received}.\\n */\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\\n */\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] memory,\\n uint256[] memory,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155BatchReceived.selector;\\n }\\n}\\n\",\"keccak256\":\"0xa2846313b89a871807cdebd0225b0bf8f23b17505ab8b3288549ec54a5a4a71b\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorCountingSimple.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\\n *\\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorCountingSimple is L2Governor {\\n /**\\n * @dev Supported vote types. Matches Governor Bravo ordering.\\n */\\n enum VoteType {\\n Against,\\n For,\\n Abstain\\n }\\n\\n struct ProposalVote {\\n uint256 againstVotes;\\n uint256 forVotes;\\n uint256 abstainVotes;\\n mapping(address => bool) hasVoted;\\n }\\n\\n mapping(uint256 => ProposalVote) private _proposalVotes;\\n\\n /**\\n * @dev See {IGovernor-COUNTING_MODE}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual override returns (string memory) {\\n return \\\"support=bravo&quorum=for,abstain\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hasVoted}.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\\n return _proposalVotes[proposalId].hasVoted[account];\\n }\\n\\n /**\\n * @dev Accessor to the internal vote counts.\\n */\\n function proposalVotes(uint256 proposalId)\\n public\\n view\\n virtual\\n returns (\\n uint256 againstVotes,\\n uint256 forVotes,\\n uint256 abstainVotes\\n )\\n {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\\n }\\n\\n /**\\n * @dev See {Governor-_quorumReached}.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return proposalvote.forVotes > proposalvote.againstVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory // params\\n ) internal virtual override {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n require(!proposalvote.hasVoted[account], \\\"GovernorVotingSimple: vote already cast\\\");\\n proposalvote.hasVoted[account] = true;\\n\\n if (support == uint8(VoteType.Against)) {\\n proposalvote.againstVotes += weight;\\n } else if (support == uint8(VoteType.For)) {\\n proposalvote.forVotes += weight;\\n } else if (support == uint8(VoteType.Abstain)) {\\n proposalvote.abstainVotes += weight;\\n } else {\\n revert(\\\"GovernorVotingSimple: invalid value for enum VoteType\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xdc37daa24118a6e6ba5208b4abefa1632af2ff340135ca6c6d7237f70102d5db\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotes is L2Governor {\\n IVotes public immutable token;\\n\\n constructor(IVotes tokenAddress) {\\n token = tokenAddress;\\n }\\n\\n /**\\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory /*params*/\\n ) internal view virtual override returns (uint256) {\\n return token.getPastVotes(account, blockTimestamp);\\n }\\n}\\n\",\"keccak256\":\"0x605a7de71228dda3cb8fd878cac313a86bc5841fd34d7344214346ba46e63af1\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotesQuorumFraction.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\\n * fraction of the total supply.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\\n uint256 private _quorumNumerator;\\n\\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\\n\\n /**\\n * @dev Initialize quorum as a fraction of the token's total supply.\\n *\\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\\n * customized by overriding {quorumDenominator}.\\n */\\n constructor(uint256 quorumNumeratorValue) {\\n _updateQuorumNumerator(quorumNumeratorValue);\\n }\\n\\n /**\\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\\n */\\n function quorumNumerator() public view virtual returns (uint256) {\\n return _quorumNumerator;\\n }\\n\\n /**\\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\\n */\\n function quorumDenominator() public view virtual returns (uint256) {\\n return 100;\\n }\\n\\n /**\\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\\n */\\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - Must be called through a governance proposal.\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\\n _updateQuorumNumerator(newQuorumNumerator);\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\\n require(\\n newQuorumNumerator <= quorumDenominator(),\\n \\\"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\\\"\\n );\\n\\n uint256 oldQuorumNumerator = _quorumNumerator;\\n _quorumNumerator = newQuorumNumerator;\\n\\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\\n }\\n}\\n\",\"keccak256\":\"0xe66d29c0ffd2274de933d80e11d68891f3acc3f078be4560a2b493b7d88dcb7f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Interface of the {Governor} core.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract IGovernor is IERC165 {\\n enum ProposalState {\\n Pending,\\n Active,\\n Canceled,\\n Defeated,\\n Succeeded,\\n Queued,\\n Expired,\\n Executed\\n }\\n\\n /**\\n * @dev Emitted when a proposal is created.\\n */\\n event ProposalCreated(\\n uint256 proposalId,\\n address proposer,\\n address[] targets,\\n uint256[] values,\\n string[] signatures,\\n bytes[] calldatas,\\n uint256 startBlock,\\n uint256 endBlock,\\n string description\\n );\\n\\n /**\\n * @dev Emitted when a proposal is canceled.\\n */\\n event ProposalCanceled(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a proposal is executed.\\n */\\n event ProposalExecuted(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a vote is cast without params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n */\\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\\n\\n /**\\n * @dev Emitted when a vote is cast with params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\\n */\\n event VoteCastWithParams(\\n address indexed voter,\\n uint256 proposalId,\\n uint8 support,\\n uint256 weight,\\n string reason,\\n bytes params\\n );\\n\\n /**\\n * @notice module:core\\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\\n */\\n function name() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \\\"1\\\"\\n */\\n function version() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:voting\\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\\n *\\n * There are 2 standard keys: `support` and `quorum`.\\n *\\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\\n * - `quorum=bravo` means that only For votes are counted towards quorum.\\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\\n *\\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\\n * name that describes the behavior. For example:\\n *\\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\\n *\\n * NOTE: The string can be decoded by the standard\\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\\n * JavaScript class.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Current state of a proposal, following Compound's convention\\n */\\n function state(uint256 proposalId) public view virtual returns (ProposalState);\\n\\n /**\\n * @notice module:core\\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\\n * beginning of the following block.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\\n * during this block.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\\n */\\n function votingDelay() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of blocks, between the vote start and vote ends.\\n *\\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\\n * duration compared to the voting delay.\\n */\\n function votingPeriod() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Minimum number of cast voted required for a proposal to be successful.\\n *\\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\\n */\\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber`.\\n *\\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\\n * multiple), {ERC20Votes} tokens.\\n */\\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockNumber,\\n bytes memory params\\n ) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:voting\\n * @dev Returns whether `account` has cast a vote on `proposalId`.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\\n\\n /**\\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\\n * {IGovernor-votingPeriod} blocks after the voting starts.\\n *\\n * Emits a {ProposalCreated} event.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\\n * deadline to be reached.\\n *\\n * Emits a {ProposalExecuted} event.\\n *\\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Cast a vote\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xa52d593ff06a2353f78fa149da31f2ca94f03d1eff99bde41977fa2fe985a92f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2e53602b96c1bf97c731ed3e2a981b4f85e23a9410a5ebd36e549a4cc93340dc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x2626d8ab3dfdad0fad630c212ad146d59473d0f48b771784c61a7c1dbbea1f3f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Tooling for timepoints, timers and delays\\n */\\nlibrary Timers {\\n struct Timestamp {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(Timestamp storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(Timestamp memory timer) internal view returns (bool) {\\n return timer._deadline > block.timestamp;\\n }\\n\\n function isExpired(Timestamp memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.timestamp;\\n }\\n\\n struct BlockNumber {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(BlockNumber storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(BlockNumber memory timer) internal view returns (bool) {\\n return timer._deadline > block.number;\\n }\\n\\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.number;\\n }\\n}\\n\",\"keccak256\":\"0x29791a62950a7983e02a673639c1a781d1e448691800456c2ce4b99715391b14\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS,\\n InvalidSignatureV // Deprecated in v4.8\\n }\\n\\n function _throwError(RecoverError error) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert(\\\"ECDSA: invalid signature\\\");\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert(\\\"ECDSA: invalid signature 's' value\\\");\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature` or error string. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\\n if (signature.length == 65) {\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n /// @solidity memory-safe-assembly\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n return tryRecover(hash, v, r, s);\\n } else {\\n return (address(0), RecoverError.InvalidSignatureLength);\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, signature);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n *\\n * _Available since v4.2._\\n */\\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature);\\n }\\n\\n return (signer, RecoverError.NoError);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from `s`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", Strings.toString(s.length), s));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Typed Data, created from a\\n * `domainSeparator` and a `structHash`. This produces hash corresponding\\n * to the one signed with the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\\n * JSON-RPC method as part of EIP-712.\\n *\\n * See {recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n }\\n}\\n\",\"keccak256\":\"0x54ee424bfc83ce63b2a918b9a1efb5090a0fb68dbd1de3b10bc667776885dd4f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ECDSA.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n /* solhint-disable var-name-mixedcase */\\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n // invalidate the cached domain separator if the chain id changes.\\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n uint256 private immutable _CACHED_CHAIN_ID;\\n address private immutable _CACHED_THIS;\\n\\n bytes32 private immutable _HASHED_NAME;\\n bytes32 private immutable _HASHED_VERSION;\\n bytes32 private immutable _TYPE_HASH;\\n\\n /* solhint-enable var-name-mixedcase */\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n constructor(string memory name, string memory version) {\\n bytes32 hashedName = keccak256(bytes(name));\\n bytes32 hashedVersion = keccak256(bytes(version));\\n bytes32 typeHash = keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n );\\n _HASHED_NAME = hashedName;\\n _HASHED_VERSION = hashedVersion;\\n _CACHED_CHAIN_ID = block.chainid;\\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n _CACHED_THIS = address(this);\\n _TYPE_HASH = typeHash;\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\\n return _CACHED_DOMAIN_SEPARATOR;\\n } else {\\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n }\\n }\\n\\n function _buildDomainSeparator(\\n bytes32 typeHash,\\n bytes32 nameHash,\\n bytes32 versionHash\\n ) private view returns (bytes32) {\\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\\n }\\n}\\n\",\"keccak256\":\"0x948d8b2d18f38141ec78c5229d770d950ebc781ed3f44cc9e3ccbb9fded5846a\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\\n\\nimport \\\"./EIP712.sol\\\";\\n\",\"keccak256\":\"0xea30c402170bc240354b74e6c6f6a8e5bdb1935d90d168cc58c0654461c6a72b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3546b156d97633f7f8cad536d5454c81d1d604687c02b2eb105fdc33cb962b41\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\\npragma solidity ^0.8.4;\\n\\nimport \\\"../math/SafeCast.sol\\\";\\n\\n/**\\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\\n * the existing queue contents are left in storage.\\n *\\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\\n * used in storage, and not in memory.\\n * ```\\n * DoubleEndedQueue.Bytes32Deque queue;\\n * ```\\n *\\n * _Available since v4.6._\\n */\\nlibrary DoubleEndedQueue {\\n /**\\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\\n */\\n error Empty();\\n\\n /**\\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\\n */\\n error OutOfBounds();\\n\\n /**\\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\\n *\\n * Struct members have an underscore prefix indicating that they are \\\"private\\\" and should not be read or written to\\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\\n * lead to unexpected behavior.\\n *\\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\\n * data[end - 1].\\n */\\n struct Bytes32Deque {\\n int128 _begin;\\n int128 _end;\\n mapping(int128 => bytes32) _data;\\n }\\n\\n /**\\n * @dev Inserts an item at the end of the queue.\\n */\\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 backIndex = deque._end;\\n deque._data[backIndex] = value;\\n unchecked {\\n deque._end = backIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Removes the item at the end of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n value = deque._data[backIndex];\\n delete deque._data[backIndex];\\n deque._end = backIndex;\\n }\\n\\n /**\\n * @dev Inserts an item at the beginning of the queue.\\n */\\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 frontIndex;\\n unchecked {\\n frontIndex = deque._begin - 1;\\n }\\n deque._data[frontIndex] = value;\\n deque._begin = frontIndex;\\n }\\n\\n /**\\n * @dev Removes the item at the beginning of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n value = deque._data[frontIndex];\\n delete deque._data[frontIndex];\\n unchecked {\\n deque._begin = frontIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Returns the item at the beginning of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n return deque._data[frontIndex];\\n }\\n\\n /**\\n * @dev Returns the item at the end of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n return deque._data[backIndex];\\n }\\n\\n /**\\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\\n * `length(deque) - 1`.\\n *\\n * Reverts with `OutOfBounds` if the index is out of bounds.\\n */\\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\\n // int256(deque._begin) is a safe upcast\\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\\n if (idx >= deque._end) revert OutOfBounds();\\n return deque._data[idx];\\n }\\n\\n /**\\n * @dev Resets the queue back to being empty.\\n *\\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\\n * out on potential gas refunds.\\n */\\n function clear(Bytes32Deque storage deque) internal {\\n deque._begin = 0;\\n deque._end = 0;\\n }\\n\\n /**\\n * @dev Returns the number of items in the queue.\\n */\\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\\n // We also assume there are at most int256.max items in the queue.\\n unchecked {\\n return uint256(int256(deque._end) - int256(deque._begin));\\n }\\n }\\n\\n /**\\n * @dev Returns true if the queue is empty.\\n */\\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\\n return deque._end <= deque._begin;\\n }\\n}\\n\",\"keccak256\":\"0x4859ffd6dd69382a1462930c00b6e394007da80e78e510f56930271034737bf2\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x61016060405260026007553480156200001757600080fd5b506040516200329a3803806200329a8339810160408190526200003a91620002ec565b6004816040518060400160405280601481526020017f56656c6f63696d6574657220476f7665726e6f7200000000000000000000000081525080620000846200015e60201b60201c565b815160208084019190912082518383012060e08290526101008190524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81880181905281830187905260608201869052608082019490945230818401528151808203909301835260c00190528051940193909320919290916080523060c05261012052505082516200012a925060009150602084019062000246565b50506001600160a01b031661014052620001448162000179565b5050600680546001600160a01b031916331790556200035a565b6040805180820190915260018152603160f81b602082015290565b6064811115620002015760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a40160405180910390fd5b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b82805462000254906200031e565b90600052602060002090601f016020900481019282620002785760008555620002c3565b82601f106200029357805160ff1916838001178555620002c3565b82800160010185558215620002c3579182015b82811115620002c3578251825591602001919060010190620002a6565b50620002d1929150620002d5565b5090565b5b80821115620002d15760008155600101620002d6565b600060208284031215620002ff57600080fd5b81516001600160a01b03811681146200031757600080fd5b9392505050565b600181811c908216806200033357607f821691505b6020821081036200035457634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e051610100516101205161014051612ed0620003ca600039600081816107df0152818161120f015281816113e40152611a0601526000611b2301526000611b7201526000611b4d01526000611aa601526000611ad001526000611afa0152612ed06000f3fe6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220619141f3666eb3d47b18cb454a5c4e73437ed9eadfb56425659bf6bb30ee8daa64736f6c634300080d0033", - "deployedBytecode": "0x6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220619141f3666eb3d47b18cb454a5c4e73437ed9eadfb56425659bf6bb30ee8daa64736f6c634300080d0033", + "numDeployments": 2, + "solcInputHash": "6e27611a2cedd773c4cc6e46935e6392", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"_ve\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"Empty\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"proposer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"string[]\",\"name\":\"signatures\",\"type\":\"string[]\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"ProposalCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"ProposalExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldQuorumNumerator\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"QuorumNumeratorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"VoteCast\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"VoteCastWithParams\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"COUNTING_MODE\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EXTENDED_BALLOT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_PROPOSAL_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROPOSAL_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"}],\"name\":\"castVote\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"castVoteWithReason\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"castVoteWithReasonAndParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"support\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"castVoteWithReasonAndParamsBySig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"execute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"getVotesWithParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasVoted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"descriptionHash\",\"type\":\"bytes32\"}],\"name\":\"hashProposal\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalDeadline\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalSnapshot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposalThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"proposalVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"againstVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"forVotes\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"abstainVotes\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"calldatas\",\"type\":\"bytes[]\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"propose\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"}],\"name\":\"quorum\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumDenominator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumNumerator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"}],\"name\":\"setProposalNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTeam\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"proposalId\",\"type\":\"uint256\"}],\"name\":\"state\",\"outputs\":[{\"internalType\":\"enum IGovernor.ProposalState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IVotes\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newQuorumNumerator\",\"type\":\"uint256\"}],\"name\":\"updateQuorumNumerator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"votingPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"Empty()\":[{\"details\":\"An operation (e.g. {front}) couldn't be completed due to the queue being empty.\"}]},\"kind\":\"dev\",\"methods\":{\"COUNTING_MODE()\":{\"details\":\"See {IGovernor-COUNTING_MODE}.\"},\"castVote(uint256,uint8)\":{\"details\":\"See {IGovernor-castVote}.\"},\"castVoteBySig(uint256,uint8,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteBySig}.\"},\"castVoteWithReason(uint256,uint8,string)\":{\"details\":\"See {IGovernor-castVoteWithReason}.\"},\"castVoteWithReasonAndParams(uint256,uint8,string,bytes)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParams}.\"},\"castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32)\":{\"details\":\"See {IGovernor-castVoteWithReasonAndParamsBySig}.\"},\"execute(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-execute}.\"},\"getVotes(address,uint256)\":{\"details\":\"See {IGovernor-getVotes}.\"},\"getVotesWithParams(address,uint256,bytes)\":{\"details\":\"See {IGovernor-getVotesWithParams}.\"},\"hasVoted(uint256,address)\":{\"details\":\"See {IGovernor-hasVoted}.\"},\"hashProposal(address[],uint256[],bytes[],bytes32)\":{\"details\":\"See {IGovernor-hashProposal}. The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in advance, before the proposal is submitted. Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the same proposal (with same operation and same description) will have the same id if submitted on multiple governors across multiple networks. This also means that in order to execute the same operation twice (on the same governor) the proposer will have to change the description in order to avoid proposal id conflicts.\"},\"name()\":{\"details\":\"See {IGovernor-name}.\"},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155BatchReceived}.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155Received}.\"},\"onERC721Received(address,address,uint256,bytes)\":{\"details\":\"See {IERC721Receiver-onERC721Received}.\"},\"proposalDeadline(uint256)\":{\"details\":\"See {IGovernor-proposalDeadline}.\"},\"proposalSnapshot(uint256)\":{\"details\":\"See {IGovernor-proposalSnapshot}.\"},\"proposalThreshold()\":{\"details\":\"Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\"},\"proposalVotes(uint256)\":{\"details\":\"Accessor to the internal vote counts.\"},\"propose(address[],uint256[],bytes[],string)\":{\"details\":\"See {IGovernor-propose}.\"},\"quorum(uint256)\":{\"details\":\"Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\"},\"quorumDenominator()\":{\"details\":\"Returns the quorum denominator. Defaults to 100, but may be overridden.\"},\"quorumNumerator()\":{\"details\":\"Returns the current quorum numerator. See {quorumDenominator}.\"},\"relay(address,uint256,bytes)\":{\"details\":\"Relays a transaction or function call to an arbitrary target. In cases where the governance executor is some contract other than the governor itself, like when using a timelock, this function can be invoked in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake. Note that if the executor is simply the governor itself, use of `relay` is redundant.\"},\"state(uint256)\":{\"details\":\"See {IGovernor-state}.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"updateQuorumNumerator(uint256)\":{\"details\":\"Changes the quorum numerator. Emits a {QuorumNumeratorUpdated} event. Requirements: - Must be called through a governance proposal. - New numerator must be smaller or equal to the denominator.\"},\"version()\":{\"details\":\"See {IGovernor-version}.\"},\"votingDelay()\":{\"details\":\"Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\"},\"votingPeriod()\":{\"details\":\"Delay, in number of blocks, between the vote start and vote ends. NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting duration compared to the voting delay.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"votingDelay()\":{\"notice\":\"module:user-config\"},\"votingPeriod()\":{\"notice\":\"module:user-config\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/FlowGovernor.sol\":\"FlowGovernor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735303535373437363232\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/FlowGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IGovernor} from \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\nimport {L2GovernorCountingSimple} from \\\"contracts/governance/L2GovernorCountingSimple.sol\\\";\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\nimport {L2GovernorVotesQuorumFraction} from \\\"contracts/governance/L2GovernorVotesQuorumFraction.sol\\\";\\n\\ncontract FlowGovernor is\\n L2Governor,\\n L2GovernorCountingSimple,\\n L2GovernorVotes,\\n L2GovernorVotesQuorumFraction\\n{\\n address public team;\\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\\n uint256 public proposalNumerator = 2; // start at 0.02%\\n\\n constructor(IVotes _ve)\\n L2Governor(\\\"Velocimeter Governor\\\")\\n L2GovernorVotes(_ve)\\n L2GovernorVotesQuorumFraction(4) // 4%\\n {\\n team = msg.sender;\\n }\\n\\n function votingDelay() public pure override(IGovernor) returns (uint256) {\\n return 15 minutes; // 1 block\\n }\\n\\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\\n return 1 weeks;\\n }\\n\\n function setTeam(address newTeam) external {\\n require(msg.sender == team, \\\"not team\\\");\\n team = newTeam;\\n }\\n\\n function setProposalNumerator(uint256 numerator) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \\\"numerator too high\\\");\\n proposalNumerator = numerator;\\n }\\n\\n function proposalThreshold()\\n public\\n view\\n override(L2Governor)\\n returns (uint256)\\n {\\n return\\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\\n PROPOSAL_DENOMINATOR;\\n }\\n}\\n\",\"keccak256\":\"0xbf02f2fa1b0179b06bba2274ce6720c31ba3783f899502567cc25a093b27edb6\",\"license\":\"MIT\"},\"contracts/governance/L2Governor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Address.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Context.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\\\";\\nimport \\\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\\n *\\n * @dev Core of the governance system, designed to be extended though various modules.\\n *\\n * This contract is abstract and requires several function to be implemented in various modules:\\n *\\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\\n * - A voting module must implement {_getVotes}\\n * - Additionanly, the {votingPeriod} must also be implemented\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\\n using SafeCast for uint256;\\n using Timers for Timers.Timestamp;\\n\\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\\\"Ballot(uint256 proposalId,uint8 support)\\\");\\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\\n keccak256(\\\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\\\");\\n\\n struct ProposalCore {\\n Timers.Timestamp voteStart;\\n Timers.Timestamp voteEnd;\\n bool executed;\\n bool canceled;\\n }\\n\\n string private _name;\\n\\n mapping(uint256 => ProposalCore) private _proposals;\\n\\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\\n\\n /**\\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\\n * parameter setters in {GovernorSettings} are protected using this modifier.\\n *\\n * The governance executing address may be different from the Governor's own address, for example it could be a\\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\\n * for example, additional timelock proposers are not able to change governance parameters without going through the\\n * governance protocol (since v4.6).\\n */\\n modifier onlyGovernance() {\\n require(_msgSender() == _executor(), \\\"Governor: onlyGovernance\\\");\\n if (_executor() != address(this)) {\\n bytes32 msgDataHash = keccak256(_msgData());\\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\\n while (_governanceCall.popFront() != msgDataHash) {}\\n }\\n _;\\n }\\n\\n /**\\n * @dev Sets the value for {name} and {version}\\n */\\n constructor(string memory name_) EIP712(name_, version()) {\\n _name = name_;\\n }\\n\\n /**\\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\\n */\\n receive() external payable virtual {\\n require(_executor() == address(this));\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\\n // include the castVoteWithReasonAndParams() function as standard\\n return\\n interfaceId ==\\n (type(IGovernor).interfaceId ^\\n this.castVoteWithReasonAndParams.selector ^\\n this.castVoteWithReasonAndParamsBySig.selector ^\\n this.getVotesWithParams.selector) ||\\n interfaceId == type(IGovernor).interfaceId ||\\n interfaceId == type(IERC1155Receiver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IGovernor-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IGovernor-version}.\\n */\\n function version() public view virtual override returns (string memory) {\\n return \\\"1\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hashProposal}.\\n *\\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\\n * advance, before the proposal is submitted.\\n *\\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual override returns (uint256) {\\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\\n }\\n\\n /**\\n * @dev See {IGovernor-state}.\\n */\\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n\\n if (proposal.executed) {\\n return ProposalState.Executed;\\n }\\n\\n if (proposal.canceled) {\\n return ProposalState.Canceled;\\n }\\n\\n uint256 start = proposalSnapshot(proposalId);\\n\\n if (start == 0) {\\n revert(\\\"Governor: unknown proposal id\\\");\\n }\\n\\n if (start >= block.timestamp) {\\n return ProposalState.Pending;\\n }\\n\\n uint256 deadline = proposalDeadline(proposalId);\\n\\n if (deadline >= block.timestamp) {\\n return ProposalState.Active;\\n }\\n\\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\\n return ProposalState.Succeeded;\\n } else {\\n return ProposalState.Defeated;\\n }\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalSnapshot}.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteStart.getDeadline();\\n }\\n\\n /**\\n * @dev See {IGovernor-proposalDeadline}.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\\n return _proposals[proposalId].voteEnd.getDeadline();\\n }\\n\\n /**\\n * @dev Part of the Governor Bravo's interface: _\\\"The number of votes required in order for a voter to become a proposer\\\"_.\\n */\\n function proposalThreshold() public view virtual returns (uint256) {\\n return 0;\\n }\\n\\n /**\\n * @dev Amount of votes already cast passes the threshold limit.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Is the proposal successful or not.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\\n\\n /**\\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) internal view virtual returns (uint256);\\n\\n /**\\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\\n *\\n * Note: Support is generic and can represent various things depending on the voting system used.\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory params\\n ) internal virtual;\\n\\n /**\\n * @dev Default additional encoded parameters used by castVote methods that don't include them\\n *\\n * Note: Should be overridden by specific implementations to use an appropriate value, the\\n * meaning of the additional params, in the context of that implementation\\n */\\n function _defaultParams() internal view virtual returns (bytes memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-propose}.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual override returns (uint256) {\\n require(\\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\\n \\\"Governor: proposer votes below proposal threshold\\\"\\n );\\n\\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\\n\\n require(targets.length == values.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length == calldatas.length, \\\"Governor: invalid proposal length\\\");\\n require(targets.length > 0, \\\"Governor: empty proposal\\\");\\n\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(proposal.voteStart.isUnset(), \\\"Governor: proposal already exists\\\");\\n\\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\\n uint64 deadline = start + votingPeriod().toUint64();\\n\\n proposal.voteStart.setDeadline(start);\\n proposal.voteEnd.setDeadline(deadline);\\n\\n emit ProposalCreated(\\n proposalId,\\n _msgSender(),\\n targets,\\n values,\\n new string[](targets.length),\\n calldatas,\\n start,\\n deadline,\\n description\\n );\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-execute}.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual override returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n\\n ProposalState status = state(proposalId);\\n require(\\n status == ProposalState.Succeeded || status == ProposalState.Queued,\\n \\\"Governor: proposal not successful\\\"\\n );\\n _proposals[proposalId].executed = true;\\n\\n emit ProposalExecuted(proposalId);\\n\\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\\n _execute(proposalId, targets, values, calldatas, descriptionHash);\\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\\n */\\n function _execute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n string memory errorMessage = \\\"Governor: call reverted without message\\\";\\n for (uint256 i = 0; i < targets.length; ++i) {\\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\\n Address.verifyCallResult(success, returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Hook before execution is triggered.\\n */\\n function _beforeExecute(\\n uint256, /* proposalId */\\n address[] memory targets,\\n uint256[] memory, /* values */\\n bytes[] memory calldatas,\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n for (uint256 i = 0; i < targets.length; ++i) {\\n if (targets[i] == address(this)) {\\n _governanceCall.pushBack(keccak256(calldatas[i]));\\n }\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook after execution is triggered.\\n */\\n function _afterExecute(\\n uint256, /* proposalId */\\n address[] memory, /* targets */\\n uint256[] memory, /* values */\\n bytes[] memory, /* calldatas */\\n bytes32 /*descriptionHash*/\\n ) internal virtual {\\n if (_executor() != address(this)) {\\n if (!_governanceCall.empty()) {\\n _governanceCall.clear();\\n }\\n }\\n }\\n\\n /**\\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\\n * canceled to allow distinguishing it from executed proposals.\\n *\\n * Emits a {IGovernor-ProposalCanceled} event.\\n */\\n function _cancel(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) internal virtual returns (uint256) {\\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\\n ProposalState status = state(proposalId);\\n\\n require(\\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\\n \\\"Governor: proposal not active\\\"\\n );\\n _proposals[proposalId].canceled = true;\\n\\n emit ProposalCanceled(proposalId);\\n\\n return proposalId;\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotes}.\\n */\\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, _defaultParams());\\n }\\n\\n /**\\n * @dev See {IGovernor-getVotesWithParams}.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory params\\n ) public view virtual override returns (uint256) {\\n return _getVotes(account, blockTimestamp, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVote}.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReason}.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual override returns (uint256) {\\n address voter = _msgSender();\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteBySig}.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\\n v,\\n r,\\n s\\n );\\n return _castVote(proposalId, voter, support, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override returns (uint256) {\\n address voter = ECDSA.recover(\\n _hashTypedDataV4(\\n keccak256(\\n abi.encode(\\n EXTENDED_BALLOT_TYPEHASH,\\n proposalId,\\n support,\\n keccak256(bytes(reason)),\\n keccak256(params)\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n return _castVote(proposalId, voter, support, reason, params);\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason\\n ) internal virtual returns (uint256) {\\n return _castVote(proposalId, account, support, reason, _defaultParams());\\n }\\n\\n /**\\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\\n *\\n * Emits a {IGovernor-VoteCast} event.\\n */\\n function _castVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n string memory reason,\\n bytes memory params\\n ) internal virtual returns (uint256) {\\n ProposalCore storage proposal = _proposals[proposalId];\\n require(state(proposalId) == ProposalState.Active, \\\"Governor: vote not currently active\\\");\\n\\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\\n _countVote(proposalId, account, support, weight, params);\\n\\n if (params.length == 0) {\\n emit VoteCast(account, proposalId, support, weight, reason);\\n } else {\\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\\n }\\n\\n return weight;\\n }\\n\\n /**\\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\\n */\\n function relay(\\n address target,\\n uint256 value,\\n bytes calldata data\\n ) external virtual onlyGovernance {\\n Address.functionCallWithValue(target, data, value);\\n }\\n\\n /**\\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\\n * through another contract such as a timelock.\\n */\\n function _executor() internal view virtual returns (address) {\\n return address(this);\\n }\\n\\n /**\\n * @dev See {IERC721Receiver-onERC721Received}.\\n */\\n function onERC721Received(\\n address,\\n address,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155Received}.\\n */\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\\n */\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] memory,\\n uint256[] memory,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155BatchReceived.selector;\\n }\\n}\\n\",\"keccak256\":\"0xa2846313b89a871807cdebd0225b0bf8f23b17505ab8b3288549ec54a5a4a71b\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorCountingSimple.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\\n *\\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorCountingSimple is L2Governor {\\n /**\\n * @dev Supported vote types. Matches Governor Bravo ordering.\\n */\\n enum VoteType {\\n Against,\\n For,\\n Abstain\\n }\\n\\n struct ProposalVote {\\n uint256 againstVotes;\\n uint256 forVotes;\\n uint256 abstainVotes;\\n mapping(address => bool) hasVoted;\\n }\\n\\n mapping(uint256 => ProposalVote) private _proposalVotes;\\n\\n /**\\n * @dev See {IGovernor-COUNTING_MODE}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual override returns (string memory) {\\n return \\\"support=bravo&quorum=for,abstain\\\";\\n }\\n\\n /**\\n * @dev See {IGovernor-hasVoted}.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\\n return _proposalVotes[proposalId].hasVoted[account];\\n }\\n\\n /**\\n * @dev Accessor to the internal vote counts.\\n */\\n function proposalVotes(uint256 proposalId)\\n public\\n view\\n virtual\\n returns (\\n uint256 againstVotes,\\n uint256 forVotes,\\n uint256 abstainVotes\\n )\\n {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\\n }\\n\\n /**\\n * @dev See {Governor-_quorumReached}.\\n */\\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\\n */\\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n return proposalvote.forVotes > proposalvote.againstVotes;\\n }\\n\\n /**\\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\\n */\\n function _countVote(\\n uint256 proposalId,\\n address account,\\n uint8 support,\\n uint256 weight,\\n bytes memory // params\\n ) internal virtual override {\\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\\n\\n require(!proposalvote.hasVoted[account], \\\"GovernorVotingSimple: vote already cast\\\");\\n proposalvote.hasVoted[account] = true;\\n\\n if (support == uint8(VoteType.Against)) {\\n proposalvote.againstVotes += weight;\\n } else if (support == uint8(VoteType.For)) {\\n proposalvote.forVotes += weight;\\n } else if (support == uint8(VoteType.Abstain)) {\\n proposalvote.abstainVotes += weight;\\n } else {\\n revert(\\\"GovernorVotingSimple: invalid value for enum VoteType\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xdc37daa24118a6e6ba5208b4abefa1632af2ff340135ca6c6d7237f70102d5db\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {L2Governor} from \\\"contracts/governance/L2Governor.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotes is L2Governor {\\n IVotes public immutable token;\\n\\n constructor(IVotes tokenAddress) {\\n token = tokenAddress;\\n }\\n\\n /**\\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\\n */\\n function _getVotes(\\n address account,\\n uint256 blockTimestamp,\\n bytes memory /*params*/\\n ) internal view virtual override returns (uint256) {\\n return token.getPastVotes(account, blockTimestamp);\\n }\\n}\\n\",\"keccak256\":\"0x605a7de71228dda3cb8fd878cac313a86bc5841fd34d7344214346ba46e63af1\",\"license\":\"MIT\"},\"contracts/governance/L2GovernorVotesQuorumFraction.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport {L2GovernorVotes} from \\\"contracts/governance/L2GovernorVotes.sol\\\";\\n\\n/**\\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\\n *\\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\\n * fraction of the total supply.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\\n uint256 private _quorumNumerator;\\n\\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\\n\\n /**\\n * @dev Initialize quorum as a fraction of the token's total supply.\\n *\\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\\n * customized by overriding {quorumDenominator}.\\n */\\n constructor(uint256 quorumNumeratorValue) {\\n _updateQuorumNumerator(quorumNumeratorValue);\\n }\\n\\n /**\\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\\n */\\n function quorumNumerator() public view virtual returns (uint256) {\\n return _quorumNumerator;\\n }\\n\\n /**\\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\\n */\\n function quorumDenominator() public view virtual returns (uint256) {\\n return 100;\\n }\\n\\n /**\\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\\n */\\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - Must be called through a governance proposal.\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\\n _updateQuorumNumerator(newQuorumNumerator);\\n }\\n\\n /**\\n * @dev Changes the quorum numerator.\\n *\\n * Emits a {QuorumNumeratorUpdated} event.\\n *\\n * Requirements:\\n *\\n * - New numerator must be smaller or equal to the denominator.\\n */\\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\\n require(\\n newQuorumNumerator <= quorumDenominator(),\\n \\\"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\\\"\\n );\\n\\n uint256 oldQuorumNumerator = _quorumNumerator;\\n _quorumNumerator = newQuorumNumerator;\\n\\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\\n }\\n}\\n\",\"keccak256\":\"0xe66d29c0ffd2274de933d80e11d68891f3acc3f078be4560a2b493b7d88dcb7f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Interface of the {Governor} core.\\n *\\n * _Available since v4.3._\\n */\\nabstract contract IGovernor is IERC165 {\\n enum ProposalState {\\n Pending,\\n Active,\\n Canceled,\\n Defeated,\\n Succeeded,\\n Queued,\\n Expired,\\n Executed\\n }\\n\\n /**\\n * @dev Emitted when a proposal is created.\\n */\\n event ProposalCreated(\\n uint256 proposalId,\\n address proposer,\\n address[] targets,\\n uint256[] values,\\n string[] signatures,\\n bytes[] calldatas,\\n uint256 startBlock,\\n uint256 endBlock,\\n string description\\n );\\n\\n /**\\n * @dev Emitted when a proposal is canceled.\\n */\\n event ProposalCanceled(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a proposal is executed.\\n */\\n event ProposalExecuted(uint256 proposalId);\\n\\n /**\\n * @dev Emitted when a vote is cast without params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n */\\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\\n\\n /**\\n * @dev Emitted when a vote is cast with params.\\n *\\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\\n */\\n event VoteCastWithParams(\\n address indexed voter,\\n uint256 proposalId,\\n uint8 support,\\n uint256 weight,\\n string reason,\\n bytes params\\n );\\n\\n /**\\n * @notice module:core\\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\\n */\\n function name() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \\\"1\\\"\\n */\\n function version() public view virtual returns (string memory);\\n\\n /**\\n * @notice module:voting\\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\\n *\\n * There are 2 standard keys: `support` and `quorum`.\\n *\\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\\n * - `quorum=bravo` means that only For votes are counted towards quorum.\\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\\n *\\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\\n * name that describes the behavior. For example:\\n *\\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\\n *\\n * NOTE: The string can be decoded by the standard\\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\\n * JavaScript class.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function COUNTING_MODE() public pure virtual returns (string memory);\\n\\n /**\\n * @notice module:core\\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\\n */\\n function hashProposal(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public pure virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Current state of a proposal, following Compound's convention\\n */\\n function state(uint256 proposalId) public view virtual returns (ProposalState);\\n\\n /**\\n * @notice module:core\\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\\n * beginning of the following block.\\n */\\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:core\\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\\n * during this block.\\n */\\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\\n */\\n function votingDelay() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Delay, in number of blocks, between the vote start and vote ends.\\n *\\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\\n * duration compared to the voting delay.\\n */\\n function votingPeriod() public view virtual returns (uint256);\\n\\n /**\\n * @notice module:user-config\\n * @dev Minimum number of cast voted required for a proposal to be successful.\\n *\\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\\n */\\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber`.\\n *\\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\\n * multiple), {ERC20Votes} tokens.\\n */\\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:reputation\\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\\n */\\n function getVotesWithParams(\\n address account,\\n uint256 blockNumber,\\n bytes memory params\\n ) public view virtual returns (uint256);\\n\\n /**\\n * @notice module:voting\\n * @dev Returns whether `account` has cast a vote on `proposalId`.\\n */\\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\\n\\n /**\\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\\n * {IGovernor-votingPeriod} blocks after the voting starts.\\n *\\n * Emits a {ProposalCreated} event.\\n */\\n function propose(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n string memory description\\n ) public virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\\n * deadline to be reached.\\n *\\n * Emits a {ProposalExecuted} event.\\n *\\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\\n */\\n function execute(\\n address[] memory targets,\\n uint256[] memory values,\\n bytes[] memory calldatas,\\n bytes32 descriptionHash\\n ) public payable virtual returns (uint256 proposalId);\\n\\n /**\\n * @dev Cast a vote\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteWithReason(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParams(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} event.\\n */\\n function castVoteBySig(\\n uint256 proposalId,\\n uint8 support,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n\\n /**\\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\\n *\\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\\n */\\n function castVoteWithReasonAndParamsBySig(\\n uint256 proposalId,\\n uint8 support,\\n string calldata reason,\\n bytes memory params,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xa52d593ff06a2353f78fa149da31f2ca94f03d1eff99bde41977fa2fe985a92f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2e53602b96c1bf97c731ed3e2a981b4f85e23a9410a5ebd36e549a4cc93340dc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x2626d8ab3dfdad0fad630c212ad146d59473d0f48b771784c61a7c1dbbea1f3f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Timers.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Tooling for timepoints, timers and delays\\n */\\nlibrary Timers {\\n struct Timestamp {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(Timestamp storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(Timestamp memory timer) internal view returns (bool) {\\n return timer._deadline > block.timestamp;\\n }\\n\\n function isExpired(Timestamp memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.timestamp;\\n }\\n\\n struct BlockNumber {\\n uint64 _deadline;\\n }\\n\\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\\n return timer._deadline;\\n }\\n\\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\\n timer._deadline = timestamp;\\n }\\n\\n function reset(BlockNumber storage timer) internal {\\n timer._deadline = 0;\\n }\\n\\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline == 0;\\n }\\n\\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\\n return timer._deadline > 0;\\n }\\n\\n function isPending(BlockNumber memory timer) internal view returns (bool) {\\n return timer._deadline > block.number;\\n }\\n\\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\\n return isStarted(timer) && timer._deadline <= block.number;\\n }\\n}\\n\",\"keccak256\":\"0x29791a62950a7983e02a673639c1a781d1e448691800456c2ce4b99715391b14\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS,\\n InvalidSignatureV // Deprecated in v4.8\\n }\\n\\n function _throwError(RecoverError error) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert(\\\"ECDSA: invalid signature\\\");\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert(\\\"ECDSA: invalid signature 's' value\\\");\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature` or error string. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\\n if (signature.length == 65) {\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n /// @solidity memory-safe-assembly\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n return tryRecover(hash, v, r, s);\\n } else {\\n return (address(0), RecoverError.InvalidSignatureLength);\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, signature);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n *\\n * _Available since v4.2._\\n */\\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature);\\n }\\n\\n return (signer, RecoverError.NoError);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from `s`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", Strings.toString(s.length), s));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Typed Data, created from a\\n * `domainSeparator` and a `structHash`. This produces hash corresponding\\n * to the one signed with the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\\n * JSON-RPC method as part of EIP-712.\\n *\\n * See {recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n }\\n}\\n\",\"keccak256\":\"0x54ee424bfc83ce63b2a918b9a1efb5090a0fb68dbd1de3b10bc667776885dd4f\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ECDSA.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n /* solhint-disable var-name-mixedcase */\\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n // invalidate the cached domain separator if the chain id changes.\\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n uint256 private immutable _CACHED_CHAIN_ID;\\n address private immutable _CACHED_THIS;\\n\\n bytes32 private immutable _HASHED_NAME;\\n bytes32 private immutable _HASHED_VERSION;\\n bytes32 private immutable _TYPE_HASH;\\n\\n /* solhint-enable var-name-mixedcase */\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n constructor(string memory name, string memory version) {\\n bytes32 hashedName = keccak256(bytes(name));\\n bytes32 hashedVersion = keccak256(bytes(version));\\n bytes32 typeHash = keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n );\\n _HASHED_NAME = hashedName;\\n _HASHED_VERSION = hashedVersion;\\n _CACHED_CHAIN_ID = block.chainid;\\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n _CACHED_THIS = address(this);\\n _TYPE_HASH = typeHash;\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\\n return _CACHED_DOMAIN_SEPARATOR;\\n } else {\\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n }\\n }\\n\\n function _buildDomainSeparator(\\n bytes32 typeHash,\\n bytes32 nameHash,\\n bytes32 versionHash\\n ) private view returns (bytes32) {\\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\\n }\\n}\\n\",\"keccak256\":\"0x948d8b2d18f38141ec78c5229d770d950ebc781ed3f44cc9e3ccbb9fded5846a\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\\n\\nimport \\\"./EIP712.sol\\\";\\n\",\"keccak256\":\"0xea30c402170bc240354b74e6c6f6a8e5bdb1935d90d168cc58c0654461c6a72b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3546b156d97633f7f8cad536d5454c81d1d604687c02b2eb105fdc33cb962b41\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\\npragma solidity ^0.8.4;\\n\\nimport \\\"../math/SafeCast.sol\\\";\\n\\n/**\\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\\n * the existing queue contents are left in storage.\\n *\\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\\n * used in storage, and not in memory.\\n * ```\\n * DoubleEndedQueue.Bytes32Deque queue;\\n * ```\\n *\\n * _Available since v4.6._\\n */\\nlibrary DoubleEndedQueue {\\n /**\\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\\n */\\n error Empty();\\n\\n /**\\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\\n */\\n error OutOfBounds();\\n\\n /**\\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\\n *\\n * Struct members have an underscore prefix indicating that they are \\\"private\\\" and should not be read or written to\\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\\n * lead to unexpected behavior.\\n *\\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\\n * data[end - 1].\\n */\\n struct Bytes32Deque {\\n int128 _begin;\\n int128 _end;\\n mapping(int128 => bytes32) _data;\\n }\\n\\n /**\\n * @dev Inserts an item at the end of the queue.\\n */\\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 backIndex = deque._end;\\n deque._data[backIndex] = value;\\n unchecked {\\n deque._end = backIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Removes the item at the end of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n value = deque._data[backIndex];\\n delete deque._data[backIndex];\\n deque._end = backIndex;\\n }\\n\\n /**\\n * @dev Inserts an item at the beginning of the queue.\\n */\\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\\n int128 frontIndex;\\n unchecked {\\n frontIndex = deque._begin - 1;\\n }\\n deque._data[frontIndex] = value;\\n deque._begin = frontIndex;\\n }\\n\\n /**\\n * @dev Removes the item at the beginning of the queue and returns it.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n value = deque._data[frontIndex];\\n delete deque._data[frontIndex];\\n unchecked {\\n deque._begin = frontIndex + 1;\\n }\\n }\\n\\n /**\\n * @dev Returns the item at the beginning of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 frontIndex = deque._begin;\\n return deque._data[frontIndex];\\n }\\n\\n /**\\n * @dev Returns the item at the end of the queue.\\n *\\n * Reverts with `Empty` if the queue is empty.\\n */\\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\\n if (empty(deque)) revert Empty();\\n int128 backIndex;\\n unchecked {\\n backIndex = deque._end - 1;\\n }\\n return deque._data[backIndex];\\n }\\n\\n /**\\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\\n * `length(deque) - 1`.\\n *\\n * Reverts with `OutOfBounds` if the index is out of bounds.\\n */\\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\\n // int256(deque._begin) is a safe upcast\\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\\n if (idx >= deque._end) revert OutOfBounds();\\n return deque._data[idx];\\n }\\n\\n /**\\n * @dev Resets the queue back to being empty.\\n *\\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\\n * out on potential gas refunds.\\n */\\n function clear(Bytes32Deque storage deque) internal {\\n deque._begin = 0;\\n deque._end = 0;\\n }\\n\\n /**\\n * @dev Returns the number of items in the queue.\\n */\\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\\n // We also assume there are at most int256.max items in the queue.\\n unchecked {\\n return uint256(int256(deque._end) - int256(deque._begin));\\n }\\n }\\n\\n /**\\n * @dev Returns true if the queue is empty.\\n */\\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\\n return deque._end <= deque._begin;\\n }\\n}\\n\",\"keccak256\":\"0x4859ffd6dd69382a1462930c00b6e394007da80e78e510f56930271034737bf2\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x61016060405260026007553480156200001757600080fd5b506040516200329a3803806200329a8339810160408190526200003a91620002ec565b6004816040518060400160405280601481526020017f56656c6f63696d6574657220476f7665726e6f7200000000000000000000000081525080620000846200015e60201b60201c565b815160208084019190912082518383012060e08290526101008190524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81880181905281830187905260608201869052608082019490945230818401528151808203909301835260c00190528051940193909320919290916080523060c05261012052505082516200012a925060009150602084019062000246565b50506001600160a01b031661014052620001448162000179565b5050600680546001600160a01b031916331790556200035a565b6040805180820190915260018152603160f81b602082015290565b6064811115620002015760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a40160405180910390fd5b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b82805462000254906200031e565b90600052602060002090601f016020900481019282620002785760008555620002c3565b82601f106200029357805160ff1916838001178555620002c3565b82800160010185558215620002c3579182015b82811115620002c3578251825591602001919060010190620002a6565b50620002d1929150620002d5565b5090565b5b80821115620002d15760008155600101620002d6565b600060208284031215620002ff57600080fd5b81516001600160a01b03811681146200031757600080fd5b9392505050565b600181811c908216806200033357607f821691505b6020821081036200035457634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e051610100516101205161014051612ed0620003ca600039600081816107df0152818161120f015281816113e40152611a0601526000611b2301526000611b7201526000611b4d01526000611aa601526000611ad001526000611afa0152612ed06000f3fe6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a264697066735822122029355c2d8f836f0a2f24736bc924b3f886cff30ff65a0c82da8594f652b6555264736f6c634300080d0033", + "deployedBytecode": "0x6080604052600436106102345760003560e01c80635f398a141161012e578063bc197c81116100ab578063deaaa7cc1161006f578063deaaa7cc1461072d578063eb9019d414610761578063f23a6e6114610781578063f8ce560a146107ad578063fc0c546a146107cd57600080fd5b8063bc197c811461065b578063c01f9e3714610687578063c28bc2fa146106a7578063c59057e4146106c7578063dd4e2ba5146106e757600080fd5b806397c3d334116100f257806397c3d334146105e75780639a802a6d146105fb5780639f8b33921461061b578063a7713a7014610631578063b58131b01461064657600080fd5b80635f398a141461053957806367e2e078146105595780637b3c71d31461056f5780637d5e81e21461058f57806385f2aef2146105af57600080fd5b80632fe3e261116101bc578063501fa8bd11610180578063501fa8bd14610465578063544ffc9c1461047a57806354fd4d50146104cf57806356781388146104f9578063592a84941461051957600080fd5b80632fe3e261146103855780633932abb1146103b95780633bccf4fd146103ce5780633e4f49e6146103ee578063438596321461041b57600080fd5b806306fdde031161020357806306fdde03146102d7578063095cf5c6146102f9578063150b7a02146103195780632656227d146103525780632d63f6931461036557600080fd5b806301ffc9a71461024257806302a251a314610277578063034201811461029757806306f3f9e6146102b757600080fd5b3661023d57005b005b600080fd5b34801561024e57600080fd5b5061026261025d366004612110565b610801565b60405190151581526020015b60405180910390f35b34801561028357600080fd5b5062093a805b60405190815260200161026e565b3480156102a357600080fd5b506102896102b2366004612255565b61086e565b3480156102c357600080fd5b5061023b6102d23660046122fb565b610966565b3480156102e357600080fd5b506102ec6109d8565b60405161026e9190612370565b34801561030557600080fd5b5061023b61031436600461239a565b610a6a565b34801561032557600080fd5b506103396103343660046123b5565b610ad1565b6040516001600160e01b0319909116815260200161026e565b61028961036036600461258b565b610ae2565b34801561037157600080fd5b506102896103803660046122fb565b610c09565b34801561039157600080fd5b506102897fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156103c557600080fd5b50610384610289565b3480156103da57600080fd5b506102896103e936600461261a565b610c40565b3480156103fa57600080fd5b5061040e6104093660046122fb565b610cb6565b60405161026e919061267e565b34801561042757600080fd5b506102626104363660046126a6565b60008281526004602090815260408083206001600160a01b038516845260030190915290205460ff1692915050565b34801561047157600080fd5b50610289603281565b34801561048657600080fd5b506104b46104953660046122fb565b6000908152600460205260409020805460018201546002909201549092565b6040805193845260208401929092529082015260600161026e565b3480156104db57600080fd5b506040805180820190915260018152603160f81b60208201526102ec565b34801561050557600080fd5b506102896105143660046126d2565b610dc5565b34801561052557600080fd5b5061023b6105343660046122fb565b610de6565b34801561054557600080fd5b506102896105543660046126f5565b610e76565b34801561056557600080fd5b506102896103e881565b34801561057b57600080fd5b5061028961058a366004612778565b610ec0565b34801561059b57600080fd5b506102896105aa3660046127d1565b610f12565b3480156105bb57600080fd5b506006546105cf906001600160a01b031681565b6040516001600160a01b03909116815260200161026e565b3480156105f357600080fd5b506064610289565b34801561060757600080fd5b50610289610616366004612885565b6111d1565b34801561062757600080fd5b5061028960075481565b34801561063d57600080fd5b50600554610289565b34801561065257600080fd5b506102896111e8565b34801561066757600080fd5b506103396106763660046128db565b63bc197c8160e01b95945050505050565b34801561069357600080fd5b506102896106a23660046122fb565b611293565b3480156106b357600080fd5b5061023b6106c236600461296a565b6112c2565b3480156106d357600080fd5b506102896106e236600461258b565b61136c565b3480156106f357600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102ec565b34801561073957600080fd5b506102897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561076d57600080fd5b5061028961077c3660046129ab565b6113a6565b34801561078d57600080fd5b5061033961079c3660046129d5565b63f23a6e6160e01b95945050505050565b3480156107b957600080fd5b506102896107c83660046122fb565b6113c7565b3480156107d957600080fd5b506105cf7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663bf26d89760e01b148061083257506001600160e01b031982166379dd796f60e01b145b8061084d57506001600160e01b03198216630271189760e51b145b8061086857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008061091261090a7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c6040516108aa929190612a39565b60405180910390208b805190602001206040516020016108ef959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061146b565b8686866114b9565b90506109588a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92506114d7915050565b9a9950505050505050505050565b3330146109b55760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064015b60405180910390fd5b6109cc565b806109c5600261163c565b036109ba57505b6109d5816116bb565b50565b6060600080546109e790612a49565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1390612a49565b8015610a605780601f10610a3557610100808354040283529160200191610a60565b820191906000526020600020905b815481529060010190602001808311610a4357829003601f168201915b5050505050905090565b6006546001600160a01b03163314610aaf5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b630a85bd0160e11b5b949350505050565b600080610af18686868661136c565b90506000610afe82610cb6565b90506004816007811115610b1457610b14612668565b1480610b3157506005816007811115610b2f57610b2f612668565b145b610b875760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b60648201526084016109ac565b600082815260016020818152604092839020600201805460ff191690921790915590518381527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f910160405180910390a1610be58288888888611783565b610bf2828888888861180f565b610bff8288888888611783565b5095945050505050565b60008181526001602090815260408083208151928301909152546001600160401b0316908190525b6001600160401b031692915050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff851660608201526000908190610c8e9061090a906080016108ef565b9050610cab8782886040518060200160405280600081525061190e565b979650505050505050565b6000818152600160205260408120600281015460ff1615610cda5750600792915050565b6002810154610100900460ff1615610cf55750600292915050565b6000610d0084610c09565b905080600003610d525760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c20696400000060448201526064016109ac565b428110610d63575060009392505050565b6000610d6e85611293565b9050428110610d8257506001949350505050565b610d8b8561193a565b8015610daa575060008581526004602052604090208054600190910154115b15610dba57506004949350505050565b506003949350505050565b600080339050610ada8482856040518060200160405280600081525061190e565b6006546001600160a01b03163314610e2b5760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064016109ac565b6032811115610e715760405162461bcd60e51b81526020600482015260126024820152710dceadacae4c2e8dee440e8dede40d0d2ced60731b60448201526064016109ac565b600755565b600080339050610cab87828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a92506114d7915050565b600080339050610f0886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061190e92505050565b9695505050505050565b6000610f1c6111e8565b610f2b3361077c600143612a99565b1015610f935760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b60648201526084016109ac565b6000610fa8868686868051906020012061136c565b90508451865114610fcb5760405162461bcd60e51b81526004016109ac90612ab0565b8351865114610fec5760405162461bcd60e51b81526004016109ac90612ab0565b600086511161103d5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c000000000000000060448201526064016109ac565b600081815260016020908152604091829020825191820190925281546001600160401b031690819052156110bd5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b60648201526084016109ac565b60006110ca610384611971565b6110d342611971565b6110dd9190612af1565b905060006110ed62093a80611971565b6110f79083612af1565b835467ffffffffffffffff19166001600160401b038416178455905060018301805467ffffffffffffffff19166001600160401b0383161790557f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084338b8b8d516001600160401b0381111561116f5761116f612198565b6040519080825280602002602001820160405280156111a257816020015b606081526020019060019003908161118d5790505b508c88888e6040516111bc99989796959493929190612be5565b60405180910390a15091979650505050505050565b60006111de8484846119dd565b90505b9392505050565b600754604051632394e7a360e21b81524260048201526000916103e8916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638e539e8c90602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a9190612cd4565b6112849190612ced565b61128e9190612d0c565b905090565b60008181526001602081815260408084208151928301909152909101546001600160401b031690819052610c31565b33301461130c5760405162461bcd60e51b8152602060048201526018602482015277476f7665726e6f723a206f6e6c79476f7665726e616e636560401b60448201526064016109ac565b611323565b8061131c600261163c565b0361131157505b6113658483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611a73915050565b5050505050565b6000848484846040516020016113859493929190612d2e565b60408051601f19818403018152919052805160209091012095945050505050565b60006111e183836113c260408051602081019091526000815290565b6119dd565b60006064600554604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190612cd4565b6114619190612ced565b6108689190612d0c565b6000610868611478611a99565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114ca87878787611bc0565b91509150610bff81611c84565b60008581526001602081905260408220906114f188610cb6565b600781111561150257611502612668565b1461155b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b60648201526084016109ac565b604080516020810190915281546001600160401b031690819052600090611584908890866119dd565b90506115938888888488611dce565b83516000036115e857866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516115db9493929190612d79565b60405180910390a2610cab565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611629959493929190612da1565b60405180910390a2979650505050505050565b60006116578254600f81810b600160801b909204900b131590565b1561167557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b606481111561173e5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4016109ac565b600580549082905560408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b611365565b845181101561180757306001600160a01b03168582815181106117ad576117ad612de7565b60200260200101516001600160a01b0316036117f7576117f78382815181106117d8576117d8612de7565b6020026020010151805190602001206002611f4890919063ffffffff16565b61180081612dfd565b9050611788565b505050505050565b6000604051806060016040528060278152602001612e4b60279139905060005b85518110156119055760008087838151811061184d5761184d612de7565b60200260200101516001600160a01b031687848151811061187057611870612de7565b602002602001015187858151811061188a5761188a612de7565b602002602001015160405161189f9190612e16565b60006040518083038185875af1925050503d80600081146118dc576040519150601f19603f3d011682016040523d82523d6000602084013e6118e1565b606091505b50915091506118f1828286611f84565b505050806118fe90612dfd565b905061182f565b50505050505050565b60006119318585858561192c60408051602081019091526000815290565b6114d7565b95945050505050565b60008181526004602052604081206002810154600182015461195c9190612e32565b6119686107c885610c09565b11159392505050565b60006001600160401b038211156119d95760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016109ac565b5090565b604051630748d63560e31b81526001600160a01b038481166004830152602482018490526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de9190612cd4565b60606111de848484604051806060016040528060298152602001612e7260299139611f9d565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611af257507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bf75750600090506003611c7b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c4b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611c7457600060019250925050611c7b565b9150600090505b94509492505050565b6000816004811115611c9857611c98612668565b03611ca05750565b6001816004811115611cb457611cb4612668565b03611d015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016109ac565b6002816004811115611d1557611d15612668565b03611d625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016109ac565b6003816004811115611d7657611d76612668565b036109d55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016109ac565b60008581526004602090815260408083206001600160a01b0388168452600381019092529091205460ff1615611e565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b60648201526084016109ac565b6001600160a01b03851660009081526003820160205260409020805460ff1916600117905560ff8416611ea25782816000016000828254611e979190612e32565b909155506118079050565b60001960ff851601611ec25782816001016000828254611e979190612e32565b60011960ff851601611ee25782816002016000828254611e979190612e32565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b60648201526084016109ac565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60608315611f935750816111e1565b6111e1838361206d565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109ac565b600080866001600160a01b0316858760405161201a9190612e16565b60006040518083038185875af1925050503d8060008114612057576040519150601f19603f3d011682016040523d82523d6000602084013e61205c565b606091505b5091509150610cab87838387612097565b81511561207d5781518083602001fd5b8060405162461bcd60e51b81526004016109ac9190612370565b606083156121065782516000036120ff576001600160a01b0385163b6120ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ac565b5081610ada565b610ada838361206d565b60006020828403121561212257600080fd5b81356001600160e01b0319811681146111e157600080fd5b803560ff8116811461214b57600080fd5b919050565b60008083601f84011261216257600080fd5b5081356001600160401b0381111561217957600080fd5b60208301915083602082850101111561219157600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156121d6576121d6612198565b604052919050565b60006001600160401b038311156121f7576121f7612198565b61220a601f8401601f19166020016121ae565b905082815283838301111561221e57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261224657600080fd5b6111e1838335602085016121de565b60008060008060008060008060e0898b03121561227157600080fd5b8835975061228160208a0161213a565b965060408901356001600160401b038082111561229d57600080fd5b6122a98c838d01612150565b909850965060608b01359150808211156122c257600080fd5b506122cf8b828c01612235565b9450506122de60808a0161213a565b925060a0890135915060c089013590509295985092959890939650565b60006020828403121561230d57600080fd5b5035919050565b60005b8381101561232f578181015183820152602001612317565b8381111561233e576000848401525b50505050565b6000815180845261235c816020860160208601612314565b601f01601f19169290920160200192915050565b6020815260006111e16020830184612344565b80356001600160a01b038116811461214b57600080fd5b6000602082840312156123ac57600080fd5b6111e182612383565b600080600080608085870312156123cb57600080fd5b6123d485612383565b93506123e260208601612383565b92506040850135915060608501356001600160401b0381111561240457600080fd5b61241087828801612235565b91505092959194509250565b60006001600160401b0382111561243557612435612198565b5060051b60200190565b600082601f83011261245057600080fd5b813560206124656124608361241c565b6121ae565b82815260059290921b8401810191818101908684111561248457600080fd5b8286015b848110156124a65761249981612383565b8352918301918301612488565b509695505050505050565b600082601f8301126124c257600080fd5b813560206124d26124608361241c565b82815260059290921b840181019181810190868411156124f157600080fd5b8286015b848110156124a657803583529183019183016124f5565b600082601f83011261251d57600080fd5b8135602061252d6124608361241c565b82815260059290921b8401810191818101908684111561254c57600080fd5b8286015b848110156124a65780356001600160401b0381111561256f5760008081fd5b61257d8986838b0101612235565b845250918301918301612550565b600080600080608085870312156125a157600080fd5b84356001600160401b03808211156125b857600080fd5b6125c48883890161243f565b955060208701359150808211156125da57600080fd5b6125e6888389016124b1565b945060408701359150808211156125fc57600080fd5b506126098782880161250c565b949793965093946060013593505050565b600080600080600060a0868803121561263257600080fd5b853594506126426020870161213a565b93506126506040870161213a565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b60208101600883106126a057634e487b7160e01b600052602160045260246000fd5b91905290565b600080604083850312156126b957600080fd5b823591506126c960208401612383565b90509250929050565b600080604083850312156126e557600080fd5b823591506126c96020840161213a565b60008060008060006080868803121561270d57600080fd5b8535945061271d6020870161213a565b935060408601356001600160401b038082111561273957600080fd5b61274589838a01612150565b9095509350606088013591508082111561275e57600080fd5b5061276b88828901612235565b9150509295509295909350565b6000806000806060858703121561278e57600080fd5b8435935061279e6020860161213a565b925060408501356001600160401b038111156127b957600080fd5b6127c587828801612150565b95989497509550505050565b600080600080608085870312156127e757600080fd5b84356001600160401b03808211156127fe57600080fd5b61280a8883890161243f565b9550602087013591508082111561282057600080fd5b61282c888389016124b1565b9450604087013591508082111561284257600080fd5b61284e8883890161250c565b9350606087013591508082111561286457600080fd5b508501601f8101871361287657600080fd5b612410878235602084016121de565b60008060006060848603121561289a57600080fd5b6128a384612383565b92506020840135915060408401356001600160401b038111156128c557600080fd5b6128d186828701612235565b9150509250925092565b600080600080600060a086880312156128f357600080fd5b6128fc86612383565b945061290a60208701612383565b935060408601356001600160401b038082111561292657600080fd5b61293289838a016124b1565b9450606088013591508082111561294857600080fd5b61295489838a016124b1565b9350608088013591508082111561275e57600080fd5b6000806000806060858703121561298057600080fd5b61298985612383565b93506020850135925060408501356001600160401b038111156127b957600080fd5b600080604083850312156129be57600080fd5b6129c783612383565b946020939093013593505050565b600080600080600060a086880312156129ed57600080fd5b6129f686612383565b9450612a0460208701612383565b9350604086013592506060860135915060808601356001600160401b03811115612a2d57600080fd5b61276b88828901612235565b8183823760009101908152919050565b600181811c90821680612a5d57607f821691505b602082108103612a7d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612aab57612aab612a83565b500390565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b60006001600160401b03808316818516808303821115612b1357612b13612a83565b01949350505050565b600081518084526020808501945080840160005b83811015612b555781516001600160a01b031687529582019590820190600101612b30565b509495945050505050565b600081518084526020808501945080840160005b83811015612b5557815187529582019590820190600101612b74565b600081518084526020808501808196508360051b8101915082860160005b85811015612bd8578284038952612bc6848351612344565b98850198935090840190600101612bae565b5091979650505050505050565b60006101208b8352602060018060a01b038c1681850152816040850152612c0e8285018c612b1c565b91508382036060850152612c22828b612b60565b915083820360808501528189518084528284019150828160051b850101838c0160005b83811015612c7357601f19878403018552612c61838351612344565b94860194925090850190600101612c45565b505086810360a0880152612c87818c612b90565b945050505050612ca260c08401876001600160401b03169052565b6001600160401b03851660e0840152828103610100840152612cc48185612344565b9c9b505050505050505050505050565b600060208284031215612ce657600080fd5b5051919050565b6000816000190483118215151615612d0757612d07612a83565b500290565b600082612d2957634e487b7160e01b600052601260045260246000fd5b500490565b608081526000612d416080830187612b1c565b8281036020840152612d538187612b60565b90508281036040840152612d678186612b90565b91505082606083015295945050505050565b84815260ff84166020820152826040820152608060608201526000610f086080830184612344565b85815260ff8516602082015283604082015260a060608201526000612dc960a0830185612344565b8281036080840152612ddb8185612344565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0f57612e0f612a83565b5060010190565b60008251612e28818460208701612314565b9190910192915050565b60008219821115612e4557612e45612a83565b50019056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a264697066735822122029355c2d8f836f0a2f24736bc924b3f886cff30ff65a0c82da8594f652b6555264736f6c634300080d0033", "devdoc": { "errors": { "Empty()": [ @@ -1210,7 +1210,7 @@ "storageLayout": { "storage": [ { - "astId": 21935, + "astId": 21937, "contract": "contracts/FlowGovernor.sol:FlowGovernor", "label": "_name", "offset": 0, @@ -1218,31 +1218,31 @@ "type": "t_string_storage" }, { - "astId": 21940, + "astId": 21942, "contract": "contracts/FlowGovernor.sol:FlowGovernor", "label": "_proposals", "offset": 0, "slot": "1", - "type": "t_mapping(t_uint256,t_struct(ProposalCore)21933_storage)" + "type": "t_mapping(t_uint256,t_struct(ProposalCore)21935_storage)" }, { - "astId": 21943, + "astId": 21945, "contract": "contracts/FlowGovernor.sol:FlowGovernor", "label": "_governanceCall", "offset": 0, "slot": "2", - "type": "t_struct(Bytes32Deque)30247_storage" + "type": "t_struct(Bytes32Deque)30250_storage" }, { - "astId": 23199, + "astId": 23201, "contract": "contracts/FlowGovernor.sol:FlowGovernor", "label": "_proposalVotes", "offset": 0, "slot": "4", - "type": "t_mapping(t_uint256,t_struct(ProposalVote)23194_storage)" + "type": "t_mapping(t_uint256,t_struct(ProposalVote)23196_storage)" }, { - "astId": 23452, + "astId": 23454, "contract": "contracts/FlowGovernor.sol:FlowGovernor", "label": "_quorumNumerator", "offset": 0, @@ -1250,7 +1250,7 @@ "type": "t_uint256" }, { - "astId": 1704, + "astId": 1705, "contract": "contracts/FlowGovernor.sol:FlowGovernor", "label": "team", "offset": 0, @@ -1258,7 +1258,7 @@ "type": "t_address" }, { - "astId": 1713, + "astId": 1714, "contract": "contracts/FlowGovernor.sol:FlowGovernor", "label": "proposalNumerator", "offset": 0, @@ -1301,31 +1301,31 @@ "numberOfBytes": "32", "value": "t_bytes32" }, - "t_mapping(t_uint256,t_struct(ProposalCore)21933_storage)": { + "t_mapping(t_uint256,t_struct(ProposalCore)21935_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct L2Governor.ProposalCore)", "numberOfBytes": "32", - "value": "t_struct(ProposalCore)21933_storage" + "value": "t_struct(ProposalCore)21935_storage" }, - "t_mapping(t_uint256,t_struct(ProposalVote)23194_storage)": { + "t_mapping(t_uint256,t_struct(ProposalVote)23196_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct L2GovernorCountingSimple.ProposalVote)", "numberOfBytes": "32", - "value": "t_struct(ProposalVote)23194_storage" + "value": "t_struct(ProposalVote)23196_storage" }, "t_string_storage": { "encoding": "bytes", "label": "string", "numberOfBytes": "32" }, - "t_struct(Bytes32Deque)30247_storage": { + "t_struct(Bytes32Deque)30250_storage": { "encoding": "inplace", "label": "struct DoubleEndedQueue.Bytes32Deque", "members": [ { - "astId": 30240, + "astId": 30243, "contract": "contracts/FlowGovernor.sol:FlowGovernor", "label": "_begin", "offset": 0, @@ -1333,7 +1333,7 @@ "type": "t_int128" }, { - "astId": 30242, + "astId": 30245, "contract": "contracts/FlowGovernor.sol:FlowGovernor", "label": "_end", "offset": 16, @@ -1341,7 +1341,7 @@ "type": "t_int128" }, { - "astId": 30246, + "astId": 30249, "contract": "contracts/FlowGovernor.sol:FlowGovernor", "label": "_data", "offset": 0, @@ -1351,28 +1351,28 @@ ], "numberOfBytes": "64" }, - "t_struct(ProposalCore)21933_storage": { + "t_struct(ProposalCore)21935_storage": { "encoding": "inplace", "label": "struct L2Governor.ProposalCore", "members": [ { - "astId": 21925, + "astId": 21927, "contract": "contracts/FlowGovernor.sol:FlowGovernor", "label": "voteStart", "offset": 0, "slot": "0", - "type": "t_struct(Timestamp)26448_storage" + "type": "t_struct(Timestamp)26451_storage" }, { - "astId": 21928, + "astId": 21930, "contract": "contracts/FlowGovernor.sol:FlowGovernor", "label": "voteEnd", "offset": 0, "slot": "1", - "type": "t_struct(Timestamp)26448_storage" + "type": "t_struct(Timestamp)26451_storage" }, { - "astId": 21930, + "astId": 21932, "contract": "contracts/FlowGovernor.sol:FlowGovernor", "label": "executed", "offset": 0, @@ -1380,7 +1380,7 @@ "type": "t_bool" }, { - "astId": 21932, + "astId": 21934, "contract": "contracts/FlowGovernor.sol:FlowGovernor", "label": "canceled", "offset": 1, @@ -1390,12 +1390,12 @@ ], "numberOfBytes": "96" }, - "t_struct(ProposalVote)23194_storage": { + "t_struct(ProposalVote)23196_storage": { "encoding": "inplace", "label": "struct L2GovernorCountingSimple.ProposalVote", "members": [ { - "astId": 23185, + "astId": 23187, "contract": "contracts/FlowGovernor.sol:FlowGovernor", "label": "againstVotes", "offset": 0, @@ -1403,7 +1403,7 @@ "type": "t_uint256" }, { - "astId": 23187, + "astId": 23189, "contract": "contracts/FlowGovernor.sol:FlowGovernor", "label": "forVotes", "offset": 0, @@ -1411,7 +1411,7 @@ "type": "t_uint256" }, { - "astId": 23189, + "astId": 23191, "contract": "contracts/FlowGovernor.sol:FlowGovernor", "label": "abstainVotes", "offset": 0, @@ -1419,7 +1419,7 @@ "type": "t_uint256" }, { - "astId": 23193, + "astId": 23195, "contract": "contracts/FlowGovernor.sol:FlowGovernor", "label": "hasVoted", "offset": 0, @@ -1429,12 +1429,12 @@ ], "numberOfBytes": "128" }, - "t_struct(Timestamp)26448_storage": { + "t_struct(Timestamp)26451_storage": { "encoding": "inplace", "label": "struct Timers.Timestamp", "members": [ { - "astId": 26447, + "astId": 26450, "contract": "contracts/FlowGovernor.sol:FlowGovernor", "label": "_deadline", "offset": 0, diff --git a/deployments/arbitrumGoerli/GaugeFactory.json b/deployments/arbitrumGoerli/GaugeFactory.json index 71387750..65c59390 100644 --- a/deployments/arbitrumGoerli/GaugeFactory.json +++ b/deployments/arbitrumGoerli/GaugeFactory.json @@ -1,5 +1,5 @@ { - "address": "0xdEA300B2495790ccc75c6918A302E1952e9c2339", + "address": "0x3d396484a6a2759074dD879865c22Ac939C4a711", "abi": [ { "inputs": [ @@ -59,28 +59,28 @@ "type": "function" } ], - "transactionHash": "0xcbf9cfffdc1928b08a835603cfa19e6e6d7fab2282b5f63487de7a9c948d726d", + "transactionHash": "0xdb808601bc16218167c22eacea3be6b21e783ebc02f7b51b39393e75c4366d68", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xdEA300B2495790ccc75c6918A302E1952e9c2339", + "contractAddress": "0x3d396484a6a2759074dD879865c22Ac939C4a711", "transactionIndex": 1, - "gasUsed": "3308273", + "gasUsed": "3308285", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x8f3ab1d694dd858328ab8b691232273c1361aec6fa132a142ce16fb6e18e1d4b", - "transactionHash": "0xcbf9cfffdc1928b08a835603cfa19e6e6d7fab2282b5f63487de7a9c948d726d", + "blockHash": "0x469bf9741a6f689578b2873fa304effbd7c4dca71a3095e0a3cecfd409ee556a", + "transactionHash": "0xdb808601bc16218167c22eacea3be6b21e783ebc02f7b51b39393e75c4366d68", "logs": [], - "blockNumber": 6069369, - "cumulativeGasUsed": "3308273", + "blockNumber": 6188413, + "cumulativeGasUsed": "3308285", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "d2a2160297444b93438826228d1e185d", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_internal_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_external_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_ve\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isPair\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_gauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/GaugeFactory.sol\":\"GaugeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Gauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\\ncontract Gauge is IGauge {\\n address public immutable stake; // the LP token that needs to be staked for rewards\\n address public immutable _ve; // the ve token used for gauges\\n address public immutable internal_bribe;\\n address public immutable external_bribe;\\n address public immutable voter;\\n\\n uint256 public derivedSupply;\\n mapping(address => uint256) public derivedBalances;\\n\\n bool public isForPair;\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 internal constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(address => uint256)) public lastEarn;\\n mapping(address => mapping(address => uint256))\\n public userRewardPerTokenStored;\\n\\n mapping(address => uint256) public tokenIds;\\n\\n uint256 public totalSupply;\\n mapping(address => uint256) public balanceOf;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n uint256 public fees0;\\n uint256 public fees1;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(\\n address _stake,\\n address _internal_bribe,\\n address _external_bribe,\\n address __ve,\\n address _voter,\\n bool _forPair,\\n address[] memory _allowedRewardTokens\\n ) {\\n stake = _stake;\\n internal_bribe = _internal_bribe;\\n external_bribe = _external_bribe;\\n _ve = __ve;\\n voter = _voter;\\n isForPair = _forPair;\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function claimFees()\\n external\\n lock\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n return _claimFees();\\n }\\n\\n function _claimFees()\\n internal\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n if (!isForPair) {\\n return (0, 0);\\n }\\n (claimed0, claimed1) = IPair(stake).claimFees();\\n if (claimed0 > 0 || claimed1 > 0) {\\n uint256 _fees0 = fees0 + claimed0;\\n uint256 _fees1 = fees1 + claimed1;\\n (address _token0, address _token1) = IPair(stake).tokens();\\n if (\\n _fees0 > IBribe(internal_bribe).left(_token0) &&\\n _fees0 / DURATION > 0\\n ) {\\n fees0 = 0;\\n _safeApprove(_token0, internal_bribe, _fees0);\\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\\n } else {\\n fees0 = _fees0;\\n }\\n if (\\n _fees1 > IBribe(internal_bribe).left(_token1) &&\\n _fees1 / DURATION > 0\\n ) {\\n fees1 = 0;\\n _safeApprove(_token1, internal_bribe, _fees1);\\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\\n } else {\\n fees1 = _fees1;\\n }\\n\\n emit ClaimFees(msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(address account, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(address account, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[account][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[account] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n derivedSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n function getReward(address account, address[] memory tokens) external lock {\\n require(msg.sender == account || msg.sender == voter);\\n _unlocked = 1;\\n IVoter(voter).distribute(address(this));\\n _unlocked = 2;\\n\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], account);\\n lastEarn[tokens[i]][account] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n\\n uint256 _derivedBalance = derivedBalances[account];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(account);\\n derivedBalances[account] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(account, derivedBalances[account]);\\n _writeSupplyCheckpoint();\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (derivedSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / derivedSupply);\\n }\\n\\n function derivedBalance(address account) public view returns (uint256) {\\n return balanceOf[account];\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\\n function earned(address token, address account)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][account],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[account] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[account] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[account][i];\\n Checkpoint memory cp1 = checkpoints[account][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[account][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][account]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n function depositAll(uint256 tokenId) external {\\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\\n }\\n\\n function deposit(uint256 amount, uint256 tokenId) public lock {\\n require(amount > 0);\\n _updateRewardForAllTokens();\\n\\n _safeTransferFrom(stake, msg.sender, address(this), amount);\\n totalSupply += amount;\\n balanceOf[msg.sender] += amount;\\n\\n if (tokenId > 0) {\\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\\n if (tokenIds[msg.sender] == 0) {\\n tokenIds[msg.sender] = tokenId;\\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\\n }\\n require(tokenIds[msg.sender] == tokenId);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, _derivedBalance);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function withdrawAll() external {\\n withdraw(balanceOf[msg.sender]);\\n }\\n\\n function withdraw(uint256 amount) public {\\n uint256 tokenId = 0;\\n if (amount == balanceOf[msg.sender]) {\\n tokenId = tokenIds[msg.sender];\\n }\\n withdrawToken(amount, tokenId);\\n }\\n\\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[msg.sender] -= amount;\\n _safeTransfer(stake, msg.sender, amount);\\n\\n if (tokenId > 0) {\\n require(tokenId == tokenIds[msg.sender]);\\n tokenIds[msg.sender] = 0;\\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(token != stake);\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"rewards tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n _claimFees();\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeApprove(\\n address token,\\n address spender,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x38cc0284dd60d8a1418d9c34e6be84911ca4a1b479dc129f19b9027e4c670e1f\",\"license\":\"MIT\"},\"contracts/factories/GaugeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/Gauge.sol';\\n\\ncontract GaugeFactory is IGaugeFactory {\\n address public last_gauge;\\n\\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\\n return last_gauge;\\n }\\n}\\n\",\"keccak256\":\"0x34f6ac4bdace9ef01d8cffda9b45842efae88b519230c67759b9936aee6acc9b\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50613b19806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea26469706673582212208a3206431587d5e0992bf170e3d9601bbd813d92d440aaedca384edc6b46150364736f6c634300080d0033a2646970667358221220e75dfbd32112b57311df28d130744f2456bb7c2368a2f6dc730071d739644b2064736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea26469706673582212208a3206431587d5e0992bf170e3d9601bbd813d92d440aaedca384edc6b46150364736f6c634300080d0033a2646970667358221220e75dfbd32112b57311df28d130744f2456bb7c2368a2f6dc730071d739644b2064736f6c634300080d0033", + "numDeployments": 2, + "solcInputHash": "6e27611a2cedd773c4cc6e46935e6392", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_internal_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_external_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_ve\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isPair\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_gauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/GaugeFactory.sol\":\"GaugeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735303535373437363232\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Gauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\\ncontract Gauge is IGauge {\\n address public immutable stake; // the LP token that needs to be staked for rewards\\n address public immutable _ve; // the ve token used for gauges\\n address public immutable internal_bribe;\\n address public immutable external_bribe;\\n address public immutable voter;\\n\\n uint256 public derivedSupply;\\n mapping(address => uint256) public derivedBalances;\\n\\n bool public isForPair;\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 internal constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(address => uint256)) public lastEarn;\\n mapping(address => mapping(address => uint256))\\n public userRewardPerTokenStored;\\n\\n mapping(address => uint256) public tokenIds;\\n\\n uint256 public totalSupply;\\n mapping(address => uint256) public balanceOf;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n uint256 public fees0;\\n uint256 public fees1;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(\\n address _stake,\\n address _internal_bribe,\\n address _external_bribe,\\n address __ve,\\n address _voter,\\n bool _forPair,\\n address[] memory _allowedRewardTokens\\n ) {\\n stake = _stake;\\n internal_bribe = _internal_bribe;\\n external_bribe = _external_bribe;\\n _ve = __ve;\\n voter = _voter;\\n isForPair = _forPair;\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function claimFees()\\n external\\n lock\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n return _claimFees();\\n }\\n\\n function _claimFees()\\n internal\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n if (!isForPair) {\\n return (0, 0);\\n }\\n (claimed0, claimed1) = IPair(stake).claimFees();\\n if (claimed0 > 0 || claimed1 > 0) {\\n uint256 _fees0 = fees0 + claimed0;\\n uint256 _fees1 = fees1 + claimed1;\\n (address _token0, address _token1) = IPair(stake).tokens();\\n if (\\n _fees0 > IBribe(internal_bribe).left(_token0) &&\\n _fees0 / DURATION > 0\\n ) {\\n fees0 = 0;\\n _safeApprove(_token0, internal_bribe, _fees0);\\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\\n } else {\\n fees0 = _fees0;\\n }\\n if (\\n _fees1 > IBribe(internal_bribe).left(_token1) &&\\n _fees1 / DURATION > 0\\n ) {\\n fees1 = 0;\\n _safeApprove(_token1, internal_bribe, _fees1);\\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\\n } else {\\n fees1 = _fees1;\\n }\\n\\n emit ClaimFees(msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(address account, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(address account, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[account][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[account] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n derivedSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n function getReward(address account, address[] memory tokens) external lock {\\n require(msg.sender == account || msg.sender == voter);\\n _unlocked = 1;\\n IVoter(voter).distribute(address(this));\\n _unlocked = 2;\\n\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], account);\\n lastEarn[tokens[i]][account] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n\\n uint256 _derivedBalance = derivedBalances[account];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(account);\\n derivedBalances[account] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(account, derivedBalances[account]);\\n _writeSupplyCheckpoint();\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (derivedSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / derivedSupply);\\n }\\n\\n function derivedBalance(address account) public view returns (uint256) {\\n return balanceOf[account];\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\\n function earned(address token, address account)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][account],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[account] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[account] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[account][i];\\n Checkpoint memory cp1 = checkpoints[account][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[account][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][account]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n function depositAll(uint256 tokenId) external {\\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\\n }\\n\\n function deposit(uint256 amount, uint256 tokenId) public lock {\\n require(amount > 0);\\n _updateRewardForAllTokens();\\n\\n _safeTransferFrom(stake, msg.sender, address(this), amount);\\n totalSupply += amount;\\n balanceOf[msg.sender] += amount;\\n\\n if (tokenId > 0) {\\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\\n if (tokenIds[msg.sender] == 0) {\\n tokenIds[msg.sender] = tokenId;\\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\\n }\\n require(tokenIds[msg.sender] == tokenId);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, _derivedBalance);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function withdrawAll() external {\\n withdraw(balanceOf[msg.sender]);\\n }\\n\\n function withdraw(uint256 amount) public {\\n uint256 tokenId = 0;\\n if (amount == balanceOf[msg.sender]) {\\n tokenId = tokenIds[msg.sender];\\n }\\n withdrawToken(amount, tokenId);\\n }\\n\\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[msg.sender] -= amount;\\n _safeTransfer(stake, msg.sender, amount);\\n\\n if (tokenId > 0) {\\n require(tokenId == tokenIds[msg.sender]);\\n tokenIds[msg.sender] = 0;\\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(token != stake);\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"rewards tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n _claimFees();\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeApprove(\\n address token,\\n address spender,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x38cc0284dd60d8a1418d9c34e6be84911ca4a1b479dc129f19b9027e4c670e1f\",\"license\":\"MIT\"},\"contracts/factories/GaugeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/Gauge.sol';\\n\\ncontract GaugeFactory is IGaugeFactory {\\n address public last_gauge;\\n\\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\\n return last_gauge;\\n }\\n}\\n\",\"keccak256\":\"0x34f6ac4bdace9ef01d8cffda9b45842efae88b519230c67759b9936aee6acc9b\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50613b19806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea264697066735822122061faacf1f1399994ce2c6f68cf9b0d3abece7ebbe5349b387be56cf9b274d73464736f6c634300080d0033a2646970667358221220d89874d2e43eff99130612f87d12bbd4b16a422911942982db3fbdbaca8e4a3364736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea264697066735822122061faacf1f1399994ce2c6f68cf9b0d3abece7ebbe5349b387be56cf9b274d73464736f6c634300080d0033a2646970667358221220d89874d2e43eff99130612f87d12bbd4b16a422911942982db3fbdbaca8e4a3364736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, @@ -94,7 +94,7 @@ "storageLayout": { "storage": [ { - "astId": 21380, + "astId": 21382, "contract": "contracts/factories/GaugeFactory.sol:GaugeFactory", "label": "last_gauge", "offset": 0, diff --git a/deployments/arbitrumGoerli/MerkleClaim.json b/deployments/arbitrumGoerli/MerkleClaim.json index d8920384..dcd9f004 100644 --- a/deployments/arbitrumGoerli/MerkleClaim.json +++ b/deployments/arbitrumGoerli/MerkleClaim.json @@ -1,5 +1,5 @@ { - "address": "0xDD6594d966d9463A7808AF67024E941fB921dB2B", + "address": "0x9c9dd01E65E0285dc9FDfb470347A39Be4a14399", "abi": [ { "inputs": [ @@ -105,31 +105,31 @@ "type": "function" } ], - "transactionHash": "0x0a82585a04a93b1c66412f4c637420cfb75b1c276744694c8e5121252ffef8ec", + "transactionHash": "0x80ebb09af24a530b8e63e87c518de1fa19da091dacaf99f09a47f021d87871d8", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xDD6594d966d9463A7808AF67024E941fB921dB2B", + "contractAddress": "0x9c9dd01E65E0285dc9FDfb470347A39Be4a14399", "transactionIndex": 1, "gasUsed": "356966", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x2bd7e64c28fbd006c2f75508801c4ef966c0b9da160c397b003f2311968c554e", - "transactionHash": "0x0a82585a04a93b1c66412f4c637420cfb75b1c276744694c8e5121252ffef8ec", + "blockHash": "0xc8ad8914a7ac3b25b8aab87c1c4b5215c7f44d4eaac39ffaab0096072a43f405", + "transactionHash": "0x80ebb09af24a530b8e63e87c518de1fa19da091dacaf99f09a47f021d87871d8", "logs": [], - "blockNumber": 6069468, + "blockNumber": 6188491, "cumulativeGasUsed": "356966", "status": 1, "byzantium": true }, "args": [ - "0x4E13914872BFf7e58f3E231b2687fDd084014999", + "0x49E4eA802DdF4CAF7C699782a80DeefdC03Dcb4B", "0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f" ], - "numDeployments": 1, - "solcInputHash": "d2a2160297444b93438826228d1e185d", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_flow\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"_merkleRoot\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Claim\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FLOW\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"hasClaimed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\",\"events\":{\"Claim(address,uint256)\":{\"params\":{\"amount\":\"of tokens claimed\",\"to\":\"recipient of claim\"}}},\"kind\":\"dev\",\"methods\":{\"claim(address,uint256,bytes32[])\":{\"params\":{\"amount\":\"of tokens owed to claimee\",\"proof\":\"merkle proof to prove address and amount are in tree\",\"to\":\"address of claimee\"}},\"constructor\":{\"params\":{\"_flow\":\"address\",\"_merkleRoot\":\"of claimees\"}}},\"title\":\"MerkleClaim\",\"version\":1},\"userdoc\":{\"events\":{\"Claim(address,uint256)\":{\"notice\":\"Emitted after a successful token claim\"}},\"kind\":\"user\",\"methods\":{\"FLOW()\":{\"notice\":\"FLOW token to claim\"},\"claim(address,uint256,bytes32[])\":{\"notice\":\"Allows claiming tokens if address is part of merkle tree\"},\"constructor\":{\"notice\":\"Creates a new MerkleClaim contract\"},\"hasClaimed(address)\":{\"notice\":\"Mapping of addresses who have claimed tokens\"},\"merkleRoot()\":{\"notice\":\"ERC20-claimee inclusion root\"}},\"notice\":\"Claims FLOW for members of a merkle tree\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/MerkleClaim.sol\":\"MerkleClaim\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/redeem/MerkleClaim.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity 0.8.13;\\n\\n/// ============ Imports ============\\n\\nimport {IFlow} from \\\"contracts/interfaces/IFlow.sol\\\";\\nimport {MerkleProof} from \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\\\"; // OZ: MerkleProof\\n\\n/// @title MerkleClaim\\n/// @notice Claims FLOW for members of a merkle tree\\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\\ncontract MerkleClaim {\\n /// ============ Immutable storage ============\\n\\n /// @notice FLOW token to claim\\n IFlow public immutable FLOW;\\n /// @notice ERC20-claimee inclusion root\\n bytes32 public immutable merkleRoot;\\n\\n /// ============ Mutable storage ============\\n\\n /// @notice Mapping of addresses who have claimed tokens\\n mapping(address => bool) public hasClaimed;\\n\\n /// ============ Constructor ============\\n\\n /// @notice Creates a new MerkleClaim contract\\n /// @param _flow address\\n /// @param _merkleRoot of claimees\\n constructor(address _flow, bytes32 _merkleRoot) {\\n FLOW = IFlow(_flow);\\n merkleRoot = _merkleRoot;\\n }\\n\\n /// ============ Events ============\\n\\n /// @notice Emitted after a successful token claim\\n /// @param to recipient of claim\\n /// @param amount of tokens claimed\\n event Claim(address indexed to, uint256 amount);\\n\\n /// ============ Functions ============\\n\\n /// @notice Allows claiming tokens if address is part of merkle tree\\n /// @param to address of claimee\\n /// @param amount of tokens owed to claimee\\n /// @param proof merkle proof to prove address and amount are in tree\\n function claim(\\n address to,\\n uint256 amount,\\n bytes32[] calldata proof\\n ) external {\\n // Throw if address has already claimed tokens\\n require(!hasClaimed[to], \\\"ALREADY_CLAIMED\\\");\\n\\n // Verify merkle proof, or revert if not in tree\\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\\n require(isValidLeaf, \\\"NOT_IN_MERKLE\\\");\\n\\n // Set address to claimed\\n hasClaimed[to] = true;\\n\\n // Claim tokens for address\\n require(FLOW.claim(to, amount), \\\"CLAIM_FAILED\\\");\\n\\n // Emit claim event\\n emit Claim(to, amount);\\n }\\n}\\n\",\"keccak256\":\"0xf169ba9559c5c39dc79b2281410b09fd92f200a3b0489b32e28ce08a00a98826\",\"license\":\"AGPL-3.0-only\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev These functions deal with verification of Merkle Tree proofs.\\n *\\n * The tree and the proofs can be generated using our\\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\\n * You will find a quickstart guide in the readme.\\n *\\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\\n * hashing, or use a hash function other than keccak256 for hashing leaves.\\n * This is because the concatenation of a sorted pair of internal nodes in\\n * the merkle tree could be reinterpreted as a leaf value.\\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\\n * against this attack out of the box.\\n */\\nlibrary MerkleProof {\\n /**\\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\\n * defined by `root`. For this, a `proof` must be provided, containing\\n * sibling hashes on the branch from the leaf to the root of the tree. Each\\n * pair of leaves and each pair of pre-images are assumed to be sorted.\\n */\\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProof(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {verify}\\n *\\n * _Available since v4.7._\\n */\\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProofCalldata(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\\n * hash matches the root of the tree. When processing the proof, the pairs\\n * of leafs & pre-images are assumed to be sorted.\\n *\\n * _Available since v4.4._\\n */\\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Calldata version of {processProof}\\n *\\n * _Available since v4.7._\\n */\\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerify(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProof(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {multiProofVerify}\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerifyCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\\n * respectively.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProof(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n /**\\n * @dev Calldata version of {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProofCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\\n }\\n\\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x00, a)\\n mstore(0x20, b)\\n value := keccak256(0x00, 0x40)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcc76dbe53154a5bbd12fdd1613a73f73f3dc7c63d813be36f7ee606f52d6a7b3\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60c060405234801561001057600080fd5b5060405161062638038061062683398101604081905261002f91610045565b6001600160a01b0390911660805260a05261007f565b6000806040838503121561005857600080fd5b82516001600160a01b038116811461006f57600080fd5b6020939093015192949293505050565b60805160a0516105766100b060003960008181605601526101ea0152600081816090015261029601526105766000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633189097b1461008b5780633d13f874146100ca57806373b2e80e146100df575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6100b27f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6100dd6100d836600461043c565b610112565b005b6101026100ed3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220735d919fc3ef07f6ea463c63e7979be0343a217a0d43a5a1ef5e61ea8954548e64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633189097b1461008b5780633d13f874146100ca57806373b2e80e146100df575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6100b27f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6100dd6100d836600461043c565b610112565b005b6101026100ed3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220735d919fc3ef07f6ea463c63e7979be0343a217a0d43a5a1ef5e61ea8954548e64736f6c634300080d0033", + "numDeployments": 2, + "solcInputHash": "6e27611a2cedd773c4cc6e46935e6392", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_flow\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"_merkleRoot\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Claim\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FLOW\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"hasClaimed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\",\"events\":{\"Claim(address,uint256)\":{\"params\":{\"amount\":\"of tokens claimed\",\"to\":\"recipient of claim\"}}},\"kind\":\"dev\",\"methods\":{\"claim(address,uint256,bytes32[])\":{\"params\":{\"amount\":\"of tokens owed to claimee\",\"proof\":\"merkle proof to prove address and amount are in tree\",\"to\":\"address of claimee\"}},\"constructor\":{\"params\":{\"_flow\":\"address\",\"_merkleRoot\":\"of claimees\"}}},\"title\":\"MerkleClaim\",\"version\":1},\"userdoc\":{\"events\":{\"Claim(address,uint256)\":{\"notice\":\"Emitted after a successful token claim\"}},\"kind\":\"user\",\"methods\":{\"FLOW()\":{\"notice\":\"FLOW token to claim\"},\"claim(address,uint256,bytes32[])\":{\"notice\":\"Allows claiming tokens if address is part of merkle tree\"},\"constructor\":{\"notice\":\"Creates a new MerkleClaim contract\"},\"hasClaimed(address)\":{\"notice\":\"Mapping of addresses who have claimed tokens\"},\"merkleRoot()\":{\"notice\":\"ERC20-claimee inclusion root\"}},\"notice\":\"Claims FLOW for members of a merkle tree\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/MerkleClaim.sol\":\"MerkleClaim\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735303535373437363232\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/redeem/MerkleClaim.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity 0.8.13;\\n\\n/// ============ Imports ============\\n\\nimport {IFlow} from \\\"contracts/interfaces/IFlow.sol\\\";\\nimport {MerkleProof} from \\\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\\\"; // OZ: MerkleProof\\n\\n/// @title MerkleClaim\\n/// @notice Claims FLOW for members of a merkle tree\\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\\ncontract MerkleClaim {\\n /// ============ Immutable storage ============\\n\\n /// @notice FLOW token to claim\\n IFlow public immutable FLOW;\\n /// @notice ERC20-claimee inclusion root\\n bytes32 public immutable merkleRoot;\\n\\n /// ============ Mutable storage ============\\n\\n /// @notice Mapping of addresses who have claimed tokens\\n mapping(address => bool) public hasClaimed;\\n\\n /// ============ Constructor ============\\n\\n /// @notice Creates a new MerkleClaim contract\\n /// @param _flow address\\n /// @param _merkleRoot of claimees\\n constructor(address _flow, bytes32 _merkleRoot) {\\n FLOW = IFlow(_flow);\\n merkleRoot = _merkleRoot;\\n }\\n\\n /// ============ Events ============\\n\\n /// @notice Emitted after a successful token claim\\n /// @param to recipient of claim\\n /// @param amount of tokens claimed\\n event Claim(address indexed to, uint256 amount);\\n\\n /// ============ Functions ============\\n\\n /// @notice Allows claiming tokens if address is part of merkle tree\\n /// @param to address of claimee\\n /// @param amount of tokens owed to claimee\\n /// @param proof merkle proof to prove address and amount are in tree\\n function claim(\\n address to,\\n uint256 amount,\\n bytes32[] calldata proof\\n ) external {\\n // Throw if address has already claimed tokens\\n require(!hasClaimed[to], \\\"ALREADY_CLAIMED\\\");\\n\\n // Verify merkle proof, or revert if not in tree\\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\\n require(isValidLeaf, \\\"NOT_IN_MERKLE\\\");\\n\\n // Set address to claimed\\n hasClaimed[to] = true;\\n\\n // Claim tokens for address\\n require(FLOW.claim(to, amount), \\\"CLAIM_FAILED\\\");\\n\\n // Emit claim event\\n emit Claim(to, amount);\\n }\\n}\\n\",\"keccak256\":\"0xf169ba9559c5c39dc79b2281410b09fd92f200a3b0489b32e28ce08a00a98826\",\"license\":\"AGPL-3.0-only\"},\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev These functions deal with verification of Merkle Tree proofs.\\n *\\n * The tree and the proofs can be generated using our\\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\\n * You will find a quickstart guide in the readme.\\n *\\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\\n * hashing, or use a hash function other than keccak256 for hashing leaves.\\n * This is because the concatenation of a sorted pair of internal nodes in\\n * the merkle tree could be reinterpreted as a leaf value.\\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\\n * against this attack out of the box.\\n */\\nlibrary MerkleProof {\\n /**\\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\\n * defined by `root`. For this, a `proof` must be provided, containing\\n * sibling hashes on the branch from the leaf to the root of the tree. Each\\n * pair of leaves and each pair of pre-images are assumed to be sorted.\\n */\\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProof(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {verify}\\n *\\n * _Available since v4.7._\\n */\\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\\n return processProofCalldata(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\\n * hash matches the root of the tree. When processing the proof, the pairs\\n * of leafs & pre-images are assumed to be sorted.\\n *\\n * _Available since v4.4._\\n */\\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Calldata version of {processProof}\\n *\\n * _Available since v4.7._\\n */\\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerify(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProof(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {multiProofVerify}\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerifyCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\\n * respectively.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProof(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n /**\\n * @dev Calldata version of {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProofCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value from the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i]\\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\\n : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n unchecked {\\n return hashes[totalHashes - 1];\\n }\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\\n }\\n\\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x00, a)\\n mstore(0x20, b)\\n value := keccak256(0x00, 0x40)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcc76dbe53154a5bbd12fdd1613a73f73f3dc7c63d813be36f7ee606f52d6a7b3\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c060405234801561001057600080fd5b5060405161062638038061062683398101604081905261002f91610045565b6001600160a01b0390911660805260a05261007f565b6000806040838503121561005857600080fd5b82516001600160a01b038116811461006f57600080fd5b6020939093015192949293505050565b60805160a0516105766100b060003960008181605601526101ea0152600081816090015261029601526105766000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633189097b1461008b5780633d13f874146100ca57806373b2e80e146100df575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6100b27f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6100dd6100d836600461043c565b610112565b005b6101026100ed3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220323b4f0f7408a55f89cbb1bd411dd05b1199a87593d6ffceef2cb6fc02b0efa364736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632eb4a7ab146100515780633189097b1461008b5780633d13f874146100ca57806373b2e80e146100df575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6100b27f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610082565b6100dd6100d836600461043c565b610112565b005b6101026100ed3660046104c6565b60006020819052908152604090205460ff1681565b6040519015158152602001610082565b6001600160a01b03841660009081526020819052604090205460ff16156101725760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b60448201526064015b60405180910390fd5b6040516bffffffffffffffffffffffff19606086901b1660208201526034810184905260009060540160405160208183030381529060405280519060200120905060006102158484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f0000000000000000000000000000000000000000000000000000000000000000925086915061038b9050565b9050806102545760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f494e5f4d45524b4c4560981b6044820152606401610169565b6001600160a01b0386811660008181526020819052604090819020805460ff1916600117905551635569f64b60e11b81526004810191909152602481018790527f00000000000000000000000000000000000000000000000000000000000000009091169063aad3ec96906044016020604051808303816000875af11580156102e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030591906104e1565b6103405760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b6044820152606401610169565b856001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d48660405161037b91815260200190565b60405180910390a2505050505050565b60008261039885846103a1565b14949350505050565b600081815b84518110156103e6576103d2828683815181106103c5576103c5610503565b60200260200101516103ee565b9150806103de81610519565b9150506103a6565b509392505050565b600081831061040a576000828152602084905260409020610419565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461043757600080fd5b919050565b6000806000806060858703121561045257600080fd5b61045b85610420565b935060208501359250604085013567ffffffffffffffff8082111561047f57600080fd5b818701915087601f83011261049357600080fd5b8135818111156104a257600080fd5b8860208260051b85010111156104b757600080fd5b95989497505060200194505050565b6000602082840312156104d857600080fd5b61041982610420565b6000602082840312156104f357600080fd5b8151801515811461041957600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161053957634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220323b4f0f7408a55f89cbb1bd411dd05b1199a87593d6ffceef2cb6fc02b0efa364736f6c634300080d0033", "devdoc": { "author": "Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)", "events": { @@ -189,7 +189,7 @@ "storageLayout": { "storage": [ { - "astId": 24472, + "astId": 24474, "contract": "contracts/redeem/MerkleClaim.sol:MerkleClaim", "label": "hasClaimed", "offset": 0, diff --git a/deployments/arbitrumGoerli/Minter.json b/deployments/arbitrumGoerli/Minter.json index 710027a1..681590f8 100644 --- a/deployments/arbitrumGoerli/Minter.json +++ b/deployments/arbitrumGoerli/Minter.json @@ -1,5 +1,5 @@ { - "address": "0x933348CCa9bA6DAAd71be824844dCd0D22d849f6", + "address": "0xe66A8A93C38234782f84BF42ed855d857b372b3c", "abi": [ { "inputs": [ @@ -324,32 +324,32 @@ "type": "function" } ], - "transactionHash": "0xa3857de90da23bfa903a6460af45cb7edb635213f934a0578b29b4156fb3adf1", + "transactionHash": "0x230d64da6bcdb9a53d75ebd2ce10a7ad8625e53acc702545a0805dc99172b40d", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x933348CCa9bA6DAAd71be824844dCd0D22d849f6", + "contractAddress": "0xe66A8A93C38234782f84BF42ed855d857b372b3c", "transactionIndex": 1, - "gasUsed": "1199207", + "gasUsed": "1199219", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x4cacb3c4bef18d95064afa2934c5269bdc4b648a8f4b530f407afe517181f950", - "transactionHash": "0xa3857de90da23bfa903a6460af45cb7edb635213f934a0578b29b4156fb3adf1", + "blockHash": "0x1cb2b4dc2ef616c62e6bc89e574b79e02c9bb63bc8ec88692524921dfe9952ee", + "transactionHash": "0x230d64da6bcdb9a53d75ebd2ce10a7ad8625e53acc702545a0805dc99172b40d", "logs": [], - "blockNumber": 6069446, - "cumulativeGasUsed": "1199207", + "blockNumber": 6188470, + "cumulativeGasUsed": "1199219", "status": 1, "byzantium": true }, "args": [ - "0x04c989FB4768739Fbd62FC1f77D06ae3c1E5eC36", - "0x6d55AFbF1cAf01E0bcA5255bbA730da6fAFD0aF4", - "0xCf24b553f519916664533A862AB100FF8185a0c8" + "0x809BCB4AC4c77F9F2B075ca9f29e160E8939D35f", + "0x38c8250FF6bD87812eDc5aAee577836c2B3c2aE6", + "0xd1A4913ec6d68944C93056504655d1B3cbd4eBd3" ], - "numDeployments": 1, - "solcInputHash": "d2a2160297444b93438826228d1e185d", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__voter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__rewards_distributor\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weekly\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_supply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_emission\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_TEAM_RATE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_flow\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_rewards_distributor\",\"outputs\":[{\"internalType\":\"contract IRewardsDistributor\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"contract IVotingEscrow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_voter\",\"outputs\":[{\"internalType\":\"contract IVoter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"active_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"calculate_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minted\",\"type\":\"uint256\"}],\"name\":\"calculate_growth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"claimants\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingTeam\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_teamRate\",\"type\":\"uint256\"}],\"name\":\"setTeamRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"teamRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"update_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Minter.sol\":\"Minter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Minter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IMinter.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\\n\\ncontract Minter is IMinter {\\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\\n uint256 internal constant EMISSION = 990;\\n uint256 internal constant TAIL_EMISSION = 2;\\n uint256 internal constant PRECISION = 1000;\\n IFlow public immutable _flow;\\n IVoter public immutable _voter;\\n IVotingEscrow public immutable _ve;\\n IRewardsDistributor public immutable _rewards_distributor;\\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M FLOW (FLOW has 18 decimals)\\n uint256 public active_period;\\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\\n\\n address internal initializer;\\n address public team;\\n address public pendingTeam;\\n uint256 public teamRate;\\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\\n\\n event Mint(\\n address indexed sender,\\n uint256 weekly,\\n uint256 circulating_supply,\\n uint256 circulating_emission\\n );\\n\\n constructor(\\n address __voter, // the voting & distribution system\\n address __ve, // the ve(3,3) system that will be locked into\\n address __rewards_distributor // the distribution system that ensures users aren't diluted\\n ) {\\n initializer = msg.sender;\\n team = msg.sender;\\n teamRate = 30; // 30 bps = 0.03%\\n _flow = IFlow(IVotingEscrow(__ve).token());\\n _voter = IVoter(__voter);\\n _ve = IVotingEscrow(__ve);\\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\\n }\\n\\n function initialize(\\n address[] memory claimants,\\n uint256[] memory amounts,\\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\\n ) external {\\n require(initializer == msg.sender);\\n _flow.mint(address(this), max);\\n _flow.approve(address(_ve), type(uint256).max);\\n for (uint256 i = 0; i < claimants.length; i++) {\\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\\n }\\n initializer = address(0);\\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\\n }\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team, \\\"not team\\\");\\n pendingTeam = _team;\\n }\\n\\n function acceptTeam() external {\\n require(msg.sender == pendingTeam, \\\"not pending team\\\");\\n team = pendingTeam;\\n }\\n\\n function setTeamRate(uint256 _teamRate) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(_teamRate <= MAX_TEAM_RATE, \\\"rate too high\\\");\\n teamRate = _teamRate;\\n }\\n\\n // calculate circulating supply as total token supply - locked supply\\n function circulating_supply() public view returns (uint256) {\\n return _flow.totalSupply() - _ve.totalSupply();\\n }\\n\\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\\n function calculate_emission() public view returns (uint256) {\\n return (weekly * EMISSION) / PRECISION;\\n }\\n\\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\\n function weekly_emission() public view returns (uint256) {\\n return MathDunks.max(calculate_emission(), circulating_emission());\\n }\\n\\n // calculates tail end (infinity) emissions as 0.2% of total supply\\n function circulating_emission() public view returns (uint256) {\\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\\n }\\n\\n // calculate inflation and adjust ve balances accordingly\\n function calculate_growth(uint256 _minted) public view returns (uint256) {\\n uint256 _veTotal = _ve.totalSupply();\\n uint256 _flowTotal = _flow.totalSupply();\\n return\\n (((((_minted * _veTotal) / _flowTotal) * _veTotal) / _flowTotal) *\\n _veTotal) /\\n _flowTotal /\\n 2;\\n }\\n\\n // update period can only be called once per cycle (1 week)\\n function update_period() external returns (uint256) {\\n uint256 _period = active_period;\\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\\n // only trigger if new week\\n _period = (block.timestamp / WEEK) * WEEK;\\n active_period = _period;\\n weekly = weekly_emission();\\n\\n uint256 _growth = calculate_growth(weekly);\\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\\n (PRECISION - teamRate);\\n uint256 _required = _growth + weekly + _teamEmissions;\\n uint256 _balanceOf = _flow.balanceOf(address(this));\\n if (_balanceOf < _required) {\\n _flow.mint(address(this), _required - _balanceOf);\\n }\\n\\n require(_flow.transfer(team, _teamEmissions));\\n require(_flow.transfer(address(_rewards_distributor), _growth));\\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\\n\\n _flow.approve(address(_voter), weekly);\\n _voter.notifyRewardAmount(weekly);\\n\\n emit Mint(\\n msg.sender,\\n weekly,\\n circulating_supply(),\\n circulating_emission()\\n );\\n }\\n return _period;\\n }\\n}\\n\",\"keccak256\":\"0xc661046dd2b90d93e4f057d2497b137703b4f0c3caccfe846f1a81906a2e1961\",\"license\":\"MIT\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x6101006040526a0c685fa11e01ec6f0000006000553480156200002157600080fd5b506040516200158938038062001589833981016040819052620000449162000156565b60028054336001600160a01b03199182168117909255600380549091169091179055601e60055560408051637e062a3560e11b815290516001600160a01b0384169163fc0c546a9160048083019260209291908290030181865afa158015620000b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d79190620001a0565b6001600160a01b0390811660805283811660a05282811660c052811660e05262093a808062000108816002620001db565b620001149042620001fd565b62000120919062000218565b6200012c9190620001db565b600155506200023b915050565b80516001600160a01b03811681146200015157600080fd5b919050565b6000806000606084860312156200016c57600080fd5b620001778462000139565b9250620001876020850162000139565b9150620001976040850162000139565b90509250925092565b600060208284031215620001b357600080fd5b620001be8262000139565b9392505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620001f857620001f8620001c5565b500290565b60008219821115620002135762000213620001c5565b500190565b6000826200023657634e487b7160e01b600052601260045260246000fd5b500490565b60805160a05160c05160e051611296620002f3600039600081816101d101528181610c3701528181610cde0152610d5101526000818161023a015281816104b30152818161055f01528181610689015261087501526000818161019201528181610e090152610ea301526000818161029d01528181610426015281816104e30152818161070f015281816108f701528181610a5f01528181610ade01528181610ba801528181610c660152610dda01526112966000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c806385170813116100ad578063cfc6c8ff11610071578063cfc6c8ff14610277578063d13996081461027f578063e038c75a14610288578063ed29fc1114610290578063fe75cac51461029857600080fd5b8063851708131461020f57806385f2aef2146102225780638dd598fb146102355780638e01fbfa1461025c578063b5cc143a1461026f57600080fd5b806336d96faf116100f457806336d96faf146101855780633db9b42a1461018d5780634b1cd5da146101cc57806359d46ffc146101f357806378ef7f021461020657600080fd5b806301c8e6fd14610131578063095cf5c61461014c5780631eebae801461016157806326cfc17b146101695780632e8f7b1f14610172575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b61015f61015a366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61015f610180366004610fb8565b610353565b6101396103de565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6004546101b4906001600160a01b031681565b61013960055481565b61015f61021d3660046110a7565b6103f3565b6003546101b4906001600160a01b031681565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b61013961026a366004610fb8565b610684565b61015f6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea264697066735822122057707c7ff21f374352214e71e7c225b391feb35beac2e749fd76e72f01a6ba6f64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c806385170813116100ad578063cfc6c8ff11610071578063cfc6c8ff14610277578063d13996081461027f578063e038c75a14610288578063ed29fc1114610290578063fe75cac51461029857600080fd5b8063851708131461020f57806385f2aef2146102225780638dd598fb146102355780638e01fbfa1461025c578063b5cc143a1461026f57600080fd5b806336d96faf116100f457806336d96faf146101855780633db9b42a1461018d5780634b1cd5da146101cc57806359d46ffc146101f357806378ef7f021461020657600080fd5b806301c8e6fd14610131578063095cf5c61461014c5780631eebae801461016157806326cfc17b146101695780632e8f7b1f14610172575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b61015f61015a366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61015f610180366004610fb8565b610353565b6101396103de565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6004546101b4906001600160a01b031681565b61013960055481565b61015f61021d3660046110a7565b6103f3565b6003546101b4906001600160a01b031681565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b61013961026a366004610fb8565b610684565b61015f6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea264697066735822122057707c7ff21f374352214e71e7c225b391feb35beac2e749fd76e72f01a6ba6f64736f6c634300080d0033", + "numDeployments": 2, + "solcInputHash": "6e27611a2cedd773c4cc6e46935e6392", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__voter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__rewards_distributor\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weekly\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_supply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_emission\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_TEAM_RATE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_flow\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_rewards_distributor\",\"outputs\":[{\"internalType\":\"contract IRewardsDistributor\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"contract IVotingEscrow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_voter\",\"outputs\":[{\"internalType\":\"contract IVoter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"active_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"calculate_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minted\",\"type\":\"uint256\"}],\"name\":\"calculate_growth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"claimants\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingTeam\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_teamRate\",\"type\":\"uint256\"}],\"name\":\"setTeamRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"teamRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"update_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Minter.sol\":\"Minter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735303535373437363232\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Minter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IMinter.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\\n\\ncontract Minter is IMinter {\\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\\n uint256 internal constant EMISSION = 990;\\n uint256 internal constant TAIL_EMISSION = 2;\\n uint256 internal constant PRECISION = 1000;\\n IFlow public immutable _flow;\\n IVoter public immutable _voter;\\n IVotingEscrow public immutable _ve;\\n IRewardsDistributor public immutable _rewards_distributor;\\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M FLOW (FLOW has 18 decimals)\\n uint256 public active_period;\\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\\n\\n address internal initializer;\\n address public team;\\n address public pendingTeam;\\n uint256 public teamRate;\\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\\n\\n event Mint(\\n address indexed sender,\\n uint256 weekly,\\n uint256 circulating_supply,\\n uint256 circulating_emission\\n );\\n\\n constructor(\\n address __voter, // the voting & distribution system\\n address __ve, // the ve(3,3) system that will be locked into\\n address __rewards_distributor // the distribution system that ensures users aren't diluted\\n ) {\\n initializer = msg.sender;\\n team = msg.sender;\\n teamRate = 30; // 30 bps = 0.03%\\n _flow = IFlow(IVotingEscrow(__ve).token());\\n _voter = IVoter(__voter);\\n _ve = IVotingEscrow(__ve);\\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\\n }\\n\\n function initialize(\\n address[] memory claimants,\\n uint256[] memory amounts,\\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\\n ) external {\\n require(initializer == msg.sender);\\n _flow.mint(address(this), max);\\n _flow.approve(address(_ve), type(uint256).max);\\n for (uint256 i = 0; i < claimants.length; i++) {\\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\\n }\\n initializer = address(0);\\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\\n }\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team, \\\"not team\\\");\\n pendingTeam = _team;\\n }\\n\\n function acceptTeam() external {\\n require(msg.sender == pendingTeam, \\\"not pending team\\\");\\n team = pendingTeam;\\n }\\n\\n function setTeamRate(uint256 _teamRate) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(_teamRate <= MAX_TEAM_RATE, \\\"rate too high\\\");\\n teamRate = _teamRate;\\n }\\n\\n // calculate circulating supply as total token supply - locked supply\\n function circulating_supply() public view returns (uint256) {\\n return _flow.totalSupply() - _ve.totalSupply();\\n }\\n\\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\\n function calculate_emission() public view returns (uint256) {\\n return (weekly * EMISSION) / PRECISION;\\n }\\n\\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\\n function weekly_emission() public view returns (uint256) {\\n return MathDunks.max(calculate_emission(), circulating_emission());\\n }\\n\\n // calculates tail end (infinity) emissions as 0.2% of total supply\\n function circulating_emission() public view returns (uint256) {\\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\\n }\\n\\n // calculate inflation and adjust ve balances accordingly\\n function calculate_growth(uint256 _minted) public view returns (uint256) {\\n uint256 _veTotal = _ve.totalSupply();\\n uint256 _flowTotal = _flow.totalSupply();\\n return\\n (((((_minted * _veTotal) / _flowTotal) * _veTotal) / _flowTotal) *\\n _veTotal) /\\n _flowTotal /\\n 2;\\n }\\n\\n // update period can only be called once per cycle (1 week)\\n function update_period() external returns (uint256) {\\n uint256 _period = active_period;\\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\\n // only trigger if new week\\n _period = (block.timestamp / WEEK) * WEEK;\\n active_period = _period;\\n weekly = weekly_emission();\\n\\n uint256 _growth = calculate_growth(weekly);\\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\\n (PRECISION - teamRate);\\n uint256 _required = _growth + weekly + _teamEmissions;\\n uint256 _balanceOf = _flow.balanceOf(address(this));\\n if (_balanceOf < _required) {\\n _flow.mint(address(this), _required - _balanceOf);\\n }\\n\\n require(_flow.transfer(team, _teamEmissions));\\n require(_flow.transfer(address(_rewards_distributor), _growth));\\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\\n\\n _flow.approve(address(_voter), weekly);\\n _voter.notifyRewardAmount(weekly);\\n\\n emit Mint(\\n msg.sender,\\n weekly,\\n circulating_supply(),\\n circulating_emission()\\n );\\n }\\n return _period;\\n }\\n}\\n\",\"keccak256\":\"0xc661046dd2b90d93e4f057d2497b137703b4f0c3caccfe846f1a81906a2e1961\",\"license\":\"MIT\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x6101006040526a0c685fa11e01ec6f0000006000553480156200002157600080fd5b506040516200158938038062001589833981016040819052620000449162000156565b60028054336001600160a01b03199182168117909255600380549091169091179055601e60055560408051637e062a3560e11b815290516001600160a01b0384169163fc0c546a9160048083019260209291908290030181865afa158015620000b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d79190620001a0565b6001600160a01b0390811660805283811660a05282811660c052811660e05262093a808062000108816002620001db565b620001149042620001fd565b62000120919062000218565b6200012c9190620001db565b600155506200023b915050565b80516001600160a01b03811681146200015157600080fd5b919050565b6000806000606084860312156200016c57600080fd5b620001778462000139565b9250620001876020850162000139565b9150620001976040850162000139565b90509250925092565b600060208284031215620001b357600080fd5b620001be8262000139565b9392505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620001f857620001f8620001c5565b500290565b60008219821115620002135762000213620001c5565b500190565b6000826200023657634e487b7160e01b600052601260045260246000fd5b500490565b60805160a05160c05160e051611296620002f3600039600081816101d101528181610c3701528181610cde0152610d5101526000818161023a015281816104b30152818161055f01528181610689015261087501526000818161019201528181610e090152610ea301526000818161029d01528181610426015281816104e30152818161070f015281816108f701528181610a5f01528181610ade01528181610ba801528181610c660152610dda01526112966000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c806385170813116100ad578063cfc6c8ff11610071578063cfc6c8ff14610277578063d13996081461027f578063e038c75a14610288578063ed29fc1114610290578063fe75cac51461029857600080fd5b8063851708131461020f57806385f2aef2146102225780638dd598fb146102355780638e01fbfa1461025c578063b5cc143a1461026f57600080fd5b806336d96faf116100f457806336d96faf146101855780633db9b42a1461018d5780634b1cd5da146101cc57806359d46ffc146101f357806378ef7f021461020657600080fd5b806301c8e6fd14610131578063095cf5c61461014c5780631eebae801461016157806326cfc17b146101695780632e8f7b1f14610172575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b61015f61015a366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61015f610180366004610fb8565b610353565b6101396103de565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6004546101b4906001600160a01b031681565b61013960055481565b61015f61021d3660046110a7565b6103f3565b6003546101b4906001600160a01b031681565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b61013961026a366004610fb8565b610684565b61015f6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea26469706673582212205daa8ec29f4aec146b0ae60a14c0b9110f3e954e3d67eca845a4898cf259df6664736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c806385170813116100ad578063cfc6c8ff11610071578063cfc6c8ff14610277578063d13996081461027f578063e038c75a14610288578063ed29fc1114610290578063fe75cac51461029857600080fd5b8063851708131461020f57806385f2aef2146102225780638dd598fb146102355780638e01fbfa1461025c578063b5cc143a1461026f57600080fd5b806336d96faf116100f457806336d96faf146101855780633db9b42a1461018d5780634b1cd5da146101cc57806359d46ffc146101f357806378ef7f021461020657600080fd5b806301c8e6fd14610131578063095cf5c61461014c5780631eebae801461016157806326cfc17b146101695780632e8f7b1f14610172575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b61015f61015a366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61015f610180366004610fb8565b610353565b6101396103de565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6004546101b4906001600160a01b031681565b61013960055481565b61015f61021d3660046110a7565b6103f3565b6003546101b4906001600160a01b031681565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b61013961026a366004610fb8565b610684565b61015f6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea26469706673582212205daa8ec29f4aec146b0ae60a14c0b9110f3e954e3d67eca845a4898cf259df6664736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, @@ -363,7 +363,7 @@ "storageLayout": { "storage": [ { - "astId": 6679, + "astId": 6680, "contract": "contracts/Minter.sol:Minter", "label": "weekly", "offset": 0, @@ -371,7 +371,7 @@ "type": "t_uint256" }, { - "astId": 6681, + "astId": 6682, "contract": "contracts/Minter.sol:Minter", "label": "active_period", "offset": 0, @@ -379,7 +379,7 @@ "type": "t_uint256" }, { - "astId": 6692, + "astId": 6693, "contract": "contracts/Minter.sol:Minter", "label": "initializer", "offset": 0, @@ -387,7 +387,7 @@ "type": "t_address" }, { - "astId": 6694, + "astId": 6695, "contract": "contracts/Minter.sol:Minter", "label": "team", "offset": 0, @@ -395,7 +395,7 @@ "type": "t_address" }, { - "astId": 6696, + "astId": 6697, "contract": "contracts/Minter.sol:Minter", "label": "pendingTeam", "offset": 0, @@ -403,7 +403,7 @@ "type": "t_address" }, { - "astId": 6698, + "astId": 6699, "contract": "contracts/Minter.sol:Minter", "label": "teamRate", "offset": 0, diff --git a/deployments/arbitrumGoerli/PairFactory.json b/deployments/arbitrumGoerli/PairFactory.json index 7677391f..f1332cc7 100644 --- a/deployments/arbitrumGoerli/PairFactory.json +++ b/deployments/arbitrumGoerli/PairFactory.json @@ -1,5 +1,5 @@ { - "address": "0x5c7C6ee91569E2658c3A52f47b35E1AAB7e8e600", + "address": "0x22E98754dBa170A64724558E668cb380516e0BE9", "abi": [ { "inputs": [], @@ -383,28 +383,28 @@ "type": "function" } ], - "transactionHash": "0x847c09e28a87c4a13b5fb2cc56d188788f105bc0ffc0428c2701093dcb76229d", + "transactionHash": "0x994de9f23ee6a194c7496e974556026276c1477f1a1865afbd3295ba491531fe", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x5c7C6ee91569E2658c3A52f47b35E1AAB7e8e600", + "contractAddress": "0x22E98754dBa170A64724558E668cb380516e0BE9", "transactionIndex": 1, - "gasUsed": "4628154", + "gasUsed": "4628142", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xdb43649995465ade5b3ae9197ef9af2693be7647cac66edd353e9fbf89463298", - "transactionHash": "0x847c09e28a87c4a13b5fb2cc56d188788f105bc0ffc0428c2701093dcb76229d", + "blockHash": "0x3b7582ebabdf03f5525a18721c2d886a61bebe8bd486da60177cd408650dda52", + "transactionHash": "0x994de9f23ee6a194c7496e974556026276c1477f1a1865afbd3295ba491531fe", "logs": [], - "blockNumber": 6069385, - "cumulativeGasUsed": "4628154", + "blockNumber": 6188430, + "cumulativeGasUsed": "4628142", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "d2a2160297444b93438826228d1e185d", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"PairCreated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_FEE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allPairs\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"allPairsLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"createPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getInitializable\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"name\":\"getPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pairCodeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingFeeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingPauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_feeManager\",\"type\":\"address\"}],\"name\":\"setFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_state\",\"type\":\"bool\"}],\"name\":\"setPause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pauser\",\"type\":\"address\"}],\"name\":\"setPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stableFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"volatileFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/PairFactory.sol\":\"PairFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Pair.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairCallee.sol\\\";\\nimport \\\"contracts/factories/PairFactory.sol\\\";\\nimport \\\"contracts/PairFees.sol\\\";\\n\\n// The base pair of pools, either stable or volatile\\ncontract Pair is IPair {\\n string public name;\\n string public symbol;\\n uint8 public constant decimals = 18;\\n\\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\\n bool public immutable stable;\\n\\n uint256 public totalSupply = 0;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n mapping(address => uint256) public balanceOf;\\n\\n bytes32 internal DOMAIN_SEPARATOR;\\n // keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 internal constant PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n mapping(address => uint256) public nonces;\\n\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n\\n address public immutable token0;\\n address public immutable token1;\\n address public immutable fees;\\n address immutable factory;\\n\\n // Structure to capture time period obervations every 30 minutes, used for local oracles\\n struct Observation {\\n uint256 timestamp;\\n uint256 reserve0Cumulative;\\n uint256 reserve1Cumulative;\\n }\\n\\n // Capture oracle reading every 30 minutes\\n uint256 constant periodSize = 1800;\\n\\n Observation[] public observations;\\n\\n uint256 internal immutable decimals0;\\n uint256 internal immutable decimals1;\\n\\n uint256 public reserve0;\\n uint256 public reserve1;\\n uint256 public blockTimestampLast;\\n\\n uint256 public reserve0CumulativeLast;\\n uint256 public reserve1CumulativeLast;\\n\\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \\\"clean\\\"\\n // this further allows LP holders to easily claim fees for tokens they have/staked\\n uint256 public index0 = 0;\\n uint256 public index1 = 0;\\n\\n // position assigned to each LP to track their current index0 & index1 vs the global position\\n mapping(address => uint256) public supplyIndex0;\\n mapping(address => uint256) public supplyIndex1;\\n\\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\\n mapping(address => uint256) public claimable0;\\n mapping(address => uint256) public claimable1;\\n\\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\\n event Burn(\\n address indexed sender,\\n uint256 amount0,\\n uint256 amount1,\\n address indexed to\\n );\\n event Swap(\\n address indexed sender,\\n uint256 amount0In,\\n uint256 amount1In,\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address indexed to\\n );\\n event Sync(uint256 reserve0, uint256 reserve1);\\n event Claim(\\n address indexed sender,\\n address indexed recipient,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 amount\\n );\\n\\n constructor() {\\n factory = msg.sender;\\n (address _token0, address _token1, bool _stable) = PairFactory(\\n msg.sender\\n ).getInitializable();\\n (token0, token1, stable) = (_token0, _token1, _stable);\\n fees = address(new PairFees(_token0, _token1));\\n if (_stable) {\\n name = string(\\n abi.encodePacked(\\n \\\"StableV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"sAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n } else {\\n name = string(\\n abi.encodePacked(\\n \\\"VolatileV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"vAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n }\\n\\n decimals0 = 10**IERC20(_token0).decimals();\\n decimals1 = 10**IERC20(_token1).decimals();\\n\\n observations.push(Observation(block.timestamp, 0, 0));\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function observationLength() external view returns (uint256) {\\n return observations.length;\\n }\\n\\n function lastObservation() public view returns (Observation memory) {\\n return observations[observations.length - 1];\\n }\\n\\n function metadata()\\n external\\n view\\n returns (\\n uint256 dec0,\\n uint256 dec1,\\n uint256 r0,\\n uint256 r1,\\n bool st,\\n address t0,\\n address t1\\n )\\n {\\n return (\\n decimals0,\\n decimals1,\\n reserve0,\\n reserve1,\\n stable,\\n token0,\\n token1\\n );\\n }\\n\\n function tokens() external view returns (address, address) {\\n return (token0, token1);\\n }\\n\\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\\n _updateFor(msg.sender);\\n\\n claimed0 = claimable0[msg.sender];\\n claimed1 = claimable1[msg.sender];\\n\\n if (claimed0 > 0 || claimed1 > 0) {\\n claimable0[msg.sender] = 0;\\n claimable1[msg.sender] = 0;\\n\\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\\n\\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n // Accrue fees on token0\\n function _update0(uint256 amount) internal {\\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index0 += _ratio;\\n }\\n emit Fees(msg.sender, amount, 0);\\n }\\n\\n // Accrue fees on token1\\n function _update1(uint256 amount) internal {\\n _safeTransfer(token1, fees, amount);\\n uint256 _ratio = (amount * 1e18) / totalSupply;\\n if (_ratio > 0) {\\n index1 += _ratio;\\n }\\n emit Fees(msg.sender, 0, amount);\\n }\\n\\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\\n // Fees are segregated from core funds, so fees can never put liquidity at risk\\n function _updateFor(address recipient) internal {\\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\\n if (_supplied > 0) {\\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\\n uint256 _supplyIndex1 = supplyIndex1[recipient];\\n uint256 _index0 = index0; // get global index0 for accumulated fees\\n uint256 _index1 = index1;\\n supplyIndex0[recipient] = _index0; // update user current position to global position\\n supplyIndex1[recipient] = _index1;\\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\\n uint256 _delta1 = _index1 - _supplyIndex1;\\n if (_delta0 > 0) {\\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\\n claimable0[recipient] += _share;\\n }\\n if (_delta1 > 0) {\\n uint256 _share = (_supplied * _delta1) / 1e18;\\n claimable1[recipient] += _share;\\n }\\n } else {\\n supplyIndex0[recipient] = index0; // new users are set to the default global state\\n supplyIndex1[recipient] = index1;\\n }\\n }\\n\\n function getReserves()\\n public\\n view\\n returns (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n )\\n {\\n _reserve0 = reserve0;\\n _reserve1 = reserve1;\\n _blockTimestampLast = blockTimestampLast;\\n }\\n\\n // update reserves and, on the first call per block, price accumulators\\n function _update(\\n uint256 balance0,\\n uint256 balance1,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal {\\n uint256 blockTimestamp = block.timestamp;\\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\\n reserve0CumulativeLast += _reserve0 * timeElapsed;\\n reserve1CumulativeLast += _reserve1 * timeElapsed;\\n }\\n\\n Observation memory _point = lastObservation();\\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\\n if (timeElapsed > periodSize) {\\n observations.push(\\n Observation(\\n blockTimestamp,\\n reserve0CumulativeLast,\\n reserve1CumulativeLast\\n )\\n );\\n }\\n reserve0 = balance0;\\n reserve1 = balance1;\\n blockTimestampLast = blockTimestamp;\\n emit Sync(reserve0, reserve1);\\n }\\n\\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\\n function currentCumulativePrices()\\n public\\n view\\n returns (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n uint256 blockTimestamp\\n )\\n {\\n blockTimestamp = block.timestamp;\\n reserve0Cumulative = reserve0CumulativeLast;\\n reserve1Cumulative = reserve1CumulativeLast;\\n\\n // if time has elapsed since the last update on the pair, mock the accumulated price values\\n (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n ) = getReserves();\\n if (_blockTimestampLast != blockTimestamp) {\\n // subtraction overflow is desired\\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\\n reserve0Cumulative += _reserve0 * timeElapsed;\\n reserve1Cumulative += _reserve1 * timeElapsed;\\n }\\n }\\n\\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\\n function current(address tokenIn, uint256 amountIn)\\n external\\n view\\n returns (uint256 amountOut)\\n {\\n Observation memory _observation = lastObservation();\\n (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n\\n ) = currentCumulativePrices();\\n if (block.timestamp == _observation.timestamp) {\\n _observation = observations[observations.length - 2];\\n }\\n\\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\\n uint256 _reserve0 = (reserve0Cumulative -\\n _observation.reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (reserve1Cumulative -\\n _observation.reserve1Cumulative) / timeElapsed;\\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n // as per `current`, however allows user configured granularity, up to the full window size\\n function quote(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 granularity\\n ) external view returns (uint256 amountOut) {\\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\\n uint256 priceAverageCumulative;\\n for (uint256 i = 0; i < _prices.length; i++) {\\n priceAverageCumulative += _prices[i];\\n }\\n return priceAverageCumulative / granularity;\\n }\\n\\n // returns a memory set of twap prices\\n function prices(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points\\n ) external view returns (uint256[] memory) {\\n return sample(tokenIn, amountIn, points, 1);\\n }\\n\\n function sample(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points,\\n uint256 window\\n ) public view returns (uint256[] memory) {\\n uint256[] memory _prices = new uint256[](points);\\n\\n uint256 length = observations.length - 1;\\n uint256 i = length - (points * window);\\n uint256 nextIndex = 0;\\n uint256 index = 0;\\n\\n for (; i < length; i += window) {\\n nextIndex = i + window;\\n uint256 timeElapsed = observations[nextIndex].timestamp -\\n observations[i].timestamp;\\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\\n observations[i].reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\\n observations[i].reserve1Cumulative) / timeElapsed;\\n _prices[index] = _getAmountOut(\\n amountIn,\\n tokenIn,\\n _reserve0,\\n _reserve1\\n );\\n // index < length; length cannot overflow\\n unchecked {\\n index = index + 1;\\n }\\n }\\n return _prices;\\n }\\n\\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\\n // standard uniswap v2 implementation\\n function mint(address to) external lock returns (uint256 liquidity) {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\\n uint256 _amount0 = _balance0 - _reserve0;\\n uint256 _amount1 = _balance1 - _reserve1;\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n if (_totalSupply == 0) {\\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\\n } else {\\n liquidity = MathDunks.min(\\n (_amount0 * _totalSupply) / _reserve0,\\n (_amount1 * _totalSupply) / _reserve1\\n );\\n }\\n require(liquidity > 0, \\\"ILM\\\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\\n _mint(to, liquidity);\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Mint(msg.sender, _amount0, _amount1);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n // standard uniswap v2 implementation\\n function burn(address to)\\n external\\n lock\\n returns (uint256 amount0, uint256 amount1)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n (address _token0, address _token1) = (token0, token1);\\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\\n uint256 _liquidity = balanceOf[address(this)];\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\\n require(amount0 > 0 && amount1 > 0, \\\"ILB\\\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\\n _burn(address(this), _liquidity);\\n _safeTransfer(_token0, to, amount0);\\n _safeTransfer(_token1, to, amount1);\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Burn(msg.sender, amount0, amount1, to);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n function swap(\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address to,\\n bytes calldata data\\n ) external lock {\\n require(!PairFactory(factory).isPaused());\\n require(amount0Out > 0 || amount1Out > 0, \\\"IOA\\\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \\\"IL\\\"); // Pair: INSUFFICIENT_LIQUIDITY\\n\\n uint256 _balance0;\\n uint256 _balance1;\\n {\\n // scope for _token{0,1}, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n require(to != _token0 && to != _token1, \\\"IT\\\"); // Pair: INVALID_TO\\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\\n if (data.length > 0)\\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n }\\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\\n ? _balance0 - (_reserve0 - amount0Out)\\n : 0;\\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\\n ? _balance1 - (_reserve1 - amount1Out)\\n : 0;\\n require(amount0In > 0 || amount1In > 0, \\\"IIA\\\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\\n {\\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n if (amount0In > 0)\\n _update0(\\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token0 and move them out of pool\\n if (amount1In > 0)\\n _update1(\\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token1 and move them out of pool\\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \\\"K\\\"); // Pair: K\\n }\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\\n }\\n\\n // force balances to match reserves\\n function skim(address to) external lock {\\n (address _token0, address _token1) = (token0, token1);\\n _safeTransfer(\\n _token0,\\n to,\\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\\n );\\n _safeTransfer(\\n _token1,\\n to,\\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\\n );\\n }\\n\\n // force reserves to match balances\\n function sync() external lock {\\n _update(\\n IERC20(token0).balanceOf(address(this)),\\n IERC20(token1).balanceOf(address(this)),\\n reserve0,\\n reserve1\\n );\\n }\\n\\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\\n 1e18 +\\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\\n 1e18;\\n }\\n\\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (3 * x0 * ((y * y) / 1e18)) /\\n 1e18 +\\n ((((x0 * x0) / 1e18) * x0) / 1e18);\\n }\\n\\n function _get_y(\\n uint256 x0,\\n uint256 xy,\\n uint256 y\\n ) internal pure returns (uint256) {\\n for (uint256 i = 0; i < 255; i++) {\\n uint256 y_prev = y;\\n uint256 k = _f(x0, y);\\n if (k < xy) {\\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\\n y = y + dy;\\n } else {\\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getAmountOut(uint256 amountIn, address tokenIn)\\n external\\n view\\n returns (uint256)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n function _getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal view returns (uint256) {\\n if (stable) {\\n uint256 xy = _k(_reserve0, _reserve1);\\n _reserve0 = (_reserve0 * 1e18) / decimals0;\\n _reserve1 = (_reserve1 * 1e18) / decimals1;\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0\\n ? (amountIn * 1e18) / decimals0\\n : (amountIn * 1e18) / decimals1;\\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\\n } else {\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n return (amountIn * reserveB) / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\\n if (stable) {\\n uint256 _x = (x * 1e18) / decimals0;\\n uint256 _y = (y * 1e18) / decimals1;\\n uint256 _a = (_x * _y) / 1e18;\\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return (_a * _b) / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n\\n function _mint(address dst, uint256 amount) internal {\\n _updateFor(dst); // balances must be updated on mint/burn/transfer\\n totalSupply += amount;\\n balanceOf[dst] += amount;\\n emit Transfer(address(0), dst, amount);\\n }\\n\\n function _burn(address dst, uint256 amount) internal {\\n _updateFor(dst);\\n totalSupply -= amount;\\n balanceOf[dst] -= amount;\\n emit Transfer(dst, address(0), amount);\\n }\\n\\n function approve(address spender, uint256 amount) external returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external {\\n require(deadline >= block.timestamp, \\\"Pair: EXPIRED\\\");\\n DOMAIN_SEPARATOR = keccak256(\\n abi.encode(\\n keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n ),\\n keccak256(bytes(name)),\\n keccak256(bytes(\\\"1\\\")),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR,\\n keccak256(\\n abi.encode(\\n PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n );\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n require(\\n recoveredAddress != address(0) && recoveredAddress == owner,\\n \\\"Pair: INVALID_SIGNATURE\\\"\\n );\\n allowance[owner][spender] = value;\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function transfer(address dst, uint256 amount) external returns (bool) {\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 amount\\n ) external returns (bool) {\\n address spender = msg.sender;\\n uint256 spenderAllowance = allowance[src][spender];\\n\\n if (spender != src && spenderAllowance != type(uint256).max) {\\n uint256 newAllowance = spenderAllowance - amount;\\n allowance[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n function _transferTokens(\\n address src,\\n address dst,\\n uint256 amount\\n ) internal {\\n _updateFor(src); // update fee position for src\\n _updateFor(dst); // update fee position for dst\\n\\n balanceOf[src] -= amount;\\n balanceOf[dst] += amount;\\n\\n emit Transfer(src, dst, amount);\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x4f508747645f4480e0b0f23d952fa9b82af1d9bc60b15b8cd1f542ee136043d1\",\"license\":\"MIT\"},\"contracts/PairFees.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IERC20.sol';\\n\\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\\ncontract PairFees {\\n\\n address internal immutable pair; // The pair it is bonded to\\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\\n\\n constructor(address _token0, address _token1) {\\n pair = msg.sender;\\n token0 = _token0;\\n token1 = _token1;\\n }\\n\\n function _safeTransfer(address token,address to,uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n // Allow the pair to transfer fees to users\\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\\n require(msg.sender == pair);\\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\\n }\\n\\n}\\n\",\"keccak256\":\"0xb772e192bab353f8642e89a95ef4ef0255d1caef08444101d7fe34469c1000ca\",\"license\":\"MIT\"},\"contracts/factories/PairFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/Pair.sol';\\n\\ncontract PairFactory is IPairFactory {\\n\\n bool public isPaused;\\n address public pauser;\\n address public pendingPauser;\\n\\n uint256 public stableFee;\\n uint256 public volatileFee;\\n uint256 public constant MAX_FEE = 5; // 0.05%\\n address public feeManager;\\n address public pendingFeeManager;\\n\\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\\n address[] public allPairs;\\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\\n\\n address internal _temp0;\\n address internal _temp1;\\n bool internal _temp;\\n\\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\\n\\n constructor() {\\n pauser = msg.sender;\\n isPaused = false;\\n feeManager = msg.sender;\\n stableFee = 2; // 0.02%\\n volatileFee = 2;\\n }\\n\\n function allPairsLength() external view returns (uint) {\\n return allPairs.length;\\n }\\n\\n function setPauser(address _pauser) external {\\n require(msg.sender == pauser);\\n pendingPauser = _pauser;\\n }\\n\\n function acceptPauser() external {\\n require(msg.sender == pendingPauser);\\n pauser = pendingPauser;\\n }\\n\\n function setPause(bool _state) external {\\n require(msg.sender == pauser);\\n isPaused = _state;\\n }\\n\\n function setFeeManager(address _feeManager) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n pendingFeeManager = _feeManager;\\n }\\n\\n function acceptFeeManager() external {\\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\\n feeManager = pendingFeeManager;\\n }\\n\\n function setFee(bool _stable, uint256 _fee) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n require(_fee <= MAX_FEE, 'fee too high');\\n require(_fee != 0, 'fee must be nonzero');\\n if (_stable) {\\n stableFee = _fee;\\n } else {\\n volatileFee = _fee;\\n }\\n }\\n\\n function getFee(bool _stable) public view returns(uint256) {\\n return _stable ? stableFee : volatileFee;\\n }\\n\\n function pairCodeHash() external pure returns (bytes32) {\\n return keccak256(type(Pair).creationCode);\\n }\\n\\n function getInitializable() external view returns (address, address, bool) {\\n return (_temp0, _temp1, _temp);\\n }\\n\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\\n (_temp0, _temp1, _temp) = (token0, token1, stable);\\n pair = address(new Pair{salt:salt}());\\n getPair[token0][token1][stable] = pair;\\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\\n allPairs.push(pair);\\n isPair[pair] = true;\\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\\n }\\n}\\n\",\"keccak256\":\"0x9b7984117a5a32188aa9ddf42b6cff024240579ab30f3776f7a201285d813e4f\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairCallee.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairCallee {\\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x3ac2de2c7a08bf59fd1006e4d108b247916369de15fbd048b72ca2b7814023ca\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50600080546001600160a81b03191633610100810260ff1916919091178255600480546001600160a01b0319169091179055600280805560035561519190819061005a90396000f3fe60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea2646970667358221220ff2c274dfd378ca71906641f0c7f06b25bb815c6c66eae6da4a0e24dbfb4a44664736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea2646970667358221220c10cd0d4059a01c44dcaa3e097beb08044a910ff60f84a22ed835f049e9cc68164736f6c634300080d0033a26469706673582212202a979b2730dcc4e33c282ae10ae03c7a51e1a33f9884927cdce3b275d33e651064736f6c634300080d0033", - "deployedBytecode": "0x60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea2646970667358221220ff2c274dfd378ca71906641f0c7f06b25bb815c6c66eae6da4a0e24dbfb4a44664736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea2646970667358221220c10cd0d4059a01c44dcaa3e097beb08044a910ff60f84a22ed835f049e9cc68164736f6c634300080d0033a26469706673582212202a979b2730dcc4e33c282ae10ae03c7a51e1a33f9884927cdce3b275d33e651064736f6c634300080d0033", + "numDeployments": 2, + "solcInputHash": "6e27611a2cedd773c4cc6e46935e6392", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"PairCreated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_FEE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allPairs\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"allPairsLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"createPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getInitializable\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"name\":\"getPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pairCodeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingFeeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingPauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_feeManager\",\"type\":\"address\"}],\"name\":\"setFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_state\",\"type\":\"bool\"}],\"name\":\"setPause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pauser\",\"type\":\"address\"}],\"name\":\"setPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stableFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"volatileFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/PairFactory.sol\":\"PairFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735303535373437363232\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Pair.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairCallee.sol\\\";\\nimport \\\"contracts/factories/PairFactory.sol\\\";\\nimport \\\"contracts/PairFees.sol\\\";\\n\\n// The base pair of pools, either stable or volatile\\ncontract Pair is IPair {\\n string public name;\\n string public symbol;\\n uint8 public constant decimals = 18;\\n\\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\\n bool public immutable stable;\\n\\n uint256 public totalSupply = 0;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n mapping(address => uint256) public balanceOf;\\n\\n bytes32 internal DOMAIN_SEPARATOR;\\n // keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 internal constant PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n mapping(address => uint256) public nonces;\\n\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n\\n address public immutable token0;\\n address public immutable token1;\\n address public immutable fees;\\n address immutable factory;\\n\\n // Structure to capture time period obervations every 30 minutes, used for local oracles\\n struct Observation {\\n uint256 timestamp;\\n uint256 reserve0Cumulative;\\n uint256 reserve1Cumulative;\\n }\\n\\n // Capture oracle reading every 30 minutes\\n uint256 constant periodSize = 1800;\\n\\n Observation[] public observations;\\n\\n uint256 internal immutable decimals0;\\n uint256 internal immutable decimals1;\\n\\n uint256 public reserve0;\\n uint256 public reserve1;\\n uint256 public blockTimestampLast;\\n\\n uint256 public reserve0CumulativeLast;\\n uint256 public reserve1CumulativeLast;\\n\\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \\\"clean\\\"\\n // this further allows LP holders to easily claim fees for tokens they have/staked\\n uint256 public index0 = 0;\\n uint256 public index1 = 0;\\n\\n // position assigned to each LP to track their current index0 & index1 vs the global position\\n mapping(address => uint256) public supplyIndex0;\\n mapping(address => uint256) public supplyIndex1;\\n\\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\\n mapping(address => uint256) public claimable0;\\n mapping(address => uint256) public claimable1;\\n\\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\\n event Burn(\\n address indexed sender,\\n uint256 amount0,\\n uint256 amount1,\\n address indexed to\\n );\\n event Swap(\\n address indexed sender,\\n uint256 amount0In,\\n uint256 amount1In,\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address indexed to\\n );\\n event Sync(uint256 reserve0, uint256 reserve1);\\n event Claim(\\n address indexed sender,\\n address indexed recipient,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 amount\\n );\\n\\n constructor() {\\n factory = msg.sender;\\n (address _token0, address _token1, bool _stable) = PairFactory(\\n msg.sender\\n ).getInitializable();\\n (token0, token1, stable) = (_token0, _token1, _stable);\\n fees = address(new PairFees(_token0, _token1));\\n if (_stable) {\\n name = string(\\n abi.encodePacked(\\n \\\"StableV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"sAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n } else {\\n name = string(\\n abi.encodePacked(\\n \\\"VolatileV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"vAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n }\\n\\n decimals0 = 10**IERC20(_token0).decimals();\\n decimals1 = 10**IERC20(_token1).decimals();\\n\\n observations.push(Observation(block.timestamp, 0, 0));\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function observationLength() external view returns (uint256) {\\n return observations.length;\\n }\\n\\n function lastObservation() public view returns (Observation memory) {\\n return observations[observations.length - 1];\\n }\\n\\n function metadata()\\n external\\n view\\n returns (\\n uint256 dec0,\\n uint256 dec1,\\n uint256 r0,\\n uint256 r1,\\n bool st,\\n address t0,\\n address t1\\n )\\n {\\n return (\\n decimals0,\\n decimals1,\\n reserve0,\\n reserve1,\\n stable,\\n token0,\\n token1\\n );\\n }\\n\\n function tokens() external view returns (address, address) {\\n return (token0, token1);\\n }\\n\\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\\n _updateFor(msg.sender);\\n\\n claimed0 = claimable0[msg.sender];\\n claimed1 = claimable1[msg.sender];\\n\\n if (claimed0 > 0 || claimed1 > 0) {\\n claimable0[msg.sender] = 0;\\n claimable1[msg.sender] = 0;\\n\\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\\n\\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n // Accrue fees on token0\\n function _update0(uint256 amount) internal {\\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index0 += _ratio;\\n }\\n emit Fees(msg.sender, amount, 0);\\n }\\n\\n // Accrue fees on token1\\n function _update1(uint256 amount) internal {\\n _safeTransfer(token1, fees, amount);\\n uint256 _ratio = (amount * 1e18) / totalSupply;\\n if (_ratio > 0) {\\n index1 += _ratio;\\n }\\n emit Fees(msg.sender, 0, amount);\\n }\\n\\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\\n // Fees are segregated from core funds, so fees can never put liquidity at risk\\n function _updateFor(address recipient) internal {\\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\\n if (_supplied > 0) {\\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\\n uint256 _supplyIndex1 = supplyIndex1[recipient];\\n uint256 _index0 = index0; // get global index0 for accumulated fees\\n uint256 _index1 = index1;\\n supplyIndex0[recipient] = _index0; // update user current position to global position\\n supplyIndex1[recipient] = _index1;\\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\\n uint256 _delta1 = _index1 - _supplyIndex1;\\n if (_delta0 > 0) {\\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\\n claimable0[recipient] += _share;\\n }\\n if (_delta1 > 0) {\\n uint256 _share = (_supplied * _delta1) / 1e18;\\n claimable1[recipient] += _share;\\n }\\n } else {\\n supplyIndex0[recipient] = index0; // new users are set to the default global state\\n supplyIndex1[recipient] = index1;\\n }\\n }\\n\\n function getReserves()\\n public\\n view\\n returns (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n )\\n {\\n _reserve0 = reserve0;\\n _reserve1 = reserve1;\\n _blockTimestampLast = blockTimestampLast;\\n }\\n\\n // update reserves and, on the first call per block, price accumulators\\n function _update(\\n uint256 balance0,\\n uint256 balance1,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal {\\n uint256 blockTimestamp = block.timestamp;\\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\\n reserve0CumulativeLast += _reserve0 * timeElapsed;\\n reserve1CumulativeLast += _reserve1 * timeElapsed;\\n }\\n\\n Observation memory _point = lastObservation();\\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\\n if (timeElapsed > periodSize) {\\n observations.push(\\n Observation(\\n blockTimestamp,\\n reserve0CumulativeLast,\\n reserve1CumulativeLast\\n )\\n );\\n }\\n reserve0 = balance0;\\n reserve1 = balance1;\\n blockTimestampLast = blockTimestamp;\\n emit Sync(reserve0, reserve1);\\n }\\n\\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\\n function currentCumulativePrices()\\n public\\n view\\n returns (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n uint256 blockTimestamp\\n )\\n {\\n blockTimestamp = block.timestamp;\\n reserve0Cumulative = reserve0CumulativeLast;\\n reserve1Cumulative = reserve1CumulativeLast;\\n\\n // if time has elapsed since the last update on the pair, mock the accumulated price values\\n (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n ) = getReserves();\\n if (_blockTimestampLast != blockTimestamp) {\\n // subtraction overflow is desired\\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\\n reserve0Cumulative += _reserve0 * timeElapsed;\\n reserve1Cumulative += _reserve1 * timeElapsed;\\n }\\n }\\n\\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\\n function current(address tokenIn, uint256 amountIn)\\n external\\n view\\n returns (uint256 amountOut)\\n {\\n Observation memory _observation = lastObservation();\\n (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n\\n ) = currentCumulativePrices();\\n if (block.timestamp == _observation.timestamp) {\\n _observation = observations[observations.length - 2];\\n }\\n\\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\\n uint256 _reserve0 = (reserve0Cumulative -\\n _observation.reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (reserve1Cumulative -\\n _observation.reserve1Cumulative) / timeElapsed;\\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n // as per `current`, however allows user configured granularity, up to the full window size\\n function quote(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 granularity\\n ) external view returns (uint256 amountOut) {\\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\\n uint256 priceAverageCumulative;\\n for (uint256 i = 0; i < _prices.length; i++) {\\n priceAverageCumulative += _prices[i];\\n }\\n return priceAverageCumulative / granularity;\\n }\\n\\n // returns a memory set of twap prices\\n function prices(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points\\n ) external view returns (uint256[] memory) {\\n return sample(tokenIn, amountIn, points, 1);\\n }\\n\\n function sample(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points,\\n uint256 window\\n ) public view returns (uint256[] memory) {\\n uint256[] memory _prices = new uint256[](points);\\n\\n uint256 length = observations.length - 1;\\n uint256 i = length - (points * window);\\n uint256 nextIndex = 0;\\n uint256 index = 0;\\n\\n for (; i < length; i += window) {\\n nextIndex = i + window;\\n uint256 timeElapsed = observations[nextIndex].timestamp -\\n observations[i].timestamp;\\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\\n observations[i].reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\\n observations[i].reserve1Cumulative) / timeElapsed;\\n _prices[index] = _getAmountOut(\\n amountIn,\\n tokenIn,\\n _reserve0,\\n _reserve1\\n );\\n // index < length; length cannot overflow\\n unchecked {\\n index = index + 1;\\n }\\n }\\n return _prices;\\n }\\n\\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\\n // standard uniswap v2 implementation\\n function mint(address to) external lock returns (uint256 liquidity) {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\\n uint256 _amount0 = _balance0 - _reserve0;\\n uint256 _amount1 = _balance1 - _reserve1;\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n if (_totalSupply == 0) {\\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\\n } else {\\n liquidity = MathDunks.min(\\n (_amount0 * _totalSupply) / _reserve0,\\n (_amount1 * _totalSupply) / _reserve1\\n );\\n }\\n require(liquidity > 0, \\\"ILM\\\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\\n _mint(to, liquidity);\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Mint(msg.sender, _amount0, _amount1);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n // standard uniswap v2 implementation\\n function burn(address to)\\n external\\n lock\\n returns (uint256 amount0, uint256 amount1)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n (address _token0, address _token1) = (token0, token1);\\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\\n uint256 _liquidity = balanceOf[address(this)];\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\\n require(amount0 > 0 && amount1 > 0, \\\"ILB\\\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\\n _burn(address(this), _liquidity);\\n _safeTransfer(_token0, to, amount0);\\n _safeTransfer(_token1, to, amount1);\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Burn(msg.sender, amount0, amount1, to);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n function swap(\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address to,\\n bytes calldata data\\n ) external lock {\\n require(!PairFactory(factory).isPaused());\\n require(amount0Out > 0 || amount1Out > 0, \\\"IOA\\\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \\\"IL\\\"); // Pair: INSUFFICIENT_LIQUIDITY\\n\\n uint256 _balance0;\\n uint256 _balance1;\\n {\\n // scope for _token{0,1}, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n require(to != _token0 && to != _token1, \\\"IT\\\"); // Pair: INVALID_TO\\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\\n if (data.length > 0)\\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n }\\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\\n ? _balance0 - (_reserve0 - amount0Out)\\n : 0;\\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\\n ? _balance1 - (_reserve1 - amount1Out)\\n : 0;\\n require(amount0In > 0 || amount1In > 0, \\\"IIA\\\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\\n {\\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n if (amount0In > 0)\\n _update0(\\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token0 and move them out of pool\\n if (amount1In > 0)\\n _update1(\\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token1 and move them out of pool\\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \\\"K\\\"); // Pair: K\\n }\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\\n }\\n\\n // force balances to match reserves\\n function skim(address to) external lock {\\n (address _token0, address _token1) = (token0, token1);\\n _safeTransfer(\\n _token0,\\n to,\\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\\n );\\n _safeTransfer(\\n _token1,\\n to,\\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\\n );\\n }\\n\\n // force reserves to match balances\\n function sync() external lock {\\n _update(\\n IERC20(token0).balanceOf(address(this)),\\n IERC20(token1).balanceOf(address(this)),\\n reserve0,\\n reserve1\\n );\\n }\\n\\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\\n 1e18 +\\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\\n 1e18;\\n }\\n\\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (3 * x0 * ((y * y) / 1e18)) /\\n 1e18 +\\n ((((x0 * x0) / 1e18) * x0) / 1e18);\\n }\\n\\n function _get_y(\\n uint256 x0,\\n uint256 xy,\\n uint256 y\\n ) internal pure returns (uint256) {\\n for (uint256 i = 0; i < 255; i++) {\\n uint256 y_prev = y;\\n uint256 k = _f(x0, y);\\n if (k < xy) {\\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\\n y = y + dy;\\n } else {\\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getAmountOut(uint256 amountIn, address tokenIn)\\n external\\n view\\n returns (uint256)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n function _getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal view returns (uint256) {\\n if (stable) {\\n uint256 xy = _k(_reserve0, _reserve1);\\n _reserve0 = (_reserve0 * 1e18) / decimals0;\\n _reserve1 = (_reserve1 * 1e18) / decimals1;\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0\\n ? (amountIn * 1e18) / decimals0\\n : (amountIn * 1e18) / decimals1;\\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\\n } else {\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n return (amountIn * reserveB) / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\\n if (stable) {\\n uint256 _x = (x * 1e18) / decimals0;\\n uint256 _y = (y * 1e18) / decimals1;\\n uint256 _a = (_x * _y) / 1e18;\\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return (_a * _b) / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n\\n function _mint(address dst, uint256 amount) internal {\\n _updateFor(dst); // balances must be updated on mint/burn/transfer\\n totalSupply += amount;\\n balanceOf[dst] += amount;\\n emit Transfer(address(0), dst, amount);\\n }\\n\\n function _burn(address dst, uint256 amount) internal {\\n _updateFor(dst);\\n totalSupply -= amount;\\n balanceOf[dst] -= amount;\\n emit Transfer(dst, address(0), amount);\\n }\\n\\n function approve(address spender, uint256 amount) external returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external {\\n require(deadline >= block.timestamp, \\\"Pair: EXPIRED\\\");\\n DOMAIN_SEPARATOR = keccak256(\\n abi.encode(\\n keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n ),\\n keccak256(bytes(name)),\\n keccak256(bytes(\\\"1\\\")),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR,\\n keccak256(\\n abi.encode(\\n PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n );\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n require(\\n recoveredAddress != address(0) && recoveredAddress == owner,\\n \\\"Pair: INVALID_SIGNATURE\\\"\\n );\\n allowance[owner][spender] = value;\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function transfer(address dst, uint256 amount) external returns (bool) {\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 amount\\n ) external returns (bool) {\\n address spender = msg.sender;\\n uint256 spenderAllowance = allowance[src][spender];\\n\\n if (spender != src && spenderAllowance != type(uint256).max) {\\n uint256 newAllowance = spenderAllowance - amount;\\n allowance[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n function _transferTokens(\\n address src,\\n address dst,\\n uint256 amount\\n ) internal {\\n _updateFor(src); // update fee position for src\\n _updateFor(dst); // update fee position for dst\\n\\n balanceOf[src] -= amount;\\n balanceOf[dst] += amount;\\n\\n emit Transfer(src, dst, amount);\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x4f508747645f4480e0b0f23d952fa9b82af1d9bc60b15b8cd1f542ee136043d1\",\"license\":\"MIT\"},\"contracts/PairFees.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IERC20.sol';\\n\\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\\ncontract PairFees {\\n\\n address internal immutable pair; // The pair it is bonded to\\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\\n\\n constructor(address _token0, address _token1) {\\n pair = msg.sender;\\n token0 = _token0;\\n token1 = _token1;\\n }\\n\\n function _safeTransfer(address token,address to,uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n // Allow the pair to transfer fees to users\\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\\n require(msg.sender == pair);\\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\\n }\\n\\n}\\n\",\"keccak256\":\"0xb772e192bab353f8642e89a95ef4ef0255d1caef08444101d7fe34469c1000ca\",\"license\":\"MIT\"},\"contracts/factories/PairFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/Pair.sol';\\n\\ncontract PairFactory is IPairFactory {\\n\\n bool public isPaused;\\n address public pauser;\\n address public pendingPauser;\\n\\n uint256 public stableFee;\\n uint256 public volatileFee;\\n uint256 public constant MAX_FEE = 5; // 0.05%\\n address public feeManager;\\n address public pendingFeeManager;\\n\\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\\n address[] public allPairs;\\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\\n\\n address internal _temp0;\\n address internal _temp1;\\n bool internal _temp;\\n\\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\\n\\n constructor() {\\n pauser = msg.sender;\\n isPaused = false;\\n feeManager = msg.sender;\\n stableFee = 2; // 0.02%\\n volatileFee = 2;\\n }\\n\\n function allPairsLength() external view returns (uint) {\\n return allPairs.length;\\n }\\n\\n function setPauser(address _pauser) external {\\n require(msg.sender == pauser);\\n pendingPauser = _pauser;\\n }\\n\\n function acceptPauser() external {\\n require(msg.sender == pendingPauser);\\n pauser = pendingPauser;\\n }\\n\\n function setPause(bool _state) external {\\n require(msg.sender == pauser);\\n isPaused = _state;\\n }\\n\\n function setFeeManager(address _feeManager) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n pendingFeeManager = _feeManager;\\n }\\n\\n function acceptFeeManager() external {\\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\\n feeManager = pendingFeeManager;\\n }\\n\\n function setFee(bool _stable, uint256 _fee) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n require(_fee <= MAX_FEE, 'fee too high');\\n require(_fee != 0, 'fee must be nonzero');\\n if (_stable) {\\n stableFee = _fee;\\n } else {\\n volatileFee = _fee;\\n }\\n }\\n\\n function getFee(bool _stable) public view returns(uint256) {\\n return _stable ? stableFee : volatileFee;\\n }\\n\\n function pairCodeHash() external pure returns (bytes32) {\\n return keccak256(type(Pair).creationCode);\\n }\\n\\n function getInitializable() external view returns (address, address, bool) {\\n return (_temp0, _temp1, _temp);\\n }\\n\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\\n (_temp0, _temp1, _temp) = (token0, token1, stable);\\n pair = address(new Pair{salt:salt}());\\n getPair[token0][token1][stable] = pair;\\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\\n allPairs.push(pair);\\n isPair[pair] = true;\\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\\n }\\n}\\n\",\"keccak256\":\"0x9b7984117a5a32188aa9ddf42b6cff024240579ab30f3776f7a201285d813e4f\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairCallee.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairCallee {\\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x3ac2de2c7a08bf59fd1006e4d108b247916369de15fbd048b72ca2b7814023ca\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50600080546001600160a81b03191633610100810260ff1916919091178255600480546001600160a01b0319169091179055600280805560035561519190819061005a90396000f3fe60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea26469706673582212206fe7268254696ba4534c6428b25f814973de660c1ad3a49fc1bc1250213a96ea64736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea2646970667358221220341a44e06960999bae8e3c68806cc97f49dd4ae9f2e0225b58f17d6d9005e49664736f6c634300080d0033a264697066735822122095f9a5a77b7973e7cb734700aa73e082aab99ac0703561075ea6b9fed73a640664736f6c634300080d0033", + "deployedBytecode": "0x60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea26469706673582212206fe7268254696ba4534c6428b25f814973de660c1ad3a49fc1bc1250213a96ea64736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea2646970667358221220341a44e06960999bae8e3c68806cc97f49dd4ae9f2e0225b58f17d6d9005e49664736f6c634300080d0033a264697066735822122095f9a5a77b7973e7cb734700aa73e082aab99ac0703561075ea6b9fed73a640664736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, @@ -418,7 +418,7 @@ "storageLayout": { "storage": [ { - "astId": 21428, + "astId": 21430, "contract": "contracts/factories/PairFactory.sol:PairFactory", "label": "isPaused", "offset": 0, @@ -426,7 +426,7 @@ "type": "t_bool" }, { - "astId": 21430, + "astId": 21432, "contract": "contracts/factories/PairFactory.sol:PairFactory", "label": "pauser", "offset": 1, @@ -434,7 +434,7 @@ "type": "t_address" }, { - "astId": 21432, + "astId": 21434, "contract": "contracts/factories/PairFactory.sol:PairFactory", "label": "pendingPauser", "offset": 0, @@ -442,7 +442,7 @@ "type": "t_address" }, { - "astId": 21434, + "astId": 21436, "contract": "contracts/factories/PairFactory.sol:PairFactory", "label": "stableFee", "offset": 0, @@ -450,7 +450,7 @@ "type": "t_uint256" }, { - "astId": 21436, + "astId": 21438, "contract": "contracts/factories/PairFactory.sol:PairFactory", "label": "volatileFee", "offset": 0, @@ -458,7 +458,7 @@ "type": "t_uint256" }, { - "astId": 21441, + "astId": 21443, "contract": "contracts/factories/PairFactory.sol:PairFactory", "label": "feeManager", "offset": 0, @@ -466,7 +466,7 @@ "type": "t_address" }, { - "astId": 21443, + "astId": 21445, "contract": "contracts/factories/PairFactory.sol:PairFactory", "label": "pendingFeeManager", "offset": 0, @@ -474,7 +474,7 @@ "type": "t_address" }, { - "astId": 21451, + "astId": 21453, "contract": "contracts/factories/PairFactory.sol:PairFactory", "label": "getPair", "offset": 0, @@ -482,7 +482,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_bool,t_address)))" }, { - "astId": 21454, + "astId": 21456, "contract": "contracts/factories/PairFactory.sol:PairFactory", "label": "allPairs", "offset": 0, @@ -490,7 +490,7 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 21458, + "astId": 21460, "contract": "contracts/factories/PairFactory.sol:PairFactory", "label": "isPair", "offset": 0, @@ -498,7 +498,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 21460, + "astId": 21462, "contract": "contracts/factories/PairFactory.sol:PairFactory", "label": "_temp0", "offset": 0, @@ -506,7 +506,7 @@ "type": "t_address" }, { - "astId": 21462, + "astId": 21464, "contract": "contracts/factories/PairFactory.sol:PairFactory", "label": "_temp1", "offset": 0, @@ -514,7 +514,7 @@ "type": "t_address" }, { - "astId": 21464, + "astId": 21466, "contract": "contracts/factories/PairFactory.sol:PairFactory", "label": "_temp", "offset": 20, diff --git a/deployments/arbitrumGoerli/RedemptionReceiver.json b/deployments/arbitrumGoerli/RedemptionReceiver.json index 87339e66..4397a867 100644 --- a/deployments/arbitrumGoerli/RedemptionReceiver.json +++ b/deployments/arbitrumGoerli/RedemptionReceiver.json @@ -1,5 +1,5 @@ { - "address": "0x130809dD1E22C2630E606EE8d59434B6C94a3F1C", + "address": "0x11aa8e6D9e2802d3744F678dE55e22002241B474", "abi": [ { "inputs": [ @@ -323,33 +323,33 @@ "type": "function" } ], - "transactionHash": "0x845732d316e017defcae74f4b923b36723d9082b3532733207fc4840e1c673e0", + "transactionHash": "0xd6fc16aa32f0149f52371821c9a733f078915a16ef7d70275c2e232257052409", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x130809dD1E22C2630E606EE8d59434B6C94a3F1C", + "contractAddress": "0x11aa8e6D9e2802d3744F678dE55e22002241B474", "transactionIndex": 1, "gasUsed": "841985", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xe54313be00af1fa1492404c3ce9b17929fe88ee1177aa9ccd3faf679f87cd58a", - "transactionHash": "0x845732d316e017defcae74f4b923b36723d9082b3532733207fc4840e1c673e0", + "blockHash": "0x034a599adf8724e3312da4117baf7827c0f57875195fbf9b19dd06ea9952939d", + "transactionHash": "0xd6fc16aa32f0149f52371821c9a733f078915a16ef7d70275c2e232257052409", "logs": [], - "blockNumber": 6069460, + "blockNumber": 6188482, "cumulativeGasUsed": "841985", "status": 1, "byzantium": true }, "args": [ "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8", - "0x4E13914872BFf7e58f3E231b2687fDd084014999", + "0x49E4eA802DdF4CAF7C699782a80DeefdC03Dcb4B", 10012, "0x3c2269811836af69497E5F486A85D7316753cf62" ], - "numDeployments": 1, - "solcInputHash": "d2a2160297444b93438826228d1e185d", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_usdc\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_flow\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"_fantomChainId\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"_endpoint\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fantomSender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableUSDC\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableFLOW\",\"type\":\"uint256\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ELIGIBLE_WEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FLOW\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"USDC\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"toAddressBytes\",\"type\":\"bytes\"}],\"name\":\"addressFromPackedBytes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimLeftovers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endpoint\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomChainId\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_fantomSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableFLOW\",\"type\":\"uint256\"}],\"name\":\"initializeReceiverWith\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"leftoverFLOW\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"srcChainId\",\"type\":\"uint16\"},{\"internalType\":\"bytes\",\"name\":\"srcAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"lzReceive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountWEVE\",\"type\":\"uint256\"}],\"name\":\"previewRedeem\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"shareOfUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shareOfFLOW\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableFLOW\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableUSDC\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemedWEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process This contract is responsible for receiving the LZ message and distributing USDC + FLOW\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/RedemptionReceiver.sol\":\"RedemptionReceiver\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/redeem/RedemptionReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\\\";\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\n\\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\\n/// This contract is responsible for receiving the LZ message and distributing USDC + FLOW\\ncontract RedemptionReceiver is ILayerZeroReceiver {\\n IERC20 public immutable USDC;\\n IFlow public immutable FLOW;\\n\\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\\n address public immutable endpoint;\\n\\n address public team;\\n uint256 public immutable deployed;\\n\\n address public fantomSender;\\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\\n uint256 public redeemedWEVE;\\n uint256 public redeemableUSDC;\\n uint256 public redeemableFLOW;\\n uint256 public leftoverFLOW;\\n\\n constructor(\\n address _usdc,\\n address _flow,\\n uint16 _fantomChainId,\\n address _endpoint\\n ) {\\n require(_fantomChainId == 12 || _fantomChainId == 10012, \\\"CHAIN_ID_NOT_FTM\\\");\\n\\n USDC = IERC20(_usdc);\\n FLOW = IFlow(_flow);\\n\\n fantomChainId = _fantomChainId;\\n endpoint = _endpoint;\\n\\n team = msg.sender;\\n deployed = block.timestamp;\\n }\\n\\n modifier onlyTeam() {\\n require(msg.sender == team, \\\"ONLY_TEAM\\\");\\n _;\\n }\\n\\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableFLOW);\\n\\n function initializeReceiverWith(\\n address _fantomSender,\\n uint256 _redeemableUSDC,\\n uint256 _redeemableFLOW\\n ) external onlyTeam {\\n require(fantomSender == address(0), \\\"ALREADY_INITIALIZED\\\");\\n require(\\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n fantomSender = _fantomSender;\\n redeemableUSDC = _redeemableUSDC;\\n redeemableFLOW = _redeemableFLOW;\\n leftoverFLOW = _redeemableFLOW;\\n\\n emit Initialized(fantomSender, redeemableUSDC, redeemableFLOW);\\n }\\n\\n function setTeam(address _team) external onlyTeam {\\n team = _team;\\n }\\n\\n function previewRedeem(uint256 amountWEVE)\\n public\\n view\\n returns (uint256 shareOfUSDC, uint256 shareOfFLOW)\\n {\\n // pro rata USDC\\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\\n // pro rata FLOW\\n shareOfFLOW = (amountWEVE * redeemableFLOW) / ELIGIBLE_WEVE;\\n }\\n\\n function lzReceive(\\n uint16 srcChainId,\\n bytes memory srcAddress,\\n uint64,\\n bytes memory payload\\n ) external override {\\n require(fantomSender != address(0), \\\"NOT_INITIALIZED\\\");\\n require(\\n msg.sender == endpoint &&\\n srcChainId == fantomChainId &&\\n addressFromPackedBytes(srcAddress) == fantomSender,\\n \\\"UNAUTHORIZED_CALLER\\\"\\n );\\n\\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\\n payload,\\n (address, uint256)\\n );\\n\\n require(\\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\\n \\\"cannot redeem more than eligible\\\"\\n );\\n (uint256 shareOfUSDC, uint256 shareOfFLOW) = previewRedeem(amountWEVE);\\n\\n require(\\n USDC.transfer(redemptionAddress, shareOfUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n leftoverFLOW -= shareOfFLOW; // this will revert if underflows\\n require(\\n FLOW.claim(redemptionAddress, shareOfFLOW),\\n \\\"CLAIM_FAILED\\\"\\n );\\n }\\n\\n function addressFromPackedBytes(bytes memory toAddressBytes)\\n public\\n pure\\n returns (address toAddress)\\n {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n toAddress := mload(add(toAddressBytes, 20))\\n }\\n }\\n\\n function claimLeftovers() external onlyTeam {\\n require(block.timestamp >= deployed + 30 days, \\\"LEFTOVERS_NOT_CLAIMABLE\\\");\\n require(\\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n }\\n}\\n\",\"keccak256\":\"0x582d45a8db937fe4a965056bcbe7d1427f71be66e8071bb1cae76d5f36c6c314\",\"license\":\"MIT\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\nimport \\\"./ILayerZeroUserApplicationConfig.sol\\\";\\n\\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\\n // @param _dstChainId - the destination chain identifier\\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\\n // @param _payload - a custom bytes payload to send to the destination contract\\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\\n\\n // @notice used by the messaging library to publish verified payload\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source contract (as bytes) at the source chain\\n // @param _dstAddress - the address on destination chain\\n // @param _nonce - the unbound message ordering nonce\\n // @param _gasLimit - the gas limit for external contract execution\\n // @param _payload - verified payload to send to the destination contract\\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\\n\\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\\n\\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\\n // @param _srcAddress - the source chain contract address\\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\\n\\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\\n // @param _dstChainId - the destination chain identifier\\n // @param _userApplication - the user app address on this EVM chain\\n // @param _payload - the custom message to send over LayerZero\\n // @param _payInZRO - if false, user app pays the protocol fee in native token\\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\\n\\n // @notice get this Endpoint's immutable source identifier\\n function getChainId() external view returns (uint16);\\n\\n // @notice the interface to retry failed message on this Endpoint destination\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n // @param _payload - the payload to be retried\\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\\n\\n // @notice query if any STORED payload (message blocking) at the endpoint.\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\\n\\n // @notice query if the _libraryAddress is valid for sending msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getSendLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the _libraryAddress is valid for receiving msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the non-reentrancy guard for send() is on\\n // @return true if the guard is on. false otherwise\\n function isSendingPayload() external view returns (bool);\\n\\n // @notice query if the non-reentrancy guard for receive() is on\\n // @return true if the guard is on. false otherwise\\n function isReceivingPayload() external view returns (bool);\\n\\n // @notice get the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _userApplication - the contract address of the user application\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\\n\\n // @notice get the send() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getSendVersion(address _userApplication) external view returns (uint16);\\n\\n // @notice get the lzReceive() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getReceiveVersion(address _userApplication) external view returns (uint16);\\n}\\n\",\"keccak256\":\"0xbc2e0022d4d53d136830aa90037be2ed7a0966f5fd1b409bf5986185984c495f\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroReceiver {\\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\\n // @param _srcChainId - the source endpoint identifier\\n // @param _srcAddress - the source sending contract address from the source chain\\n // @param _nonce - the ordered message nonce\\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\\n}\\n\",\"keccak256\":\"0xd1617e455d90d41556bba636bc440627d301ec481de16ff04fbd520333c3c6f3\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroUserApplicationConfig {\\n // @notice set the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n // @param _config - configuration in the bytes. can encode arbitrary content.\\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\\n\\n // @notice set the send() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setSendVersion(uint16 _version) external;\\n\\n // @notice set the lzReceive() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setReceiveVersion(uint16 _version) external;\\n\\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\\n // @param _srcChainId - the chainId of the source chain\\n // @param _srcAddress - the contract address of the source contract at the source chain\\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\\n}\\n\",\"keccak256\":\"0xdc7e072cf3064081a8edf4a286ca43ddecc24330f2923d96f416f9d3f6538447\",\"license\":\"BUSL-1.1\"}},\"version\":1}", - "bytecode": "0x61012060405234801561001157600080fd5b50604051610f81380380610f81833981016040819052610030916100e2565b8161ffff16600c148061004857508161ffff1661271c145b61008b5760405162461bcd60e51b815260206004820152601060248201526f434841494e5f49445f4e4f545f46544d60801b604482015260640160405180910390fd5b6001600160a01b0393841660805291831660a05261ffff1660c0521660e052600080546001600160a01b03191633179055426101005261013f565b80516001600160a01b03811681146100dd57600080fd5b919050565b600080600080608085870312156100f857600080fd5b610101856100c6565b935061010f602086016100c6565b9250604085015161ffff8116811461012657600080fd5b9150610134606086016100c6565b905092959194509250565b60805160a05160c05160e05161010051610dcd6101b4600039600081816102d601526108c00152600081816101d30152610352015260008181610263015261037c015260008181610163015261059f01526000818161023c015281816104d70152818161078e015261094c0152610dcd6000f3fe608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a408bb4c11610071578063a408bb4c14610298578063aaa8f2ef146102a0578063b8ea6281146102b3578063caccb667146102c8578063f905c15a146102d157600080fd5b80636bfd23a71461021b57806385f2aef21461022457806389a3027114610237578063997a03b71461025e57600080fd5b806347db1a6a116100e957806347db1a6a1461019d5780634cdad506146101a65780635e280f11146101ce57806363b4eb8d146101f557806368ecc6bc1461020857600080fd5b80621d35671461011a578063095cf5c61461012f5780631308db08146101425780633189097b1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60055481565b6040519081526020015b60405180910390f35b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b61014b60035481565b6101b96101b4366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b600154610185906001600160a01b031681565b61012d610216366004610be5565b6106f3565b61014b60025481565b600054610185906001600160a01b031681565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6102857f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101856102c1366004610c1a565b6014015190565b61014b60045481565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea2646970667358221220a9aafa04aaa7657df3b5764d57c3e104f4a4dc11cc4b9091c82503073c559cb264736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a408bb4c11610071578063a408bb4c14610298578063aaa8f2ef146102a0578063b8ea6281146102b3578063caccb667146102c8578063f905c15a146102d157600080fd5b80636bfd23a71461021b57806385f2aef21461022457806389a3027114610237578063997a03b71461025e57600080fd5b806347db1a6a116100e957806347db1a6a1461019d5780634cdad506146101a65780635e280f11146101ce57806363b4eb8d146101f557806368ecc6bc1461020857600080fd5b80621d35671461011a578063095cf5c61461012f5780631308db08146101425780633189097b1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60055481565b6040519081526020015b60405180910390f35b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b61014b60035481565b6101b96101b4366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b600154610185906001600160a01b031681565b61012d610216366004610be5565b6106f3565b61014b60025481565b600054610185906001600160a01b031681565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6102857f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101856102c1366004610c1a565b6014015190565b61014b60045481565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea2646970667358221220a9aafa04aaa7657df3b5764d57c3e104f4a4dc11cc4b9091c82503073c559cb264736f6c634300080d0033", + "numDeployments": 2, + "solcInputHash": "6e27611a2cedd773c4cc6e46935e6392", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_usdc\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_flow\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"_fantomChainId\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"_endpoint\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fantomSender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableUSDC\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemableFLOW\",\"type\":\"uint256\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ELIGIBLE_WEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FLOW\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"USDC\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"toAddressBytes\",\"type\":\"bytes\"}],\"name\":\"addressFromPackedBytes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimLeftovers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endpoint\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomChainId\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fantomSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_fantomSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_redeemableFLOW\",\"type\":\"uint256\"}],\"name\":\"initializeReceiverWith\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"leftoverFLOW\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"srcChainId\",\"type\":\"uint16\"},{\"internalType\":\"bytes\",\"name\":\"srcAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"lzReceive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountWEVE\",\"type\":\"uint256\"}],\"name\":\"previewRedeem\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"shareOfUSDC\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shareOfFLOW\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableFLOW\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemableUSDC\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemedWEVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process This contract is responsible for receiving the LZ message and distributing USDC + FLOW\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/redeem/RedemptionReceiver.sol\":\"RedemptionReceiver\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735303535373437363232\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/redeem/RedemptionReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\\\";\\nimport \\\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\n\\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\\n/// This contract is responsible for receiving the LZ message and distributing USDC + FLOW\\ncontract RedemptionReceiver is ILayerZeroReceiver {\\n IERC20 public immutable USDC;\\n IFlow public immutable FLOW;\\n\\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\\n address public immutable endpoint;\\n\\n address public team;\\n uint256 public immutable deployed;\\n\\n address public fantomSender;\\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\\n uint256 public redeemedWEVE;\\n uint256 public redeemableUSDC;\\n uint256 public redeemableFLOW;\\n uint256 public leftoverFLOW;\\n\\n constructor(\\n address _usdc,\\n address _flow,\\n uint16 _fantomChainId,\\n address _endpoint\\n ) {\\n require(_fantomChainId == 12 || _fantomChainId == 10012, \\\"CHAIN_ID_NOT_FTM\\\");\\n\\n USDC = IERC20(_usdc);\\n FLOW = IFlow(_flow);\\n\\n fantomChainId = _fantomChainId;\\n endpoint = _endpoint;\\n\\n team = msg.sender;\\n deployed = block.timestamp;\\n }\\n\\n modifier onlyTeam() {\\n require(msg.sender == team, \\\"ONLY_TEAM\\\");\\n _;\\n }\\n\\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableFLOW);\\n\\n function initializeReceiverWith(\\n address _fantomSender,\\n uint256 _redeemableUSDC,\\n uint256 _redeemableFLOW\\n ) external onlyTeam {\\n require(fantomSender == address(0), \\\"ALREADY_INITIALIZED\\\");\\n require(\\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n fantomSender = _fantomSender;\\n redeemableUSDC = _redeemableUSDC;\\n redeemableFLOW = _redeemableFLOW;\\n leftoverFLOW = _redeemableFLOW;\\n\\n emit Initialized(fantomSender, redeemableUSDC, redeemableFLOW);\\n }\\n\\n function setTeam(address _team) external onlyTeam {\\n team = _team;\\n }\\n\\n function previewRedeem(uint256 amountWEVE)\\n public\\n view\\n returns (uint256 shareOfUSDC, uint256 shareOfFLOW)\\n {\\n // pro rata USDC\\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\\n // pro rata FLOW\\n shareOfFLOW = (amountWEVE * redeemableFLOW) / ELIGIBLE_WEVE;\\n }\\n\\n function lzReceive(\\n uint16 srcChainId,\\n bytes memory srcAddress,\\n uint64,\\n bytes memory payload\\n ) external override {\\n require(fantomSender != address(0), \\\"NOT_INITIALIZED\\\");\\n require(\\n msg.sender == endpoint &&\\n srcChainId == fantomChainId &&\\n addressFromPackedBytes(srcAddress) == fantomSender,\\n \\\"UNAUTHORIZED_CALLER\\\"\\n );\\n\\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\\n payload,\\n (address, uint256)\\n );\\n\\n require(\\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\\n \\\"cannot redeem more than eligible\\\"\\n );\\n (uint256 shareOfUSDC, uint256 shareOfFLOW) = previewRedeem(amountWEVE);\\n\\n require(\\n USDC.transfer(redemptionAddress, shareOfUSDC),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n\\n leftoverFLOW -= shareOfFLOW; // this will revert if underflows\\n require(\\n FLOW.claim(redemptionAddress, shareOfFLOW),\\n \\\"CLAIM_FAILED\\\"\\n );\\n }\\n\\n function addressFromPackedBytes(bytes memory toAddressBytes)\\n public\\n pure\\n returns (address toAddress)\\n {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n toAddress := mload(add(toAddressBytes, 20))\\n }\\n }\\n\\n function claimLeftovers() external onlyTeam {\\n require(block.timestamp >= deployed + 30 days, \\\"LEFTOVERS_NOT_CLAIMABLE\\\");\\n require(\\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\\n \\\"USDC_TRANSFER_FAILED\\\"\\n );\\n }\\n}\\n\",\"keccak256\":\"0x582d45a8db937fe4a965056bcbe7d1427f71be66e8071bb1cae76d5f36c6c314\",\"license\":\"MIT\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\nimport \\\"./ILayerZeroUserApplicationConfig.sol\\\";\\n\\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\\n // @param _dstChainId - the destination chain identifier\\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\\n // @param _payload - a custom bytes payload to send to the destination contract\\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\\n\\n // @notice used by the messaging library to publish verified payload\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source contract (as bytes) at the source chain\\n // @param _dstAddress - the address on destination chain\\n // @param _nonce - the unbound message ordering nonce\\n // @param _gasLimit - the gas limit for external contract execution\\n // @param _payload - verified payload to send to the destination contract\\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\\n\\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\\n\\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\\n // @param _srcAddress - the source chain contract address\\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\\n\\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\\n // @param _dstChainId - the destination chain identifier\\n // @param _userApplication - the user app address on this EVM chain\\n // @param _payload - the custom message to send over LayerZero\\n // @param _payInZRO - if false, user app pays the protocol fee in native token\\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\\n\\n // @notice get this Endpoint's immutable source identifier\\n function getChainId() external view returns (uint16);\\n\\n // @notice the interface to retry failed message on this Endpoint destination\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n // @param _payload - the payload to be retried\\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\\n\\n // @notice query if any STORED payload (message blocking) at the endpoint.\\n // @param _srcChainId - the source chain identifier\\n // @param _srcAddress - the source chain contract address\\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\\n\\n // @notice query if the _libraryAddress is valid for sending msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getSendLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the _libraryAddress is valid for receiving msgs.\\n // @param _userApplication - the user app address on this EVM chain\\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\\n\\n // @notice query if the non-reentrancy guard for send() is on\\n // @return true if the guard is on. false otherwise\\n function isSendingPayload() external view returns (bool);\\n\\n // @notice query if the non-reentrancy guard for receive() is on\\n // @return true if the guard is on. false otherwise\\n function isReceivingPayload() external view returns (bool);\\n\\n // @notice get the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _userApplication - the contract address of the user application\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\\n\\n // @notice get the send() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getSendVersion(address _userApplication) external view returns (uint16);\\n\\n // @notice get the lzReceive() LayerZero messaging library version\\n // @param _userApplication - the contract address of the user application\\n function getReceiveVersion(address _userApplication) external view returns (uint16);\\n}\\n\",\"keccak256\":\"0xbc2e0022d4d53d136830aa90037be2ed7a0966f5fd1b409bf5986185984c495f\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroReceiver {\\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\\n // @param _srcChainId - the source endpoint identifier\\n // @param _srcAddress - the source sending contract address from the source chain\\n // @param _nonce - the ordered message nonce\\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\\n}\\n\",\"keccak256\":\"0xd1617e455d90d41556bba636bc440627d301ec481de16ff04fbd520333c3c6f3\",\"license\":\"BUSL-1.1\"},\"lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity >=0.5.0;\\n\\ninterface ILayerZeroUserApplicationConfig {\\n // @notice set the configuration of the LayerZero messaging library of the specified version\\n // @param _version - messaging library version\\n // @param _chainId - the chainId for the pending config change\\n // @param _configType - type of configuration. every messaging library has its own convention.\\n // @param _config - configuration in the bytes. can encode arbitrary content.\\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\\n\\n // @notice set the send() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setSendVersion(uint16 _version) external;\\n\\n // @notice set the lzReceive() LayerZero messaging library version to _version\\n // @param _version - new messaging library version\\n function setReceiveVersion(uint16 _version) external;\\n\\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\\n // @param _srcChainId - the chainId of the source chain\\n // @param _srcAddress - the contract address of the source contract at the source chain\\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\\n}\\n\",\"keccak256\":\"0xdc7e072cf3064081a8edf4a286ca43ddecc24330f2923d96f416f9d3f6538447\",\"license\":\"BUSL-1.1\"}},\"version\":1}", + "bytecode": "0x61012060405234801561001157600080fd5b50604051610f81380380610f81833981016040819052610030916100e2565b8161ffff16600c148061004857508161ffff1661271c145b61008b5760405162461bcd60e51b815260206004820152601060248201526f434841494e5f49445f4e4f545f46544d60801b604482015260640160405180910390fd5b6001600160a01b0393841660805291831660a05261ffff1660c0521660e052600080546001600160a01b03191633179055426101005261013f565b80516001600160a01b03811681146100dd57600080fd5b919050565b600080600080608085870312156100f857600080fd5b610101856100c6565b935061010f602086016100c6565b9250604085015161ffff8116811461012657600080fd5b9150610134606086016100c6565b905092959194509250565b60805160a05160c05160e05161010051610dcd6101b4600039600081816102d601526108c00152600081816101d30152610352015260008181610263015261037c015260008181610163015261059f01526000818161023c015281816104d70152818161078e015261094c0152610dcd6000f3fe608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a408bb4c11610071578063a408bb4c14610298578063aaa8f2ef146102a0578063b8ea6281146102b3578063caccb667146102c8578063f905c15a146102d157600080fd5b80636bfd23a71461021b57806385f2aef21461022457806389a3027114610237578063997a03b71461025e57600080fd5b806347db1a6a116100e957806347db1a6a1461019d5780634cdad506146101a65780635e280f11146101ce57806363b4eb8d146101f557806368ecc6bc1461020857600080fd5b80621d35671461011a578063095cf5c61461012f5780631308db08146101425780633189097b1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60055481565b6040519081526020015b60405180910390f35b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b61014b60035481565b6101b96101b4366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b600154610185906001600160a01b031681565b61012d610216366004610be5565b6106f3565b61014b60025481565b600054610185906001600160a01b031681565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6102857f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101856102c1366004610c1a565b6014015190565b61014b60045481565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea2646970667358221220efcd9b1051d17e4b1e2acdad7cd7b7d3d781f7a05f5b1d93fdabd39fb87acb7b64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101155760003560e01c80636bfd23a7116100a2578063a408bb4c11610071578063a408bb4c14610298578063aaa8f2ef146102a0578063b8ea6281146102b3578063caccb667146102c8578063f905c15a146102d157600080fd5b80636bfd23a71461021b57806385f2aef21461022457806389a3027114610237578063997a03b71461025e57600080fd5b806347db1a6a116100e957806347db1a6a1461019d5780634cdad506146101a65780635e280f11146101ce57806363b4eb8d146101f557806368ecc6bc1461020857600080fd5b80621d35671461011a578063095cf5c61461012f5780631308db08146101425780633189097b1461015e575b600080fd5b61012d610128366004610af9565b6102f8565b005b61012d61013d366004610ba8565b610651565b61014b60055481565b6040519081526020015b60405180910390f35b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610155565b61014b60035481565b6101b96101b4366004610bcc565b61069d565b60408051928352602083019190915201610155565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b600154610185906001600160a01b031681565b61012d610216366004610be5565b6106f3565b61014b60025481565b600054610185906001600160a01b031681565b6101857f000000000000000000000000000000000000000000000000000000000000000081565b6102857f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610155565b61012d610891565b61014b6b0136492b8a2b999d53f0000081565b6101856102c1366004610c1a565b6014015190565b61014b60045481565b61014b7f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03166103475760405162461bcd60e51b815260206004820152600f60248201526e1393d517d253925512505312569151608a1b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156103a657507f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff16145b80156103cf57506001546001600160a01b03166103c4846014015190565b6001600160a01b0316145b6104115760405162461bcd60e51b81526020600482015260136024820152722aa720aaaa2427a924ad22a22fa1a0a62622a960691b604482015260640161033e565b600080828060200190518101906104289190610c57565b915091506b0136492b8a2b999d53f00000816002600082825461044b9190610c9b565b925050819055111561049f5760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742072656465656d206d6f7265207468616e20656c696769626c65604482015260640161033e565b6000806104ab8361069d565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190610cb3565b6105625760405162461bcd60e51b815260040161033e90610cd5565b80600560008282546105749190610d03565b9091555050604051635569f64b60e11b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063aad3ec96906044016020604051808303816000875af11580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190610cb3565b6106475760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d1905253115160a21b604482015260640161033e565b5050505050505050565b6000546001600160a01b0316331461067b5760405162461bcd60e51b815260040161033e90610d1a565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806b0136492b8a2b999d53f00000600354846106bb9190610d3d565b6106c59190610d5c565b91506b0136492b8a2b999d53f00000600454846106e29190610d3d565b6106ec9190610d5c565b9050915091565b6000546001600160a01b0316331461071d5760405162461bcd60e51b815260040161033e90610d1a565b6001546001600160a01b03161561076c5760405162461bcd60e51b81526020600482015260136024820152721053149150511657d253925512505312569151606a1b604482015260640161033e565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190610cb3565b61081f5760405162461bcd60e51b815260040161033e90610cd5565b600180546001600160a01b0319166001600160a01b038516908117909155600383905560048290556005829055604080519182526020820184905281018290527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050565b6000546001600160a01b031633146108bb5760405162461bcd60e51b815260040161033e90610d1a565b6108e87f000000000000000000000000000000000000000000000000000000000000000062278d00610c9b565b4210156109375760405162461bcd60e51b815260206004820152601760248201527f4c4546544f564552535f4e4f545f434c41494d41424c45000000000000000000604482015260640161033e565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190610d7e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190610cb3565b610a545760405162461bcd60e51b815260040161033e90610cd5565b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a7d57600080fd5b813567ffffffffffffffff80821115610a9857610a98610a56565b604051601f8301601f19908116603f01168101908282118183101715610ac057610ac0610a56565b81604052838152866020858801011115610ad957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060808587031215610b0f57600080fd5b843561ffff81168114610b2157600080fd5b9350602085013567ffffffffffffffff80821115610b3e57600080fd5b610b4a88838901610a6c565b9450604087013591508082168214610b6157600080fd5b90925060608601359080821115610b7757600080fd5b50610b8487828801610a6c565b91505092959194509250565b6001600160a01b0381168114610ba557600080fd5b50565b600060208284031215610bba57600080fd5b8135610bc581610b90565b9392505050565b600060208284031215610bde57600080fd5b5035919050565b600080600060608486031215610bfa57600080fd5b8335610c0581610b90565b95602085013595506040909401359392505050565b600060208284031215610c2c57600080fd5b813567ffffffffffffffff811115610c4357600080fd5b610c4f84828501610a6c565b949350505050565b60008060408385031215610c6a57600080fd5b8251610c7581610b90565b6020939093015192949293505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610cae57610cae610c85565b500190565b600060208284031215610cc557600080fd5b81518015158114610bc557600080fd5b6020808252601490820152731554d110d7d514905394d1915497d1905253115160621b604082015260600190565b600082821015610d1557610d15610c85565b500390565b6020808252600990820152684f4e4c595f5445414d60b81b604082015260600190565b6000816000190483118215151615610d5757610d57610c85565b500290565b600082610d7957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215610d9057600080fd5b505191905056fea2646970667358221220efcd9b1051d17e4b1e2acdad7cd7b7d3d781f7a05f5b1d93fdabd39fb87acb7b64736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, @@ -364,7 +364,7 @@ "storageLayout": { "storage": [ { - "astId": 24584, + "astId": 24586, "contract": "contracts/redeem/RedemptionReceiver.sol:RedemptionReceiver", "label": "team", "offset": 0, @@ -372,7 +372,7 @@ "type": "t_address" }, { - "astId": 24588, + "astId": 24590, "contract": "contracts/redeem/RedemptionReceiver.sol:RedemptionReceiver", "label": "fantomSender", "offset": 0, @@ -380,7 +380,7 @@ "type": "t_address" }, { - "astId": 24595, + "astId": 24597, "contract": "contracts/redeem/RedemptionReceiver.sol:RedemptionReceiver", "label": "redeemedWEVE", "offset": 0, @@ -388,7 +388,7 @@ "type": "t_uint256" }, { - "astId": 24597, + "astId": 24599, "contract": "contracts/redeem/RedemptionReceiver.sol:RedemptionReceiver", "label": "redeemableUSDC", "offset": 0, @@ -396,7 +396,7 @@ "type": "t_uint256" }, { - "astId": 24599, + "astId": 24601, "contract": "contracts/redeem/RedemptionReceiver.sol:RedemptionReceiver", "label": "redeemableFLOW", "offset": 0, @@ -404,7 +404,7 @@ "type": "t_uint256" }, { - "astId": 24601, + "astId": 24603, "contract": "contracts/redeem/RedemptionReceiver.sol:RedemptionReceiver", "label": "leftoverFLOW", "offset": 0, diff --git a/deployments/arbitrumGoerli/RewardsDistributor.json b/deployments/arbitrumGoerli/RewardsDistributor.json index f936ce33..acf4b7d9 100644 --- a/deployments/arbitrumGoerli/RewardsDistributor.json +++ b/deployments/arbitrumGoerli/RewardsDistributor.json @@ -1,5 +1,5 @@ { - "address": "0xCf24b553f519916664533A862AB100FF8185a0c8", + "address": "0xd1A4913ec6d68944C93056504655d1B3cbd4eBd3", "abi": [ { "inputs": [ @@ -351,45 +351,45 @@ "type": "function" } ], - "transactionHash": "0x75066d42d182dea37155901963c580184fcb3e0e902b517cc222b5c4b6ab3a23", + "transactionHash": "0x19a62f40b488088580b9bd428cb0dce578126076213e61403a5aba853eeecc2a", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xCf24b553f519916664533A862AB100FF8185a0c8", + "contractAddress": "0xd1A4913ec6d68944C93056504655d1B3cbd4eBd3", "transactionIndex": 1, - "gasUsed": "1623336", - "logsBloom": "0x00000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000080000020000000000000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000010000000000040000000000000000000000000000000000000000000000000", - "blockHash": "0x9a71f97bc8bed760d25373911577b73bacdf3ed08c9344833c324f1b56183fc4", - "transactionHash": "0x75066d42d182dea37155901963c580184fcb3e0e902b517cc222b5c4b6ab3a23", + "gasUsed": "1623324", + "logsBloom": "0x00000000000000040000000000000000000000800000000000000000080000000000000000000000400000000000000000000000010000000000000080200000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000020000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xe58bbbd28d39d27cbdc84c6daaa5d6274843927a7f3fdefcba783fe042c3e5fe", + "transactionHash": "0x19a62f40b488088580b9bd428cb0dce578126076213e61403a5aba853eeecc2a", "logs": [ { "transactionIndex": 1, - "blockNumber": 6069419, - "transactionHash": "0x75066d42d182dea37155901963c580184fcb3e0e902b517cc222b5c4b6ab3a23", - "address": "0x4E13914872BFf7e58f3E231b2687fDd084014999", + "blockNumber": 6188457, + "transactionHash": "0x19a62f40b488088580b9bd428cb0dce578126076213e61403a5aba853eeecc2a", + "address": "0x49E4eA802DdF4CAF7C699782a80DeefdC03Dcb4B", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000cf24b553f519916664533a862ab100ff8185a0c8", - "0x0000000000000000000000006d55afbf1caf01e0bca5255bba730da6fafd0af4" + "0x000000000000000000000000d1a4913ec6d68944c93056504655d1b3cbd4ebd3", + "0x00000000000000000000000038c8250ff6bd87812edc5aaee577836c2b3c2ae6" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "logIndex": 0, - "blockHash": "0x9a71f97bc8bed760d25373911577b73bacdf3ed08c9344833c324f1b56183fc4" + "blockHash": "0xe58bbbd28d39d27cbdc84c6daaa5d6274843927a7f3fdefcba783fe042c3e5fe" } ], - "blockNumber": 6069419, - "cumulativeGasUsed": "1623336", + "blockNumber": 6188457, + "cumulativeGasUsed": "1623324", "status": 1, "byzantium": true }, "args": [ - "0x6d55AFbF1cAf01E0bcA5255bbA730da6fAFD0aF4" + "0x38c8250FF6bD87812eDc5aAee577836c2B3c2aE6" ], - "numDeployments": 1, - "solcInputHash": "d2a2160297444b93438826228d1e185d", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voting_escrow\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"time\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"CheckpointToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"claim_epoch\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"max_epoch\",\"type\":\"uint256\"}],\"name\":\"Claimed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"checkpoint_token\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint_total_supply\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"_tokenIds\",\"type\":\"uint256[]\"}],\"name\":\"claim_many\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_token_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"}],\"name\":\"setDepositor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"start_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"time_cursor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"time_cursor_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token_last_balance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"tokens_per_week\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_epoch_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"ve_for_at\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ve_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voting_escrow\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RewardsDistributor.sol\":\"RewardsDistributor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/*\\n\\n@title Curve Fee Distribution modified for ve(3,3) emissions\\n@author Curve Finance, andrecronje\\n@license MIT\\n\\n*/\\n\\ncontract RewardsDistributor is IRewardsDistributor {\\n event CheckpointToken(uint256 time, uint256 tokens);\\n\\n event Claimed(\\n uint256 tokenId,\\n uint256 amount,\\n uint256 claim_epoch,\\n uint256 max_epoch\\n );\\n\\n uint256 constant WEEK = 7 * 86400;\\n\\n uint256 public start_time;\\n uint256 public time_cursor;\\n mapping(uint256 => uint256) public time_cursor_of;\\n mapping(uint256 => uint256) public user_epoch_of;\\n\\n uint256 public last_token_time;\\n uint256[1000000000000000] public tokens_per_week;\\n\\n address public voting_escrow;\\n address public token;\\n uint256 public token_last_balance;\\n\\n uint256[1000000000000000] public ve_supply;\\n\\n address public depositor;\\n\\n constructor(address _voting_escrow) {\\n uint256 _t = (block.timestamp / WEEK) * WEEK;\\n start_time = _t;\\n last_token_time = _t;\\n time_cursor = _t;\\n address _token = IVotingEscrow(_voting_escrow).token();\\n token = _token;\\n voting_escrow = _voting_escrow;\\n depositor = msg.sender;\\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\\n }\\n\\n function timestamp() external view returns (uint256) {\\n return (block.timestamp / WEEK) * WEEK;\\n }\\n\\n function _checkpoint_token() internal {\\n uint256 token_balance = IERC20(token).balanceOf(address(this));\\n uint256 to_distribute = token_balance - token_last_balance;\\n token_last_balance = token_balance;\\n\\n uint256 t = last_token_time;\\n uint256 since_last = block.timestamp - t;\\n last_token_time = block.timestamp;\\n uint256 this_week = (t / WEEK) * WEEK;\\n uint256 next_week = 0;\\n\\n for (uint256 i = 0; i < 20; i++) {\\n next_week = this_week + WEEK;\\n if (block.timestamp < next_week) {\\n if (since_last == 0 && block.timestamp == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (block.timestamp - t)) /\\n since_last;\\n }\\n break;\\n } else {\\n if (since_last == 0 && next_week == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (next_week - t)) /\\n since_last;\\n }\\n }\\n t = next_week;\\n this_week = next_week;\\n }\\n emit CheckpointToken(block.timestamp, to_distribute);\\n }\\n\\n function checkpoint_token() external {\\n assert(msg.sender == depositor);\\n _checkpoint_token();\\n }\\n\\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\\n internal\\n view\\n returns (uint256)\\n {\\n uint256 _min = 0;\\n uint256 _max = IVotingEscrow(ve).epoch();\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n _mid\\n );\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function _find_timestamp_user_epoch(\\n address ve,\\n uint256 tokenId,\\n uint256 _timestamp,\\n uint256 max_user_epoch\\n ) internal view returns (uint256) {\\n uint256 _min = 0;\\n uint256 _max = max_user_epoch;\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\\n .user_point_history(tokenId, _mid);\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\\n external\\n view\\n returns (uint256)\\n {\\n address ve = voting_escrow;\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _timestamp,\\n max_user_epoch\\n );\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n epoch\\n );\\n return\\n MathDunks.max(\\n uint256(\\n int256(\\n pt.bias -\\n pt.slope *\\n (int128(int256(_timestamp - pt.ts)))\\n )\\n ),\\n 0\\n );\\n }\\n\\n function _checkpoint_total_supply() internal {\\n address ve = voting_escrow;\\n uint256 t = time_cursor;\\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\\n IVotingEscrow(ve).checkpoint();\\n\\n for (uint256 i = 0; i < 20; i++) {\\n if (t > rounded_timestamp) {\\n break;\\n } else {\\n uint256 epoch = _find_timestamp_epoch(ve, t);\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n epoch\\n );\\n int128 dt = 0;\\n if (t > pt.ts) {\\n dt = int128(int256(t - pt.ts));\\n }\\n ve_supply[t] = MathDunks.max(\\n uint256(int256(pt.bias - pt.slope * dt)),\\n 0\\n );\\n }\\n t += WEEK;\\n }\\n time_cursor = t;\\n }\\n\\n function checkpoint_total_supply() external {\\n _checkpoint_total_supply();\\n }\\n\\n function _claim(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\\n user_epoch_of[_tokenId] = user_epoch;\\n time_cursor_of[_tokenId] = week_cursor;\\n\\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\\n\\n return to_distribute;\\n }\\n\\n function _claimable(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal view returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n return to_distribute;\\n }\\n\\n function claimable(uint256 _tokenId) external view returns (uint256) {\\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\\n return _claimable(_tokenId, voting_escrow, _last_token_time);\\n }\\n\\n function claim(uint256 _tokenId) external returns (uint256) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\\n token_last_balance -= amount;\\n }\\n return amount;\\n }\\n\\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n address _voting_escrow = voting_escrow;\\n uint256 total = 0;\\n\\n for (uint256 i = 0; i < _tokenIds.length; i++) {\\n uint256 _tokenId = _tokenIds[i];\\n if (_tokenId == 0) break;\\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\\n total += amount;\\n }\\n }\\n if (total != 0) {\\n token_last_balance -= total;\\n }\\n\\n return true;\\n }\\n\\n // Once off event on contract initialize\\n function setDepositor(address _depositor) external {\\n require(msg.sender == depositor);\\n depositor = _depositor;\\n }\\n}\\n\",\"keccak256\":\"0xc3e7c3c7944974ce250313d2794fbfa3a98786e2040c685dc250c71ff9002829\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b5060405162001b9f38038062001b9f83398101604081905262000034916200019f565b600062093a80620000468142620001d1565b620000529190620001f4565b90508060008190555080600481905550806001819055506000826001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000aa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d091906200019f565b66038d7ea4c6800680546001600160a01b038381166001600160a01b0319928316811790935566038d7ea4c6800580549188169183168217905566071afd498d00088054909216331790915560405163095ea7b360e01b8152600481019190915260001960248201529192509063095ea7b3906044016020604051808303816000875af115801562000166573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200018c919062000222565b6200019657600080fd5b50505062000246565b600060208284031215620001b257600080fd5b81516001600160a01b0381168114620001ca57600080fd5b9392505050565b600082620001ef57634e487b7160e01b600052601260045260246000fd5b500490565b60008160001904831182151516156200021d57634e487b7160e01b600052601160045260246000fd5b500290565b6000602082840312156200023557600080fd5b81518015158114620001ca57600080fd5b61194980620002566000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea26469706673582212204e4dafd337698280bf8dd6511ad20df90506619fef65a85df15dbb0da22eb0cf64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea26469706673582212204e4dafd337698280bf8dd6511ad20df90506619fef65a85df15dbb0da22eb0cf64736f6c634300080d0033", + "numDeployments": 2, + "solcInputHash": "6e27611a2cedd773c4cc6e46935e6392", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voting_escrow\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"time\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"CheckpointToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"claim_epoch\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"max_epoch\",\"type\":\"uint256\"}],\"name\":\"Claimed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"checkpoint_token\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint_total_supply\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"_tokenIds\",\"type\":\"uint256[]\"}],\"name\":\"claim_many\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_token_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"}],\"name\":\"setDepositor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"start_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"time_cursor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"time_cursor_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token_last_balance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"tokens_per_week\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_epoch_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"ve_for_at\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ve_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voting_escrow\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RewardsDistributor.sol\":\"RewardsDistributor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735303535373437363232\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/*\\n\\n@title Curve Fee Distribution modified for ve(3,3) emissions\\n@author Curve Finance, andrecronje\\n@license MIT\\n\\n*/\\n\\ncontract RewardsDistributor is IRewardsDistributor {\\n event CheckpointToken(uint256 time, uint256 tokens);\\n\\n event Claimed(\\n uint256 tokenId,\\n uint256 amount,\\n uint256 claim_epoch,\\n uint256 max_epoch\\n );\\n\\n uint256 constant WEEK = 7 * 86400;\\n\\n uint256 public start_time;\\n uint256 public time_cursor;\\n mapping(uint256 => uint256) public time_cursor_of;\\n mapping(uint256 => uint256) public user_epoch_of;\\n\\n uint256 public last_token_time;\\n uint256[1000000000000000] public tokens_per_week;\\n\\n address public voting_escrow;\\n address public token;\\n uint256 public token_last_balance;\\n\\n uint256[1000000000000000] public ve_supply;\\n\\n address public depositor;\\n\\n constructor(address _voting_escrow) {\\n uint256 _t = (block.timestamp / WEEK) * WEEK;\\n start_time = _t;\\n last_token_time = _t;\\n time_cursor = _t;\\n address _token = IVotingEscrow(_voting_escrow).token();\\n token = _token;\\n voting_escrow = _voting_escrow;\\n depositor = msg.sender;\\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\\n }\\n\\n function timestamp() external view returns (uint256) {\\n return (block.timestamp / WEEK) * WEEK;\\n }\\n\\n function _checkpoint_token() internal {\\n uint256 token_balance = IERC20(token).balanceOf(address(this));\\n uint256 to_distribute = token_balance - token_last_balance;\\n token_last_balance = token_balance;\\n\\n uint256 t = last_token_time;\\n uint256 since_last = block.timestamp - t;\\n last_token_time = block.timestamp;\\n uint256 this_week = (t / WEEK) * WEEK;\\n uint256 next_week = 0;\\n\\n for (uint256 i = 0; i < 20; i++) {\\n next_week = this_week + WEEK;\\n if (block.timestamp < next_week) {\\n if (since_last == 0 && block.timestamp == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (block.timestamp - t)) /\\n since_last;\\n }\\n break;\\n } else {\\n if (since_last == 0 && next_week == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (next_week - t)) /\\n since_last;\\n }\\n }\\n t = next_week;\\n this_week = next_week;\\n }\\n emit CheckpointToken(block.timestamp, to_distribute);\\n }\\n\\n function checkpoint_token() external {\\n assert(msg.sender == depositor);\\n _checkpoint_token();\\n }\\n\\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\\n internal\\n view\\n returns (uint256)\\n {\\n uint256 _min = 0;\\n uint256 _max = IVotingEscrow(ve).epoch();\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n _mid\\n );\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function _find_timestamp_user_epoch(\\n address ve,\\n uint256 tokenId,\\n uint256 _timestamp,\\n uint256 max_user_epoch\\n ) internal view returns (uint256) {\\n uint256 _min = 0;\\n uint256 _max = max_user_epoch;\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\\n .user_point_history(tokenId, _mid);\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\\n external\\n view\\n returns (uint256)\\n {\\n address ve = voting_escrow;\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _timestamp,\\n max_user_epoch\\n );\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n epoch\\n );\\n return\\n MathDunks.max(\\n uint256(\\n int256(\\n pt.bias -\\n pt.slope *\\n (int128(int256(_timestamp - pt.ts)))\\n )\\n ),\\n 0\\n );\\n }\\n\\n function _checkpoint_total_supply() internal {\\n address ve = voting_escrow;\\n uint256 t = time_cursor;\\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\\n IVotingEscrow(ve).checkpoint();\\n\\n for (uint256 i = 0; i < 20; i++) {\\n if (t > rounded_timestamp) {\\n break;\\n } else {\\n uint256 epoch = _find_timestamp_epoch(ve, t);\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n epoch\\n );\\n int128 dt = 0;\\n if (t > pt.ts) {\\n dt = int128(int256(t - pt.ts));\\n }\\n ve_supply[t] = MathDunks.max(\\n uint256(int256(pt.bias - pt.slope * dt)),\\n 0\\n );\\n }\\n t += WEEK;\\n }\\n time_cursor = t;\\n }\\n\\n function checkpoint_total_supply() external {\\n _checkpoint_total_supply();\\n }\\n\\n function _claim(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\\n user_epoch_of[_tokenId] = user_epoch;\\n time_cursor_of[_tokenId] = week_cursor;\\n\\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\\n\\n return to_distribute;\\n }\\n\\n function _claimable(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal view returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n return to_distribute;\\n }\\n\\n function claimable(uint256 _tokenId) external view returns (uint256) {\\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\\n return _claimable(_tokenId, voting_escrow, _last_token_time);\\n }\\n\\n function claim(uint256 _tokenId) external returns (uint256) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\\n token_last_balance -= amount;\\n }\\n return amount;\\n }\\n\\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n address _voting_escrow = voting_escrow;\\n uint256 total = 0;\\n\\n for (uint256 i = 0; i < _tokenIds.length; i++) {\\n uint256 _tokenId = _tokenIds[i];\\n if (_tokenId == 0) break;\\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\\n total += amount;\\n }\\n }\\n if (total != 0) {\\n token_last_balance -= total;\\n }\\n\\n return true;\\n }\\n\\n // Once off event on contract initialize\\n function setDepositor(address _depositor) external {\\n require(msg.sender == depositor);\\n depositor = _depositor;\\n }\\n}\\n\",\"keccak256\":\"0xc3e7c3c7944974ce250313d2794fbfa3a98786e2040c685dc250c71ff9002829\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b5060405162001b9f38038062001b9f83398101604081905262000034916200019f565b600062093a80620000468142620001d1565b620000529190620001f4565b90508060008190555080600481905550806001819055506000826001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000aa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d091906200019f565b66038d7ea4c6800680546001600160a01b038381166001600160a01b0319928316811790935566038d7ea4c6800580549188169183168217905566071afd498d00088054909216331790915560405163095ea7b360e01b8152600481019190915260001960248201529192509063095ea7b3906044016020604051808303816000875af115801562000166573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200018c919062000222565b6200019657600080fd5b50505062000246565b600060208284031215620001b257600080fd5b81516001600160a01b0381168114620001ca57600080fd5b9392505050565b600082620001ef57634e487b7160e01b600052601260045260246000fd5b500490565b60008160001904831182151516156200021d57634e487b7160e01b600052601160045260246000fd5b500290565b6000602082840312156200023557600080fd5b81518015158114620001ca57600080fd5b61194980620002566000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea264697066735822122016c48dd1b890c77eb51206101ddc9ee8875888f1f13f77a6a18d754b005eb25064736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea264697066735822122016c48dd1b890c77eb51206101ddc9ee8875888f1f13f77a6a18d754b005eb25064736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, @@ -403,7 +403,7 @@ "storageLayout": { "storage": [ { - "astId": 9902, + "astId": 9903, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "start_time", "offset": 0, @@ -411,7 +411,7 @@ "type": "t_uint256" }, { - "astId": 9904, + "astId": 9905, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "time_cursor", "offset": 0, @@ -419,7 +419,7 @@ "type": "t_uint256" }, { - "astId": 9908, + "astId": 9909, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "time_cursor_of", "offset": 0, @@ -427,7 +427,7 @@ "type": "t_mapping(t_uint256,t_uint256)" }, { - "astId": 9912, + "astId": 9913, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "user_epoch_of", "offset": 0, @@ -435,7 +435,7 @@ "type": "t_mapping(t_uint256,t_uint256)" }, { - "astId": 9914, + "astId": 9915, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "last_token_time", "offset": 0, @@ -443,7 +443,7 @@ "type": "t_uint256" }, { - "astId": 9918, + "astId": 9919, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "tokens_per_week", "offset": 0, @@ -451,7 +451,7 @@ "type": "t_array(t_uint256)1000000000000000_storage" }, { - "astId": 9920, + "astId": 9921, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "voting_escrow", "offset": 0, @@ -459,7 +459,7 @@ "type": "t_address" }, { - "astId": 9922, + "astId": 9923, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "token", "offset": 0, @@ -467,7 +467,7 @@ "type": "t_address" }, { - "astId": 9924, + "astId": 9925, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "token_last_balance", "offset": 0, @@ -475,7 +475,7 @@ "type": "t_uint256" }, { - "astId": 9928, + "astId": 9929, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "ve_supply", "offset": 0, @@ -483,7 +483,7 @@ "type": "t_array(t_uint256)1000000000000000_storage" }, { - "astId": 9930, + "astId": 9931, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "depositor", "offset": 0, diff --git a/deployments/arbitrumGoerli/Router.json b/deployments/arbitrumGoerli/Router.json index 708e9018..9bc62d62 100644 --- a/deployments/arbitrumGoerli/Router.json +++ b/deployments/arbitrumGoerli/Router.json @@ -1,5 +1,5 @@ { - "address": "0x5E88C567F60466cdCA5c9C331090bBB7391fd70a", + "address": "0x86Aa8EBc207134BC4965Cabc5f5C57559Fd5A325", "abi": [ { "inputs": [ @@ -979,31 +979,31 @@ "type": "receive" } ], - "transactionHash": "0xab7d722327422765de9bd74c97d5b2cbc7a184525a93f31d154e2677f1e78ea4", + "transactionHash": "0x9f716b1ac9238590393bf47d37f88307958c67e4898e85565179ab9065d93c65", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x5E88C567F60466cdCA5c9C331090bBB7391fd70a", + "contractAddress": "0x86Aa8EBc207134BC4965Cabc5f5C57559Fd5A325", "transactionIndex": 1, - "gasUsed": "3145959", + "gasUsed": "3145971", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc714c1597f31846e6778667da3182aadf1a40233d8a2251dee00237bb2e5a0a6", - "transactionHash": "0xab7d722327422765de9bd74c97d5b2cbc7a184525a93f31d154e2677f1e78ea4", + "blockHash": "0x3bcfb08306f21919adec7e11f024590d9d1380d8dbd49d6f8367c04e09066b2e", + "transactionHash": "0x9f716b1ac9238590393bf47d37f88307958c67e4898e85565179ab9065d93c65", "logs": [], - "blockNumber": 6069390, - "cumulativeGasUsed": "3145959", + "blockNumber": 6188437, + "cumulativeGasUsed": "3145971", "status": 1, "byzantium": true }, "args": [ - "0x5c7C6ee91569E2658c3A52f47b35E1AAB7e8e600", + "0x22E98754dBa170A64724558E668cb380516e0BE9", "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1" ], - "numDeployments": 1, - "solcInputHash": "d2a2160297444b93438826228d1e185d", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_weth\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"UNSAFE_swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"}],\"name\":\"getAmountsOut\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reserveA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"pairFor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"}],\"name\":\"quoteAddLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"name\":\"quoteRemoveLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityETHWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"}],\"name\":\"sortTokens\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactETHForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForETH\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenFrom\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenTo\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokensSimple\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weth\",\"outputs\":[{\"internalType\":\"contract IWETH\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Router.sol\":\"Router\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Router.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairFactory.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\nimport \\\"contracts/interfaces/IWETH.sol\\\";\\n\\ncontract Router is IRouter {\\n struct route {\\n address from;\\n address to;\\n bool stable;\\n }\\n\\n address public immutable factory;\\n IWETH public immutable weth;\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n bytes32 immutable pairCodeHash;\\n\\n modifier ensure(uint256 deadline) {\\n require(deadline >= block.timestamp, \\\"Router: EXPIRED\\\");\\n _;\\n }\\n\\n constructor(address _factory, address _weth) {\\n factory = _factory;\\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\\n weth = IWETH(_weth);\\n }\\n\\n receive() external payable {\\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\\n }\\n\\n function sortTokens(address tokenA, address tokenB)\\n public\\n pure\\n returns (address token0, address token1)\\n {\\n require(tokenA != tokenB, \\\"Router: IDENTICAL_ADDRESSES\\\");\\n (token0, token1) = tokenA < tokenB\\n ? (tokenA, tokenB)\\n : (tokenB, tokenA);\\n require(token0 != address(0), \\\"Router: ZERO_ADDRESS\\\");\\n }\\n\\n // calculates the CREATE2 address for a pair without making any external calls\\n function pairFor(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (address pair) {\\n (address token0, address token1) = sortTokens(tokenA, tokenB);\\n pair = address(\\n uint160(\\n uint256(\\n keccak256(\\n abi.encodePacked(\\n hex\\\"ff\\\",\\n factory,\\n keccak256(abi.encodePacked(token0, token1, stable)),\\n pairCodeHash // init code hash\\n )\\n )\\n )\\n )\\n );\\n }\\n\\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\\n function quoteLiquidity(\\n uint256 amountA,\\n uint256 reserveA,\\n uint256 reserveB\\n ) internal pure returns (uint256 amountB) {\\n require(amountA > 0, \\\"Router: INSUFFICIENT_AMOUNT\\\");\\n require(reserveA > 0 && reserveB > 0, \\\"Router: INSUFFICIENT_LIQUIDITY\\\");\\n amountB = (amountA * reserveB) / reserveA;\\n }\\n\\n // fetches and sorts the reserves for a pair\\n function getReserves(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (uint256 reserveA, uint256 reserveB) {\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (uint256 reserve0, uint256 reserve1, ) = IPair(\\n pairFor(tokenA, tokenB, stable)\\n ).getReserves();\\n (reserveA, reserveB) = tokenA == token0\\n ? (reserve0, reserve1)\\n : (reserve1, reserve0);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n address tokenOut\\n ) external view returns (uint256 amount, bool stable) {\\n address pair = pairFor(tokenIn, tokenOut, true);\\n uint256 amountStable;\\n uint256 amountVolatile;\\n if (IPairFactory(factory).isPair(pair)) {\\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n pair = pairFor(tokenIn, tokenOut, false);\\n if (IPairFactory(factory).isPair(pair)) {\\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n return\\n amountStable > amountVolatile\\n ? (amountStable, true)\\n : (amountVolatile, false);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountsOut(uint256 amountIn, route[] memory routes)\\n public\\n view\\n returns (uint256[] memory amounts)\\n {\\n require(routes.length >= 1, \\\"Router: INVALID_PATH\\\");\\n amounts = new uint256[](routes.length + 1);\\n amounts[0] = amountIn;\\n for (uint256 i = 0; i < routes.length; i++) {\\n address pair = pairFor(\\n routes[i].from,\\n routes[i].to,\\n routes[i].stable\\n );\\n if (IPairFactory(factory).isPair(pair)) {\\n amounts[i + 1] = IPair(pair).getAmountOut(\\n amounts[i],\\n routes[i].from\\n );\\n }\\n }\\n }\\n\\n function isPair(address pair) external view returns (bool) {\\n return IPairFactory(factory).isPair(pair);\\n }\\n\\n function quoteAddLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired\\n )\\n external\\n view\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n (uint256 reserveA, uint256 reserveB) = (0, 0);\\n uint256 _totalSupply = 0;\\n if (_pair != address(0)) {\\n _totalSupply = IERC20(_pair).totalSupply();\\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\\n }\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n }\\n }\\n }\\n\\n function quoteRemoveLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity\\n ) external view returns (uint256 amountA, uint256 amountB) {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n\\n if (_pair == address(0)) {\\n return (0, 0);\\n }\\n\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n uint256 _totalSupply = IERC20(_pair).totalSupply();\\n\\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\\n }\\n\\n function _addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin\\n ) internal returns (uint256 amountA, uint256 amountB) {\\n require(amountADesired >= amountAMin);\\n require(amountBDesired >= amountBMin);\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n if (_pair == address(0)) {\\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\\n }\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n require(\\n amountBOptimal >= amountBMin,\\n \\\"Router: INSUFFICIENT_B_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n assert(amountAOptimal <= amountADesired);\\n require(\\n amountAOptimal >= amountAMin,\\n \\\"Router: INSUFFICIENT_A_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n }\\n }\\n }\\n\\n function addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n ensure(deadline)\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n (amountA, amountB) = _addLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n amountADesired,\\n amountBDesired,\\n amountAMin,\\n amountBMin\\n );\\n address pair = pairFor(tokenA, tokenB, stable);\\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\\n liquidity = IPair(pair).mint(to);\\n }\\n\\n function addLiquidityETH(\\n address token,\\n bool stable,\\n uint256 amountTokenDesired,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n payable\\n ensure(deadline)\\n returns (\\n uint256 amountToken,\\n uint256 amountETH,\\n uint256 liquidity\\n )\\n {\\n (amountToken, amountETH) = _addLiquidity(\\n token,\\n address(weth),\\n stable,\\n amountTokenDesired,\\n msg.value,\\n amountTokenMin,\\n amountETHMin\\n );\\n address pair = pairFor(token, address(weth), stable);\\n _safeTransferFrom(token, msg.sender, pair, amountToken);\\n weth.deposit{value: amountETH}();\\n assert(weth.transfer(pair, amountETH));\\n liquidity = IPair(pair).mint(to);\\n // refund dust eth, if any\\n if (msg.value > amountETH)\\n _safeTransferETH(msg.sender, msg.value - amountETH);\\n }\\n\\n // **** REMOVE LIQUIDITY ****\\n function removeLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (amountA, amountB) = tokenA == token0\\n ? (amount0, amount1)\\n : (amount1, amount0);\\n require(amountA >= amountAMin, \\\"Router: INSUFFICIENT_A_AMOUNT\\\");\\n require(amountB >= amountBMin, \\\"Router: INSUFFICIENT_B_AMOUNT\\\");\\n }\\n\\n function removeLiquidityETH(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\\n (amountToken, amountETH) = removeLiquidity(\\n token,\\n address(weth),\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n address(this),\\n deadline\\n );\\n _safeTransfer(token, to, amountToken);\\n weth.withdraw(amountETH);\\n _safeTransferETH(to, amountETH);\\n }\\n\\n function removeLiquidityWithPermit(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n {\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(\\n msg.sender,\\n address(this),\\n value,\\n deadline,\\n v,\\n r,\\n s\\n );\\n }\\n\\n (amountA, amountB) = removeLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n liquidity,\\n amountAMin,\\n amountBMin,\\n to,\\n deadline\\n );\\n }\\n\\n function removeLiquidityETHWithPermit(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountToken, uint256 amountETH) {\\n address pair = pairFor(token, address(weth), stable);\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\\n (amountToken, amountETH) = removeLiquidityETH(\\n token,\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n to,\\n deadline\\n );\\n }\\n\\n // **** SWAP ****\\n // requires the initial amount to have already been sent to the first pair\\n function _swap(\\n uint256[] memory amounts,\\n route[] memory routes,\\n address _to\\n ) internal virtual {\\n for (uint256 i = 0; i < routes.length; i++) {\\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\\n uint256 amountOut = amounts[i + 1];\\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\\n ? (uint256(0), amountOut)\\n : (amountOut, uint256(0));\\n address to = i < routes.length - 1\\n ? pairFor(\\n routes[i + 1].from,\\n routes[i + 1].to,\\n routes[i + 1].stable\\n )\\n : _to;\\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\\n amount0Out,\\n amount1Out,\\n to,\\n new bytes(0)\\n );\\n }\\n }\\n\\n function swapExactTokensForTokensSimple(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n address tokenFrom,\\n address tokenTo,\\n bool stable,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n route[] memory routes = new route[](1);\\n routes[0].from = tokenFrom;\\n routes[0].to = tokenTo;\\n routes[0].stable = stable;\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForTokens(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactETHForTokens(\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\\n require(routes[0].from == address(weth), \\\"Router: INVALID_PATH\\\");\\n amounts = getAmountsOut(msg.value, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n weth.deposit{value: amounts[0]}();\\n assert(\\n weth.transfer(\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n )\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForETH(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n require(\\n routes[routes.length - 1].to == address(weth),\\n \\\"Router: INVALID_PATH\\\"\\n );\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, address(this));\\n weth.withdraw(amounts[amounts.length - 1]);\\n _safeTransferETH(to, amounts[amounts.length - 1]);\\n }\\n\\n function UNSAFE_swapExactTokensForTokens(\\n uint256[] memory amounts,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory) {\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n return amounts;\\n }\\n\\n function _safeTransferETH(address to, uint256 value) internal {\\n (bool success, ) = to.call{value: value}(new bytes(0));\\n require(success, \\\"TransferHelper: ETH_TRANSFER_FAILED\\\");\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x3d84c846129d645eec66c37a493bb7fb401a2524497f450eaced155088305ead\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"},\"contracts/interfaces/IWETH.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n function transfer(address to, uint256 value) external returns (bool);\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0x20ad0b3a319a36e3430f0d8512ee3755de8f85a80effe78d06f333f5326ee3d7\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x60e06040523480156200001157600080fd5b50604051620039bc380380620039bc8339810160408190526200003491620000d8565b6001600160a01b038216608081905260408051631355724960e31b81529051639aab9248916004808201926020929091908290030181865afa1580156200007f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000a5919062000110565b60c0526001600160a01b031660a052506200012a565b80516001600160a01b0381168114620000d357600080fd5b919050565b60008060408385031215620000ec57600080fd5b620000f783620000bb565b91506200010760208401620000bb565b90509250929050565b6000602082840312156200012357600080fd5b5051919050565b60805160a05160c0516137c8620001f46000396000610ef901526000818161013e0152818161020b0152818161091901528181610b5801528181610da901528181611470015281816115830152818161161101528181611de901528181611e1f01528181611e5401528181611ee901528181612028015261207801526000818161042d01528181610c3e01528181610ebe015281816111770152818161128b0152818161199601528181611b0a01528181612115015281816126ff01526127a001526137c86000f3fe60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea264697066735822122046a69c5fee9debde0f2e78a460c20964bd28cb71755b1fff51a930e4072f254664736f6c634300080d0033", - "deployedBytecode": "0x60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea264697066735822122046a69c5fee9debde0f2e78a460c20964bd28cb71755b1fff51a930e4072f254664736f6c634300080d0033", + "numDeployments": 2, + "solcInputHash": "6e27611a2cedd773c4cc6e46935e6392", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_weth\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"UNSAFE_swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"}],\"name\":\"getAmountsOut\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reserveA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"pairFor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"}],\"name\":\"quoteAddLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"name\":\"quoteRemoveLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityETHWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"}],\"name\":\"sortTokens\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactETHForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForETH\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenFrom\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenTo\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokensSimple\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weth\",\"outputs\":[{\"internalType\":\"contract IWETH\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Router.sol\":\"Router\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735303535373437363232\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Router.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairFactory.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\nimport \\\"contracts/interfaces/IWETH.sol\\\";\\n\\ncontract Router is IRouter {\\n struct route {\\n address from;\\n address to;\\n bool stable;\\n }\\n\\n address public immutable factory;\\n IWETH public immutable weth;\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n bytes32 immutable pairCodeHash;\\n\\n modifier ensure(uint256 deadline) {\\n require(deadline >= block.timestamp, \\\"Router: EXPIRED\\\");\\n _;\\n }\\n\\n constructor(address _factory, address _weth) {\\n factory = _factory;\\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\\n weth = IWETH(_weth);\\n }\\n\\n receive() external payable {\\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\\n }\\n\\n function sortTokens(address tokenA, address tokenB)\\n public\\n pure\\n returns (address token0, address token1)\\n {\\n require(tokenA != tokenB, \\\"Router: IDENTICAL_ADDRESSES\\\");\\n (token0, token1) = tokenA < tokenB\\n ? (tokenA, tokenB)\\n : (tokenB, tokenA);\\n require(token0 != address(0), \\\"Router: ZERO_ADDRESS\\\");\\n }\\n\\n // calculates the CREATE2 address for a pair without making any external calls\\n function pairFor(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (address pair) {\\n (address token0, address token1) = sortTokens(tokenA, tokenB);\\n pair = address(\\n uint160(\\n uint256(\\n keccak256(\\n abi.encodePacked(\\n hex\\\"ff\\\",\\n factory,\\n keccak256(abi.encodePacked(token0, token1, stable)),\\n pairCodeHash // init code hash\\n )\\n )\\n )\\n )\\n );\\n }\\n\\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\\n function quoteLiquidity(\\n uint256 amountA,\\n uint256 reserveA,\\n uint256 reserveB\\n ) internal pure returns (uint256 amountB) {\\n require(amountA > 0, \\\"Router: INSUFFICIENT_AMOUNT\\\");\\n require(reserveA > 0 && reserveB > 0, \\\"Router: INSUFFICIENT_LIQUIDITY\\\");\\n amountB = (amountA * reserveB) / reserveA;\\n }\\n\\n // fetches and sorts the reserves for a pair\\n function getReserves(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (uint256 reserveA, uint256 reserveB) {\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (uint256 reserve0, uint256 reserve1, ) = IPair(\\n pairFor(tokenA, tokenB, stable)\\n ).getReserves();\\n (reserveA, reserveB) = tokenA == token0\\n ? (reserve0, reserve1)\\n : (reserve1, reserve0);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n address tokenOut\\n ) external view returns (uint256 amount, bool stable) {\\n address pair = pairFor(tokenIn, tokenOut, true);\\n uint256 amountStable;\\n uint256 amountVolatile;\\n if (IPairFactory(factory).isPair(pair)) {\\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n pair = pairFor(tokenIn, tokenOut, false);\\n if (IPairFactory(factory).isPair(pair)) {\\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n return\\n amountStable > amountVolatile\\n ? (amountStable, true)\\n : (amountVolatile, false);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountsOut(uint256 amountIn, route[] memory routes)\\n public\\n view\\n returns (uint256[] memory amounts)\\n {\\n require(routes.length >= 1, \\\"Router: INVALID_PATH\\\");\\n amounts = new uint256[](routes.length + 1);\\n amounts[0] = amountIn;\\n for (uint256 i = 0; i < routes.length; i++) {\\n address pair = pairFor(\\n routes[i].from,\\n routes[i].to,\\n routes[i].stable\\n );\\n if (IPairFactory(factory).isPair(pair)) {\\n amounts[i + 1] = IPair(pair).getAmountOut(\\n amounts[i],\\n routes[i].from\\n );\\n }\\n }\\n }\\n\\n function isPair(address pair) external view returns (bool) {\\n return IPairFactory(factory).isPair(pair);\\n }\\n\\n function quoteAddLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired\\n )\\n external\\n view\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n (uint256 reserveA, uint256 reserveB) = (0, 0);\\n uint256 _totalSupply = 0;\\n if (_pair != address(0)) {\\n _totalSupply = IERC20(_pair).totalSupply();\\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\\n }\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n }\\n }\\n }\\n\\n function quoteRemoveLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity\\n ) external view returns (uint256 amountA, uint256 amountB) {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n\\n if (_pair == address(0)) {\\n return (0, 0);\\n }\\n\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n uint256 _totalSupply = IERC20(_pair).totalSupply();\\n\\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\\n }\\n\\n function _addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin\\n ) internal returns (uint256 amountA, uint256 amountB) {\\n require(amountADesired >= amountAMin);\\n require(amountBDesired >= amountBMin);\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n if (_pair == address(0)) {\\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\\n }\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n require(\\n amountBOptimal >= amountBMin,\\n \\\"Router: INSUFFICIENT_B_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n assert(amountAOptimal <= amountADesired);\\n require(\\n amountAOptimal >= amountAMin,\\n \\\"Router: INSUFFICIENT_A_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n }\\n }\\n }\\n\\n function addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n ensure(deadline)\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n (amountA, amountB) = _addLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n amountADesired,\\n amountBDesired,\\n amountAMin,\\n amountBMin\\n );\\n address pair = pairFor(tokenA, tokenB, stable);\\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\\n liquidity = IPair(pair).mint(to);\\n }\\n\\n function addLiquidityETH(\\n address token,\\n bool stable,\\n uint256 amountTokenDesired,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n payable\\n ensure(deadline)\\n returns (\\n uint256 amountToken,\\n uint256 amountETH,\\n uint256 liquidity\\n )\\n {\\n (amountToken, amountETH) = _addLiquidity(\\n token,\\n address(weth),\\n stable,\\n amountTokenDesired,\\n msg.value,\\n amountTokenMin,\\n amountETHMin\\n );\\n address pair = pairFor(token, address(weth), stable);\\n _safeTransferFrom(token, msg.sender, pair, amountToken);\\n weth.deposit{value: amountETH}();\\n assert(weth.transfer(pair, amountETH));\\n liquidity = IPair(pair).mint(to);\\n // refund dust eth, if any\\n if (msg.value > amountETH)\\n _safeTransferETH(msg.sender, msg.value - amountETH);\\n }\\n\\n // **** REMOVE LIQUIDITY ****\\n function removeLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (amountA, amountB) = tokenA == token0\\n ? (amount0, amount1)\\n : (amount1, amount0);\\n require(amountA >= amountAMin, \\\"Router: INSUFFICIENT_A_AMOUNT\\\");\\n require(amountB >= amountBMin, \\\"Router: INSUFFICIENT_B_AMOUNT\\\");\\n }\\n\\n function removeLiquidityETH(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\\n (amountToken, amountETH) = removeLiquidity(\\n token,\\n address(weth),\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n address(this),\\n deadline\\n );\\n _safeTransfer(token, to, amountToken);\\n weth.withdraw(amountETH);\\n _safeTransferETH(to, amountETH);\\n }\\n\\n function removeLiquidityWithPermit(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n {\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(\\n msg.sender,\\n address(this),\\n value,\\n deadline,\\n v,\\n r,\\n s\\n );\\n }\\n\\n (amountA, amountB) = removeLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n liquidity,\\n amountAMin,\\n amountBMin,\\n to,\\n deadline\\n );\\n }\\n\\n function removeLiquidityETHWithPermit(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountToken, uint256 amountETH) {\\n address pair = pairFor(token, address(weth), stable);\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\\n (amountToken, amountETH) = removeLiquidityETH(\\n token,\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n to,\\n deadline\\n );\\n }\\n\\n // **** SWAP ****\\n // requires the initial amount to have already been sent to the first pair\\n function _swap(\\n uint256[] memory amounts,\\n route[] memory routes,\\n address _to\\n ) internal virtual {\\n for (uint256 i = 0; i < routes.length; i++) {\\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\\n uint256 amountOut = amounts[i + 1];\\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\\n ? (uint256(0), amountOut)\\n : (amountOut, uint256(0));\\n address to = i < routes.length - 1\\n ? pairFor(\\n routes[i + 1].from,\\n routes[i + 1].to,\\n routes[i + 1].stable\\n )\\n : _to;\\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\\n amount0Out,\\n amount1Out,\\n to,\\n new bytes(0)\\n );\\n }\\n }\\n\\n function swapExactTokensForTokensSimple(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n address tokenFrom,\\n address tokenTo,\\n bool stable,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n route[] memory routes = new route[](1);\\n routes[0].from = tokenFrom;\\n routes[0].to = tokenTo;\\n routes[0].stable = stable;\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForTokens(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactETHForTokens(\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\\n require(routes[0].from == address(weth), \\\"Router: INVALID_PATH\\\");\\n amounts = getAmountsOut(msg.value, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n weth.deposit{value: amounts[0]}();\\n assert(\\n weth.transfer(\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n )\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForETH(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n require(\\n routes[routes.length - 1].to == address(weth),\\n \\\"Router: INVALID_PATH\\\"\\n );\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, address(this));\\n weth.withdraw(amounts[amounts.length - 1]);\\n _safeTransferETH(to, amounts[amounts.length - 1]);\\n }\\n\\n function UNSAFE_swapExactTokensForTokens(\\n uint256[] memory amounts,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory) {\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n return amounts;\\n }\\n\\n function _safeTransferETH(address to, uint256 value) internal {\\n (bool success, ) = to.call{value: value}(new bytes(0));\\n require(success, \\\"TransferHelper: ETH_TRANSFER_FAILED\\\");\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x3d84c846129d645eec66c37a493bb7fb401a2524497f450eaced155088305ead\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"},\"contracts/interfaces/IWETH.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n function transfer(address to, uint256 value) external returns (bool);\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0x20ad0b3a319a36e3430f0d8512ee3755de8f85a80effe78d06f333f5326ee3d7\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x60e06040523480156200001157600080fd5b50604051620039bc380380620039bc8339810160408190526200003491620000d8565b6001600160a01b038216608081905260408051631355724960e31b81529051639aab9248916004808201926020929091908290030181865afa1580156200007f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000a5919062000110565b60c0526001600160a01b031660a052506200012a565b80516001600160a01b0381168114620000d357600080fd5b919050565b60008060408385031215620000ec57600080fd5b620000f783620000bb565b91506200010760208401620000bb565b90509250929050565b6000602082840312156200012357600080fd5b5051919050565b60805160a05160c0516137c8620001f46000396000610ef901526000818161013e0152818161020b0152818161091901528181610b5801528181610da901528181611470015281816115830152818161161101528181611de901528181611e1f01528181611e5401528181611ee901528181612028015261207801526000818161042d01528181610c3e01528181610ebe015281816111770152818161128b0152818161199601528181611b0a01528181612115015281816126ff01526127a001526137c86000f3fe60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea2646970667358221220af0b6783515166b30266900ba8f4148688e8260b5cfda5233dabcc508d1246e964736f6c634300080d0033", + "deployedBytecode": "0x60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea2646970667358221220af0b6783515166b30266900ba8f4148688e8260b5cfda5233dabcc508d1246e964736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/VeArtProxy.json b/deployments/arbitrumGoerli/VeArtProxy.json index 0d2f8b90..5692bd08 100644 --- a/deployments/arbitrumGoerli/VeArtProxy.json +++ b/deployments/arbitrumGoerli/VeArtProxy.json @@ -1,5 +1,5 @@ { - "address": "0x765df7268ed8Ecd71Cb4bcb70751771eD66c9131", + "address": "0x820D1Dc5A5B63490cBC521E18be5Aa948f49FDD0", "abi": [ { "inputs": [ @@ -36,28 +36,28 @@ "type": "function" } ], - "transactionHash": "0xd4fa9113f47bad388342b1680bc672d0549aa6d397df52bca1d50616d8c2bf94", + "transactionHash": "0xc72afd4e9fae71c82707ff37a5f382f266e90be6e8f1a7ab6f48a40584d7cb6c", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x765df7268ed8Ecd71Cb4bcb70751771eD66c9131", - "transactionIndex": 1, - "gasUsed": "615440", + "contractAddress": "0x820D1Dc5A5B63490cBC521E18be5Aa948f49FDD0", + "transactionIndex": 2, + "gasUsed": "615428", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x48f98916092a1b24f6033f37fd39fbac17c697447e8995b63b023e8db14625e3", - "transactionHash": "0xd4fa9113f47bad388342b1680bc672d0549aa6d397df52bca1d50616d8c2bf94", + "blockHash": "0x57978c2f0af190ea5c889143767e49c00bd8fab5642ca7691e649988bc642336", + "transactionHash": "0xc72afd4e9fae71c82707ff37a5f382f266e90be6e8f1a7ab6f48a40584d7cb6c", "logs": [], - "blockNumber": 6069402, - "cumulativeGasUsed": "615440", + "blockNumber": 6188447, + "cumulativeGasUsed": "896801", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "d2a2160297444b93438826228d1e185d", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_locked_end\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"_tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"output\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VeArtProxy.sol\":\"VeArtProxy\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\nimport {Base64} from \\\"contracts/libraries/Base64.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\n\\ncontract VeArtProxy is IVeArtProxy {\\n function toString(uint value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT license\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint temp = value;\\n uint digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\\n output = '';\\n output = string(abi.encodePacked(output, \\\"token \\\", toString(_tokenId), ''));\\n output = string(abi.encodePacked(output, \\\"balanceOf \\\", toString(_balanceOf), ''));\\n output = string(abi.encodePacked(output, \\\"locked_end \\\", toString(_locked_end), ''));\\n output = string(abi.encodePacked(output, \\\"value \\\", toString(_value), ''));\\n\\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\\\"name\\\": \\\"lock #', toString(_tokenId), '\\\", \\\"description\\\": \\\"Velocimeter locks, can be used to boost gauge yields, vote on token emission, and receive bribes\\\", \\\"image\\\": \\\"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\\\"}'))));\\n output = string(abi.encodePacked('data:application/json;base64,', json));\\n }\\n}\\n\",\"keccak256\":\"0xc526ae7232c93412d664837d1171f1bf5d231a4ea33bcc7a8d0b4e3fa6a9e227\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/libraries/Base64.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n/// [MIT License]\\n/// @title Base64\\n/// @notice Provides a function for encoding some bytes in base64\\n/// @author Brecht Devos \\nlibrary Base64 {\\n bytes internal constant TABLE = \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\";\\n\\n /// @notice Encodes some bytes to the base64 representation\\n function encode(bytes memory data) internal pure returns (string memory) {\\n uint len = data.length;\\n if (len == 0) return \\\"\\\";\\n\\n // multiply by 4/3 rounded up\\n uint encodedLen = 4 * ((len + 2) / 3);\\n\\n // Add some extra buffer at the end\\n bytes memory result = new bytes(encodedLen + 32);\\n\\n bytes memory table = TABLE;\\n\\n assembly {\\n let tablePtr := add(table, 1)\\n let resultPtr := add(result, 32)\\n\\n for {\\n let i := 0\\n } lt(i, len) {\\n\\n } {\\n i := add(i, 3)\\n let input := and(mload(add(data, i)), 0xffffff)\\n\\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\\n out := shl(224, out)\\n\\n mstore(resultPtr, out)\\n\\n resultPtr := add(resultPtr, 4)\\n }\\n\\n switch mod(len, 3)\\n case 1 {\\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\\n }\\n case 2 {\\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\\n }\\n\\n mstore(result, encodedLen)\\n }\\n\\n return string(result);\\n }\\n}\\n\",\"keccak256\":\"0x55535e1e0a14bbac370fe5f25df23aa88c678b915af53517672130f9a54f7e3e\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50610a2b806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f63696d65746572206c6010918401918201527f6f636b732c2063616e206265207573656420746f20626f6f737420676175676560308201527f207969656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c60508201527f20616e64207265636569766520627269626573222c2022696d616765223a202260708201527f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000609082015283516107718160aa840160208801610435565b61227d60f01b60aa929091019182015260ac01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212200245977ba7ac6e458e61e7a78ff819f305af12f1712643deedef07226e96ec5b64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f63696d65746572206c6010918401918201527f6f636b732c2063616e206265207573656420746f20626f6f737420676175676560308201527f207969656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c60508201527f20616e64207265636569766520627269626573222c2022696d616765223a202260708201527f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000609082015283516107718160aa840160208801610435565b61227d60f01b60aa929091019182015260ac01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212200245977ba7ac6e458e61e7a78ff819f305af12f1712643deedef07226e96ec5b64736f6c634300080d0033", + "numDeployments": 2, + "solcInputHash": "6e27611a2cedd773c4cc6e46935e6392", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_locked_end\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"_tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"output\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VeArtProxy.sol\":\"VeArtProxy\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735303535373437363232\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\nimport {Base64} from \\\"contracts/libraries/Base64.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\n\\ncontract VeArtProxy is IVeArtProxy {\\n function toString(uint value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT license\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint temp = value;\\n uint digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\\n output = '';\\n output = string(abi.encodePacked(output, \\\"token \\\", toString(_tokenId), ''));\\n output = string(abi.encodePacked(output, \\\"balanceOf \\\", toString(_balanceOf), ''));\\n output = string(abi.encodePacked(output, \\\"locked_end \\\", toString(_locked_end), ''));\\n output = string(abi.encodePacked(output, \\\"value \\\", toString(_value), ''));\\n\\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\\\"name\\\": \\\"lock #', toString(_tokenId), '\\\", \\\"description\\\": \\\"Velocimeter locks, can be used to boost gauge yields, vote on token emission, and receive bribes\\\", \\\"image\\\": \\\"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\\\"}'))));\\n output = string(abi.encodePacked('data:application/json;base64,', json));\\n }\\n}\\n\",\"keccak256\":\"0xc526ae7232c93412d664837d1171f1bf5d231a4ea33bcc7a8d0b4e3fa6a9e227\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/libraries/Base64.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n/// [MIT License]\\n/// @title Base64\\n/// @notice Provides a function for encoding some bytes in base64\\n/// @author Brecht Devos \\nlibrary Base64 {\\n bytes internal constant TABLE = \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\";\\n\\n /// @notice Encodes some bytes to the base64 representation\\n function encode(bytes memory data) internal pure returns (string memory) {\\n uint len = data.length;\\n if (len == 0) return \\\"\\\";\\n\\n // multiply by 4/3 rounded up\\n uint encodedLen = 4 * ((len + 2) / 3);\\n\\n // Add some extra buffer at the end\\n bytes memory result = new bytes(encodedLen + 32);\\n\\n bytes memory table = TABLE;\\n\\n assembly {\\n let tablePtr := add(table, 1)\\n let resultPtr := add(result, 32)\\n\\n for {\\n let i := 0\\n } lt(i, len) {\\n\\n } {\\n i := add(i, 3)\\n let input := and(mload(add(data, i)), 0xffffff)\\n\\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\\n out := shl(224, out)\\n\\n mstore(resultPtr, out)\\n\\n resultPtr := add(resultPtr, 4)\\n }\\n\\n switch mod(len, 3)\\n case 1 {\\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\\n }\\n case 2 {\\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\\n }\\n\\n mstore(result, encodedLen)\\n }\\n\\n return string(result);\\n }\\n}\\n\",\"keccak256\":\"0x55535e1e0a14bbac370fe5f25df23aa88c678b915af53517672130f9a54f7e3e\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610a2b806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f63696d65746572206c6010918401918201527f6f636b732c2063616e206265207573656420746f20626f6f737420676175676560308201527f207969656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c60508201527f20616e64207265636569766520627269626573222c2022696d616765223a202260708201527f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000609082015283516107718160aa840160208801610435565b61227d60f01b60aa929091019182015260ac01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220a7fb0a9bf1378210f80c5900dd81917c35e9798b9b7c037ff93f9d5ad20f07fc64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f63696d65746572206c6010918401918201527f6f636b732c2063616e206265207573656420746f20626f6f737420676175676560308201527f207969656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c60508201527f20616e64207265636569766520627269626573222c2022696d616765223a202260708201527f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000609082015283516107718160aa840160208801610435565b61227d60f01b60aa929091019182015260ac01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220a7fb0a9bf1378210f80c5900dd81917c35e9798b9b7c037ff93f9d5ad20f07fc64736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/VelocimeterLibrary.json b/deployments/arbitrumGoerli/VelocimeterLibrary.json index 29d95353..1dd16b71 100644 --- a/deployments/arbitrumGoerli/VelocimeterLibrary.json +++ b/deployments/arbitrumGoerli/VelocimeterLibrary.json @@ -1,5 +1,5 @@ { - "address": "0xB0983F8e787A6E8079F722925D81D2C784a52E9E", + "address": "0x162C6409a3086887411A965BE68878552F940143", "abi": [ { "inputs": [ @@ -188,30 +188,30 @@ "type": "function" } ], - "transactionHash": "0xa00f5308ea82e068442ac690aab2e1276828215758ff85d72a042442ae06efe3", + "transactionHash": "0x445278016ddb22a62ecad28a1289be911a5af65f5c634af02420955352083836", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xB0983F8e787A6E8079F722925D81D2C784a52E9E", + "contractAddress": "0x162C6409a3086887411A965BE68878552F940143", "transactionIndex": 1, "gasUsed": "904028", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x9c90007e20856d7071d2e06612fcf775ab1e7d31722474d1b0ab38af7e7c14d2", - "transactionHash": "0xa00f5308ea82e068442ac690aab2e1276828215758ff85d72a042442ae06efe3", + "blockHash": "0x5aa8ba07a9e00dc54aea96f3f6dfc416eaef85e40c2a781237fb0c0eb88ca31f", + "transactionHash": "0x445278016ddb22a62ecad28a1289be911a5af65f5c634af02420955352083836", "logs": [], - "blockNumber": 6069399, + "blockNumber": 6188439, "cumulativeGasUsed": "904028", "status": 1, "byzantium": true }, "args": [ - "0x5E88C567F60466cdCA5c9C331090bBB7391fd70a" + "0x86Aa8EBc207134BC4965Cabc5f5C57559Fd5A325" ], - "numDeployments": 1, - "solcInputHash": "d2a2160297444b93438826228d1e185d", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getMinimumValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getSample\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VelocimeterLibrary.sol\":\"VelocimeterLibrary\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VelocimeterLibrary.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\n\\ncontract VelocimeterLibrary {\\n IRouter internal immutable router;\\n\\n constructor(address _router) {\\n router = IRouter(_router);\\n }\\n\\n function _f(uint x0, uint y) internal pure returns (uint) {\\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\\n }\\n\\n function _d(uint x0, uint y) internal pure returns (uint) {\\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\\n }\\n\\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\\n for (uint i = 0; i < 255; i++) {\\n uint y_prev = y;\\n uint k = _f(x0, y);\\n if (k < xy) {\\n uint dy = (xy - k)*1e18/_d(x0, y);\\n y = y + dy;\\n } else {\\n uint dy = (k - xy)*1e18/_d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n }\\n\\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return (sample, r0, r1);\\n }\\n\\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\\n if (stable) {\\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\\n _reserve0 = _reserve0 * 1e18 / decimals0;\\n _reserve1 = _reserve1 * 1e18 / decimals1;\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\\n } else {\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n return amountIn * reserveB / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\\n if (stable) {\\n uint _x = x * 1e18 / decimals0;\\n uint _y = y * 1e18 / decimals1;\\n uint _a = (_x * _y) / 1e18;\\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return _a * _b / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n \\n}\\n\",\"keccak256\":\"0x8fa888fd7bda7d3d44a2cc0fd62aeb594c767907f24e7cd390a5fe998d60f388\",\"license\":\"MIT\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"}},\"version\":1}", - "bytecode": "0x60a060405234801561001057600080fd5b5060405161100238038061100283398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051610f626100a06000396000818161010c015281816102730152818161043701526105cb0152610f626000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea2646970667358221220af3305b69464063ea72cd6f5a279509086a4a4891a18d5b72ebe271acc1e08d364736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea2646970667358221220af3305b69464063ea72cd6f5a279509086a4a4891a18d5b72ebe271acc1e08d364736f6c634300080d0033", + "numDeployments": 2, + "solcInputHash": "6e27611a2cedd773c4cc6e46935e6392", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getMinimumValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getSample\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VelocimeterLibrary.sol\":\"VelocimeterLibrary\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735303535373437363232\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VelocimeterLibrary.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\n\\ncontract VelocimeterLibrary {\\n IRouter internal immutable router;\\n\\n constructor(address _router) {\\n router = IRouter(_router);\\n }\\n\\n function _f(uint x0, uint y) internal pure returns (uint) {\\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\\n }\\n\\n function _d(uint x0, uint y) internal pure returns (uint) {\\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\\n }\\n\\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\\n for (uint i = 0; i < 255; i++) {\\n uint y_prev = y;\\n uint k = _f(x0, y);\\n if (k < xy) {\\n uint dy = (xy - k)*1e18/_d(x0, y);\\n y = y + dy;\\n } else {\\n uint dy = (k - xy)*1e18/_d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n }\\n\\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return (sample, r0, r1);\\n }\\n\\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\\n if (stable) {\\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\\n _reserve0 = _reserve0 * 1e18 / decimals0;\\n _reserve1 = _reserve1 * 1e18 / decimals1;\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\\n } else {\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n return amountIn * reserveB / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\\n if (stable) {\\n uint _x = x * 1e18 / decimals0;\\n uint _y = y * 1e18 / decimals1;\\n uint _a = (_x * _y) / 1e18;\\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return _a * _b / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n \\n}\\n\",\"keccak256\":\"0x8fa888fd7bda7d3d44a2cc0fd62aeb594c767907f24e7cd390a5fe998d60f388\",\"license\":\"MIT\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"}},\"version\":1}", + "bytecode": "0x60a060405234801561001057600080fd5b5060405161100238038061100283398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051610f626100a06000396000818161010c015281816102730152818161043701526105cb0152610f626000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea2646970667358221220883d9f758b4d70628b0728b78b2e45d8098268c7ed6c83df96bc8bad69590df464736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea2646970667358221220883d9f758b4d70628b0728b78b2e45d8098268c7ed6c83df96bc8bad69590df464736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumGoerli/Voter.json b/deployments/arbitrumGoerli/Voter.json index 413eeafe..26dc0ec7 100644 --- a/deployments/arbitrumGoerli/Voter.json +++ b/deployments/arbitrumGoerli/Voter.json @@ -1,5 +1,5 @@ { - "address": "0x04c989FB4768739Fbd62FC1f77D06ae3c1E5eC36", + "address": "0x809BCB4AC4c77F9F2B075ca9f29e160E8939D35f", "abi": [ { "inputs": [ @@ -1141,33 +1141,33 @@ "type": "function" } ], - "transactionHash": "0x3dc77529d2eda4399520704a61c0b112dc589b5282a811c626de39141207eb9c", + "transactionHash": "0xc7a89ae95f6266f5b11ace4896ee2f7f6ef2d2811ebfc58db2aa336f222cbcf3", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x04c989FB4768739Fbd62FC1f77D06ae3c1E5eC36", + "contractAddress": "0x809BCB4AC4c77F9F2B075ca9f29e160E8939D35f", "transactionIndex": 1, - "gasUsed": "3013796", + "gasUsed": "3013820", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xe4a31a974213d9527d10f75839c65c6d302673e5dc4312f1d1d03d136eb75598", - "transactionHash": "0x3dc77529d2eda4399520704a61c0b112dc589b5282a811c626de39141207eb9c", + "blockHash": "0xadbc9fa9ad293eda7ab9e75826675949e344db0e53f6d6b538ce9aed878db3c7", + "transactionHash": "0xc7a89ae95f6266f5b11ace4896ee2f7f6ef2d2811ebfc58db2aa336f222cbcf3", "logs": [], - "blockNumber": 6069432, - "cumulativeGasUsed": "3013796", + "blockNumber": 6188465, + "cumulativeGasUsed": "3013820", "status": 1, "byzantium": true }, "args": [ - "0x6d55AFbF1cAf01E0bcA5255bbA730da6fAFD0aF4", - "0x5c7C6ee91569E2658c3A52f47b35E1AAB7e8e600", - "0xdEA300B2495790ccc75c6918A302E1952e9c2339", - "0x751B8A4792de90f5c774032f688bcAFA976b78d2" + "0x38c8250FF6bD87812eDc5aAee577836c2B3c2aE6", + "0x22E98754dBa170A64724558E668cb380516e0BE9", + "0x3d396484a6a2759074dD879865c22Ac939C4a711", + "0xb506F3C710Dbb31177A128d73bDA1D99b90512F2" ], - "numDeployments": 1, - "solcInputHash": "d2a2160297444b93438826228d1e185d", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_gauges\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_bribes\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Abstained\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Attach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Detach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributeReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"internal_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"external_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"name\":\"GaugeCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeKilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeRevived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"reward\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NotifyReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Voted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"whitelister\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"Whitelisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"attachTokenToGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bribefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_bribes\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimBribes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_fees\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"}],\"name\":\"claimRewards\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"detachTokenFromGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"finish\",\"type\":\"uint256\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distributeFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distro\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"emergencyCouncil\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"external_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gaugefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"gauges\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_tokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"internal_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isAlive\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isGauge\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isWhitelisted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"killGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"lastVoted\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"length\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"notifyRewardAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"poke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolForGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"poolVote\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"reset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"reviveGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_council\",\"type\":\"address\"}],\"name\":\"setEmergencyCouncil\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"setGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalWeight\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"updateFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"name\":\"updateForRange\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"updateGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedWeights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"_poolVote\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_weights\",\"type\":\"uint256[]\"}],\"name\":\"vote\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"votes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"weights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"whitelist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Voter.sol\":\"Voter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Voter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/libraries/Math.sol';\\nimport 'contracts/interfaces/IBribe.sol';\\nimport 'contracts/interfaces/IBribeFactory.sol';\\nimport 'contracts/interfaces/IGauge.sol';\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/interfaces/IERC20.sol';\\nimport 'contracts/interfaces/IMinter.sol';\\nimport 'contracts/interfaces/IPair.sol';\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/interfaces/IVoter.sol';\\nimport 'contracts/interfaces/IVotingEscrow.sol';\\n\\ncontract Voter is IVoter {\\n\\n address public immutable _ve; // the ve token that governs these contracts\\n address public immutable factory; // the PairFactory\\n address internal immutable base;\\n address public immutable gaugefactory;\\n address public immutable bribefactory;\\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\\n address public minter;\\n address public governor; // should be set to an IGovernor\\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\\n\\n uint public totalWeight; // total voting weight\\n\\n address[] public pools; // all pools viable for incentives\\n mapping(address => address) public gauges; // pool => gauge\\n mapping(address => address) public poolForGauge; // gauge => pool\\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\\n mapping(address => uint256) public weights; // pool => weight\\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\\n mapping(uint => address[]) public poolVote; // nft => pools\\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\\n mapping(address => bool) public isGauge;\\n mapping(address => bool) public isWhitelisted;\\n mapping(address => bool) public isAlive;\\n\\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\\n event GaugeKilled(address indexed gauge);\\n event GaugeRevived(address indexed gauge);\\n event Voted(address indexed voter, uint tokenId, uint256 weight);\\n event Abstained(uint tokenId, uint256 weight);\\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\\n event Whitelisted(address indexed whitelister, address indexed token);\\n\\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\\n _ve = __ve;\\n factory = _factory;\\n base = IVotingEscrow(__ve).token();\\n gaugefactory = _gauges;\\n bribefactory = _bribes;\\n minter = msg.sender;\\n governor = msg.sender;\\n emergencyCouncil = msg.sender;\\n }\\n\\n // simple re-entrancy check\\n uint internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n modifier onlyNewEpoch(uint _tokenId) {\\n // ensure new epoch since last vote \\n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \\\"TOKEN_ALREADY_VOTED_THIS_EPOCH\\\");\\n _;\\n }\\n\\n function initialize(address[] memory _tokens, address _minter) external {\\n require(msg.sender == minter);\\n for (uint i = 0; i < _tokens.length; i++) {\\n _whitelist(_tokens[i]);\\n }\\n minter = _minter;\\n }\\n\\n function setGovernor(address _governor) public {\\n require(msg.sender == governor);\\n governor = _governor;\\n }\\n\\n function setEmergencyCouncil(address _council) public {\\n require(msg.sender == emergencyCouncil);\\n emergencyCouncil = _council;\\n }\\n\\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n lastVoted[_tokenId] = block.timestamp;\\n _reset(_tokenId);\\n IVotingEscrow(_ve).abstain(_tokenId);\\n }\\n\\n function _reset(uint _tokenId) internal {\\n address[] storage _poolVote = poolVote[_tokenId];\\n uint _poolVoteCnt = _poolVote.length;\\n uint256 _totalWeight = 0;\\n\\n for (uint i = 0; i < _poolVoteCnt; i ++) {\\n address _pool = _poolVote[i];\\n uint256 _votes = votes[_tokenId][_pool];\\n\\n if (_votes != 0) {\\n _updateFor(gauges[_pool]);\\n weights[_pool] -= _votes;\\n votes[_tokenId][_pool] -= _votes;\\n if (_votes > 0) {\\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n _totalWeight += _votes;\\n } else {\\n _totalWeight -= _votes;\\n }\\n emit Abstained(_tokenId, _votes);\\n }\\n }\\n totalWeight -= uint256(_totalWeight);\\n usedWeights[_tokenId] = 0;\\n delete poolVote[_tokenId];\\n }\\n\\n function poke(uint _tokenId) external {\\n address[] memory _poolVote = poolVote[_tokenId];\\n uint _poolCnt = _poolVote.length;\\n uint256[] memory _weights = new uint256[](_poolCnt);\\n\\n for (uint i = 0; i < _poolCnt; i ++) {\\n _weights[i] = votes[_tokenId][_poolVote[i]];\\n }\\n\\n _vote(_tokenId, _poolVote, _weights);\\n }\\n\\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\\n _reset(_tokenId);\\n uint _poolCnt = _poolVote.length;\\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\\n uint256 _totalVoteWeight = 0;\\n uint256 _totalWeight = 0;\\n uint256 _usedWeight = 0;\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n _totalVoteWeight += _weights[i];\\n }\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n address _pool = _poolVote[i];\\n address _gauge = gauges[_pool];\\n\\n if (isGauge[_gauge]) {\\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\\n require(votes[_tokenId][_pool] == 0);\\n require(_poolWeight != 0);\\n _updateFor(_gauge);\\n\\n poolVote[_tokenId].push(_pool);\\n\\n weights[_pool] += _poolWeight;\\n votes[_tokenId][_pool] += _poolWeight;\\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n _usedWeight += _poolWeight;\\n _totalWeight += _poolWeight;\\n emit Voted(msg.sender, _tokenId, _poolWeight);\\n }\\n }\\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\\n totalWeight += uint256(_totalWeight);\\n usedWeights[_tokenId] = uint256(_usedWeight);\\n }\\n\\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n require(_poolVote.length == _weights.length);\\n lastVoted[tokenId] = block.timestamp;\\n _vote(tokenId, _poolVote, _weights);\\n }\\n\\n function whitelist(address _token) public {\\n require(msg.sender == governor);\\n _whitelist(_token);\\n }\\n\\n function _whitelist(address _token) internal {\\n require(!isWhitelisted[_token]);\\n isWhitelisted[_token] = true;\\n emit Whitelisted(msg.sender, _token);\\n }\\n\\n function createGauge(address _pool) external returns (address) {\\n require(gauges[_pool] == address(0x0), \\\"exists\\\");\\n address[] memory allowedRewards = new address[](3);\\n address[] memory internalRewards = new address[](2);\\n bool isPair = IPairFactory(factory).isPair(_pool);\\n address tokenA;\\n address tokenB;\\n\\n if (isPair) {\\n (tokenA, tokenB) = IPair(_pool).tokens();\\n allowedRewards[0] = tokenA;\\n allowedRewards[1] = tokenB;\\n internalRewards[0] = tokenA;\\n internalRewards[1] = tokenB;\\n\\n if (base != tokenA && base != tokenB) {\\n allowedRewards[2] = base;\\n }\\n }\\n\\n if (msg.sender != governor) { // gov can create for any pool, even non-Velocimeter pairs\\n require(isPair, \\\"!_pool\\\");\\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \\\"!whitelisted\\\");\\n }\\n\\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\\n\\n IERC20(base).approve(_gauge, type(uint).max);\\n internal_bribes[_gauge] = _internal_bribe;\\n external_bribes[_gauge] = _external_bribe;\\n gauges[_pool] = _gauge;\\n poolForGauge[_gauge] = _pool;\\n isGauge[_gauge] = true;\\n isAlive[_gauge] = true;\\n _updateFor(_gauge);\\n pools.push(_pool);\\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\\n return _gauge;\\n }\\n\\n function killGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(isAlive[_gauge], \\\"gauge already dead\\\");\\n isAlive[_gauge] = false;\\n claimable[_gauge] = 0;\\n emit GaugeKilled(_gauge);\\n }\\n\\n function reviveGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(!isAlive[_gauge], \\\"gauge already alive\\\");\\n isAlive[_gauge] = true;\\n emit GaugeRevived(_gauge);\\n }\\n\\n function attachTokenToGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\\n emit Attach(account, msg.sender, tokenId);\\n }\\n\\n function emitDeposit(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]);\\n emit Deposit(account, msg.sender, tokenId, amount);\\n }\\n\\n function detachTokenFromGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\\n emit Detach(account, msg.sender, tokenId);\\n }\\n\\n function emitWithdraw(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n emit Withdraw(account, msg.sender, tokenId, amount);\\n }\\n\\n function length() external view returns (uint) {\\n return pools.length;\\n }\\n\\n uint internal index;\\n mapping(address => uint) internal supplyIndex;\\n mapping(address => uint) public claimable;\\n\\n function notifyRewardAmount(uint amount) external {\\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index += _ratio;\\n }\\n emit NotifyReward(msg.sender, base, amount);\\n }\\n\\n function updateFor(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n _updateFor(_gauges[i]);\\n }\\n }\\n\\n function updateForRange(uint start, uint end) public {\\n for (uint i = start; i < end; i++) {\\n _updateFor(gauges[pools[i]]);\\n }\\n }\\n\\n function updateAll() external {\\n updateForRange(0, pools.length);\\n }\\n\\n function updateGauge(address _gauge) external {\\n _updateFor(_gauge);\\n }\\n\\n function _updateFor(address _gauge) internal {\\n address _pool = poolForGauge[_gauge];\\n uint256 _supplied = weights[_pool];\\n if (_supplied > 0) {\\n uint _supplyIndex = supplyIndex[_gauge];\\n uint _index = index; // get global index0 for accumulated distro\\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\\n if (_delta > 0) {\\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\\n if (isAlive[_gauge]) {\\n claimable[_gauge] += _share;\\n }\\n }\\n } else {\\n supplyIndex[_gauge] = index; // new users are set to the default global state\\n }\\n }\\n\\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\\n }\\n }\\n\\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _bribes.length; i++) {\\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _fees.length; i++) {\\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function distributeFees(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n if (IGauge(_gauges[i]).isForPair()){\\n IGauge(_gauges[i]).claimFees();\\n }\\n }\\n }\\n\\n function distribute(address _gauge) public lock {\\n IMinter(minter).update_period();\\n _updateFor(_gauge); // should set claimable to 0 if killed\\n uint _claimable = claimable[_gauge];\\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\\n claimable[_gauge] = 0;\\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\\n emit DistributeReward(msg.sender, _gauge, _claimable);\\n }\\n }\\n\\n function distro() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute(uint start, uint finish) public {\\n for (uint x = start; x < finish; x++) {\\n distribute(gauges[pools[x]]);\\n }\\n }\\n\\n function distribute(address[] memory _gauges) external {\\n for (uint x = 0; x < _gauges.length; x++) {\\n distribute(_gauges[x]);\\n }\\n }\\n\\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x16f98751f0144d1758ecb2bec2062be56c718e18d65f0b948fd2a1404b37e6f8\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x61012060405260016011553480156200001757600080fd5b5060405162003656380380620036568339810160408190526200003a916200011c565b6001600160a01b03808516608081905290841660a05260408051637e062a3560e11b8152905163fc0c546a916004808201926020929091908290030181865afa1580156200008c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b2919062000179565b6001600160a01b0390811660c05291821660e0521661010052505060008054336001600160a01b03199182168117909255600180548216831790556002805490911690911790556200019e565b80516001600160a01b03811681146200011757600080fd5b919050565b600080600080608085870312156200013357600080fd5b6200013e85620000ff565b93506200014e60208601620000ff565b92506200015e60408601620000ff565b91506200016e60608601620000ff565b905092959194509250565b6000602082840312156200018c57600080fd5b6200019782620000ff565b9392505050565b60805160a05160c05160e051610100516133e062000276600039600081816103e701528181611c680152611ce60152600081816104d30152611d79015260008181610b9401528181610c0d01528181610edd01528181610f9901528181611acd01528181611b0601528181611b380152611e5a0152600081816106fc015261192401526000818161058c0152818161092b015281816109d701528181610c9a01528181611069015281816111ea0152818161131a015281816114d901528181611dab015281816125e501526129a801526133e06000f3fe608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea26469706673582212205e5525f027f33aeaba46aa3ccebb40d0e06be6975265ddae6ddb36ab444278f264736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea26469706673582212205e5525f027f33aeaba46aa3ccebb40d0e06be6975265ddae6ddb36ab444278f264736f6c634300080d0033", + "numDeployments": 2, + "solcInputHash": "6e27611a2cedd773c4cc6e46935e6392", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_gauges\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_bribes\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Abstained\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Attach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Detach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributeReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"internal_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"external_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"name\":\"GaugeCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeKilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeRevived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"reward\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NotifyReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Voted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"whitelister\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"Whitelisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"attachTokenToGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bribefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_bribes\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimBribes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_fees\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"}],\"name\":\"claimRewards\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"detachTokenFromGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"finish\",\"type\":\"uint256\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distributeFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distro\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"emergencyCouncil\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"external_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gaugefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"gauges\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_tokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"internal_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isAlive\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isGauge\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isWhitelisted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"killGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"lastVoted\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"length\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"notifyRewardAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"poke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolForGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"poolVote\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"reset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"reviveGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_council\",\"type\":\"address\"}],\"name\":\"setEmergencyCouncil\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"setGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalWeight\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"updateFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"name\":\"updateForRange\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"updateGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedWeights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"_poolVote\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_weights\",\"type\":\"uint256[]\"}],\"name\":\"vote\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"votes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"weights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"whitelist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Voter.sol\":\"Voter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735303535373437363232\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Voter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/libraries/Math.sol';\\nimport 'contracts/interfaces/IBribe.sol';\\nimport 'contracts/interfaces/IBribeFactory.sol';\\nimport 'contracts/interfaces/IGauge.sol';\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/interfaces/IERC20.sol';\\nimport 'contracts/interfaces/IMinter.sol';\\nimport 'contracts/interfaces/IPair.sol';\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/interfaces/IVoter.sol';\\nimport 'contracts/interfaces/IVotingEscrow.sol';\\n\\ncontract Voter is IVoter {\\n\\n address public immutable _ve; // the ve token that governs these contracts\\n address public immutable factory; // the PairFactory\\n address internal immutable base;\\n address public immutable gaugefactory;\\n address public immutable bribefactory;\\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\\n address public minter;\\n address public governor; // should be set to an IGovernor\\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\\n\\n uint public totalWeight; // total voting weight\\n\\n address[] public pools; // all pools viable for incentives\\n mapping(address => address) public gauges; // pool => gauge\\n mapping(address => address) public poolForGauge; // gauge => pool\\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\\n mapping(address => uint256) public weights; // pool => weight\\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\\n mapping(uint => address[]) public poolVote; // nft => pools\\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\\n mapping(address => bool) public isGauge;\\n mapping(address => bool) public isWhitelisted;\\n mapping(address => bool) public isAlive;\\n\\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\\n event GaugeKilled(address indexed gauge);\\n event GaugeRevived(address indexed gauge);\\n event Voted(address indexed voter, uint tokenId, uint256 weight);\\n event Abstained(uint tokenId, uint256 weight);\\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\\n event Whitelisted(address indexed whitelister, address indexed token);\\n\\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\\n _ve = __ve;\\n factory = _factory;\\n base = IVotingEscrow(__ve).token();\\n gaugefactory = _gauges;\\n bribefactory = _bribes;\\n minter = msg.sender;\\n governor = msg.sender;\\n emergencyCouncil = msg.sender;\\n }\\n\\n // simple re-entrancy check\\n uint internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n modifier onlyNewEpoch(uint _tokenId) {\\n // ensure new epoch since last vote \\n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \\\"TOKEN_ALREADY_VOTED_THIS_EPOCH\\\");\\n _;\\n }\\n\\n function initialize(address[] memory _tokens, address _minter) external {\\n require(msg.sender == minter);\\n for (uint i = 0; i < _tokens.length; i++) {\\n _whitelist(_tokens[i]);\\n }\\n minter = _minter;\\n }\\n\\n function setGovernor(address _governor) public {\\n require(msg.sender == governor);\\n governor = _governor;\\n }\\n\\n function setEmergencyCouncil(address _council) public {\\n require(msg.sender == emergencyCouncil);\\n emergencyCouncil = _council;\\n }\\n\\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n lastVoted[_tokenId] = block.timestamp;\\n _reset(_tokenId);\\n IVotingEscrow(_ve).abstain(_tokenId);\\n }\\n\\n function _reset(uint _tokenId) internal {\\n address[] storage _poolVote = poolVote[_tokenId];\\n uint _poolVoteCnt = _poolVote.length;\\n uint256 _totalWeight = 0;\\n\\n for (uint i = 0; i < _poolVoteCnt; i ++) {\\n address _pool = _poolVote[i];\\n uint256 _votes = votes[_tokenId][_pool];\\n\\n if (_votes != 0) {\\n _updateFor(gauges[_pool]);\\n weights[_pool] -= _votes;\\n votes[_tokenId][_pool] -= _votes;\\n if (_votes > 0) {\\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n _totalWeight += _votes;\\n } else {\\n _totalWeight -= _votes;\\n }\\n emit Abstained(_tokenId, _votes);\\n }\\n }\\n totalWeight -= uint256(_totalWeight);\\n usedWeights[_tokenId] = 0;\\n delete poolVote[_tokenId];\\n }\\n\\n function poke(uint _tokenId) external {\\n address[] memory _poolVote = poolVote[_tokenId];\\n uint _poolCnt = _poolVote.length;\\n uint256[] memory _weights = new uint256[](_poolCnt);\\n\\n for (uint i = 0; i < _poolCnt; i ++) {\\n _weights[i] = votes[_tokenId][_poolVote[i]];\\n }\\n\\n _vote(_tokenId, _poolVote, _weights);\\n }\\n\\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\\n _reset(_tokenId);\\n uint _poolCnt = _poolVote.length;\\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\\n uint256 _totalVoteWeight = 0;\\n uint256 _totalWeight = 0;\\n uint256 _usedWeight = 0;\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n _totalVoteWeight += _weights[i];\\n }\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n address _pool = _poolVote[i];\\n address _gauge = gauges[_pool];\\n\\n if (isGauge[_gauge]) {\\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\\n require(votes[_tokenId][_pool] == 0);\\n require(_poolWeight != 0);\\n _updateFor(_gauge);\\n\\n poolVote[_tokenId].push(_pool);\\n\\n weights[_pool] += _poolWeight;\\n votes[_tokenId][_pool] += _poolWeight;\\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n _usedWeight += _poolWeight;\\n _totalWeight += _poolWeight;\\n emit Voted(msg.sender, _tokenId, _poolWeight);\\n }\\n }\\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\\n totalWeight += uint256(_totalWeight);\\n usedWeights[_tokenId] = uint256(_usedWeight);\\n }\\n\\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n require(_poolVote.length == _weights.length);\\n lastVoted[tokenId] = block.timestamp;\\n _vote(tokenId, _poolVote, _weights);\\n }\\n\\n function whitelist(address _token) public {\\n require(msg.sender == governor);\\n _whitelist(_token);\\n }\\n\\n function _whitelist(address _token) internal {\\n require(!isWhitelisted[_token]);\\n isWhitelisted[_token] = true;\\n emit Whitelisted(msg.sender, _token);\\n }\\n\\n function createGauge(address _pool) external returns (address) {\\n require(gauges[_pool] == address(0x0), \\\"exists\\\");\\n address[] memory allowedRewards = new address[](3);\\n address[] memory internalRewards = new address[](2);\\n bool isPair = IPairFactory(factory).isPair(_pool);\\n address tokenA;\\n address tokenB;\\n\\n if (isPair) {\\n (tokenA, tokenB) = IPair(_pool).tokens();\\n allowedRewards[0] = tokenA;\\n allowedRewards[1] = tokenB;\\n internalRewards[0] = tokenA;\\n internalRewards[1] = tokenB;\\n\\n if (base != tokenA && base != tokenB) {\\n allowedRewards[2] = base;\\n }\\n }\\n\\n if (msg.sender != governor) { // gov can create for any pool, even non-Velocimeter pairs\\n require(isPair, \\\"!_pool\\\");\\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \\\"!whitelisted\\\");\\n }\\n\\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\\n\\n IERC20(base).approve(_gauge, type(uint).max);\\n internal_bribes[_gauge] = _internal_bribe;\\n external_bribes[_gauge] = _external_bribe;\\n gauges[_pool] = _gauge;\\n poolForGauge[_gauge] = _pool;\\n isGauge[_gauge] = true;\\n isAlive[_gauge] = true;\\n _updateFor(_gauge);\\n pools.push(_pool);\\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\\n return _gauge;\\n }\\n\\n function killGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(isAlive[_gauge], \\\"gauge already dead\\\");\\n isAlive[_gauge] = false;\\n claimable[_gauge] = 0;\\n emit GaugeKilled(_gauge);\\n }\\n\\n function reviveGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(!isAlive[_gauge], \\\"gauge already alive\\\");\\n isAlive[_gauge] = true;\\n emit GaugeRevived(_gauge);\\n }\\n\\n function attachTokenToGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\\n emit Attach(account, msg.sender, tokenId);\\n }\\n\\n function emitDeposit(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]);\\n emit Deposit(account, msg.sender, tokenId, amount);\\n }\\n\\n function detachTokenFromGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\\n emit Detach(account, msg.sender, tokenId);\\n }\\n\\n function emitWithdraw(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n emit Withdraw(account, msg.sender, tokenId, amount);\\n }\\n\\n function length() external view returns (uint) {\\n return pools.length;\\n }\\n\\n uint internal index;\\n mapping(address => uint) internal supplyIndex;\\n mapping(address => uint) public claimable;\\n\\n function notifyRewardAmount(uint amount) external {\\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index += _ratio;\\n }\\n emit NotifyReward(msg.sender, base, amount);\\n }\\n\\n function updateFor(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n _updateFor(_gauges[i]);\\n }\\n }\\n\\n function updateForRange(uint start, uint end) public {\\n for (uint i = start; i < end; i++) {\\n _updateFor(gauges[pools[i]]);\\n }\\n }\\n\\n function updateAll() external {\\n updateForRange(0, pools.length);\\n }\\n\\n function updateGauge(address _gauge) external {\\n _updateFor(_gauge);\\n }\\n\\n function _updateFor(address _gauge) internal {\\n address _pool = poolForGauge[_gauge];\\n uint256 _supplied = weights[_pool];\\n if (_supplied > 0) {\\n uint _supplyIndex = supplyIndex[_gauge];\\n uint _index = index; // get global index0 for accumulated distro\\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\\n if (_delta > 0) {\\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\\n if (isAlive[_gauge]) {\\n claimable[_gauge] += _share;\\n }\\n }\\n } else {\\n supplyIndex[_gauge] = index; // new users are set to the default global state\\n }\\n }\\n\\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\\n }\\n }\\n\\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _bribes.length; i++) {\\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _fees.length; i++) {\\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function distributeFees(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n if (IGauge(_gauges[i]).isForPair()){\\n IGauge(_gauges[i]).claimFees();\\n }\\n }\\n }\\n\\n function distribute(address _gauge) public lock {\\n IMinter(minter).update_period();\\n _updateFor(_gauge); // should set claimable to 0 if killed\\n uint _claimable = claimable[_gauge];\\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\\n claimable[_gauge] = 0;\\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\\n emit DistributeReward(msg.sender, _gauge, _claimable);\\n }\\n }\\n\\n function distro() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute(uint start, uint finish) public {\\n for (uint x = start; x < finish; x++) {\\n distribute(gauges[pools[x]]);\\n }\\n }\\n\\n function distribute(address[] memory _gauges) external {\\n for (uint x = 0; x < _gauges.length; x++) {\\n distribute(_gauges[x]);\\n }\\n }\\n\\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x16f98751f0144d1758ecb2bec2062be56c718e18d65f0b948fd2a1404b37e6f8\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x61012060405260016011553480156200001757600080fd5b5060405162003656380380620036568339810160408190526200003a916200011c565b6001600160a01b03808516608081905290841660a05260408051637e062a3560e11b8152905163fc0c546a916004808201926020929091908290030181865afa1580156200008c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b2919062000179565b6001600160a01b0390811660c05291821660e0521661010052505060008054336001600160a01b03199182168117909255600180548216831790556002805490911690911790556200019e565b80516001600160a01b03811681146200011757600080fd5b919050565b600080600080608085870312156200013357600080fd5b6200013e85620000ff565b93506200014e60208601620000ff565b92506200015e60408601620000ff565b91506200016e60608601620000ff565b905092959194509250565b6000602082840312156200018c57600080fd5b6200019782620000ff565b9392505050565b60805160a05160c05160e051610100516133e062000276600039600081816103e701528181611c680152611ce60152600081816104d30152611d79015260008181610b9401528181610c0d01528181610edd01528181610f9901528181611acd01528181611b0601528181611b380152611e5a0152600081816106fc015261192401526000818161058c0152818161092b015281816109d701528181610c9a01528181611069015281816111ea0152818161131a015281816114d901528181611dab015281816125e501526129a801526133e06000f3fe608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea2646970667358221220c4e52496281d3e327734d86405d756a8437c4e6c0e2f416c5e5e06da9b7e57e064736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea2646970667358221220c4e52496281d3e327734d86405d756a8437c4e6c0e2f416c5e5e06da9b7e57e064736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, @@ -1181,7 +1181,7 @@ "storageLayout": { "storage": [ { - "astId": 14322, + "astId": 14323, "contract": "contracts/Voter.sol:Voter", "label": "minter", "offset": 0, @@ -1189,7 +1189,7 @@ "type": "t_address" }, { - "astId": 14324, + "astId": 14325, "contract": "contracts/Voter.sol:Voter", "label": "governor", "offset": 0, @@ -1197,7 +1197,7 @@ "type": "t_address" }, { - "astId": 14326, + "astId": 14327, "contract": "contracts/Voter.sol:Voter", "label": "emergencyCouncil", "offset": 0, @@ -1205,7 +1205,7 @@ "type": "t_address" }, { - "astId": 14328, + "astId": 14329, "contract": "contracts/Voter.sol:Voter", "label": "totalWeight", "offset": 0, @@ -1213,7 +1213,7 @@ "type": "t_uint256" }, { - "astId": 14331, + "astId": 14332, "contract": "contracts/Voter.sol:Voter", "label": "pools", "offset": 0, @@ -1221,7 +1221,7 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 14335, + "astId": 14336, "contract": "contracts/Voter.sol:Voter", "label": "gauges", "offset": 0, @@ -1229,7 +1229,7 @@ "type": "t_mapping(t_address,t_address)" }, { - "astId": 14339, + "astId": 14340, "contract": "contracts/Voter.sol:Voter", "label": "poolForGauge", "offset": 0, @@ -1237,7 +1237,7 @@ "type": "t_mapping(t_address,t_address)" }, { - "astId": 14343, + "astId": 14344, "contract": "contracts/Voter.sol:Voter", "label": "internal_bribes", "offset": 0, @@ -1245,7 +1245,7 @@ "type": "t_mapping(t_address,t_address)" }, { - "astId": 14347, + "astId": 14348, "contract": "contracts/Voter.sol:Voter", "label": "external_bribes", "offset": 0, @@ -1253,7 +1253,7 @@ "type": "t_mapping(t_address,t_address)" }, { - "astId": 14351, + "astId": 14352, "contract": "contracts/Voter.sol:Voter", "label": "weights", "offset": 0, @@ -1261,7 +1261,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 14357, + "astId": 14358, "contract": "contracts/Voter.sol:Voter", "label": "votes", "offset": 0, @@ -1269,7 +1269,7 @@ "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))" }, { - "astId": 14362, + "astId": 14363, "contract": "contracts/Voter.sol:Voter", "label": "poolVote", "offset": 0, @@ -1277,7 +1277,7 @@ "type": "t_mapping(t_uint256,t_array(t_address)dyn_storage)" }, { - "astId": 14366, + "astId": 14367, "contract": "contracts/Voter.sol:Voter", "label": "usedWeights", "offset": 0, @@ -1285,7 +1285,7 @@ "type": "t_mapping(t_uint256,t_uint256)" }, { - "astId": 14370, + "astId": 14371, "contract": "contracts/Voter.sol:Voter", "label": "lastVoted", "offset": 0, @@ -1293,7 +1293,7 @@ "type": "t_mapping(t_uint256,t_uint256)" }, { - "astId": 14374, + "astId": 14375, "contract": "contracts/Voter.sol:Voter", "label": "isGauge", "offset": 0, @@ -1301,7 +1301,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 14378, + "astId": 14379, "contract": "contracts/Voter.sol:Voter", "label": "isWhitelisted", "offset": 0, @@ -1309,7 +1309,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 14382, + "astId": 14383, "contract": "contracts/Voter.sol:Voter", "label": "isAlive", "offset": 0, @@ -1317,7 +1317,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 14528, + "astId": 14529, "contract": "contracts/Voter.sol:Voter", "label": "_unlocked", "offset": 0, @@ -1325,7 +1325,7 @@ "type": "t_uint256" }, { - "astId": 15620, + "astId": 15621, "contract": "contracts/Voter.sol:Voter", "label": "index", "offset": 0, @@ -1333,7 +1333,7 @@ "type": "t_uint256" }, { - "astId": 15624, + "astId": 15625, "contract": "contracts/Voter.sol:Voter", "label": "supplyIndex", "offset": 0, @@ -1341,7 +1341,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 15628, + "astId": 15629, "contract": "contracts/Voter.sol:Voter", "label": "claimable", "offset": 0, diff --git a/deployments/arbitrumGoerli/VotingEscrow.json b/deployments/arbitrumGoerli/VotingEscrow.json index 3982df18..a2d236a7 100644 --- a/deployments/arbitrumGoerli/VotingEscrow.json +++ b/deployments/arbitrumGoerli/VotingEscrow.json @@ -1,5 +1,5 @@ { - "address": "0x6d55AFbF1cAf01E0bcA5255bbA730da6fAFD0aF4", + "address": "0x38c8250FF6bD87812eDc5aAee577836c2B3c2aE6", "abi": [ { "inputs": [ @@ -1521,62 +1521,62 @@ "type": "function" } ], - "transactionHash": "0x3270beffcd60bd8139eb66a4fd2befed24efd33fa3ce97ff40823aea884abbce", + "transactionHash": "0xcc3d7381e990dc406a7af4e2219465109ddea5f2000190e4feb327f0b7a0bb23", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x6d55AFbF1cAf01E0bcA5255bbA730da6fAFD0aF4", - "transactionIndex": 2, + "contractAddress": "0x38c8250FF6bD87812eDc5aAee577836c2B3c2aE6", + "transactionIndex": 1, "gasUsed": "4240754", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000020000000000000000000000000000000000000000000020000000000000020000800000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000010000000000000000000000000000000006000000000000000000000000000000000000000020000000000020000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xb2679ecc240d27e76793e4f63ef24aa1bb2e54562033879ec015874ddc119f35", - "transactionHash": "0x3270beffcd60bd8139eb66a4fd2befed24efd33fa3ce97ff40823aea884abbce", + "logsBloom": "0x00000000000000040000000000000000000000800000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000008000000000000000020000000000000000000000000000000020000000000000000000800000000000000000000000010000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x1ac11d1c1115d5c2473f5d63c4036e42e706c7001ce3730100036620cd607072", + "transactionHash": "0xcc3d7381e990dc406a7af4e2219465109ddea5f2000190e4feb327f0b7a0bb23", "logs": [ { - "transactionIndex": 2, - "blockNumber": 6069407, - "transactionHash": "0x3270beffcd60bd8139eb66a4fd2befed24efd33fa3ce97ff40823aea884abbce", - "address": "0x6d55AFbF1cAf01E0bcA5255bbA730da6fAFD0aF4", + "transactionIndex": 1, + "blockNumber": 6188451, + "transactionHash": "0xcc3d7381e990dc406a7af4e2219465109ddea5f2000190e4feb327f0b7a0bb23", + "address": "0x38c8250FF6bD87812eDc5aAee577836c2B3c2aE6", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000006d55afbf1caf01e0bca5255bba730da6fafd0af4", + "0x00000000000000000000000038c8250ff6bd87812edc5aaee577836c2b3c2ae6", "0x0000000000000000000000000000000000000000000000000000000000000000" ], "data": "0x", "logIndex": 0, - "blockHash": "0xb2679ecc240d27e76793e4f63ef24aa1bb2e54562033879ec015874ddc119f35" + "blockHash": "0x1ac11d1c1115d5c2473f5d63c4036e42e706c7001ce3730100036620cd607072" }, { - "transactionIndex": 2, - "blockNumber": 6069407, - "transactionHash": "0x3270beffcd60bd8139eb66a4fd2befed24efd33fa3ce97ff40823aea884abbce", - "address": "0x6d55AFbF1cAf01E0bcA5255bbA730da6fAFD0aF4", + "transactionIndex": 1, + "blockNumber": 6188451, + "transactionHash": "0xcc3d7381e990dc406a7af4e2219465109ddea5f2000190e4feb327f0b7a0bb23", + "address": "0x38c8250FF6bD87812eDc5aAee577836c2B3c2aE6", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x0000000000000000000000006d55afbf1caf01e0bca5255bba730da6fafd0af4", + "0x00000000000000000000000038c8250ff6bd87812edc5aaee577836c2b3c2ae6", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000" ], "data": "0x", "logIndex": 1, - "blockHash": "0xb2679ecc240d27e76793e4f63ef24aa1bb2e54562033879ec015874ddc119f35" + "blockHash": "0x1ac11d1c1115d5c2473f5d63c4036e42e706c7001ce3730100036620cd607072" } ], - "blockNumber": 6069407, - "cumulativeGasUsed": "4288479", + "blockNumber": 6188451, + "cumulativeGasUsed": "4240754", "status": 1, "byzantium": true }, "args": [ - "0x4E13914872BFf7e58f3E231b2687fDd084014999", - "0x765df7268ed8Ecd71Cb4bcb70751771eD66c9131" + "0x49E4eA802DdF4CAF7C699782a80DeefdC03Dcb4B", + "0x820D1Dc5A5B63490cBC521E18be5Aa948f49FDD0" ], - "numDeployments": 1, - "solcInputHash": "d2a2160297444b93438826228d1e185d", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token_addr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"art_proxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromDelegate\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toDelegate\",\"type\":\"address\"}],\"name\":\"DelegateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"DelegateVotesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"locktime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum VotingEscrow.DepositType\",\"name\":\"deposit_type\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"prevSupply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"supply\",\"type\":\"uint256\"}],\"name\":\"Supply\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DELEGATION_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_DELEGATES\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"abstain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_approved\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"artProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"attach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"attachments\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"balanceOfAtNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_t\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFTAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"block_number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"checkpoints\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"create_lock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"create_lock_for\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"}],\"name\":\"delegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"delegateBySig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"}],\"name\":\"delegates\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"deposit_for\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"detach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastTotalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotesIndex\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"get_last_user_slope\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"increase_amount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"increase_unlock_time\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"isApprovedOrOwner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"locked\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"amount\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"locked__end\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_from\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_to\",\"type\":\"uint256\"}],\"name\":\"merge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"numCheckpoints\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ownership_change\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_proxy\",\"type\":\"address\"}],\"name\":\"setArtProxy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voter\",\"type\":\"address\"}],\"name\":\"setVoter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"slope_changes\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenIndex\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"t\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAtT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_idx\",\"type\":\"uint256\"}],\"name\":\"user_point_history__ts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"voted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"voting\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\",\"details\":\"Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\",\"kind\":\"dev\",\"methods\":{\"approve(address,uint256)\":{\"details\":\"Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address. Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner. Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP) Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"Address to be approved for the given NFT ID.\",\"_tokenId\":\"ID of the token to be approved.\"}},\"balanceOf(address)\":{\"details\":\"Returns the number of NFTs owned by `_owner`. Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\",\"params\":{\"_owner\":\"Address for whom to query the balance.\"}},\"constructor\":{\"params\":{\"token_addr\":\"`FLOW` token address\"}},\"create_lock(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_value\":\"Amount to deposit\"}},\"create_lock_for(uint256,uint256,address)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_to\":\"Address to deposit\",\"_value\":\"Amount to deposit\"}},\"delegate(address)\":{\"params\":{\"delegatee\":\"The address to delegate votes to\"}},\"delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Delegates votes from signer to `delegatee`.\"},\"deposit_for(uint256,uint256)\":{\"details\":\"Anyone (even a smart contract) can deposit for someone else, but cannot extend their locktime and deposit for a brand new user\",\"params\":{\"_tokenId\":\"lock NFT\",\"_value\":\"Amount to add to user's lock\"}},\"getApproved(uint256)\":{\"details\":\"Get the approved address for a single NFT.\",\"params\":{\"_tokenId\":\"ID of the NFT to query the approval of.\"}},\"getVotes(address)\":{\"params\":{\"account\":\"The address to get votes balance\"},\"returns\":{\"_0\":\"The number of current votes for `account`\"}},\"get_last_user_slope(uint256)\":{\"params\":{\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Value of the slope\"}},\"increase_amount(uint256,uint256)\":{\"params\":{\"_value\":\"Amount of tokens to deposit and add to the lock\"}},\"increase_unlock_time(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"New number of seconds until tokens unlock\"}},\"isApprovedForAll(address,address)\":{\"details\":\"Checks if `_operator` is an approved operator for `_owner`.\",\"params\":{\"_operator\":\"The address that acts on behalf of the owner.\",\"_owner\":\"The address that owns the NFTs.\"}},\"locked__end(uint256)\":{\"params\":{\"_tokenId\":\"User NFT\"},\"returns\":{\"_0\":\"Epoch time of the lock end\"}},\"ownerOf(uint256)\":{\"details\":\"Returns the address of the owner of the NFT.\",\"params\":{\"_tokenId\":\"The identifier for an NFT.\"}},\"safeTransferFrom(address,address,uint256)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"safeTransferFrom(address,address,uint256,bytes)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_data\":\"Additional data with no specified format, sent in call to `_to`.\",\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"details\":\"Enables or disables approval for a third party (\\\"operator\\\") to manage all of `msg.sender`'s assets. It also emits the ApprovalForAll event. Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"True if the operators is approved, false to revoke approval.\",\"_operator\":\"Address to add to the set of authorized operators.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Interface identification is specified in ERC-165.\",\"params\":{\"_interfaceID\":\"Id of the interface\"}},\"tokenOfOwnerByIndex(address,uint256)\":{\"details\":\"Get token by index\"},\"tokenURI(uint256)\":{\"details\":\"Returns current token URI metadata\",\"params\":{\"_tokenId\":\"Token ID to fetch URI for.\"}},\"totalSupplyAt(uint256)\":{\"params\":{\"_block\":\"Block to calculate the total voting power at\"},\"returns\":{\"_0\":\"Total voting power at `_block`\"}},\"totalSupplyAtT(uint256)\":{\"details\":\"Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\",\"returns\":{\"_0\":\"Total voting power\"}},\"transferFrom(address,address,uint256)\":{\"details\":\"Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"user_point_history__ts(uint256,uint256)\":{\"params\":{\"_idx\":\"User epoch number\",\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Epoch time of the checkpoint\"}},\"withdraw(uint256)\":{\"details\":\"Only possible if the lock has expired\"}},\"stateVariables\":{\"ERC165_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC165\"},\"ERC721_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721\"},\"ERC721_METADATA_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721Metadata\"},\"_not_entered\":{\"details\":\"reentrancy guard\"},\"idToApprovals\":{\"details\":\"Mapping from NFT ID to approved address.\"},\"idToOwner\":{\"details\":\"Mapping from NFT ID to the address that owns it.\"},\"name\":{\"details\":\"Returns the token collection name.\"},\"ownerToNFTokenCount\":{\"details\":\"Mapping from owner address to count of his tokens.\"},\"ownerToNFTokenIdList\":{\"details\":\"Mapping from owner address to mapping of index to tokenIds\"},\"ownerToOperators\":{\"details\":\"Mapping from owner address to mapping of operator addresses.\"},\"supportedInterfaces\":{\"details\":\"Mapping of interface id to bool about whether or not it's supported\"},\"symbol\":{\"details\":\"Returns the token collection symbol.\"},\"tokenId\":{\"details\":\"Current count of token\"},\"tokenToOwnerIndex\":{\"details\":\"Mapping from NFT ID to index of owner\"}},\"title\":\"Voting Escrow\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DELEGATION_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the delegation struct used by the contract\"},\"DOMAIN_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the contract's domain\"},\"checkpoint()\":{\"notice\":\"Record global data to checkpoint\"},\"checkpoints(address,uint32)\":{\"notice\":\"A record of delegated token checkpoints for each account, by index\"},\"constructor\":{\"notice\":\"Contract constructor\"},\"create_lock(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\"},\"create_lock_for(uint256,uint256,address)\":{\"notice\":\"Deposit `_value` tokens for `_to` and lock for `_lock_duration`\"},\"delegate(address)\":{\"notice\":\"Delegate votes from `msg.sender` to `delegatee`\"},\"delegates(address)\":{\"notice\":\"Overrides the standard `Comp.sol` delegates mapping to return the delegator's own address if they haven't delegated. This avoids having to delegate to oneself.\"},\"deposit_for(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `_tokenId` and add to the lock\"},\"getVotes(address)\":{\"notice\":\"Gets the current votes balance for `account`\"},\"get_last_user_slope(uint256)\":{\"notice\":\"Get the most recently recorded rate of voting power decrease for `_tokenId`\"},\"increase_amount(uint256,uint256)\":{\"notice\":\"Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\"},\"increase_unlock_time(uint256,uint256)\":{\"notice\":\"Extend the unlock time for `_tokenId`\"},\"locked__end(uint256)\":{\"notice\":\"Get timestamp when `_tokenId`'s lock finishes\"},\"nonces(address)\":{\"notice\":\"A record of states for signing / validating signatures\"},\"numCheckpoints(address)\":{\"notice\":\"The number of checkpoints for each account\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"This works even if sender doesn't own any tokens at the time.\"},\"totalSupplyAt(uint256)\":{\"notice\":\"Calculate total voting power at some point in the past\"},\"totalSupplyAtT(uint256)\":{\"notice\":\"Calculate total voting power\"},\"transferFrom(address,address,uint256)\":{\"notice\":\"The caller is responsible to confirm that `_to` is capable of receiving NFTs or else they maybe be permanently lost.\"},\"user_point_history__ts(uint256,uint256)\":{\"notice\":\"Get the timestamp for checkpoint `_idx` for `_tokenId`\"},\"withdraw(uint256)\":{\"notice\":\"Withdraw all tokens for `_tokenId`\"}},\"notice\":\"veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFTVotes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VotingEscrow.sol\":\"VotingEscrow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363734393838363334363530\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VotingEscrow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IERC721, IERC721Metadata} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {IERC721Receiver} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {IERC20} from \\\"contracts/interfaces/IERC20.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\nimport {IVotingEscrow} from \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/// @title Voting Escrow\\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\\n enum DepositType {\\n DEPOSIT_FOR_TYPE,\\n CREATE_LOCK_TYPE,\\n INCREASE_LOCK_AMOUNT,\\n INCREASE_UNLOCK_TIME,\\n MERGE_TYPE\\n }\\n\\n struct LockedBalance {\\n int128 amount;\\n uint end;\\n }\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint ts;\\n uint blk; // block\\n }\\n /* We cannot really do block numbers per se b/c slope is per time, not per block\\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\\n * What we can do is to extrapolate ***At functions */\\n\\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\\n struct Checkpoint {\\n uint timestamp;\\n uint[] tokenIds;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Deposit(\\n address indexed provider,\\n uint tokenId,\\n uint value,\\n uint indexed locktime,\\n DepositType deposit_type,\\n uint ts\\n );\\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\\n event Supply(uint prevSupply, uint supply);\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n address public immutable token;\\n address public voter;\\n address public team;\\n address public artProxy;\\n\\n mapping(uint => Point) public point_history; // epoch -> unsigned point\\n\\n /// @dev Mapping of interface id to bool about whether or not it's supported\\n mapping(bytes4 => bool) internal supportedInterfaces;\\n\\n /// @dev ERC165 interface ID of ERC165\\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\\n\\n /// @dev ERC165 interface ID of ERC721\\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\\n\\n /// @dev ERC165 interface ID of ERC721Metadata\\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\\n\\n /// @dev Current count of token\\n uint internal tokenId;\\n\\n /// @notice Contract constructor\\n /// @param token_addr `FLOW` token address\\n constructor(address token_addr, address art_proxy) {\\n token = token_addr;\\n voter = msg.sender;\\n team = msg.sender;\\n artProxy = art_proxy;\\n\\n point_history[0].blk = block.number;\\n point_history[0].ts = block.timestamp;\\n\\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\\n\\n // mint-ish\\n emit Transfer(address(0), address(this), tokenId);\\n // burn-ish\\n emit Transfer(address(this), address(0), tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n MODIFIERS\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev reentrancy guard\\n uint8 internal constant _not_entered = 1;\\n uint8 internal constant _entered = 2;\\n uint8 internal _entered_state = 1;\\n modifier nonreentrant() {\\n require(_entered_state == _not_entered);\\n _entered_state = _entered;\\n _;\\n _entered_state = _not_entered;\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string constant public name = \\\"veNFT\\\";\\n string constant public symbol = \\\"veNFT\\\";\\n string constant public version = \\\"1.0.0\\\";\\n uint8 constant public decimals = 18;\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team);\\n team = _team;\\n }\\n\\n function setArtProxy(address _proxy) external {\\n require(msg.sender == team);\\n artProxy = _proxy;\\n }\\n\\n /// @dev Returns current token URI metadata\\n /// @param _tokenId Token ID to fetch URI for.\\n function tokenURI(uint _tokenId) external view returns (string memory) {\\n require(idToOwner[_tokenId] != address(0), \\\"Query for nonexistent token\\\");\\n LockedBalance memory _locked = locked[_tokenId];\\n return IVeArtProxy(artProxy)._tokenURI(\\n _tokenId,\\n _balanceOfNFT(_tokenId, block.timestamp),\\n _locked.end,\\n uint(int256(_locked.amount))\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 BALANCE/OWNER STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to the address that owns it.\\n mapping(uint => address) internal idToOwner;\\n\\n /// @dev Mapping from owner address to count of his tokens.\\n mapping(address => uint) internal ownerToNFTokenCount;\\n\\n /// @dev Returns the address of the owner of the NFT.\\n /// @param _tokenId The identifier for an NFT.\\n function ownerOf(uint _tokenId) public view returns (address) {\\n return idToOwner[_tokenId];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function _balance(address _owner) internal view returns (uint) {\\n return ownerToNFTokenCount[_owner];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function balanceOf(address _owner) external view returns (uint) {\\n return _balance(_owner);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 APPROVAL STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to approved address.\\n mapping(uint => address) internal idToApprovals;\\n\\n /// @dev Mapping from owner address to mapping of operator addresses.\\n mapping(address => mapping(address => bool)) internal ownerToOperators;\\n\\n mapping(uint => uint) public ownership_change;\\n\\n /// @dev Get the approved address for a single NFT.\\n /// @param _tokenId ID of the NFT to query the approval of.\\n function getApproved(uint _tokenId) external view returns (address) {\\n return idToApprovals[_tokenId];\\n }\\n\\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\\n /// @param _owner The address that owns the NFTs.\\n /// @param _operator The address that acts on behalf of the owner.\\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\\n return (ownerToOperators[_owner])[_operator];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\\n /// @param _approved Address to be approved for the given NFT ID.\\n /// @param _tokenId ID of the token to be approved.\\n function approve(address _approved, uint _tokenId) public {\\n address owner = idToOwner[_tokenId];\\n // Throws if `_tokenId` is not a valid NFT\\n require(owner != address(0));\\n // Throws if `_approved` is the current owner\\n require(_approved != owner);\\n // Check requirements\\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\\n require(senderIsOwner || senderIsApprovedForAll);\\n // Set the approval\\n idToApprovals[_tokenId] = _approved;\\n emit Approval(owner, _approved, _tokenId);\\n }\\n\\n /// @dev Enables or disables approval for a third party (\\\"operator\\\") to manage all of\\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\\n /// @notice This works even if sender doesn't own any tokens at the time.\\n /// @param _operator Address to add to the set of authorized operators.\\n /// @param _approved True if the operators is approved, false to revoke approval.\\n function setApprovalForAll(address _operator, bool _approved) external {\\n // Throws if `_operator` is the `msg.sender`\\n assert(_operator != msg.sender);\\n ownerToOperators[msg.sender][_operator] = _approved;\\n emit ApprovalForAll(msg.sender, _operator, _approved);\\n }\\n\\n /* TRANSFER FUNCTIONS */\\n /// @dev Clear an approval of a given address\\n /// Throws if `_owner` is not the current owner.\\n function _clearApproval(address _owner, uint _tokenId) internal {\\n // Throws if `_owner` is not the current owner\\n assert(idToOwner[_tokenId] == _owner);\\n if (idToApprovals[_tokenId] != address(0)) {\\n // Reset approvals\\n idToApprovals[_tokenId] = address(0);\\n }\\n }\\n\\n /// @dev Returns whether the given spender can transfer a given token ID\\n /// @param _spender address of the spender to query\\n /// @param _tokenId uint ID of the token to be transferred\\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\\n address owner = idToOwner[_tokenId];\\n bool spenderIsOwner = owner == _spender;\\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\\n }\\n\\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\\n return _isApprovedOrOwner(_spender, _tokenId);\\n }\\n\\n /// @dev Exeute transfer of a NFT.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_tokenId` is not a valid NFT.\\n function _transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n address _sender\\n ) internal {\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n // Check requirements\\n require(_isApprovedOrOwner(_sender, _tokenId));\\n // Clear approval. Throws if `_from` is not the current owner\\n _clearApproval(_from, _tokenId);\\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\\n _removeTokenFrom(_from, _tokenId);\\n // auto re-delegate\\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\\n // Add NFT\\n _addTokenTo(_to, _tokenId);\\n // Set the block of ownership transfer (for Flash NFT protection)\\n ownership_change[_tokenId] = block.number;\\n // Log the transfer\\n emit Transfer(_from, _to, _tokenId);\\n }\\n\\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\\n /// they maybe be permanently lost.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n safeTransferFrom(_from, _to, _tokenId, \\\"\\\");\\n }\\n\\n function _isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n uint size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n /// @param _data Additional data with no specified format, sent in call to `_to`.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n bytes memory _data\\n ) public {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n\\n if (_isContract(_to)) {\\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\\n revert(\\\"ERC721: ERC721Receiver rejected tokens\\\");\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert('ERC721: transfer to non ERC721Receiver implementer');\\n } else {\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC165 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Interface identification is specified in ERC-165.\\n /// @param _interfaceID Id of the interface\\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\\n return supportedInterfaces[_interfaceID];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from owner address to mapping of index to tokenIds\\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\\n\\n /// @dev Mapping from NFT ID to index of owner\\n mapping(uint => uint) internal tokenToOwnerIndex;\\n\\n /// @dev Get token by index\\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\\n return ownerToNFTokenIdList[_owner][_tokenIndex];\\n }\\n\\n /// @dev Add a NFT to an index mapping to a given address\\n /// @param _to address of the receiver\\n /// @param _tokenId uint ID Of the token to be added\\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\\n uint current_count = _balance(_to);\\n\\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\\n tokenToOwnerIndex[_tokenId] = current_count;\\n }\\n\\n /// @dev Add a NFT to a given address\\n /// Throws if `_tokenId` is owned by someone.\\n function _addTokenTo(address _to, uint _tokenId) internal {\\n // Throws if `_tokenId` is owned by someone\\n assert(idToOwner[_tokenId] == address(0));\\n // Change the owner\\n idToOwner[_tokenId] = _to;\\n // Update owner token index tracking\\n _addTokenToOwnerList(_to, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_to] += 1;\\n }\\n\\n /// @dev Function to mint tokens\\n /// Throws if `_to` is zero address.\\n /// Throws if `_tokenId` is owned by someone.\\n /// @param _to The address that will receive the minted tokens.\\n /// @param _tokenId The token id to mint.\\n /// @return A boolean that indicates if the operation was successful.\\n function _mint(address _to, uint _tokenId) internal returns (bool) {\\n // Throws if `_to` is zero address\\n assert(_to != address(0));\\n // checkpoint for gov\\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\\n // Add NFT. Throws if `_tokenId` is owned by someone\\n _addTokenTo(_to, _tokenId);\\n emit Transfer(address(0), _to, _tokenId);\\n return true;\\n }\\n\\n /// @dev Remove a NFT from an index mapping to a given address\\n /// @param _from address of the sender\\n /// @param _tokenId uint ID Of the token to be removed\\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\\n // Delete\\n uint current_count = _balance(_from) - 1;\\n uint current_index = tokenToOwnerIndex[_tokenId];\\n\\n if (current_count == current_index) {\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n } else {\\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\\n\\n // Add\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[lastTokenId] = current_index;\\n\\n // Delete\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n }\\n }\\n\\n /// @dev Remove a NFT from a given address\\n /// Throws if `_from` is not the current owner.\\n function _removeTokenFrom(address _from, uint _tokenId) internal {\\n // Throws if `_from` is not the current owner\\n assert(idToOwner[_tokenId] == _from);\\n // Change the owner\\n idToOwner[_tokenId] = address(0);\\n // Update owner token index tracking\\n _removeTokenFromOwnerList(_from, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_from] -= 1;\\n }\\n\\n function _burn(uint _tokenId) internal {\\n require(_isApprovedOrOwner(msg.sender, _tokenId), \\\"caller is not owner nor approved\\\");\\n\\n address owner = ownerOf(_tokenId);\\n\\n // Clear approval\\n approve(address(0), _tokenId);\\n // checkpoint for gov\\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\\n // Remove token\\n _removeTokenFrom(msg.sender, _tokenId);\\n emit Transfer(owner, address(0), _tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public user_point_epoch;\\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\\n mapping(uint => LockedBalance) public locked;\\n uint public epoch;\\n mapping(uint => int128) public slope_changes; // time -> signed slope change\\n uint public supply;\\n\\n uint internal constant WEEK = 1 weeks;\\n uint internal constant MAXTIME = 4 * 365 * 86400;\\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\\n uint internal constant MULTIPLIER = 1 ether;\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @return Value of the slope\\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\\n uint uepoch = user_point_epoch[_tokenId];\\n return user_point_history[_tokenId][uepoch].slope;\\n }\\n\\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @param _idx User epoch number\\n /// @return Epoch time of the checkpoint\\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\\n return user_point_history[_tokenId][_idx].ts;\\n }\\n\\n /// @notice Get timestamp when `_tokenId`'s lock finishes\\n /// @param _tokenId User NFT\\n /// @return Epoch time of the lock end\\n function locked__end(uint _tokenId) external view returns (uint) {\\n return locked[_tokenId].end;\\n }\\n\\n /// @notice Record global and per-user data to checkpoint\\n /// @param _tokenId NFT token ID. No user checkpoint if 0\\n /// @param old_locked Pevious locked amount / end lock time for the user\\n /// @param new_locked New locked amount / end lock time for the user\\n function _checkpoint(\\n uint _tokenId,\\n LockedBalance memory old_locked,\\n LockedBalance memory new_locked\\n ) internal {\\n Point memory u_old;\\n Point memory u_new;\\n int128 old_dslope = 0;\\n int128 new_dslope = 0;\\n uint _epoch = epoch;\\n\\n if (_tokenId != 0) {\\n // Calculate slopes and biases\\n // Kept at zero when they have to\\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\\n u_old.slope = old_locked.amount / iMAXTIME;\\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\\n }\\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\\n u_new.slope = new_locked.amount / iMAXTIME;\\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\\n }\\n\\n // Read values of scheduled changes in the slope\\n // old_locked.end can be in the past and in the future\\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\\n old_dslope = slope_changes[old_locked.end];\\n if (new_locked.end != 0) {\\n if (new_locked.end == old_locked.end) {\\n new_dslope = old_dslope;\\n } else {\\n new_dslope = slope_changes[new_locked.end];\\n }\\n }\\n }\\n\\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\\n if (_epoch > 0) {\\n last_point = point_history[_epoch];\\n }\\n uint last_checkpoint = last_point.ts;\\n // initial_last_point is used for extrapolation to calculate block number\\n // (approximately, for *At methods) and save them\\n // as we cannot figure that out exactly from inside the contract\\n Point memory initial_last_point = last_point;\\n uint block_slope = 0; // dblock/dt\\n if (block.timestamp > last_point.ts) {\\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\\n }\\n // If last point is already recorded in this block, slope=0\\n // But that's ok b/c we know the block in such case\\n\\n // Go over weeks to fill history and calculate what the current point is\\n {\\n uint t_i = (last_checkpoint / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n // Hopefully it won't happen that this won't get used in 5 years!\\n // If it does, users will be able to withdraw but vote weight will be broken\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > block.timestamp) {\\n t_i = block.timestamp;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\\n last_point.slope += d_slope;\\n if (last_point.bias < 0) {\\n // This can happen\\n last_point.bias = 0;\\n }\\n if (last_point.slope < 0) {\\n // This cannot happen - just in case\\n last_point.slope = 0;\\n }\\n last_checkpoint = t_i;\\n last_point.ts = t_i;\\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\\n _epoch += 1;\\n if (t_i == block.timestamp) {\\n last_point.blk = block.number;\\n break;\\n } else {\\n point_history[_epoch] = last_point;\\n }\\n }\\n }\\n\\n epoch = _epoch;\\n // Now point_history is filled until t=now\\n\\n if (_tokenId != 0) {\\n // If last point was in this block, the slope change has been applied already\\n // But in such case we have 0 slope(s)\\n last_point.slope += (u_new.slope - u_old.slope);\\n last_point.bias += (u_new.bias - u_old.bias);\\n if (last_point.slope < 0) {\\n last_point.slope = 0;\\n }\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n }\\n\\n // Record the changed point into history\\n point_history[_epoch] = last_point;\\n\\n if (_tokenId != 0) {\\n // Schedule the slope changes (slope is going down)\\n // We subtract new_user_slope from [new_locked.end]\\n // and add old_user_slope to [old_locked.end]\\n if (old_locked.end > block.timestamp) {\\n // old_dslope was - u_old.slope, so we cancel that\\n old_dslope += u_old.slope;\\n if (new_locked.end == old_locked.end) {\\n old_dslope -= u_new.slope; // It was a new deposit, not extension\\n }\\n slope_changes[old_locked.end] = old_dslope;\\n }\\n\\n if (new_locked.end > block.timestamp) {\\n if (new_locked.end > old_locked.end) {\\n new_dslope -= u_new.slope; // old slope disappeared at this point\\n slope_changes[new_locked.end] = new_dslope;\\n }\\n // else: we recorded it already in old_dslope\\n }\\n // Now handle user history\\n uint user_epoch = user_point_epoch[_tokenId] + 1;\\n\\n user_point_epoch[_tokenId] = user_epoch;\\n u_new.ts = block.timestamp;\\n u_new.blk = block.number;\\n user_point_history[_tokenId][user_epoch] = u_new;\\n }\\n }\\n\\n /// @notice Deposit and lock tokens for a user\\n /// @param _tokenId NFT that holds lock\\n /// @param _value Amount to deposit\\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\\n /// @param locked_balance Previous locked amount / timestamp\\n /// @param deposit_type The type of deposit\\n function _deposit_for(\\n uint _tokenId,\\n uint _value,\\n uint unlock_time,\\n LockedBalance memory locked_balance,\\n DepositType deposit_type\\n ) internal {\\n LockedBalance memory _locked = locked_balance;\\n uint supply_before = supply;\\n\\n supply = supply_before + _value;\\n LockedBalance memory old_locked;\\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\\n // Adding to existing lock, or if a lock is expired - creating a new one\\n _locked.amount += int128(int256(_value));\\n if (unlock_time != 0) {\\n _locked.end = unlock_time;\\n }\\n locked[_tokenId] = _locked;\\n\\n // Possibilities:\\n // Both old_locked.end could be current or expired (>/< block.timestamp)\\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\\n // _locked.end > block.timestamp (always)\\n _checkpoint(_tokenId, old_locked, _locked);\\n\\n address from = msg.sender;\\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\\n assert(IERC20(token).transferFrom(from, address(this), _value));\\n }\\n\\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\\n emit Supply(supply_before, supply_before + _value);\\n }\\n\\n function block_number() external view returns (uint) {\\n return block.number;\\n }\\n\\n /// @notice Record global data to checkpoint\\n function checkpoint() external {\\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\\n }\\n\\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\\n /// cannot extend their locktime and deposit for a brand new user\\n /// @param _tokenId lock NFT\\n /// @param _value Amount to add to user's lock\\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n require(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_value > 0); // dev: need non-zero value\\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n ++tokenId;\\n uint _tokenId = tokenId;\\n _mint(_to, _tokenId);\\n\\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\\n return _tokenId;\\n }\\n\\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, msg.sender);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, _to);\\n }\\n\\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\\n /// @param _value Amount of tokens to deposit and add to the lock\\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n assert(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\\n }\\n\\n /// @notice Extend the unlock time for `_tokenId`\\n /// @param _lock_duration New number of seconds until tokens unlock\\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_locked.end > block.timestamp, 'Lock expired');\\n require(_locked.amount > 0, 'Nothing is locked');\\n require(unlock_time > _locked.end, 'Can only increase lock duration');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\\n }\\n\\n /// @notice Withdraw all tokens for `_tokenId`\\n /// @dev Only possible if the lock has expired\\n function withdraw(uint _tokenId) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n require(block.timestamp >= _locked.end, \\\"The lock didn't expire\\\");\\n uint value = uint(int256(_locked.amount));\\n\\n locked[_tokenId] = LockedBalance(0,0);\\n uint supply_before = supply;\\n supply = supply_before - value;\\n\\n // old_locked can have either expired <= timestamp or zero end\\n // _locked has only 0 end\\n // Both can have >= 0 amount\\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\\n\\n assert(IERC20(token).transfer(msg.sender, value));\\n\\n // Burn the NFT\\n _burn(_tokenId);\\n\\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\\n emit Supply(supply_before, supply_before - value);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\\n // They measure the weights for the purpose of voting, so they don't represent\\n // real coins.\\n\\n /// @notice Binary search to estimate timestamp for block number\\n /// @param _block Block to find\\n /// @param max_epoch Don't go beyond this epoch\\n /// @return Approximate timestamp for block\\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\\n // Binary search\\n uint _min = 0;\\n uint _max = max_epoch;\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (point_history[_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n /// @notice Get the current voting power for `_tokenId`\\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\\n /// @param _tokenId NFT for lock\\n /// @param _t Epoch time to return voting power at\\n /// @return User voting power\\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\\n uint _epoch = user_point_epoch[_tokenId];\\n if (_epoch == 0) {\\n return 0;\\n } else {\\n Point memory last_point = user_point_history[_tokenId][_epoch];\\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(int256(last_point.bias));\\n }\\n }\\n\\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\\n if (ownership_change[_tokenId] == block.number) return 0;\\n return _balanceOfNFT(_tokenId, block.timestamp);\\n }\\n\\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\\n return _balanceOfNFT(_tokenId, _t);\\n }\\n\\n /// @notice Measure voting power of `_tokenId` at block height `_block`\\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\\n /// @param _tokenId User's wallet NFT\\n /// @param _block Block to calculate the voting power at\\n /// @return Voting power\\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\\n // Copying and pasting totalSupply code because Vyper cannot pass by\\n // reference yet\\n assert(_block <= block.number);\\n\\n // Binary search\\n uint _min = 0;\\n uint _max = user_point_epoch[_tokenId];\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (user_point_history[_tokenId][_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n\\n Point memory upoint = user_point_history[_tokenId][_min];\\n\\n uint max_epoch = epoch;\\n uint _epoch = _find_block_epoch(_block, max_epoch);\\n Point memory point_0 = point_history[_epoch];\\n uint d_block = 0;\\n uint d_t = 0;\\n if (_epoch < max_epoch) {\\n Point memory point_1 = point_history[_epoch + 1];\\n d_block = point_1.blk - point_0.blk;\\n d_t = point_1.ts - point_0.ts;\\n } else {\\n d_block = block.number - point_0.blk;\\n d_t = block.timestamp - point_0.ts;\\n }\\n uint block_time = point_0.ts;\\n if (d_block != 0) {\\n block_time += (d_t * (_block - point_0.blk)) / d_block;\\n }\\n\\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\\n if (upoint.bias >= 0) {\\n return uint(uint128(upoint.bias));\\n } else {\\n return 0;\\n }\\n }\\n\\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\\n return _balanceOfAtNFT(_tokenId, _block);\\n }\\n\\n /// @notice Calculate total voting power at some point in the past\\n /// @param _block Block to calculate the total voting power at\\n /// @return Total voting power at `_block`\\n function totalSupplyAt(uint _block) external view returns (uint) {\\n assert(_block <= block.number);\\n uint _epoch = epoch;\\n uint target_epoch = _find_block_epoch(_block, _epoch);\\n\\n Point memory point = point_history[target_epoch];\\n uint dt = 0;\\n if (target_epoch < _epoch) {\\n Point memory point_next = point_history[target_epoch + 1];\\n if (point.blk != point_next.blk) {\\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\\n }\\n } else {\\n if (point.blk != block.number) {\\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\\n }\\n }\\n // Now dt contains info on how far are we beyond point\\n return _supply_at(point, point.ts + dt);\\n }\\n /// @notice Calculate total voting power at some point in the past\\n /// @param point The point (bias/slope) to start search from\\n /// @param t Time to calculate the total voting power at\\n /// @return Total voting power at that time\\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\\n Point memory last_point = point;\\n uint t_i = (last_point.ts / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > t) {\\n t_i = t;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\\n if (t_i == t) {\\n break;\\n }\\n last_point.slope += d_slope;\\n last_point.ts = t_i;\\n }\\n\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(uint128(last_point.bias));\\n }\\n\\n function totalSupply() external view returns (uint) {\\n return totalSupplyAtT(block.timestamp);\\n }\\n\\n /// @notice Calculate total voting power\\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\\n /// @return Total voting power\\n function totalSupplyAtT(uint t) public view returns (uint) {\\n uint _epoch = epoch;\\n Point memory last_point = point_history[_epoch];\\n return _supply_at(last_point, t);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public attachments;\\n mapping(uint => bool) public voted;\\n\\n function setVoter(address _voter) external {\\n require(msg.sender == voter);\\n voter = _voter;\\n }\\n\\n function voting(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = true;\\n }\\n\\n function abstain(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = false;\\n }\\n\\n function attach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] + 1;\\n }\\n\\n function detach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] - 1;\\n }\\n\\n function merge(uint _from, uint _to) external {\\n require(attachments[_from] == 0 && !voted[_from], \\\"attached\\\");\\n require(_from != _to);\\n require(_isApprovedOrOwner(msg.sender, _from));\\n require(_isApprovedOrOwner(msg.sender, _to));\\n\\n LockedBalance memory _locked0 = locked[_from];\\n LockedBalance memory _locked1 = locked[_to];\\n uint value0 = uint(int256(_locked0.amount));\\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\\n\\n locked[_from] = LockedBalance(0, 0);\\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\\n _burn(_from);\\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of each accounts delegate\\n mapping(address => address) private _delegates;\\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\\n\\n /// @notice A record of delegated token checkpoints for each account, by index\\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint32) public numCheckpoints;\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping(address => uint) public nonces;\\n\\n /**\\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\\n * the delegator's own address if they haven't delegated.\\n * This avoids having to delegate to oneself.\\n */\\n function delegates(address delegator) public view returns (address) {\\n address current = _delegates[delegator];\\n return current == address(0) ? delegator : current;\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getVotes(address account) external view returns (uint) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n votes = votes + _balanceOfNFT(tId, block.timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint storage cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPastVotes(address account, uint timestamp)\\n public\\n view\\n returns (uint)\\n {\\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\\n // Sum votes\\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n // Use the provided input timestamp here to get the right decay\\n votes = votes + _balanceOfNFT(tId, timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\\n return totalSupplyAtT(timestamp);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _moveTokenDelegates(\\n address srcRep,\\n address dstRep,\\n uint _tokenId\\n ) internal {\\n if (srcRep != dstRep && _tokenId > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except _tokenId\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (tId != _tokenId) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n // All the same plus _tokenId\\n require(\\n dstRepOld.length + 1 <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n dstRepNew.push(_tokenId);\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _findWhatCheckpointToWrite(address account)\\n internal\\n view\\n returns (uint32)\\n {\\n uint _timestamp = block.timestamp;\\n uint32 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n return _nCheckPoints - 1;\\n } else {\\n return _nCheckPoints;\\n }\\n }\\n\\n function _moveAllDelegates(\\n address owner,\\n address srcRep,\\n address dstRep\\n ) internal {\\n // You can only redelegate what you own\\n if (srcRep != dstRep) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except what owner owns\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (idToOwner[tId] != owner) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n uint ownerTokenCount = ownerToNFTokenCount[owner];\\n require(\\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n // All the same\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n // Plus all that's owned\\n for (uint i = 0; i < ownerTokenCount; i++) {\\n uint tId = ownerToNFTokenIdList[owner][i];\\n dstRepNew.push(tId);\\n }\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\\n address currentDelegate = delegates(delegator);\\n\\n _delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n _moveAllDelegates(delegator, currentDelegate, delegatee);\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n if (delegatee == address(0)) delegatee = msg.sender;\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n function delegateBySig(\\n address delegatee,\\n uint nonce,\\n uint expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public {\\n bytes32 domainSeparator = keccak256(\\n abi.encode(\\n DOMAIN_TYPEHASH,\\n keccak256(bytes(name)),\\n keccak256(bytes(version)),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 structHash = keccak256(\\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash)\\n );\\n address signatory = ecrecover(digest, v, r, s);\\n require(\\n signatory != address(0),\\n \\\"VotingEscrow::delegateBySig: invalid signature\\\"\\n );\\n require(\\n nonce == nonces[signatory]++,\\n \\\"VotingEscrow::delegateBySig: invalid nonce\\\"\\n );\\n require(\\n block.timestamp <= expiry,\\n \\\"VotingEscrow::delegateBySig: signature expired\\\"\\n );\\n return _delegate(signatory, delegatee);\\n }\\n}\\n\",\"keccak256\":\"0x7109ed9d84b5504fe5d4c73d5a10997a0b73f2f4d45813ce5e161997d405fd73\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x41bbb2c41036ca64b2f6c9e973e8cfaa113ebc42af86702cd0d267f915a7e886\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60a06040526006805460ff191660011790553480156200001e57600080fd5b5060405162004a1c38038062004a1c8339810160408190526200004191620001b8565b6001600160a01b0382811660805260008054336001600160a01b031991821681178355600180548316909117815560028054909216938516939093179055437f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f0155427f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f005560046020527f9fe05126d2d9ecf60592e254dead906a4b2e492f36cca727682c38e9008c6ac1805460ff1990811684179091557f4267c0a6fd96b7a87f183ee8744f24d011423cd0e0142b3f563f183d8d9a456b8054821684179055635b5e139f60e01b82527e24030bcf4927897dffe721c2d8dda4bfd8910861687c42b03a463b43b04147805490911690921790915560055460405190913091600080516020620049fc833981519152908290a46005546040516000903090600080516020620049fc833981519152908390a45050620001f0565b80516001600160a01b0381168114620001b357600080fd5b919050565b60008060408385031215620001cc57600080fd5b620001d7836200019b565b9150620001e7602084016200019b565b90509250929050565b6080516147e26200021a60003960008181610b220152818161101801526133b501526147e26000f3fe608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea264697066735822122098b1358028f64f409b693ae89fbabe991f348f6d1fe6dea27f8f63e0a686c2fd64736f6c634300080d0033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea264697066735822122098b1358028f64f409b693ae89fbabe991f348f6d1fe6dea27f8f63e0a686c2fd64736f6c634300080d0033", + "numDeployments": 2, + "solcInputHash": "6e27611a2cedd773c4cc6e46935e6392", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token_addr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"art_proxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromDelegate\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toDelegate\",\"type\":\"address\"}],\"name\":\"DelegateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"DelegateVotesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"locktime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum VotingEscrow.DepositType\",\"name\":\"deposit_type\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"prevSupply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"supply\",\"type\":\"uint256\"}],\"name\":\"Supply\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DELEGATION_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_DELEGATES\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"abstain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_approved\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"artProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"attach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"attachments\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"balanceOfAtNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_t\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFTAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"block_number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"checkpoints\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"create_lock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"create_lock_for\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"}],\"name\":\"delegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"delegateBySig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"}],\"name\":\"delegates\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"deposit_for\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"detach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastTotalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotesIndex\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"get_last_user_slope\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"increase_amount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"increase_unlock_time\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"isApprovedOrOwner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"locked\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"amount\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"locked__end\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_from\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_to\",\"type\":\"uint256\"}],\"name\":\"merge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"numCheckpoints\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ownership_change\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_proxy\",\"type\":\"address\"}],\"name\":\"setArtProxy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voter\",\"type\":\"address\"}],\"name\":\"setVoter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"slope_changes\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenIndex\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"t\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAtT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_idx\",\"type\":\"uint256\"}],\"name\":\"user_point_history__ts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"voted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"voting\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\",\"details\":\"Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\",\"kind\":\"dev\",\"methods\":{\"approve(address,uint256)\":{\"details\":\"Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address. Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner. Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP) Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"Address to be approved for the given NFT ID.\",\"_tokenId\":\"ID of the token to be approved.\"}},\"balanceOf(address)\":{\"details\":\"Returns the number of NFTs owned by `_owner`. Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\",\"params\":{\"_owner\":\"Address for whom to query the balance.\"}},\"constructor\":{\"params\":{\"token_addr\":\"`FLOW` token address\"}},\"create_lock(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_value\":\"Amount to deposit\"}},\"create_lock_for(uint256,uint256,address)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_to\":\"Address to deposit\",\"_value\":\"Amount to deposit\"}},\"delegate(address)\":{\"params\":{\"delegatee\":\"The address to delegate votes to\"}},\"delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Delegates votes from signer to `delegatee`.\"},\"deposit_for(uint256,uint256)\":{\"details\":\"Anyone (even a smart contract) can deposit for someone else, but cannot extend their locktime and deposit for a brand new user\",\"params\":{\"_tokenId\":\"lock NFT\",\"_value\":\"Amount to add to user's lock\"}},\"getApproved(uint256)\":{\"details\":\"Get the approved address for a single NFT.\",\"params\":{\"_tokenId\":\"ID of the NFT to query the approval of.\"}},\"getVotes(address)\":{\"params\":{\"account\":\"The address to get votes balance\"},\"returns\":{\"_0\":\"The number of current votes for `account`\"}},\"get_last_user_slope(uint256)\":{\"params\":{\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Value of the slope\"}},\"increase_amount(uint256,uint256)\":{\"params\":{\"_value\":\"Amount of tokens to deposit and add to the lock\"}},\"increase_unlock_time(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"New number of seconds until tokens unlock\"}},\"isApprovedForAll(address,address)\":{\"details\":\"Checks if `_operator` is an approved operator for `_owner`.\",\"params\":{\"_operator\":\"The address that acts on behalf of the owner.\",\"_owner\":\"The address that owns the NFTs.\"}},\"locked__end(uint256)\":{\"params\":{\"_tokenId\":\"User NFT\"},\"returns\":{\"_0\":\"Epoch time of the lock end\"}},\"ownerOf(uint256)\":{\"details\":\"Returns the address of the owner of the NFT.\",\"params\":{\"_tokenId\":\"The identifier for an NFT.\"}},\"safeTransferFrom(address,address,uint256)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"safeTransferFrom(address,address,uint256,bytes)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_data\":\"Additional data with no specified format, sent in call to `_to`.\",\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"details\":\"Enables or disables approval for a third party (\\\"operator\\\") to manage all of `msg.sender`'s assets. It also emits the ApprovalForAll event. Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"True if the operators is approved, false to revoke approval.\",\"_operator\":\"Address to add to the set of authorized operators.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Interface identification is specified in ERC-165.\",\"params\":{\"_interfaceID\":\"Id of the interface\"}},\"tokenOfOwnerByIndex(address,uint256)\":{\"details\":\"Get token by index\"},\"tokenURI(uint256)\":{\"details\":\"Returns current token URI metadata\",\"params\":{\"_tokenId\":\"Token ID to fetch URI for.\"}},\"totalSupplyAt(uint256)\":{\"params\":{\"_block\":\"Block to calculate the total voting power at\"},\"returns\":{\"_0\":\"Total voting power at `_block`\"}},\"totalSupplyAtT(uint256)\":{\"details\":\"Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\",\"returns\":{\"_0\":\"Total voting power\"}},\"transferFrom(address,address,uint256)\":{\"details\":\"Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"user_point_history__ts(uint256,uint256)\":{\"params\":{\"_idx\":\"User epoch number\",\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Epoch time of the checkpoint\"}},\"withdraw(uint256)\":{\"details\":\"Only possible if the lock has expired\"}},\"stateVariables\":{\"ERC165_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC165\"},\"ERC721_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721\"},\"ERC721_METADATA_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721Metadata\"},\"_not_entered\":{\"details\":\"reentrancy guard\"},\"idToApprovals\":{\"details\":\"Mapping from NFT ID to approved address.\"},\"idToOwner\":{\"details\":\"Mapping from NFT ID to the address that owns it.\"},\"name\":{\"details\":\"Returns the token collection name.\"},\"ownerToNFTokenCount\":{\"details\":\"Mapping from owner address to count of his tokens.\"},\"ownerToNFTokenIdList\":{\"details\":\"Mapping from owner address to mapping of index to tokenIds\"},\"ownerToOperators\":{\"details\":\"Mapping from owner address to mapping of operator addresses.\"},\"supportedInterfaces\":{\"details\":\"Mapping of interface id to bool about whether or not it's supported\"},\"symbol\":{\"details\":\"Returns the token collection symbol.\"},\"tokenId\":{\"details\":\"Current count of token\"},\"tokenToOwnerIndex\":{\"details\":\"Mapping from NFT ID to index of owner\"}},\"title\":\"Voting Escrow\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DELEGATION_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the delegation struct used by the contract\"},\"DOMAIN_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the contract's domain\"},\"checkpoint()\":{\"notice\":\"Record global data to checkpoint\"},\"checkpoints(address,uint32)\":{\"notice\":\"A record of delegated token checkpoints for each account, by index\"},\"constructor\":{\"notice\":\"Contract constructor\"},\"create_lock(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\"},\"create_lock_for(uint256,uint256,address)\":{\"notice\":\"Deposit `_value` tokens for `_to` and lock for `_lock_duration`\"},\"delegate(address)\":{\"notice\":\"Delegate votes from `msg.sender` to `delegatee`\"},\"delegates(address)\":{\"notice\":\"Overrides the standard `Comp.sol` delegates mapping to return the delegator's own address if they haven't delegated. This avoids having to delegate to oneself.\"},\"deposit_for(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `_tokenId` and add to the lock\"},\"getVotes(address)\":{\"notice\":\"Gets the current votes balance for `account`\"},\"get_last_user_slope(uint256)\":{\"notice\":\"Get the most recently recorded rate of voting power decrease for `_tokenId`\"},\"increase_amount(uint256,uint256)\":{\"notice\":\"Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\"},\"increase_unlock_time(uint256,uint256)\":{\"notice\":\"Extend the unlock time for `_tokenId`\"},\"locked__end(uint256)\":{\"notice\":\"Get timestamp when `_tokenId`'s lock finishes\"},\"nonces(address)\":{\"notice\":\"A record of states for signing / validating signatures\"},\"numCheckpoints(address)\":{\"notice\":\"The number of checkpoints for each account\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"This works even if sender doesn't own any tokens at the time.\"},\"totalSupplyAt(uint256)\":{\"notice\":\"Calculate total voting power at some point in the past\"},\"totalSupplyAtT(uint256)\":{\"notice\":\"Calculate total voting power\"},\"transferFrom(address,address,uint256)\":{\"notice\":\"The caller is responsible to confirm that `_to` is capable of receiving NFTs or else they maybe be permanently lost.\"},\"user_point_history__ts(uint256,uint256)\":{\"notice\":\"Get the timestamp for checkpoint `_idx` for `_tokenId`\"},\"withdraw(uint256)\":{\"notice\":\"Withdraw all tokens for `_tokenId`\"}},\"notice\":\"veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFTVotes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VotingEscrow.sol\":\"VotingEscrow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735303535373437363232\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VotingEscrow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IERC721, IERC721Metadata} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {IERC721Receiver} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {IERC20} from \\\"contracts/interfaces/IERC20.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\nimport {IVotingEscrow} from \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/// @title Voting Escrow\\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\\n enum DepositType {\\n DEPOSIT_FOR_TYPE,\\n CREATE_LOCK_TYPE,\\n INCREASE_LOCK_AMOUNT,\\n INCREASE_UNLOCK_TIME,\\n MERGE_TYPE\\n }\\n\\n struct LockedBalance {\\n int128 amount;\\n uint end;\\n }\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint ts;\\n uint blk; // block\\n }\\n /* We cannot really do block numbers per se b/c slope is per time, not per block\\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\\n * What we can do is to extrapolate ***At functions */\\n\\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\\n struct Checkpoint {\\n uint timestamp;\\n uint[] tokenIds;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Deposit(\\n address indexed provider,\\n uint tokenId,\\n uint value,\\n uint indexed locktime,\\n DepositType deposit_type,\\n uint ts\\n );\\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\\n event Supply(uint prevSupply, uint supply);\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n address public immutable token;\\n address public voter;\\n address public team;\\n address public artProxy;\\n\\n mapping(uint => Point) public point_history; // epoch -> unsigned point\\n\\n /// @dev Mapping of interface id to bool about whether or not it's supported\\n mapping(bytes4 => bool) internal supportedInterfaces;\\n\\n /// @dev ERC165 interface ID of ERC165\\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\\n\\n /// @dev ERC165 interface ID of ERC721\\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\\n\\n /// @dev ERC165 interface ID of ERC721Metadata\\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\\n\\n /// @dev Current count of token\\n uint internal tokenId;\\n\\n /// @notice Contract constructor\\n /// @param token_addr `FLOW` token address\\n constructor(address token_addr, address art_proxy) {\\n token = token_addr;\\n voter = msg.sender;\\n team = msg.sender;\\n artProxy = art_proxy;\\n\\n point_history[0].blk = block.number;\\n point_history[0].ts = block.timestamp;\\n\\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\\n\\n // mint-ish\\n emit Transfer(address(0), address(this), tokenId);\\n // burn-ish\\n emit Transfer(address(this), address(0), tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n MODIFIERS\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev reentrancy guard\\n uint8 internal constant _not_entered = 1;\\n uint8 internal constant _entered = 2;\\n uint8 internal _entered_state = 1;\\n modifier nonreentrant() {\\n require(_entered_state == _not_entered);\\n _entered_state = _entered;\\n _;\\n _entered_state = _not_entered;\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string constant public name = \\\"veNFT\\\";\\n string constant public symbol = \\\"veNFT\\\";\\n string constant public version = \\\"1.0.0\\\";\\n uint8 constant public decimals = 18;\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team);\\n team = _team;\\n }\\n\\n function setArtProxy(address _proxy) external {\\n require(msg.sender == team);\\n artProxy = _proxy;\\n }\\n\\n /// @dev Returns current token URI metadata\\n /// @param _tokenId Token ID to fetch URI for.\\n function tokenURI(uint _tokenId) external view returns (string memory) {\\n require(idToOwner[_tokenId] != address(0), \\\"Query for nonexistent token\\\");\\n LockedBalance memory _locked = locked[_tokenId];\\n return IVeArtProxy(artProxy)._tokenURI(\\n _tokenId,\\n _balanceOfNFT(_tokenId, block.timestamp),\\n _locked.end,\\n uint(int256(_locked.amount))\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 BALANCE/OWNER STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to the address that owns it.\\n mapping(uint => address) internal idToOwner;\\n\\n /// @dev Mapping from owner address to count of his tokens.\\n mapping(address => uint) internal ownerToNFTokenCount;\\n\\n /// @dev Returns the address of the owner of the NFT.\\n /// @param _tokenId The identifier for an NFT.\\n function ownerOf(uint _tokenId) public view returns (address) {\\n return idToOwner[_tokenId];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function _balance(address _owner) internal view returns (uint) {\\n return ownerToNFTokenCount[_owner];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function balanceOf(address _owner) external view returns (uint) {\\n return _balance(_owner);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 APPROVAL STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to approved address.\\n mapping(uint => address) internal idToApprovals;\\n\\n /// @dev Mapping from owner address to mapping of operator addresses.\\n mapping(address => mapping(address => bool)) internal ownerToOperators;\\n\\n mapping(uint => uint) public ownership_change;\\n\\n /// @dev Get the approved address for a single NFT.\\n /// @param _tokenId ID of the NFT to query the approval of.\\n function getApproved(uint _tokenId) external view returns (address) {\\n return idToApprovals[_tokenId];\\n }\\n\\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\\n /// @param _owner The address that owns the NFTs.\\n /// @param _operator The address that acts on behalf of the owner.\\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\\n return (ownerToOperators[_owner])[_operator];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\\n /// @param _approved Address to be approved for the given NFT ID.\\n /// @param _tokenId ID of the token to be approved.\\n function approve(address _approved, uint _tokenId) public {\\n address owner = idToOwner[_tokenId];\\n // Throws if `_tokenId` is not a valid NFT\\n require(owner != address(0));\\n // Throws if `_approved` is the current owner\\n require(_approved != owner);\\n // Check requirements\\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\\n require(senderIsOwner || senderIsApprovedForAll);\\n // Set the approval\\n idToApprovals[_tokenId] = _approved;\\n emit Approval(owner, _approved, _tokenId);\\n }\\n\\n /// @dev Enables or disables approval for a third party (\\\"operator\\\") to manage all of\\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\\n /// @notice This works even if sender doesn't own any tokens at the time.\\n /// @param _operator Address to add to the set of authorized operators.\\n /// @param _approved True if the operators is approved, false to revoke approval.\\n function setApprovalForAll(address _operator, bool _approved) external {\\n // Throws if `_operator` is the `msg.sender`\\n assert(_operator != msg.sender);\\n ownerToOperators[msg.sender][_operator] = _approved;\\n emit ApprovalForAll(msg.sender, _operator, _approved);\\n }\\n\\n /* TRANSFER FUNCTIONS */\\n /// @dev Clear an approval of a given address\\n /// Throws if `_owner` is not the current owner.\\n function _clearApproval(address _owner, uint _tokenId) internal {\\n // Throws if `_owner` is not the current owner\\n assert(idToOwner[_tokenId] == _owner);\\n if (idToApprovals[_tokenId] != address(0)) {\\n // Reset approvals\\n idToApprovals[_tokenId] = address(0);\\n }\\n }\\n\\n /// @dev Returns whether the given spender can transfer a given token ID\\n /// @param _spender address of the spender to query\\n /// @param _tokenId uint ID of the token to be transferred\\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\\n address owner = idToOwner[_tokenId];\\n bool spenderIsOwner = owner == _spender;\\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\\n }\\n\\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\\n return _isApprovedOrOwner(_spender, _tokenId);\\n }\\n\\n /// @dev Exeute transfer of a NFT.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_tokenId` is not a valid NFT.\\n function _transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n address _sender\\n ) internal {\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n // Check requirements\\n require(_isApprovedOrOwner(_sender, _tokenId));\\n // Clear approval. Throws if `_from` is not the current owner\\n _clearApproval(_from, _tokenId);\\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\\n _removeTokenFrom(_from, _tokenId);\\n // auto re-delegate\\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\\n // Add NFT\\n _addTokenTo(_to, _tokenId);\\n // Set the block of ownership transfer (for Flash NFT protection)\\n ownership_change[_tokenId] = block.number;\\n // Log the transfer\\n emit Transfer(_from, _to, _tokenId);\\n }\\n\\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\\n /// they maybe be permanently lost.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n safeTransferFrom(_from, _to, _tokenId, \\\"\\\");\\n }\\n\\n function _isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n uint size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n /// @param _data Additional data with no specified format, sent in call to `_to`.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n bytes memory _data\\n ) public {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n\\n if (_isContract(_to)) {\\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\\n revert(\\\"ERC721: ERC721Receiver rejected tokens\\\");\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert('ERC721: transfer to non ERC721Receiver implementer');\\n } else {\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC165 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Interface identification is specified in ERC-165.\\n /// @param _interfaceID Id of the interface\\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\\n return supportedInterfaces[_interfaceID];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from owner address to mapping of index to tokenIds\\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\\n\\n /// @dev Mapping from NFT ID to index of owner\\n mapping(uint => uint) internal tokenToOwnerIndex;\\n\\n /// @dev Get token by index\\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\\n return ownerToNFTokenIdList[_owner][_tokenIndex];\\n }\\n\\n /// @dev Add a NFT to an index mapping to a given address\\n /// @param _to address of the receiver\\n /// @param _tokenId uint ID Of the token to be added\\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\\n uint current_count = _balance(_to);\\n\\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\\n tokenToOwnerIndex[_tokenId] = current_count;\\n }\\n\\n /// @dev Add a NFT to a given address\\n /// Throws if `_tokenId` is owned by someone.\\n function _addTokenTo(address _to, uint _tokenId) internal {\\n // Throws if `_tokenId` is owned by someone\\n assert(idToOwner[_tokenId] == address(0));\\n // Change the owner\\n idToOwner[_tokenId] = _to;\\n // Update owner token index tracking\\n _addTokenToOwnerList(_to, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_to] += 1;\\n }\\n\\n /// @dev Function to mint tokens\\n /// Throws if `_to` is zero address.\\n /// Throws if `_tokenId` is owned by someone.\\n /// @param _to The address that will receive the minted tokens.\\n /// @param _tokenId The token id to mint.\\n /// @return A boolean that indicates if the operation was successful.\\n function _mint(address _to, uint _tokenId) internal returns (bool) {\\n // Throws if `_to` is zero address\\n assert(_to != address(0));\\n // checkpoint for gov\\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\\n // Add NFT. Throws if `_tokenId` is owned by someone\\n _addTokenTo(_to, _tokenId);\\n emit Transfer(address(0), _to, _tokenId);\\n return true;\\n }\\n\\n /// @dev Remove a NFT from an index mapping to a given address\\n /// @param _from address of the sender\\n /// @param _tokenId uint ID Of the token to be removed\\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\\n // Delete\\n uint current_count = _balance(_from) - 1;\\n uint current_index = tokenToOwnerIndex[_tokenId];\\n\\n if (current_count == current_index) {\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n } else {\\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\\n\\n // Add\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[lastTokenId] = current_index;\\n\\n // Delete\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n }\\n }\\n\\n /// @dev Remove a NFT from a given address\\n /// Throws if `_from` is not the current owner.\\n function _removeTokenFrom(address _from, uint _tokenId) internal {\\n // Throws if `_from` is not the current owner\\n assert(idToOwner[_tokenId] == _from);\\n // Change the owner\\n idToOwner[_tokenId] = address(0);\\n // Update owner token index tracking\\n _removeTokenFromOwnerList(_from, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_from] -= 1;\\n }\\n\\n function _burn(uint _tokenId) internal {\\n require(_isApprovedOrOwner(msg.sender, _tokenId), \\\"caller is not owner nor approved\\\");\\n\\n address owner = ownerOf(_tokenId);\\n\\n // Clear approval\\n approve(address(0), _tokenId);\\n // checkpoint for gov\\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\\n // Remove token\\n _removeTokenFrom(msg.sender, _tokenId);\\n emit Transfer(owner, address(0), _tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public user_point_epoch;\\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\\n mapping(uint => LockedBalance) public locked;\\n uint public epoch;\\n mapping(uint => int128) public slope_changes; // time -> signed slope change\\n uint public supply;\\n\\n uint internal constant WEEK = 1 weeks;\\n uint internal constant MAXTIME = 4 * 365 * 86400;\\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\\n uint internal constant MULTIPLIER = 1 ether;\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @return Value of the slope\\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\\n uint uepoch = user_point_epoch[_tokenId];\\n return user_point_history[_tokenId][uepoch].slope;\\n }\\n\\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @param _idx User epoch number\\n /// @return Epoch time of the checkpoint\\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\\n return user_point_history[_tokenId][_idx].ts;\\n }\\n\\n /// @notice Get timestamp when `_tokenId`'s lock finishes\\n /// @param _tokenId User NFT\\n /// @return Epoch time of the lock end\\n function locked__end(uint _tokenId) external view returns (uint) {\\n return locked[_tokenId].end;\\n }\\n\\n /// @notice Record global and per-user data to checkpoint\\n /// @param _tokenId NFT token ID. No user checkpoint if 0\\n /// @param old_locked Pevious locked amount / end lock time for the user\\n /// @param new_locked New locked amount / end lock time for the user\\n function _checkpoint(\\n uint _tokenId,\\n LockedBalance memory old_locked,\\n LockedBalance memory new_locked\\n ) internal {\\n Point memory u_old;\\n Point memory u_new;\\n int128 old_dslope = 0;\\n int128 new_dslope = 0;\\n uint _epoch = epoch;\\n\\n if (_tokenId != 0) {\\n // Calculate slopes and biases\\n // Kept at zero when they have to\\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\\n u_old.slope = old_locked.amount / iMAXTIME;\\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\\n }\\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\\n u_new.slope = new_locked.amount / iMAXTIME;\\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\\n }\\n\\n // Read values of scheduled changes in the slope\\n // old_locked.end can be in the past and in the future\\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\\n old_dslope = slope_changes[old_locked.end];\\n if (new_locked.end != 0) {\\n if (new_locked.end == old_locked.end) {\\n new_dslope = old_dslope;\\n } else {\\n new_dslope = slope_changes[new_locked.end];\\n }\\n }\\n }\\n\\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\\n if (_epoch > 0) {\\n last_point = point_history[_epoch];\\n }\\n uint last_checkpoint = last_point.ts;\\n // initial_last_point is used for extrapolation to calculate block number\\n // (approximately, for *At methods) and save them\\n // as we cannot figure that out exactly from inside the contract\\n Point memory initial_last_point = last_point;\\n uint block_slope = 0; // dblock/dt\\n if (block.timestamp > last_point.ts) {\\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\\n }\\n // If last point is already recorded in this block, slope=0\\n // But that's ok b/c we know the block in such case\\n\\n // Go over weeks to fill history and calculate what the current point is\\n {\\n uint t_i = (last_checkpoint / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n // Hopefully it won't happen that this won't get used in 5 years!\\n // If it does, users will be able to withdraw but vote weight will be broken\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > block.timestamp) {\\n t_i = block.timestamp;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\\n last_point.slope += d_slope;\\n if (last_point.bias < 0) {\\n // This can happen\\n last_point.bias = 0;\\n }\\n if (last_point.slope < 0) {\\n // This cannot happen - just in case\\n last_point.slope = 0;\\n }\\n last_checkpoint = t_i;\\n last_point.ts = t_i;\\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\\n _epoch += 1;\\n if (t_i == block.timestamp) {\\n last_point.blk = block.number;\\n break;\\n } else {\\n point_history[_epoch] = last_point;\\n }\\n }\\n }\\n\\n epoch = _epoch;\\n // Now point_history is filled until t=now\\n\\n if (_tokenId != 0) {\\n // If last point was in this block, the slope change has been applied already\\n // But in such case we have 0 slope(s)\\n last_point.slope += (u_new.slope - u_old.slope);\\n last_point.bias += (u_new.bias - u_old.bias);\\n if (last_point.slope < 0) {\\n last_point.slope = 0;\\n }\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n }\\n\\n // Record the changed point into history\\n point_history[_epoch] = last_point;\\n\\n if (_tokenId != 0) {\\n // Schedule the slope changes (slope is going down)\\n // We subtract new_user_slope from [new_locked.end]\\n // and add old_user_slope to [old_locked.end]\\n if (old_locked.end > block.timestamp) {\\n // old_dslope was - u_old.slope, so we cancel that\\n old_dslope += u_old.slope;\\n if (new_locked.end == old_locked.end) {\\n old_dslope -= u_new.slope; // It was a new deposit, not extension\\n }\\n slope_changes[old_locked.end] = old_dslope;\\n }\\n\\n if (new_locked.end > block.timestamp) {\\n if (new_locked.end > old_locked.end) {\\n new_dslope -= u_new.slope; // old slope disappeared at this point\\n slope_changes[new_locked.end] = new_dslope;\\n }\\n // else: we recorded it already in old_dslope\\n }\\n // Now handle user history\\n uint user_epoch = user_point_epoch[_tokenId] + 1;\\n\\n user_point_epoch[_tokenId] = user_epoch;\\n u_new.ts = block.timestamp;\\n u_new.blk = block.number;\\n user_point_history[_tokenId][user_epoch] = u_new;\\n }\\n }\\n\\n /// @notice Deposit and lock tokens for a user\\n /// @param _tokenId NFT that holds lock\\n /// @param _value Amount to deposit\\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\\n /// @param locked_balance Previous locked amount / timestamp\\n /// @param deposit_type The type of deposit\\n function _deposit_for(\\n uint _tokenId,\\n uint _value,\\n uint unlock_time,\\n LockedBalance memory locked_balance,\\n DepositType deposit_type\\n ) internal {\\n LockedBalance memory _locked = locked_balance;\\n uint supply_before = supply;\\n\\n supply = supply_before + _value;\\n LockedBalance memory old_locked;\\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\\n // Adding to existing lock, or if a lock is expired - creating a new one\\n _locked.amount += int128(int256(_value));\\n if (unlock_time != 0) {\\n _locked.end = unlock_time;\\n }\\n locked[_tokenId] = _locked;\\n\\n // Possibilities:\\n // Both old_locked.end could be current or expired (>/< block.timestamp)\\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\\n // _locked.end > block.timestamp (always)\\n _checkpoint(_tokenId, old_locked, _locked);\\n\\n address from = msg.sender;\\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\\n assert(IERC20(token).transferFrom(from, address(this), _value));\\n }\\n\\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\\n emit Supply(supply_before, supply_before + _value);\\n }\\n\\n function block_number() external view returns (uint) {\\n return block.number;\\n }\\n\\n /// @notice Record global data to checkpoint\\n function checkpoint() external {\\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\\n }\\n\\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\\n /// cannot extend their locktime and deposit for a brand new user\\n /// @param _tokenId lock NFT\\n /// @param _value Amount to add to user's lock\\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n require(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_value > 0); // dev: need non-zero value\\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n ++tokenId;\\n uint _tokenId = tokenId;\\n _mint(_to, _tokenId);\\n\\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\\n return _tokenId;\\n }\\n\\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, msg.sender);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, _to);\\n }\\n\\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\\n /// @param _value Amount of tokens to deposit and add to the lock\\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n assert(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\\n }\\n\\n /// @notice Extend the unlock time for `_tokenId`\\n /// @param _lock_duration New number of seconds until tokens unlock\\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_locked.end > block.timestamp, 'Lock expired');\\n require(_locked.amount > 0, 'Nothing is locked');\\n require(unlock_time > _locked.end, 'Can only increase lock duration');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\\n }\\n\\n /// @notice Withdraw all tokens for `_tokenId`\\n /// @dev Only possible if the lock has expired\\n function withdraw(uint _tokenId) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n require(block.timestamp >= _locked.end, \\\"The lock didn't expire\\\");\\n uint value = uint(int256(_locked.amount));\\n\\n locked[_tokenId] = LockedBalance(0,0);\\n uint supply_before = supply;\\n supply = supply_before - value;\\n\\n // old_locked can have either expired <= timestamp or zero end\\n // _locked has only 0 end\\n // Both can have >= 0 amount\\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\\n\\n assert(IERC20(token).transfer(msg.sender, value));\\n\\n // Burn the NFT\\n _burn(_tokenId);\\n\\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\\n emit Supply(supply_before, supply_before - value);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\\n // They measure the weights for the purpose of voting, so they don't represent\\n // real coins.\\n\\n /// @notice Binary search to estimate timestamp for block number\\n /// @param _block Block to find\\n /// @param max_epoch Don't go beyond this epoch\\n /// @return Approximate timestamp for block\\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\\n // Binary search\\n uint _min = 0;\\n uint _max = max_epoch;\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (point_history[_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n /// @notice Get the current voting power for `_tokenId`\\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\\n /// @param _tokenId NFT for lock\\n /// @param _t Epoch time to return voting power at\\n /// @return User voting power\\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\\n uint _epoch = user_point_epoch[_tokenId];\\n if (_epoch == 0) {\\n return 0;\\n } else {\\n Point memory last_point = user_point_history[_tokenId][_epoch];\\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(int256(last_point.bias));\\n }\\n }\\n\\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\\n if (ownership_change[_tokenId] == block.number) return 0;\\n return _balanceOfNFT(_tokenId, block.timestamp);\\n }\\n\\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\\n return _balanceOfNFT(_tokenId, _t);\\n }\\n\\n /// @notice Measure voting power of `_tokenId` at block height `_block`\\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\\n /// @param _tokenId User's wallet NFT\\n /// @param _block Block to calculate the voting power at\\n /// @return Voting power\\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\\n // Copying and pasting totalSupply code because Vyper cannot pass by\\n // reference yet\\n assert(_block <= block.number);\\n\\n // Binary search\\n uint _min = 0;\\n uint _max = user_point_epoch[_tokenId];\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (user_point_history[_tokenId][_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n\\n Point memory upoint = user_point_history[_tokenId][_min];\\n\\n uint max_epoch = epoch;\\n uint _epoch = _find_block_epoch(_block, max_epoch);\\n Point memory point_0 = point_history[_epoch];\\n uint d_block = 0;\\n uint d_t = 0;\\n if (_epoch < max_epoch) {\\n Point memory point_1 = point_history[_epoch + 1];\\n d_block = point_1.blk - point_0.blk;\\n d_t = point_1.ts - point_0.ts;\\n } else {\\n d_block = block.number - point_0.blk;\\n d_t = block.timestamp - point_0.ts;\\n }\\n uint block_time = point_0.ts;\\n if (d_block != 0) {\\n block_time += (d_t * (_block - point_0.blk)) / d_block;\\n }\\n\\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\\n if (upoint.bias >= 0) {\\n return uint(uint128(upoint.bias));\\n } else {\\n return 0;\\n }\\n }\\n\\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\\n return _balanceOfAtNFT(_tokenId, _block);\\n }\\n\\n /// @notice Calculate total voting power at some point in the past\\n /// @param _block Block to calculate the total voting power at\\n /// @return Total voting power at `_block`\\n function totalSupplyAt(uint _block) external view returns (uint) {\\n assert(_block <= block.number);\\n uint _epoch = epoch;\\n uint target_epoch = _find_block_epoch(_block, _epoch);\\n\\n Point memory point = point_history[target_epoch];\\n uint dt = 0;\\n if (target_epoch < _epoch) {\\n Point memory point_next = point_history[target_epoch + 1];\\n if (point.blk != point_next.blk) {\\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\\n }\\n } else {\\n if (point.blk != block.number) {\\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\\n }\\n }\\n // Now dt contains info on how far are we beyond point\\n return _supply_at(point, point.ts + dt);\\n }\\n /// @notice Calculate total voting power at some point in the past\\n /// @param point The point (bias/slope) to start search from\\n /// @param t Time to calculate the total voting power at\\n /// @return Total voting power at that time\\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\\n Point memory last_point = point;\\n uint t_i = (last_point.ts / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > t) {\\n t_i = t;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\\n if (t_i == t) {\\n break;\\n }\\n last_point.slope += d_slope;\\n last_point.ts = t_i;\\n }\\n\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(uint128(last_point.bias));\\n }\\n\\n function totalSupply() external view returns (uint) {\\n return totalSupplyAtT(block.timestamp);\\n }\\n\\n /// @notice Calculate total voting power\\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\\n /// @return Total voting power\\n function totalSupplyAtT(uint t) public view returns (uint) {\\n uint _epoch = epoch;\\n Point memory last_point = point_history[_epoch];\\n return _supply_at(last_point, t);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public attachments;\\n mapping(uint => bool) public voted;\\n\\n function setVoter(address _voter) external {\\n require(msg.sender == voter);\\n voter = _voter;\\n }\\n\\n function voting(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = true;\\n }\\n\\n function abstain(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = false;\\n }\\n\\n function attach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] + 1;\\n }\\n\\n function detach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] - 1;\\n }\\n\\n function merge(uint _from, uint _to) external {\\n require(attachments[_from] == 0 && !voted[_from], \\\"attached\\\");\\n require(_from != _to);\\n require(_isApprovedOrOwner(msg.sender, _from));\\n require(_isApprovedOrOwner(msg.sender, _to));\\n\\n LockedBalance memory _locked0 = locked[_from];\\n LockedBalance memory _locked1 = locked[_to];\\n uint value0 = uint(int256(_locked0.amount));\\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\\n\\n locked[_from] = LockedBalance(0, 0);\\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\\n _burn(_from);\\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of each accounts delegate\\n mapping(address => address) private _delegates;\\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\\n\\n /// @notice A record of delegated token checkpoints for each account, by index\\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint32) public numCheckpoints;\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping(address => uint) public nonces;\\n\\n /**\\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\\n * the delegator's own address if they haven't delegated.\\n * This avoids having to delegate to oneself.\\n */\\n function delegates(address delegator) public view returns (address) {\\n address current = _delegates[delegator];\\n return current == address(0) ? delegator : current;\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getVotes(address account) external view returns (uint) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n votes = votes + _balanceOfNFT(tId, block.timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint storage cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPastVotes(address account, uint timestamp)\\n public\\n view\\n returns (uint)\\n {\\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\\n // Sum votes\\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n // Use the provided input timestamp here to get the right decay\\n votes = votes + _balanceOfNFT(tId, timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\\n return totalSupplyAtT(timestamp);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _moveTokenDelegates(\\n address srcRep,\\n address dstRep,\\n uint _tokenId\\n ) internal {\\n if (srcRep != dstRep && _tokenId > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except _tokenId\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (tId != _tokenId) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n // All the same plus _tokenId\\n require(\\n dstRepOld.length + 1 <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n dstRepNew.push(_tokenId);\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _findWhatCheckpointToWrite(address account)\\n internal\\n view\\n returns (uint32)\\n {\\n uint _timestamp = block.timestamp;\\n uint32 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n return _nCheckPoints - 1;\\n } else {\\n return _nCheckPoints;\\n }\\n }\\n\\n function _moveAllDelegates(\\n address owner,\\n address srcRep,\\n address dstRep\\n ) internal {\\n // You can only redelegate what you own\\n if (srcRep != dstRep) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except what owner owns\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (idToOwner[tId] != owner) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n uint ownerTokenCount = ownerToNFTokenCount[owner];\\n require(\\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n // All the same\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n // Plus all that's owned\\n for (uint i = 0; i < ownerTokenCount; i++) {\\n uint tId = ownerToNFTokenIdList[owner][i];\\n dstRepNew.push(tId);\\n }\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\\n address currentDelegate = delegates(delegator);\\n\\n _delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n _moveAllDelegates(delegator, currentDelegate, delegatee);\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n if (delegatee == address(0)) delegatee = msg.sender;\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n function delegateBySig(\\n address delegatee,\\n uint nonce,\\n uint expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public {\\n bytes32 domainSeparator = keccak256(\\n abi.encode(\\n DOMAIN_TYPEHASH,\\n keccak256(bytes(name)),\\n keccak256(bytes(version)),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 structHash = keccak256(\\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash)\\n );\\n address signatory = ecrecover(digest, v, r, s);\\n require(\\n signatory != address(0),\\n \\\"VotingEscrow::delegateBySig: invalid signature\\\"\\n );\\n require(\\n nonce == nonces[signatory]++,\\n \\\"VotingEscrow::delegateBySig: invalid nonce\\\"\\n );\\n require(\\n block.timestamp <= expiry,\\n \\\"VotingEscrow::delegateBySig: signature expired\\\"\\n );\\n return _delegate(signatory, delegatee);\\n }\\n}\\n\",\"keccak256\":\"0x7109ed9d84b5504fe5d4c73d5a10997a0b73f2f4d45813ce5e161997d405fd73\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x41bbb2c41036ca64b2f6c9e973e8cfaa113ebc42af86702cd0d267f915a7e886\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a06040526006805460ff191660011790553480156200001e57600080fd5b5060405162004a1c38038062004a1c8339810160408190526200004191620001b8565b6001600160a01b0382811660805260008054336001600160a01b031991821681178355600180548316909117815560028054909216938516939093179055437f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f0155427f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f005560046020527f9fe05126d2d9ecf60592e254dead906a4b2e492f36cca727682c38e9008c6ac1805460ff1990811684179091557f4267c0a6fd96b7a87f183ee8744f24d011423cd0e0142b3f563f183d8d9a456b8054821684179055635b5e139f60e01b82527e24030bcf4927897dffe721c2d8dda4bfd8910861687c42b03a463b43b04147805490911690921790915560055460405190913091600080516020620049fc833981519152908290a46005546040516000903090600080516020620049fc833981519152908390a45050620001f0565b80516001600160a01b0381168114620001b357600080fd5b919050565b60008060408385031215620001cc57600080fd5b620001d7836200019b565b9150620001e7602084016200019b565b90509250929050565b6080516147e26200021a60003960008181610b220152818161101801526133b501526147e26000f3fe608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea2646970667358221220a4ace575587bb054f0f68456418aa3852256d45a84f88c76453bf28e3d048c9564736f6c634300080d0033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea2646970667358221220a4ace575587bb054f0f68456418aa3852256d45a84f88c76453bf28e3d048c9564736f6c634300080d0033", "devdoc": { "author": "Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)", "details": "Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).", @@ -1881,7 +1881,7 @@ "storageLayout": { "storage": [ { - "astId": 16268, + "astId": 16269, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "voter", "offset": 0, @@ -1889,7 +1889,7 @@ "type": "t_address" }, { - "astId": 16270, + "astId": 16271, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "team", "offset": 0, @@ -1897,7 +1897,7 @@ "type": "t_address" }, { - "astId": 16272, + "astId": 16273, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "artProxy", "offset": 0, @@ -1905,15 +1905,15 @@ "type": "t_address" }, { - "astId": 16277, + "astId": 16278, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "point_history", "offset": 0, "slot": "3", - "type": "t_mapping(t_uint256,t_struct(Point)16227_storage)" + "type": "t_mapping(t_uint256,t_struct(Point)16228_storage)" }, { - "astId": 16282, + "astId": 16283, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "supportedInterfaces", "offset": 0, @@ -1921,7 +1921,7 @@ "type": "t_mapping(t_bytes4,t_bool)" }, { - "astId": 16297, + "astId": 16298, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "tokenId", "offset": 0, @@ -1929,7 +1929,7 @@ "type": "t_uint256" }, { - "astId": 16392, + "astId": 16393, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "_entered_state", "offset": 0, @@ -1937,7 +1937,7 @@ "type": "t_uint8" }, { - "astId": 16511, + "astId": 16512, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "idToOwner", "offset": 0, @@ -1945,7 +1945,7 @@ "type": "t_mapping(t_uint256,t_address)" }, { - "astId": 16516, + "astId": 16517, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "ownerToNFTokenCount", "offset": 0, @@ -1953,7 +1953,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 16560, + "astId": 16561, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "idToApprovals", "offset": 0, @@ -1961,7 +1961,7 @@ "type": "t_mapping(t_uint256,t_address)" }, { - "astId": 16567, + "astId": 16568, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "ownerToOperators", "offset": 0, @@ -1969,7 +1969,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 16571, + "astId": 16572, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "ownership_change", "offset": 0, @@ -1977,7 +1977,7 @@ "type": "t_mapping(t_uint256,t_uint256)" }, { - "astId": 17016, + "astId": 17017, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "ownerToNFTokenIdList", "offset": 0, @@ -1985,7 +1985,7 @@ "type": "t_mapping(t_address,t_mapping(t_uint256,t_uint256))" }, { - "astId": 17021, + "astId": 17022, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "tokenToOwnerIndex", "offset": 0, @@ -1993,7 +1993,7 @@ "type": "t_mapping(t_uint256,t_uint256)" }, { - "astId": 17326, + "astId": 17327, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "user_point_epoch", "offset": 0, @@ -2001,23 +2001,23 @@ "type": "t_mapping(t_uint256,t_uint256)" }, { - "astId": 17333, + "astId": 17334, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "user_point_history", "offset": 0, "slot": "15", - "type": "t_mapping(t_uint256,t_array(t_struct(Point)16227_storage)1000000000_storage)" + "type": "t_mapping(t_uint256,t_array(t_struct(Point)16228_storage)1000000000_storage)" }, { - "astId": 17338, + "astId": 17339, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "locked", "offset": 0, "slot": "16", - "type": "t_mapping(t_uint256,t_struct(LockedBalance)16218_storage)" + "type": "t_mapping(t_uint256,t_struct(LockedBalance)16219_storage)" }, { - "astId": 17340, + "astId": 17341, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "epoch", "offset": 0, @@ -2025,7 +2025,7 @@ "type": "t_uint256" }, { - "astId": 17344, + "astId": 17345, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "slope_changes", "offset": 0, @@ -2033,7 +2033,7 @@ "type": "t_mapping(t_uint256,t_int128)" }, { - "astId": 17346, + "astId": 17347, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "supply", "offset": 0, @@ -2041,7 +2041,7 @@ "type": "t_uint256" }, { - "astId": 19217, + "astId": 19218, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "attachments", "offset": 0, @@ -2049,7 +2049,7 @@ "type": "t_mapping(t_uint256,t_uint256)" }, { - "astId": 19221, + "astId": 19222, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "voted", "offset": 0, @@ -2057,7 +2057,7 @@ "type": "t_mapping(t_uint256,t_bool)" }, { - "astId": 19452, + "astId": 19453, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "_delegates", "offset": 0, @@ -2065,15 +2065,15 @@ "type": "t_mapping(t_address,t_address)" }, { - "astId": 19463, + "astId": 19464, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "checkpoints", "offset": 0, "slot": "23", - "type": "t_mapping(t_address,t_mapping(t_uint32,t_struct(Checkpoint)16233_storage))" + "type": "t_mapping(t_address,t_mapping(t_uint32,t_struct(Checkpoint)16234_storage))" }, { - "astId": 19468, + "astId": 19469, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "numCheckpoints", "offset": 0, @@ -2081,7 +2081,7 @@ "type": "t_mapping(t_address,t_uint32)" }, { - "astId": 19473, + "astId": 19474, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "nonces", "offset": 0, @@ -2095,8 +2095,8 @@ "label": "address", "numberOfBytes": "20" }, - "t_array(t_struct(Point)16227_storage)1000000000_storage": { - "base": "t_struct(Point)16227_storage", + "t_array(t_struct(Point)16228_storage)1000000000_storage": { + "base": "t_struct(Point)16228_storage", "encoding": "inplace", "label": "struct VotingEscrow.Point[1000000000]", "numberOfBytes": "96000000000" @@ -2150,12 +2150,12 @@ "numberOfBytes": "32", "value": "t_mapping(t_uint256,t_uint256)" }, - "t_mapping(t_address,t_mapping(t_uint32,t_struct(Checkpoint)16233_storage))": { + "t_mapping(t_address,t_mapping(t_uint32,t_struct(Checkpoint)16234_storage))": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => mapping(uint32 => struct VotingEscrow.Checkpoint))", "numberOfBytes": "32", - "value": "t_mapping(t_uint32,t_struct(Checkpoint)16233_storage)" + "value": "t_mapping(t_uint32,t_struct(Checkpoint)16234_storage)" }, "t_mapping(t_address,t_uint256)": { "encoding": "mapping", @@ -2185,12 +2185,12 @@ "numberOfBytes": "32", "value": "t_address" }, - "t_mapping(t_uint256,t_array(t_struct(Point)16227_storage)1000000000_storage)": { + "t_mapping(t_uint256,t_array(t_struct(Point)16228_storage)1000000000_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct VotingEscrow.Point[1000000000])", "numberOfBytes": "32", - "value": "t_array(t_struct(Point)16227_storage)1000000000_storage" + "value": "t_array(t_struct(Point)16228_storage)1000000000_storage" }, "t_mapping(t_uint256,t_bool)": { "encoding": "mapping", @@ -2206,19 +2206,19 @@ "numberOfBytes": "32", "value": "t_int128" }, - "t_mapping(t_uint256,t_struct(LockedBalance)16218_storage)": { + "t_mapping(t_uint256,t_struct(LockedBalance)16219_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct VotingEscrow.LockedBalance)", "numberOfBytes": "32", - "value": "t_struct(LockedBalance)16218_storage" + "value": "t_struct(LockedBalance)16219_storage" }, - "t_mapping(t_uint256,t_struct(Point)16227_storage)": { + "t_mapping(t_uint256,t_struct(Point)16228_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct VotingEscrow.Point)", "numberOfBytes": "32", - "value": "t_struct(Point)16227_storage" + "value": "t_struct(Point)16228_storage" }, "t_mapping(t_uint256,t_uint256)": { "encoding": "mapping", @@ -2227,19 +2227,19 @@ "numberOfBytes": "32", "value": "t_uint256" }, - "t_mapping(t_uint32,t_struct(Checkpoint)16233_storage)": { + "t_mapping(t_uint32,t_struct(Checkpoint)16234_storage)": { "encoding": "mapping", "key": "t_uint32", "label": "mapping(uint32 => struct VotingEscrow.Checkpoint)", "numberOfBytes": "32", - "value": "t_struct(Checkpoint)16233_storage" + "value": "t_struct(Checkpoint)16234_storage" }, - "t_struct(Checkpoint)16233_storage": { + "t_struct(Checkpoint)16234_storage": { "encoding": "inplace", "label": "struct VotingEscrow.Checkpoint", "members": [ { - "astId": 16229, + "astId": 16230, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "timestamp", "offset": 0, @@ -2247,7 +2247,7 @@ "type": "t_uint256" }, { - "astId": 16232, + "astId": 16233, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "tokenIds", "offset": 0, @@ -2257,12 +2257,12 @@ ], "numberOfBytes": "64" }, - "t_struct(LockedBalance)16218_storage": { + "t_struct(LockedBalance)16219_storage": { "encoding": "inplace", "label": "struct VotingEscrow.LockedBalance", "members": [ { - "astId": 16215, + "astId": 16216, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "amount", "offset": 0, @@ -2270,7 +2270,7 @@ "type": "t_int128" }, { - "astId": 16217, + "astId": 16218, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "end", "offset": 0, @@ -2280,12 +2280,12 @@ ], "numberOfBytes": "64" }, - "t_struct(Point)16227_storage": { + "t_struct(Point)16228_storage": { "encoding": "inplace", "label": "struct VotingEscrow.Point", "members": [ { - "astId": 16220, + "astId": 16221, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "bias", "offset": 0, @@ -2293,7 +2293,7 @@ "type": "t_int128" }, { - "astId": 16222, + "astId": 16223, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "slope", "offset": 16, @@ -2301,7 +2301,7 @@ "type": "t_int128" }, { - "astId": 16224, + "astId": 16225, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "ts", "offset": 0, @@ -2309,7 +2309,7 @@ "type": "t_uint256" }, { - "astId": 16226, + "astId": 16227, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "blk", "offset": 0, diff --git a/deployments/arbitrumGoerli/WrappedExternalBribeFactory.json b/deployments/arbitrumGoerli/WrappedExternalBribeFactory.json new file mode 100644 index 00000000..5c70b130 --- /dev/null +++ b/deployments/arbitrumGoerli/WrappedExternalBribeFactory.json @@ -0,0 +1,148 @@ +{ + "address": "0x924E5A03DEeFD4f24597f0237E15460e12F348Dc", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_voter", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "existing_bribe", + "type": "address" + } + ], + "name": "createBribe", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "last_bribe", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "oldBribeToNew", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "voter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x4ed9a47378787f773e1835521450d1535ae07ecb0189263e7333fda1e6c36323", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x924E5A03DEeFD4f24597f0237E15460e12F348Dc", + "transactionIndex": 1, + "gasUsed": "1642990", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xa3b20b93ee08515b48ebc4f82427ffb799f737d27238e03a49633f5586490f98", + "transactionHash": "0x4ed9a47378787f773e1835521450d1535ae07ecb0189263e7333fda1e6c36323", + "logs": [], + "blockNumber": 6188498, + "cumulativeGasUsed": "1642990", + "status": 1, + "byzantium": true + }, + "args": [ + "0x809BCB4AC4c77F9F2B075ca9f29e160E8939D35f" + ], + "numDeployments": 1, + "solcInputHash": "6e27611a2cedd773c4cc6e46935e6392", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voter\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"existing_bribe\",\"type\":\"address\"}],\"name\":\"createBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"oldBribeToNew\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/WrappedExternalBribeFactory.sol\":\"WrappedExternalBribeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735303535373437363232\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/ExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract ExternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve; // \\u5929\\u4f7f\\u306e\\u305f\\u307e\\u3054\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balanceOf;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n _prevSupply = supplyCheckpoints[\\n getPriorSupplyIndex(_nextEpochStart + DURATION)\\n ].supply;\\n prevRewards.balanceOf =\\n (cp0.balanceOf *\\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (block.timestamp > _lastEpochEnd) {\\n reward +=\\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\\n }\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0xfe1e53dea8a63ce448c5856a740ed73038ad29a9dcd0f2a2752049b146bb4eb0\",\"license\":\"MIT\"},\"contracts/WrappedExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/ExternalBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract WrappedExternalBribe {\\n address public immutable voter;\\n address public immutable _ve;\\n ExternalBribe public underlying_bribe;\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct RewardCheckpoint {\\n uint256 timestamp;\\n uint256 balance;\\n }\\n\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address _old_bribe) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n underlying_bribe = ExternalBribe(_old_bribe);\\n\\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\\n address underlying_reward = underlying_bribe.rewards(i);\\n if (underlying_reward != address(0)) {\\n isReward[underlying_reward] = true;\\n rewards.push(underlying_reward);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\\n tokenId,\\n _startTimestamp\\n );\\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n RewardCheckpoint memory prevRewards;\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevTs = 0;\\n uint256 _prevBal = 0;\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\\n uint256 _nextEpochStart = _bribeStart(_prevTs);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balance;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\\n underlying_bribe.getPriorSupplyIndex(\\n _nextEpochStart + DURATION\\n )\\n );\\n prevRewards.balance =\\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\\n uint256 _lastEpochStart = _bribeStart(_prevTs);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (\\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\\n ) {\\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\\n );\\n reward +=\\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n _prevSupply;\\n }\\n\\n return reward;\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x855fa341d3139522255811d9a9df463636e27fd6e21bd07c38adacad734af6ed\",\"license\":\"MIT\"},\"contracts/factories/WrappedExternalBribeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\\n\\ncontract WrappedExternalBribeFactory {\\n address public immutable voter;\\n mapping(address => address) public oldBribeToNew;\\n address public last_bribe;\\n\\n constructor(address _voter) {\\n voter = _voter;\\n }\\n\\n function createBribe(address existing_bribe) external returns (address) {\\n require(\\n oldBribeToNew[existing_bribe] == address(0),\\n \\\"Wrapped bribe already created\\\"\\n );\\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\\n oldBribeToNew[existing_bribe] = last_bribe;\\n return last_bribe;\\n }\\n}\\n\",\"keccak256\":\"0x4e88b50000e3cf490ae8602b55555bbc02f95fda5926b1a532debfe54ac06bb2\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x60a060405234801561001057600080fd5b50604051611d5d380380611d5d83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051611ccc61009160003960008181609b01526101530152611ccc6000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632fcd8f271461005157806346c96aac146100965780636bd1a72c146100bd578063b1d0fc82146100d0575b600080fd5b61007a61005f366004610205565b6000602081905290815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b61007a7f000000000000000000000000000000000000000000000000000000000000000081565b61007a6100cb366004610205565b6100e3565b60015461007a906001600160a01b031681565b6001600160a01b03818116600090815260208190526040812054909116156101515760405162461bcd60e51b815260206004820152601d60248201527f5772617070656420627269626520616c72656164792063726561746564000000604482015260640160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000008260405161017f906101f8565b6001600160a01b03928316815291166020820152604001604051809103906000f0801580156101b2573d6000803e3d6000fd5b50600180546001600160a01b039283166001600160a01b031991821681178355948316600090815260208190526040902080549091169094179093559154909116919050565b611a618061023683390190565b60006020828403121561021757600080fd5b81356001600160a01b038116811461022e57600080fd5b939250505056fe60c060405260016006553480156200001657600080fd5b5060405162001a6138038062001a61833981016040819052620000399162000275565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002ad565b6001600160a01b0390811660a052600080546001600160a01b0319169183169190911781555b60008054906101000a90046001600160a01b03166001600160a01b031663e68863966040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000122573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001489190620002d2565b8110156200024f5760008054604051637980d7a160e11b8152600481018490526001600160a01b039091169063f301af4290602401602060405180830381865afa1580156200019b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001c19190620002ad565b90506001600160a01b0381161562000239576001600160a01b0381166000818152600560205260408120805460ff191660019081179091556004805491820181559091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b03191690911790555b50806200024681620002ec565b915050620000d0565b50505062000314565b80516001600160a01b03811681146200027057600080fd5b919050565b600080604083850312156200028957600080fd5b620002948362000258565b9150620002a46020840162000258565b90509250929050565b600060208284031215620002c057600080fd5b620002cb8262000258565b9392505050565b600060208284031215620002e557600080fd5b5051919050565b6000600182016200030d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a0516117046200035d600039600081816101e6015281816108f301528181610b1d0152610fd701526000818161014e01528181610ada0152610d1801526117046000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80639418f939116100a2578063da09d19d11610071578063da09d19d14610281578063e6886396146102a1578063f25e55a5146102a9578063f301af42146102d4578063f5f8d365146102e757600080fd5b80639418f9391461023357806399bcc05214610248578063a7852afa1461025b578063b66503cf1461026e57600080fd5b8063638634ee116100de578063638634ee146101bb5780636c4f5398146101ce5780638dd598fb146101e157806392777b291461020857600080fd5b80630175e23b146101105780633e491d471461013657806346c96aac146101495780634d5ce03814610188575b600080fd5b61012361011e366004611393565b6102fa565b6040519081526020015b60405180910390f35b6101236101443660046113d4565b61033c565b6101707f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161012d565b6101ab610196366004611400565b60056020526000908152604090205460ff1681565b604051901515815260200161012d565b6101236101c9366004611400565b6108cd565b600054610170906001600160a01b031681565b6101707f000000000000000000000000000000000000000000000000000000000000000081565b6101236102163660046113d4565b600160209081526000928352604080842090915290825290205481565b61024661024136600461141d565b6108f1565b005b610123610256366004611400565b610a82565b610246610269366004611475565b610abb565b61024661027c3660046113d4565b610cbb565b61012361028f366004611400565b60026020526000908152604090205481565b600454610123565b6101236102b73660046113d4565b600360209081526000928352604080842090915290825290205481565b6101706102e2366004611393565b610f7d565b6102466102f5366004611475565b610fa7565b6000806103068361117b565b9050600061031762093a808361155c565b90508084106103325761032d8262093a8061155c565b610334565b815b949350505050565b6001600160a01b0382811660009081526003602090815260408083208584529091528082205482549151635058979360e01b81526004810186905292939092911690635058979390602401602060405180830381865afa1580156103a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103c89190611574565b6000036103d95760009150506108c7565b600080546040516328a3532760e21b815260048101869052602481018490526001600160a01b039091169063a28d4c9c90604401602060405180830381865afa15801561042a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044e9190611574565b60008054604051635058979360e01b81526004810188905292935090916001916001600160a01b031690635058979390602401602060405180830381865afa15801561049e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c29190611574565b6104cc919061158d565b905060006104ed604051806040016040528060008152602001600081525090565b6104f68561117b565b8152600080600185156106f357865b61051060018861158d565b81116106f157600054604051631277308160e21b8152600481018d9052602481018390526001600160a01b03909116906349dcc204906044016040805180830381865afa158015610565573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058991906115a4565b909450925060006105998561117b565b86519091508111156105b75760208601516105b4908861155c565b96505b8086526000546001600160a01b031663f7412baf816376f4be366105de62093a808661155c565b6040518263ffffffff1660e01b81526004016105fc91815260200190565b602060405180830381865afa158015610619573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063d9190611574565b6040518263ffffffff1660e01b815260040161065b91815260200190565b6040805180830381865afa158015610677573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061069b91906115a4565b6001600160a01b038f1660009081526001602090815260408083208684529091529020549094508491506106cf90866115c8565b6106d991906115fd565b602087015250806106e981611611565b915050610505565b505b600054604051631277308160e21b8152600481018c9052602481018890526001600160a01b03909116906349dcc204906044016040805180830381865afa158015610742573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076691906115a4565b909350915060006107768461117b565b9050600061078762093a808361155c565b905080421180156107975750808a105b156108ba57600054604051633b7a5f1b60e11b8152600481018390526001600160a01b039091169063f7412baf9082906376f4be3690602401602060405180830381865afa1580156107ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108119190611574565b6040518263ffffffff1660e01b815260040161082f91815260200190565b6040805180830381865afa15801561084b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086f91906115a4565b6001600160a01b038f1660009081526001602090815260408083208784529091529020549094508491506108a390866115c8565b6108ad91906115fd565b6108b7908861155c565b96505b5094985050505050505050505b92915050565b6001600160a01b0381166000908152600260205260408120546108c7904290611194565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610951573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610975919061162a565b6001600160a01b0316336001600160a01b0316146109c65760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600484815481106109e3576109e3611647565b6000918252602090912001546001600160a01b031614610a0257600080fd5b6001600160a01b03808316600090815260056020526040808220805460ff1990811690915592841682529020805490911660011790556004805482919085908110610a4f57610a4f611647565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a8e426102fa565b6001600160a01b039093166000908152600160209081526040808320958352949052929092205492915050565b600654600114610aca57600080fd5b6002600655336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b0457600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610b6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b90919061162a565b905060005b8251811015610cb0576000610bc3848381518110610bb557610bb5611647565b60200260200101518661033c565b90504260036000868581518110610bdc57610bdc611647565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610c3757610c37848381518110610c2857610c28611647565b602002602001015184836111ac565b838281518110610c4957610c49611647565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610c9591815260200190565b60405180910390a35080610ca881611611565b915050610b95565b505060016006555050565b600654600114610cca57600080fd5b600260065580610cd957600080fd5b6001600160a01b03821660009081526005602052604090205460ff16610e2157604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610d5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d83919061165d565b610dcf5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c697374656460448201526064016109bd565b600454601011610e215760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e7300000000000000000060448201526064016109bd565b6000610e2c426102fa565b6001600160a01b0384166000908152600160209081526040808320848452909152902054909150610e5f8433308661129b565b610e69838261155c565b6001600160a01b0385166000908152600160209081526040808320868452909152902055610e9a62093a808361155c565b6001600160a01b03851660009081526002602090815260408083209390935560059052205460ff16610f2c576001600160a01b0384166000818152600560205260408120805460ff191660019081179091556004805491820181559091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a3505060016006555050565b60048181548110610f8d57600080fd5b6000918252602090912001546001600160a01b0316905081565b600654600114610fb657600080fd5b600260065560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611026573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104a919061165d565b61105357600080fd5b60005b815181101561117157600061108483838151811061107657611076611647565b60200260200101518561033c565b9050426003600085858151811061109d5761109d611647565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812088825290925290205580156110f8576110f88383815181106110e9576110e9611647565b602002602001015133836111ac565b82828151811061110a5761110a611647565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161115691815260200190565b60405180910390a3508061116981611611565b915050611056565b5050600160065550565b600061118a62093a808361167f565b6108c7908361158d565b60008183106111a357816111a5565b825b9392505050565b6000836001600160a01b03163b116111c357600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161121f9190611693565b6000604051808303816000865af19150503d806000811461125c576040519150601f19603f3d011682016040523d82523d6000602084013e611261565b606091505b509150915081801561128b57508051158061128b57508080602001905181019061128b919061165d565b61129457600080fd5b5050505050565b6000846001600160a01b03163b116112b257600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916113169190611693565b6000604051808303816000865af19150503d8060008114611353576040519150601f19603f3d011682016040523d82523d6000602084013e611358565b606091505b5091509150818015611382575080511580611382575080806020019051810190611382919061165d565b61138b57600080fd5b505050505050565b6000602082840312156113a557600080fd5b5035919050565b6001600160a01b03811681146113c157600080fd5b50565b80356113cf816113ac565b919050565b600080604083850312156113e757600080fd5b82356113f2816113ac565b946020939093013593505050565b60006020828403121561141257600080fd5b81356111a5816113ac565b60008060006060848603121561143257600080fd5b833592506020840135611444816113ac565b91506040840135611454816113ac565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561148857600080fd5b8235915060208084013567ffffffffffffffff808211156114a857600080fd5b818601915086601f8301126114bc57600080fd5b8135818111156114ce576114ce61145f565b8060051b604051601f19603f830116810181811085821117156114f3576114f361145f565b60405291825284820192508381018501918983111561151157600080fd5b938501935b8285101561153657611527856113c4565b84529385019392850192611516565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561156f5761156f611546565b500190565b60006020828403121561158657600080fd5b5051919050565b60008282101561159f5761159f611546565b500390565b600080604083850312156115b757600080fd5b505080516020909101519092909150565b60008160001904831182151516156115e2576115e2611546565b500290565b634e487b7160e01b600052601260045260246000fd5b60008261160c5761160c6115e7565b500490565b60006001820161162357611623611546565b5060010190565b60006020828403121561163c57600080fd5b81516111a5816113ac565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561166f57600080fd5b815180151581146111a557600080fd5b60008261168e5761168e6115e7565b500690565b6000825160005b818110156116b4576020818601810151858301520161169a565b818111156116c3576000828501525b50919091019291505056fea2646970667358221220d5a00c434328e4f91f2b6b71f42164d9fc686985cf62d4138e3745f994fef26464736f6c634300080d0033a26469706673582212200c34552995c011003b15f88cb3fad5f7585da18bada1394e4637fac2b8f9346064736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632fcd8f271461005157806346c96aac146100965780636bd1a72c146100bd578063b1d0fc82146100d0575b600080fd5b61007a61005f366004610205565b6000602081905290815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b61007a7f000000000000000000000000000000000000000000000000000000000000000081565b61007a6100cb366004610205565b6100e3565b60015461007a906001600160a01b031681565b6001600160a01b03818116600090815260208190526040812054909116156101515760405162461bcd60e51b815260206004820152601d60248201527f5772617070656420627269626520616c72656164792063726561746564000000604482015260640160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000008260405161017f906101f8565b6001600160a01b03928316815291166020820152604001604051809103906000f0801580156101b2573d6000803e3d6000fd5b50600180546001600160a01b039283166001600160a01b031991821681178355948316600090815260208190526040902080549091169094179093559154909116919050565b611a618061023683390190565b60006020828403121561021757600080fd5b81356001600160a01b038116811461022e57600080fd5b939250505056fe60c060405260016006553480156200001657600080fd5b5060405162001a6138038062001a61833981016040819052620000399162000275565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002ad565b6001600160a01b0390811660a052600080546001600160a01b0319169183169190911781555b60008054906101000a90046001600160a01b03166001600160a01b031663e68863966040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000122573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001489190620002d2565b8110156200024f5760008054604051637980d7a160e11b8152600481018490526001600160a01b039091169063f301af4290602401602060405180830381865afa1580156200019b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001c19190620002ad565b90506001600160a01b0381161562000239576001600160a01b0381166000818152600560205260408120805460ff191660019081179091556004805491820181559091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b03191690911790555b50806200024681620002ec565b915050620000d0565b50505062000314565b80516001600160a01b03811681146200027057600080fd5b919050565b600080604083850312156200028957600080fd5b620002948362000258565b9150620002a46020840162000258565b90509250929050565b600060208284031215620002c057600080fd5b620002cb8262000258565b9392505050565b600060208284031215620002e557600080fd5b5051919050565b6000600182016200030d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a0516117046200035d600039600081816101e6015281816108f301528181610b1d0152610fd701526000818161014e01528181610ada0152610d1801526117046000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80639418f939116100a2578063da09d19d11610071578063da09d19d14610281578063e6886396146102a1578063f25e55a5146102a9578063f301af42146102d4578063f5f8d365146102e757600080fd5b80639418f9391461023357806399bcc05214610248578063a7852afa1461025b578063b66503cf1461026e57600080fd5b8063638634ee116100de578063638634ee146101bb5780636c4f5398146101ce5780638dd598fb146101e157806392777b291461020857600080fd5b80630175e23b146101105780633e491d471461013657806346c96aac146101495780634d5ce03814610188575b600080fd5b61012361011e366004611393565b6102fa565b6040519081526020015b60405180910390f35b6101236101443660046113d4565b61033c565b6101707f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161012d565b6101ab610196366004611400565b60056020526000908152604090205460ff1681565b604051901515815260200161012d565b6101236101c9366004611400565b6108cd565b600054610170906001600160a01b031681565b6101707f000000000000000000000000000000000000000000000000000000000000000081565b6101236102163660046113d4565b600160209081526000928352604080842090915290825290205481565b61024661024136600461141d565b6108f1565b005b610123610256366004611400565b610a82565b610246610269366004611475565b610abb565b61024661027c3660046113d4565b610cbb565b61012361028f366004611400565b60026020526000908152604090205481565b600454610123565b6101236102b73660046113d4565b600360209081526000928352604080842090915290825290205481565b6101706102e2366004611393565b610f7d565b6102466102f5366004611475565b610fa7565b6000806103068361117b565b9050600061031762093a808361155c565b90508084106103325761032d8262093a8061155c565b610334565b815b949350505050565b6001600160a01b0382811660009081526003602090815260408083208584529091528082205482549151635058979360e01b81526004810186905292939092911690635058979390602401602060405180830381865afa1580156103a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103c89190611574565b6000036103d95760009150506108c7565b600080546040516328a3532760e21b815260048101869052602481018490526001600160a01b039091169063a28d4c9c90604401602060405180830381865afa15801561042a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044e9190611574565b60008054604051635058979360e01b81526004810188905292935090916001916001600160a01b031690635058979390602401602060405180830381865afa15801561049e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c29190611574565b6104cc919061158d565b905060006104ed604051806040016040528060008152602001600081525090565b6104f68561117b565b8152600080600185156106f357865b61051060018861158d565b81116106f157600054604051631277308160e21b8152600481018d9052602481018390526001600160a01b03909116906349dcc204906044016040805180830381865afa158015610565573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058991906115a4565b909450925060006105998561117b565b86519091508111156105b75760208601516105b4908861155c565b96505b8086526000546001600160a01b031663f7412baf816376f4be366105de62093a808661155c565b6040518263ffffffff1660e01b81526004016105fc91815260200190565b602060405180830381865afa158015610619573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063d9190611574565b6040518263ffffffff1660e01b815260040161065b91815260200190565b6040805180830381865afa158015610677573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061069b91906115a4565b6001600160a01b038f1660009081526001602090815260408083208684529091529020549094508491506106cf90866115c8565b6106d991906115fd565b602087015250806106e981611611565b915050610505565b505b600054604051631277308160e21b8152600481018c9052602481018890526001600160a01b03909116906349dcc204906044016040805180830381865afa158015610742573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076691906115a4565b909350915060006107768461117b565b9050600061078762093a808361155c565b905080421180156107975750808a105b156108ba57600054604051633b7a5f1b60e11b8152600481018390526001600160a01b039091169063f7412baf9082906376f4be3690602401602060405180830381865afa1580156107ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108119190611574565b6040518263ffffffff1660e01b815260040161082f91815260200190565b6040805180830381865afa15801561084b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086f91906115a4565b6001600160a01b038f1660009081526001602090815260408083208784529091529020549094508491506108a390866115c8565b6108ad91906115fd565b6108b7908861155c565b96505b5094985050505050505050505b92915050565b6001600160a01b0381166000908152600260205260408120546108c7904290611194565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610951573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610975919061162a565b6001600160a01b0316336001600160a01b0316146109c65760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600484815481106109e3576109e3611647565b6000918252602090912001546001600160a01b031614610a0257600080fd5b6001600160a01b03808316600090815260056020526040808220805460ff1990811690915592841682529020805490911660011790556004805482919085908110610a4f57610a4f611647565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a8e426102fa565b6001600160a01b039093166000908152600160209081526040808320958352949052929092205492915050565b600654600114610aca57600080fd5b6002600655336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b0457600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610b6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b90919061162a565b905060005b8251811015610cb0576000610bc3848381518110610bb557610bb5611647565b60200260200101518661033c565b90504260036000868581518110610bdc57610bdc611647565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610c3757610c37848381518110610c2857610c28611647565b602002602001015184836111ac565b838281518110610c4957610c49611647565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610c9591815260200190565b60405180910390a35080610ca881611611565b915050610b95565b505060016006555050565b600654600114610cca57600080fd5b600260065580610cd957600080fd5b6001600160a01b03821660009081526005602052604090205460ff16610e2157604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610d5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d83919061165d565b610dcf5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c697374656460448201526064016109bd565b600454601011610e215760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e7300000000000000000060448201526064016109bd565b6000610e2c426102fa565b6001600160a01b0384166000908152600160209081526040808320848452909152902054909150610e5f8433308661129b565b610e69838261155c565b6001600160a01b0385166000908152600160209081526040808320868452909152902055610e9a62093a808361155c565b6001600160a01b03851660009081526002602090815260408083209390935560059052205460ff16610f2c576001600160a01b0384166000818152600560205260408120805460ff191660019081179091556004805491820181559091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a3505060016006555050565b60048181548110610f8d57600080fd5b6000918252602090912001546001600160a01b0316905081565b600654600114610fb657600080fd5b600260065560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611026573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104a919061165d565b61105357600080fd5b60005b815181101561117157600061108483838151811061107657611076611647565b60200260200101518561033c565b9050426003600085858151811061109d5761109d611647565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812088825290925290205580156110f8576110f88383815181106110e9576110e9611647565b602002602001015133836111ac565b82828151811061110a5761110a611647565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161115691815260200190565b60405180910390a3508061116981611611565b915050611056565b5050600160065550565b600061118a62093a808361167f565b6108c7908361158d565b60008183106111a357816111a5565b825b9392505050565b6000836001600160a01b03163b116111c357600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161121f9190611693565b6000604051808303816000865af19150503d806000811461125c576040519150601f19603f3d011682016040523d82523d6000602084013e611261565b606091505b509150915081801561128b57508051158061128b57508080602001905181019061128b919061165d565b61129457600080fd5b5050505050565b6000846001600160a01b03163b116112b257600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916113169190611693565b6000604051808303816000865af19150503d8060008114611353576040519150601f19603f3d011682016040523d82523d6000602084013e611358565b606091505b5091509150818015611382575080511580611382575080806020019051810190611382919061165d565b61138b57600080fd5b505050505050565b6000602082840312156113a557600080fd5b5035919050565b6001600160a01b03811681146113c157600080fd5b50565b80356113cf816113ac565b919050565b600080604083850312156113e757600080fd5b82356113f2816113ac565b946020939093013593505050565b60006020828403121561141257600080fd5b81356111a5816113ac565b60008060006060848603121561143257600080fd5b833592506020840135611444816113ac565b91506040840135611454816113ac565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561148857600080fd5b8235915060208084013567ffffffffffffffff808211156114a857600080fd5b818601915086601f8301126114bc57600080fd5b8135818111156114ce576114ce61145f565b8060051b604051601f19603f830116810181811085821117156114f3576114f361145f565b60405291825284820192508381018501918983111561151157600080fd5b938501935b8285101561153657611527856113c4565b84529385019392850192611516565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561156f5761156f611546565b500190565b60006020828403121561158657600080fd5b5051919050565b60008282101561159f5761159f611546565b500390565b600080604083850312156115b757600080fd5b505080516020909101519092909150565b60008160001904831182151516156115e2576115e2611546565b500290565b634e487b7160e01b600052601260045260246000fd5b60008261160c5761160c6115e7565b500490565b60006001820161162357611623611546565b5060010190565b60006020828403121561163c57600080fd5b81516111a5816113ac565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561166f57600080fd5b815180151581146111a557600080fd5b60008261168e5761168e6115e7565b500690565b6000825160005b818110156116b4576020818601810151858301520161169a565b818111156116c3576000828501525b50919091019291505056fea2646970667358221220d5a00c434328e4f91f2b6b71f42164d9fc686985cf62d4138e3745f994fef26464736f6c634300080d0033a26469706673582212200c34552995c011003b15f88cb3fad5f7585da18bada1394e4637fac2b8f9346064736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 21824, + "contract": "contracts/factories/WrappedExternalBribeFactory.sol:WrappedExternalBribeFactory", + "label": "oldBribeToNew", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 21826, + "contract": "contracts/factories/WrappedExternalBribeFactory.sol:WrappedExternalBribeFactory", + "label": "last_bribe", + "offset": 0, + "slot": "1", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_address)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => address)", + "numberOfBytes": "32", + "value": "t_address" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/solcInputs/6e27611a2cedd773c4cc6e46935e6392.json b/deployments/arbitrumGoerli/solcInputs/6e27611a2cedd773c4cc6e46935e6392.json new file mode 100644 index 00000000..8c3860b5 --- /dev/null +++ b/deployments/arbitrumGoerli/solcInputs/6e27611a2cedd773c4cc6e46935e6392.json @@ -0,0 +1,247 @@ +{ + "language": "Solidity", + "sources": { + "contracts/ExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/ExternalBribeV.sol": { + "content": "" + }, + "contracts/factories/BribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport \"contracts/InternalBribe.sol\";\nimport \"contracts/ExternalBribe.sol\";\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards)\n external\n returns (address)\n {\n last_internal_bribe = address(\n new InternalBribe(msg.sender, allowedRewards)\n );\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards)\n external\n returns (address)\n {\n last_external_bribe = address(\n new ExternalBribe(msg.sender, allowedRewards)\n );\n return last_external_bribe;\n }\n}\n" + }, + "contracts/factories/GaugeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" + }, + "contracts/factories/PairFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" + }, + "contracts/factories/WrappedExternalBribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" + }, + "contracts/Flow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IFlow.sol\";\n\ncontract Flow is IFlow {\n\n string public constant name = \"Velocimeter\";\n string public constant symbol = \"FLOW\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" + }, + "contracts/FlowGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract FlowGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velocimeter Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" + }, + "contracts/Gauge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/governance/L2Governor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" + }, + "contracts/governance/L2GovernorCountingSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" + }, + "contracts/governance/L2GovernorVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" + }, + "contracts/governance/L2GovernorVotesQuorumFraction.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" + }, + "contracts/interfaces/IBribe.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IBribeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IERC20.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" + }, + "contracts/interfaces/IFlow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IFlow {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" + }, + "contracts/interfaces/IGauge.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" + }, + "contracts/interfaces/IGaugeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IMinter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" + }, + "contracts/interfaces/IPair.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IPairCallee.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" + }, + "contracts/interfaces/IPairFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" + }, + "contracts/interfaces/IRewardsDistributor.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" + }, + "contracts/interfaces/IRouter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" + }, + "contracts/interfaces/IVeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" + }, + "contracts/interfaces/IVoter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" + }, + "contracts/interfaces/IVotingEscrow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" + }, + "contracts/interfaces/IWETH.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" + }, + "contracts/InternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/libraries/Base64.sol": { + "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" + }, + "contracts/libraries/Math.sol": { + "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" + }, + "contracts/Minter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IFlow.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IFlow public immutable _flow;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M FLOW (FLOW has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 0.03%\n _flow = IFlow(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants,\n uint256[] memory amounts,\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _flow.mint(address(this), max);\n _flow.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _flow.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _flowTotal = _flow.totalSupply();\n return\n (((((_minted * _veTotal) / _flowTotal) * _veTotal) / _flowTotal) *\n _veTotal) /\n _flowTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _flow.balanceOf(address(this));\n if (_balanceOf < _required) {\n _flow.mint(address(this), _required - _balanceOf);\n }\n\n require(_flow.transfer(team, _teamEmissions));\n require(_flow.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _flow.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" + }, + "contracts/Pair.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/PairFees.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" + }, + "contracts/redeem/MerkleClaim.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IFlow} from \"contracts/interfaces/IFlow.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims FLOW for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice FLOW token to claim\n IFlow public immutable FLOW;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _flow address\n /// @param _merkleRoot of claimees\n constructor(address _flow, bytes32 _merkleRoot) {\n FLOW = IFlow(_flow);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(FLOW.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" + }, + "contracts/redeem/RedemptionReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IFlow.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + FLOW\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IFlow public immutable FLOW;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableFLOW;\n uint256 public leftoverFLOW;\n\n constructor(\n address _usdc,\n address _flow,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n FLOW = IFlow(_flow);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableFLOW);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableFLOW\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableFLOW = _redeemableFLOW;\n leftoverFLOW = _redeemableFLOW;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableFLOW);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfFLOW)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata FLOW\n shareOfFLOW = (amountWEVE * redeemableFLOW) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfFLOW) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverFLOW -= shareOfFLOW; // this will revert if underflows\n require(\n FLOW.claim(redemptionAddress, shareOfFLOW),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" + }, + "contracts/redeem/RedemptionSender.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" + }, + "contracts/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" + }, + "contracts/Router.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/routerV.sol": { + "content": "" + }, + "contracts/VeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velocimeter locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" + }, + "contracts/VelocimeterLibrary.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelocimeterLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" + }, + "contracts/Voter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velocimeter pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VotingEscrow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `FLOW` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" + }, + "contracts/WrappedExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/WrappedExternalBribeV.sol": { + "content": "" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + }, + "libraries": { + "": { + "__CACHE_BREAKER__": "0x0000000000000031363735303535373437363232" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumOne/WrappedExternalBribeFactory.json b/deployments/arbitrumOne/WrappedExternalBribeFactory.json new file mode 100644 index 00000000..020f594f --- /dev/null +++ b/deployments/arbitrumOne/WrappedExternalBribeFactory.json @@ -0,0 +1,148 @@ +{ + "address": "0xbb88E349257e4355946C2604fEd168165989285c", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_voter", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "existing_bribe", + "type": "address" + } + ], + "name": "createBribe", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "last_bribe", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "oldBribeToNew", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "voter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xe910624a59ad0487fff48182a26d189b2e6384c5389ce0ae2483da6dbc9bcf00", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0xbb88E349257e4355946C2604fEd168165989285c", + "transactionIndex": 1, + "gasUsed": "10475233", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x502c654130fc432a20ef80e86336a8d5e1aed325c26ae2a13d4eb3b2a8779b33", + "transactionHash": "0xe910624a59ad0487fff48182a26d189b2e6384c5389ce0ae2483da6dbc9bcf00", + "logs": [], + "blockNumber": 56592743, + "cumulativeGasUsed": "10475233", + "status": 1, + "byzantium": true + }, + "args": [ + "0x29C487a354D11315059204Df4F7d8AB1aa008ebb" + ], + "numDeployments": 1, + "solcInputHash": "4e21824d68c90a2d8601cfb8f8d80414", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voter\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"existing_bribe\",\"type\":\"address\"}],\"name\":\"createBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"oldBribeToNew\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/WrappedExternalBribeFactory.sol\":\"WrappedExternalBribeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735303731393533363138\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/ExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract ExternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve; // \\u5929\\u4f7f\\u306e\\u305f\\u307e\\u3054\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balanceOf;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n _prevSupply = supplyCheckpoints[\\n getPriorSupplyIndex(_nextEpochStart + DURATION)\\n ].supply;\\n prevRewards.balanceOf =\\n (cp0.balanceOf *\\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (block.timestamp > _lastEpochEnd) {\\n reward +=\\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\\n }\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0xfe1e53dea8a63ce448c5856a740ed73038ad29a9dcd0f2a2752049b146bb4eb0\",\"license\":\"MIT\"},\"contracts/WrappedExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/ExternalBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract WrappedExternalBribe {\\n address public immutable voter;\\n address public immutable _ve;\\n ExternalBribe public underlying_bribe;\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct RewardCheckpoint {\\n uint256 timestamp;\\n uint256 balance;\\n }\\n\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address _old_bribe) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n underlying_bribe = ExternalBribe(_old_bribe);\\n\\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\\n address underlying_reward = underlying_bribe.rewards(i);\\n if (underlying_reward != address(0)) {\\n isReward[underlying_reward] = true;\\n rewards.push(underlying_reward);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\\n tokenId,\\n _startTimestamp\\n );\\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n RewardCheckpoint memory prevRewards;\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevTs = 0;\\n uint256 _prevBal = 0;\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\\n uint256 _nextEpochStart = _bribeStart(_prevTs);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balance;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\\n underlying_bribe.getPriorSupplyIndex(\\n _nextEpochStart + DURATION\\n )\\n );\\n prevRewards.balance =\\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\\n uint256 _lastEpochStart = _bribeStart(_prevTs);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (\\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\\n ) {\\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\\n );\\n reward +=\\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n _prevSupply;\\n }\\n\\n return reward;\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x855fa341d3139522255811d9a9df463636e27fd6e21bd07c38adacad734af6ed\",\"license\":\"MIT\"},\"contracts/factories/WrappedExternalBribeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\\n\\ncontract WrappedExternalBribeFactory {\\n address public immutable voter;\\n mapping(address => address) public oldBribeToNew;\\n address public last_bribe;\\n\\n constructor(address _voter) {\\n voter = _voter;\\n }\\n\\n function createBribe(address existing_bribe) external returns (address) {\\n require(\\n oldBribeToNew[existing_bribe] == address(0),\\n \\\"Wrapped bribe already created\\\"\\n );\\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\\n oldBribeToNew[existing_bribe] = last_bribe;\\n return last_bribe;\\n }\\n}\\n\",\"keccak256\":\"0x4e88b50000e3cf490ae8602b55555bbc02f95fda5926b1a532debfe54ac06bb2\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x60a060405234801561001057600080fd5b50604051611d5d380380611d5d83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051611ccc61009160003960008181609b01526101530152611ccc6000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632fcd8f271461005157806346c96aac146100965780636bd1a72c146100bd578063b1d0fc82146100d0575b600080fd5b61007a61005f366004610205565b6000602081905290815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b61007a7f000000000000000000000000000000000000000000000000000000000000000081565b61007a6100cb366004610205565b6100e3565b60015461007a906001600160a01b031681565b6001600160a01b03818116600090815260208190526040812054909116156101515760405162461bcd60e51b815260206004820152601d60248201527f5772617070656420627269626520616c72656164792063726561746564000000604482015260640160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000008260405161017f906101f8565b6001600160a01b03928316815291166020820152604001604051809103906000f0801580156101b2573d6000803e3d6000fd5b50600180546001600160a01b039283166001600160a01b031991821681178355948316600090815260208190526040902080549091169094179093559154909116919050565b611a618061023683390190565b60006020828403121561021757600080fd5b81356001600160a01b038116811461022e57600080fd5b939250505056fe60c060405260016006553480156200001657600080fd5b5060405162001a6138038062001a61833981016040819052620000399162000275565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002ad565b6001600160a01b0390811660a052600080546001600160a01b0319169183169190911781555b60008054906101000a90046001600160a01b03166001600160a01b031663e68863966040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000122573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001489190620002d2565b8110156200024f5760008054604051637980d7a160e11b8152600481018490526001600160a01b039091169063f301af4290602401602060405180830381865afa1580156200019b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001c19190620002ad565b90506001600160a01b0381161562000239576001600160a01b0381166000818152600560205260408120805460ff191660019081179091556004805491820181559091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b03191690911790555b50806200024681620002ec565b915050620000d0565b50505062000314565b80516001600160a01b03811681146200027057600080fd5b919050565b600080604083850312156200028957600080fd5b620002948362000258565b9150620002a46020840162000258565b90509250929050565b600060208284031215620002c057600080fd5b620002cb8262000258565b9392505050565b600060208284031215620002e557600080fd5b5051919050565b6000600182016200030d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a0516117046200035d600039600081816101e6015281816108f301528181610b1d0152610fd701526000818161014e01528181610ada0152610d1801526117046000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80639418f939116100a2578063da09d19d11610071578063da09d19d14610281578063e6886396146102a1578063f25e55a5146102a9578063f301af42146102d4578063f5f8d365146102e757600080fd5b80639418f9391461023357806399bcc05214610248578063a7852afa1461025b578063b66503cf1461026e57600080fd5b8063638634ee116100de578063638634ee146101bb5780636c4f5398146101ce5780638dd598fb146101e157806392777b291461020857600080fd5b80630175e23b146101105780633e491d471461013657806346c96aac146101495780634d5ce03814610188575b600080fd5b61012361011e366004611393565b6102fa565b6040519081526020015b60405180910390f35b6101236101443660046113d4565b61033c565b6101707f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161012d565b6101ab610196366004611400565b60056020526000908152604090205460ff1681565b604051901515815260200161012d565b6101236101c9366004611400565b6108cd565b600054610170906001600160a01b031681565b6101707f000000000000000000000000000000000000000000000000000000000000000081565b6101236102163660046113d4565b600160209081526000928352604080842090915290825290205481565b61024661024136600461141d565b6108f1565b005b610123610256366004611400565b610a82565b610246610269366004611475565b610abb565b61024661027c3660046113d4565b610cbb565b61012361028f366004611400565b60026020526000908152604090205481565b600454610123565b6101236102b73660046113d4565b600360209081526000928352604080842090915290825290205481565b6101706102e2366004611393565b610f7d565b6102466102f5366004611475565b610fa7565b6000806103068361117b565b9050600061031762093a808361155c565b90508084106103325761032d8262093a8061155c565b610334565b815b949350505050565b6001600160a01b0382811660009081526003602090815260408083208584529091528082205482549151635058979360e01b81526004810186905292939092911690635058979390602401602060405180830381865afa1580156103a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103c89190611574565b6000036103d95760009150506108c7565b600080546040516328a3532760e21b815260048101869052602481018490526001600160a01b039091169063a28d4c9c90604401602060405180830381865afa15801561042a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044e9190611574565b60008054604051635058979360e01b81526004810188905292935090916001916001600160a01b031690635058979390602401602060405180830381865afa15801561049e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c29190611574565b6104cc919061158d565b905060006104ed604051806040016040528060008152602001600081525090565b6104f68561117b565b8152600080600185156106f357865b61051060018861158d565b81116106f157600054604051631277308160e21b8152600481018d9052602481018390526001600160a01b03909116906349dcc204906044016040805180830381865afa158015610565573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058991906115a4565b909450925060006105998561117b565b86519091508111156105b75760208601516105b4908861155c565b96505b8086526000546001600160a01b031663f7412baf816376f4be366105de62093a808661155c565b6040518263ffffffff1660e01b81526004016105fc91815260200190565b602060405180830381865afa158015610619573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063d9190611574565b6040518263ffffffff1660e01b815260040161065b91815260200190565b6040805180830381865afa158015610677573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061069b91906115a4565b6001600160a01b038f1660009081526001602090815260408083208684529091529020549094508491506106cf90866115c8565b6106d991906115fd565b602087015250806106e981611611565b915050610505565b505b600054604051631277308160e21b8152600481018c9052602481018890526001600160a01b03909116906349dcc204906044016040805180830381865afa158015610742573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076691906115a4565b909350915060006107768461117b565b9050600061078762093a808361155c565b905080421180156107975750808a105b156108ba57600054604051633b7a5f1b60e11b8152600481018390526001600160a01b039091169063f7412baf9082906376f4be3690602401602060405180830381865afa1580156107ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108119190611574565b6040518263ffffffff1660e01b815260040161082f91815260200190565b6040805180830381865afa15801561084b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086f91906115a4565b6001600160a01b038f1660009081526001602090815260408083208784529091529020549094508491506108a390866115c8565b6108ad91906115fd565b6108b7908861155c565b96505b5094985050505050505050505b92915050565b6001600160a01b0381166000908152600260205260408120546108c7904290611194565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610951573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610975919061162a565b6001600160a01b0316336001600160a01b0316146109c65760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600484815481106109e3576109e3611647565b6000918252602090912001546001600160a01b031614610a0257600080fd5b6001600160a01b03808316600090815260056020526040808220805460ff1990811690915592841682529020805490911660011790556004805482919085908110610a4f57610a4f611647565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a8e426102fa565b6001600160a01b039093166000908152600160209081526040808320958352949052929092205492915050565b600654600114610aca57600080fd5b6002600655336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b0457600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610b6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b90919061162a565b905060005b8251811015610cb0576000610bc3848381518110610bb557610bb5611647565b60200260200101518661033c565b90504260036000868581518110610bdc57610bdc611647565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610c3757610c37848381518110610c2857610c28611647565b602002602001015184836111ac565b838281518110610c4957610c49611647565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610c9591815260200190565b60405180910390a35080610ca881611611565b915050610b95565b505060016006555050565b600654600114610cca57600080fd5b600260065580610cd957600080fd5b6001600160a01b03821660009081526005602052604090205460ff16610e2157604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610d5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d83919061165d565b610dcf5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c697374656460448201526064016109bd565b600454601011610e215760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e7300000000000000000060448201526064016109bd565b6000610e2c426102fa565b6001600160a01b0384166000908152600160209081526040808320848452909152902054909150610e5f8433308661129b565b610e69838261155c565b6001600160a01b0385166000908152600160209081526040808320868452909152902055610e9a62093a808361155c565b6001600160a01b03851660009081526002602090815260408083209390935560059052205460ff16610f2c576001600160a01b0384166000818152600560205260408120805460ff191660019081179091556004805491820181559091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a3505060016006555050565b60048181548110610f8d57600080fd5b6000918252602090912001546001600160a01b0316905081565b600654600114610fb657600080fd5b600260065560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611026573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104a919061165d565b61105357600080fd5b60005b815181101561117157600061108483838151811061107657611076611647565b60200260200101518561033c565b9050426003600085858151811061109d5761109d611647565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812088825290925290205580156110f8576110f88383815181106110e9576110e9611647565b602002602001015133836111ac565b82828151811061110a5761110a611647565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161115691815260200190565b60405180910390a3508061116981611611565b915050611056565b5050600160065550565b600061118a62093a808361167f565b6108c7908361158d565b60008183106111a357816111a5565b825b9392505050565b6000836001600160a01b03163b116111c357600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161121f9190611693565b6000604051808303816000865af19150503d806000811461125c576040519150601f19603f3d011682016040523d82523d6000602084013e611261565b606091505b509150915081801561128b57508051158061128b57508080602001905181019061128b919061165d565b61129457600080fd5b5050505050565b6000846001600160a01b03163b116112b257600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916113169190611693565b6000604051808303816000865af19150503d8060008114611353576040519150601f19603f3d011682016040523d82523d6000602084013e611358565b606091505b5091509150818015611382575080511580611382575080806020019051810190611382919061165d565b61138b57600080fd5b505050505050565b6000602082840312156113a557600080fd5b5035919050565b6001600160a01b03811681146113c157600080fd5b50565b80356113cf816113ac565b919050565b600080604083850312156113e757600080fd5b82356113f2816113ac565b946020939093013593505050565b60006020828403121561141257600080fd5b81356111a5816113ac565b60008060006060848603121561143257600080fd5b833592506020840135611444816113ac565b91506040840135611454816113ac565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561148857600080fd5b8235915060208084013567ffffffffffffffff808211156114a857600080fd5b818601915086601f8301126114bc57600080fd5b8135818111156114ce576114ce61145f565b8060051b604051601f19603f830116810181811085821117156114f3576114f361145f565b60405291825284820192508381018501918983111561151157600080fd5b938501935b8285101561153657611527856113c4565b84529385019392850192611516565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561156f5761156f611546565b500190565b60006020828403121561158657600080fd5b5051919050565b60008282101561159f5761159f611546565b500390565b600080604083850312156115b757600080fd5b505080516020909101519092909150565b60008160001904831182151516156115e2576115e2611546565b500290565b634e487b7160e01b600052601260045260246000fd5b60008261160c5761160c6115e7565b500490565b60006001820161162357611623611546565b5060010190565b60006020828403121561163c57600080fd5b81516111a5816113ac565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561166f57600080fd5b815180151581146111a557600080fd5b60008261168e5761168e6115e7565b500690565b6000825160005b818110156116b4576020818601810151858301520161169a565b818111156116c3576000828501525b50919091019291505056fea26469706673582212200cd58109058435150b86689c579157aac22bb1bf34bcba8fe86630ae677bab0f64736f6c634300080d0033a26469706673582212204aa3dda9eda9f8a5fdd9bf2ced3a5d88c86e34ca5a36bacbb53589f8e2fccc7164736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632fcd8f271461005157806346c96aac146100965780636bd1a72c146100bd578063b1d0fc82146100d0575b600080fd5b61007a61005f366004610205565b6000602081905290815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b61007a7f000000000000000000000000000000000000000000000000000000000000000081565b61007a6100cb366004610205565b6100e3565b60015461007a906001600160a01b031681565b6001600160a01b03818116600090815260208190526040812054909116156101515760405162461bcd60e51b815260206004820152601d60248201527f5772617070656420627269626520616c72656164792063726561746564000000604482015260640160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000008260405161017f906101f8565b6001600160a01b03928316815291166020820152604001604051809103906000f0801580156101b2573d6000803e3d6000fd5b50600180546001600160a01b039283166001600160a01b031991821681178355948316600090815260208190526040902080549091169094179093559154909116919050565b611a618061023683390190565b60006020828403121561021757600080fd5b81356001600160a01b038116811461022e57600080fd5b939250505056fe60c060405260016006553480156200001657600080fd5b5060405162001a6138038062001a61833981016040819052620000399162000275565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002ad565b6001600160a01b0390811660a052600080546001600160a01b0319169183169190911781555b60008054906101000a90046001600160a01b03166001600160a01b031663e68863966040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000122573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001489190620002d2565b8110156200024f5760008054604051637980d7a160e11b8152600481018490526001600160a01b039091169063f301af4290602401602060405180830381865afa1580156200019b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001c19190620002ad565b90506001600160a01b0381161562000239576001600160a01b0381166000818152600560205260408120805460ff191660019081179091556004805491820181559091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b03191690911790555b50806200024681620002ec565b915050620000d0565b50505062000314565b80516001600160a01b03811681146200027057600080fd5b919050565b600080604083850312156200028957600080fd5b620002948362000258565b9150620002a46020840162000258565b90509250929050565b600060208284031215620002c057600080fd5b620002cb8262000258565b9392505050565b600060208284031215620002e557600080fd5b5051919050565b6000600182016200030d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a0516117046200035d600039600081816101e6015281816108f301528181610b1d0152610fd701526000818161014e01528181610ada0152610d1801526117046000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80639418f939116100a2578063da09d19d11610071578063da09d19d14610281578063e6886396146102a1578063f25e55a5146102a9578063f301af42146102d4578063f5f8d365146102e757600080fd5b80639418f9391461023357806399bcc05214610248578063a7852afa1461025b578063b66503cf1461026e57600080fd5b8063638634ee116100de578063638634ee146101bb5780636c4f5398146101ce5780638dd598fb146101e157806392777b291461020857600080fd5b80630175e23b146101105780633e491d471461013657806346c96aac146101495780634d5ce03814610188575b600080fd5b61012361011e366004611393565b6102fa565b6040519081526020015b60405180910390f35b6101236101443660046113d4565b61033c565b6101707f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161012d565b6101ab610196366004611400565b60056020526000908152604090205460ff1681565b604051901515815260200161012d565b6101236101c9366004611400565b6108cd565b600054610170906001600160a01b031681565b6101707f000000000000000000000000000000000000000000000000000000000000000081565b6101236102163660046113d4565b600160209081526000928352604080842090915290825290205481565b61024661024136600461141d565b6108f1565b005b610123610256366004611400565b610a82565b610246610269366004611475565b610abb565b61024661027c3660046113d4565b610cbb565b61012361028f366004611400565b60026020526000908152604090205481565b600454610123565b6101236102b73660046113d4565b600360209081526000928352604080842090915290825290205481565b6101706102e2366004611393565b610f7d565b6102466102f5366004611475565b610fa7565b6000806103068361117b565b9050600061031762093a808361155c565b90508084106103325761032d8262093a8061155c565b610334565b815b949350505050565b6001600160a01b0382811660009081526003602090815260408083208584529091528082205482549151635058979360e01b81526004810186905292939092911690635058979390602401602060405180830381865afa1580156103a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103c89190611574565b6000036103d95760009150506108c7565b600080546040516328a3532760e21b815260048101869052602481018490526001600160a01b039091169063a28d4c9c90604401602060405180830381865afa15801561042a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044e9190611574565b60008054604051635058979360e01b81526004810188905292935090916001916001600160a01b031690635058979390602401602060405180830381865afa15801561049e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c29190611574565b6104cc919061158d565b905060006104ed604051806040016040528060008152602001600081525090565b6104f68561117b565b8152600080600185156106f357865b61051060018861158d565b81116106f157600054604051631277308160e21b8152600481018d9052602481018390526001600160a01b03909116906349dcc204906044016040805180830381865afa158015610565573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058991906115a4565b909450925060006105998561117b565b86519091508111156105b75760208601516105b4908861155c565b96505b8086526000546001600160a01b031663f7412baf816376f4be366105de62093a808661155c565b6040518263ffffffff1660e01b81526004016105fc91815260200190565b602060405180830381865afa158015610619573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063d9190611574565b6040518263ffffffff1660e01b815260040161065b91815260200190565b6040805180830381865afa158015610677573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061069b91906115a4565b6001600160a01b038f1660009081526001602090815260408083208684529091529020549094508491506106cf90866115c8565b6106d991906115fd565b602087015250806106e981611611565b915050610505565b505b600054604051631277308160e21b8152600481018c9052602481018890526001600160a01b03909116906349dcc204906044016040805180830381865afa158015610742573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076691906115a4565b909350915060006107768461117b565b9050600061078762093a808361155c565b905080421180156107975750808a105b156108ba57600054604051633b7a5f1b60e11b8152600481018390526001600160a01b039091169063f7412baf9082906376f4be3690602401602060405180830381865afa1580156107ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108119190611574565b6040518263ffffffff1660e01b815260040161082f91815260200190565b6040805180830381865afa15801561084b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086f91906115a4565b6001600160a01b038f1660009081526001602090815260408083208784529091529020549094508491506108a390866115c8565b6108ad91906115fd565b6108b7908861155c565b96505b5094985050505050505050505b92915050565b6001600160a01b0381166000908152600260205260408120546108c7904290611194565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610951573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610975919061162a565b6001600160a01b0316336001600160a01b0316146109c65760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600484815481106109e3576109e3611647565b6000918252602090912001546001600160a01b031614610a0257600080fd5b6001600160a01b03808316600090815260056020526040808220805460ff1990811690915592841682529020805490911660011790556004805482919085908110610a4f57610a4f611647565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a8e426102fa565b6001600160a01b039093166000908152600160209081526040808320958352949052929092205492915050565b600654600114610aca57600080fd5b6002600655336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b0457600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610b6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b90919061162a565b905060005b8251811015610cb0576000610bc3848381518110610bb557610bb5611647565b60200260200101518661033c565b90504260036000868581518110610bdc57610bdc611647565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610c3757610c37848381518110610c2857610c28611647565b602002602001015184836111ac565b838281518110610c4957610c49611647565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610c9591815260200190565b60405180910390a35080610ca881611611565b915050610b95565b505060016006555050565b600654600114610cca57600080fd5b600260065580610cd957600080fd5b6001600160a01b03821660009081526005602052604090205460ff16610e2157604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610d5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d83919061165d565b610dcf5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c697374656460448201526064016109bd565b600454601011610e215760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e7300000000000000000060448201526064016109bd565b6000610e2c426102fa565b6001600160a01b0384166000908152600160209081526040808320848452909152902054909150610e5f8433308661129b565b610e69838261155c565b6001600160a01b0385166000908152600160209081526040808320868452909152902055610e9a62093a808361155c565b6001600160a01b03851660009081526002602090815260408083209390935560059052205460ff16610f2c576001600160a01b0384166000818152600560205260408120805460ff191660019081179091556004805491820181559091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a3505060016006555050565b60048181548110610f8d57600080fd5b6000918252602090912001546001600160a01b0316905081565b600654600114610fb657600080fd5b600260065560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611026573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104a919061165d565b61105357600080fd5b60005b815181101561117157600061108483838151811061107657611076611647565b60200260200101518561033c565b9050426003600085858151811061109d5761109d611647565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812088825290925290205580156110f8576110f88383815181106110e9576110e9611647565b602002602001015133836111ac565b82828151811061110a5761110a611647565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161115691815260200190565b60405180910390a3508061116981611611565b915050611056565b5050600160065550565b600061118a62093a808361167f565b6108c7908361158d565b60008183106111a357816111a5565b825b9392505050565b6000836001600160a01b03163b116111c357600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161121f9190611693565b6000604051808303816000865af19150503d806000811461125c576040519150601f19603f3d011682016040523d82523d6000602084013e611261565b606091505b509150915081801561128b57508051158061128b57508080602001905181019061128b919061165d565b61129457600080fd5b5050505050565b6000846001600160a01b03163b116112b257600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916113169190611693565b6000604051808303816000865af19150503d8060008114611353576040519150601f19603f3d011682016040523d82523d6000602084013e611358565b606091505b5091509150818015611382575080511580611382575080806020019051810190611382919061165d565b61138b57600080fd5b505050505050565b6000602082840312156113a557600080fd5b5035919050565b6001600160a01b03811681146113c157600080fd5b50565b80356113cf816113ac565b919050565b600080604083850312156113e757600080fd5b82356113f2816113ac565b946020939093013593505050565b60006020828403121561141257600080fd5b81356111a5816113ac565b60008060006060848603121561143257600080fd5b833592506020840135611444816113ac565b91506040840135611454816113ac565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561148857600080fd5b8235915060208084013567ffffffffffffffff808211156114a857600080fd5b818601915086601f8301126114bc57600080fd5b8135818111156114ce576114ce61145f565b8060051b604051601f19603f830116810181811085821117156114f3576114f361145f565b60405291825284820192508381018501918983111561151157600080fd5b938501935b8285101561153657611527856113c4565b84529385019392850192611516565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561156f5761156f611546565b500190565b60006020828403121561158657600080fd5b5051919050565b60008282101561159f5761159f611546565b500390565b600080604083850312156115b757600080fd5b505080516020909101519092909150565b60008160001904831182151516156115e2576115e2611546565b500290565b634e487b7160e01b600052601260045260246000fd5b60008261160c5761160c6115e7565b500490565b60006001820161162357611623611546565b5060010190565b60006020828403121561163c57600080fd5b81516111a5816113ac565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561166f57600080fd5b815180151581146111a557600080fd5b60008261168e5761168e6115e7565b500690565b6000825160005b818110156116b4576020818601810151858301520161169a565b818111156116c3576000828501525b50919091019291505056fea26469706673582212200cd58109058435150b86689c579157aac22bb1bf34bcba8fe86630ae677bab0f64736f6c634300080d0033a26469706673582212204aa3dda9eda9f8a5fdd9bf2ced3a5d88c86e34ca5a36bacbb53589f8e2fccc7164736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 21824, + "contract": "contracts/factories/WrappedExternalBribeFactory.sol:WrappedExternalBribeFactory", + "label": "oldBribeToNew", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 21826, + "contract": "contracts/factories/WrappedExternalBribeFactory.sol:WrappedExternalBribeFactory", + "label": "last_bribe", + "offset": 0, + "slot": "1", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_address)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => address)", + "numberOfBytes": "32", + "value": "t_address" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumOne/solcInputs/4e21824d68c90a2d8601cfb8f8d80414.json b/deployments/arbitrumOne/solcInputs/4e21824d68c90a2d8601cfb8f8d80414.json new file mode 100644 index 00000000..58802f43 --- /dev/null +++ b/deployments/arbitrumOne/solcInputs/4e21824d68c90a2d8601cfb8f8d80414.json @@ -0,0 +1,247 @@ +{ + "language": "Solidity", + "sources": { + "contracts/ExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/ExternalBribeV.sol": { + "content": "" + }, + "contracts/factories/BribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport \"contracts/InternalBribe.sol\";\nimport \"contracts/ExternalBribe.sol\";\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards)\n external\n returns (address)\n {\n last_internal_bribe = address(\n new InternalBribe(msg.sender, allowedRewards)\n );\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards)\n external\n returns (address)\n {\n last_external_bribe = address(\n new ExternalBribe(msg.sender, allowedRewards)\n );\n return last_external_bribe;\n }\n}\n" + }, + "contracts/factories/GaugeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" + }, + "contracts/factories/PairFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/Pair.sol';\n\ncontract PairFactory is IPairFactory {\n\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 5; // 0.05%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n stableFee = 2; // 0.02%\n volatileFee = 2;\n }\n\n function allPairsLength() external view returns (uint) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, 'not fee manager');\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, 'not fee manager');\n require(_fee <= MAX_FEE, 'fee too high');\n require(_fee != 0, 'fee must be nonzero');\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns(uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable() external view returns (address, address, bool) {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt:salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" + }, + "contracts/factories/WrappedExternalBribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" + }, + "contracts/Flow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IFlow.sol\";\n\ncontract Flow is IFlow {\n\n string public constant name = \"Velocimeter\";\n string public constant symbol = \"FLOW\";\n uint8 public constant decimals = 18;\n uint public totalSupply = 0;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // Initial mint: total 82M\n // 4M for \"Genesis\" pools\n // 30M for liquid team allocation (40M excl init veNFT)\n // 48M for future partners\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 82 * 1e6 * 1e18);\n }\n\n function approve(address _spender, uint _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(address _from, address _to, uint _value) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(address _from, address _to, uint _value) external returns (bool) {\n uint allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" + }, + "contracts/FlowGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract FlowGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velocimeter Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" + }, + "contracts/Gauge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/governance/L2Governor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" + }, + "contracts/governance/L2GovernorCountingSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" + }, + "contracts/governance/L2GovernorVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" + }, + "contracts/governance/L2GovernorVotesQuorumFraction.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" + }, + "contracts/interfaces/IBribe.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IBribeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IERC20.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" + }, + "contracts/interfaces/IFlow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IFlow {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" + }, + "contracts/interfaces/IGauge.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" + }, + "contracts/interfaces/IGaugeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IMinter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" + }, + "contracts/interfaces/IPair.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IPairCallee.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" + }, + "contracts/interfaces/IPairFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" + }, + "contracts/interfaces/IRewardsDistributor.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" + }, + "contracts/interfaces/IRouter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" + }, + "contracts/interfaces/IVeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" + }, + "contracts/interfaces/IVoter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" + }, + "contracts/interfaces/IVotingEscrow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" + }, + "contracts/interfaces/IWETH.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" + }, + "contracts/InternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n uint256 public constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\n return (\n (((MathDunks.min(endTime, periodFinish[token]) -\n MathDunks.min(\n MathDunks.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n MathDunks.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = MathDunks.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n MathDunks.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/libraries/Base64.sol": { + "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" + }, + "contracts/libraries/Math.sol": { + "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary MathDunks {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" + }, + "contracts/Minter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IFlow.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IFlow public immutable _flow;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M FLOW (FLOW has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 3%\n _flow = IFlow(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants, // partnerAddrs\n uint256[] memory amounts, // partnerAmounts\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _flow.mint(address(this), max);\n _flow.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _flow.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return MathDunks.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _flowTotal = _flow.totalSupply();\n return\n (((((_minted * _veTotal) / _flowTotal) * _veTotal) / _flowTotal) *\n _veTotal) /\n _flowTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _flow.balanceOf(address(this));\n if (_balanceOf < _required) {\n _flow.mint(address(this), _required - _balanceOf);\n }\n\n require(_flow.transfer(team, _teamEmissions));\n require(_flow.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _flow.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" + }, + "contracts/Pair.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = MathDunks.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/PairFees.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" + }, + "contracts/redeem/MerkleClaim.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IFlow} from \"contracts/interfaces/IFlow.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims FLOW for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice FLOW token to claim\n IFlow public immutable FLOW;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _flow address\n /// @param _merkleRoot of claimees\n constructor(address _flow, bytes32 _merkleRoot) {\n FLOW = IFlow(_flow);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(FLOW.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" + }, + "contracts/redeem/RedemptionReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IFlow.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + FLOW\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IFlow public immutable FLOW;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableFLOW;\n uint256 public leftoverFLOW;\n\n constructor(\n address _usdc,\n address _flow,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n FLOW = IFlow(_flow);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableFLOW);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableFLOW\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableFLOW = _redeemableFLOW;\n leftoverFLOW = _redeemableFLOW;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableFLOW);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfFLOW)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata FLOW\n shareOfFLOW = (amountWEVE * redeemableFLOW) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfFLOW) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverFLOW -= shareOfFLOW; // this will revert if underflows\n require(\n FLOW.claim(redemptionAddress, shareOfFLOW),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" + }, + "contracts/redeem/RedemptionSender.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" + }, + "contracts/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n MathDunks.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = MathDunks.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = MathDunks.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" + }, + "contracts/Router.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = MathDunks.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/routerV.sol": { + "content": "" + }, + "contracts/VeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velocimeter locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" + }, + "contracts/VelocimeterLibrary.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelocimeterLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" + }, + "contracts/Voter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/libraries/Math.sol';\nimport 'contracts/interfaces/IBribe.sol';\nimport 'contracts/interfaces/IBribeFactory.sol';\nimport 'contracts/interfaces/IGauge.sol';\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/interfaces/IERC20.sol';\nimport 'contracts/interfaces/IMinter.sol';\nimport 'contracts/interfaces/IPair.sol';\nimport 'contracts/interfaces/IPairFactory.sol';\nimport 'contracts/interfaces/IVoter.sol';\nimport 'contracts/interfaces/IVotingEscrow.sol';\n\ncontract Voter is IVoter {\n\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint => address[]) public poolVote; // nft => pools\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint tokenId, uint256 weight);\n event Abstained(uint tokenId, uint256 weight);\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint _tokenId) {\n // ensure new epoch since last vote \n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \"TOKEN_ALREADY_VOTED_THIS_EPOCH\");\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint i = 0; i < _poolVoteCnt; i ++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n function poke(uint _tokenId) external {\n address[] memory _poolVote = poolVote[_tokenId];\n uint _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint i = 0; i < _poolCnt; i ++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\n _reset(_tokenId);\n uint _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) { // gov can create for any pool, even non-Velocimeter pairs\n require(isPair, \"!_pool\");\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \"!whitelisted\");\n }\n\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\n\n IERC20(base).approve(_gauge, type(uint).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(uint tokenId, address account, uint amount) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint) {\n return pools.length;\n }\n\n uint internal index;\n mapping(address => uint) internal supplyIndex;\n mapping(address => uint) public claimable;\n\n function notifyRewardAmount(uint amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint start, uint end) public {\n for (uint i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint _supplyIndex = supplyIndex[_gauge];\n uint _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\n for (uint i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()){\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint _claimable = claimable[_gauge];\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint start, uint finish) public {\n for (uint x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VotingEscrow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `FLOW` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" + }, + "contracts/WrappedExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/libraries/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return MathDunks.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/WrappedExternalBribeV.sol": { + "content": "" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + }, + "libraries": { + "": { + "__CACHE_BREAKER__": "0x0000000000000031363735303731393533363138" + } + } + } +} \ No newline at end of file diff --git a/package.json b/package.json index cde00b8d..15e1ec54 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,9 @@ "export": "npx hardhat --network arbitrumGoerli export --export ./exported.json", "exportMainnet": "npx hardhat --network arbitrum export --export ./mainnet-exported.json", "deploy": "npx hardhat deploy --network arbitrumGoerli", + "deployArb": "npx hardhat deploy --network arbitrumOne --tags WrappedExternalBribeFactory", "deployHardhat": "npx hardhat deploy --network hardhat", - "verifyMainnet": "npx hardhat --network arbitrum etherscan-verify --solc-input --sleep", + "verifyMainnet": "npx hardhat --network arbitrumOne etherscan-verify --solc-input --sleep", "verifyGoerli": "npx hardhat --network arbitrumGoerli etherscan-verify --solc-input --sleep" }, "devDependencies": { diff --git a/tasks/deploy/constants/arbConfig.ts b/tasks/deploy/constants/arbConfig.ts index 42812379..615fbb44 100644 --- a/tasks/deploy/constants/arbConfig.ts +++ b/tasks/deploy/constants/arbConfig.ts @@ -1,5 +1,7 @@ import { ethers } from 'ethers' +// this is the actual config that we are using for arbOne + const TOKEN_DECIMALS = ethers.BigNumber.from('10').pow( ethers.BigNumber.from('18') ) @@ -77,26 +79,32 @@ const arbConfig = { // // MILLION, // 10 1/4 % // // MILLION // 11 // ], - partnerAddrs: [TEAM_MULTISIG, dunks, t0rb1k, dunks, t0rb1k, dunks, t0rb1k], - partnerAmts: [SIXTY_MILLION, FOUR_MILLION, FOUR_MILLION, ONE_MILLION], // MILLION Mint 0.001 WTF pls halp + partnerAddrs: [ + TEAM_MULTISIG, + dunks, + t0rb1k, + dunks, + t0rb1k, + dunks, + t0rb1k, + dunks + ], + partnerAmts: [ + SIXTY_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + FOUR_MILLION, + ONE_MILLION + ], // MILLION Mint 0.001 WTF pls halp partnerMax: PARTNER_MAX, // Addresses teamEOA: TEAM_EOA, teamMultisig: TEAM_MULTISIG, - coolie: TEAM_EOA, - dunks: '0x069e85D4F1010DD961897dC8C095FBB5FF297434', - ceazor: '0x3c5Aac016EF2F178e8699D6208796A2D67557fe2', - faeflow: '', //update - wtck: '0x78e801136F77805239A7F533521A7a5570F572C8', - torbik: '0x0b776552c1Aef1Dc33005DD25AcDA22493b6615d', - - arbitrumTeam: TEAM_MULTISIG, - velodromeMultisig: TEAM_MULTISIG, - anton: TEAM_MULTISIG, - andre: TEAM_MULTISIG, - - emergencyCouncil: '0xcC2D01030eC2cd187346F70bFc483F24488C32E8', + emergencyCouncil: TEAM_MULTISIG, merkleRoot: '0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f', From 0c4cf28fb4949331927dea17968088d10c0bf71f Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Tue, 31 Jan 2023 10:37:05 +1100 Subject: [PATCH 27/43] Removed the airdrop and weve redemption plus governer. Delay the partner NFT mint and epoch start --- deploy/15_init.ts | 22 +++++++++---------- deploy/17_dist.ts | 12 +++++----- .../_____13_redemptionReceiver.ts | 0 .../_____14_merkleClaim.ts | 0 .../_______12_veloGovernor.ts | 0 5 files changed, 17 insertions(+), 17 deletions(-) rename deploy/13_redemptionReceiver.ts => removed/_____13_redemptionReceiver.ts (100%) rename deploy/14_merkleClaim.ts => removed/_____14_merkleClaim.ts (100%) rename deploy/12_veloGovernor.ts => removed/_______12_veloGovernor.ts (100%) diff --git a/deploy/15_init.ts b/deploy/15_init.ts index 571fe2bc..bb14f259 100644 --- a/deploy/15_init.ts +++ b/deploy/15_init.ts @@ -13,21 +13,21 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const escrow = await ethers.getContract('VotingEscrow') const voter = await ethers.getContract('Voter') const distributor = await ethers.getContract('RewardsDistributor') - const governor = await ethers.getContract('FlowGovernor') + // const governor = await ethers.getContract('FlowGovernor') const minter = await ethers.getContract('Minter') - const receiver = await ethers.getContract('RedemptionReceiver') + // const receiver = await ethers.getContract('RedemptionReceiver') - const claim = await deployments.get('MerkleClaim') + // const claim = await deployments.get('MerkleClaim') // Initialize await flow.initialMint(ARB_TEST_CONFIG.teamEOA) console.log('Initial minted') - await flow.setRedemptionReceiver(receiver.address) - console.log('RedemptionReceiver set') + // await flow.setRedemptionReceiver(receiver.address) + // console.log('RedemptionReceiver set') - await flow.setMerkleClaim(claim.address) - console.log('MerkleClaim set') + // await flow.setMerkleClaim(claim.address) + // console.log('MerkleClaim set') await flow.setMinter(minter.address) console.log('Minter set') @@ -56,11 +56,11 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { await distributor.setDepositor(minter.address) console.log('Depositor set') - await receiver.setTeam(ARB_TEST_CONFIG.teamMultisig) - console.log('Team set for receiver') + // await receiver.setTeam(ARB_TEST_CONFIG.teamMultisig) + // console.log('Team set for receiver') - await governor.setTeam(ARB_TEST_CONFIG.teamMultisig) - console.log('Team set for governor') + // await governor.setTeam(ARB_TEST_CONFIG.teamMultisig) + // console.log('Team set for governor') await minter.setTeam(ARB_TEST_CONFIG.teamMultisig) console.log('Team set for minter') diff --git a/deploy/17_dist.ts b/deploy/17_dist.ts index 7197686e..88774cfa 100644 --- a/deploy/17_dist.ts +++ b/deploy/17_dist.ts @@ -19,12 +19,12 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const flow = await deployments.get('Flow') // Initial veVELO distro // this is not inside dist lets see if its being used for deploys?? - await minter.initialize( - ARB_TEST_CONFIG.partnerAddrs, - ARB_TEST_CONFIG.partnerAmts, - ARB_TEST_CONFIG.partnerMax - ) - console.log('veVELO distributed') + // await minter.initialize( + // ARB_TEST_CONFIG.partnerAddrs, + // ARB_TEST_CONFIG.partnerAmts, + // ARB_TEST_CONFIG.partnerMax + // ) + console.log('veVELO not distributed yet') // we will run this when we want to start the epoch and have the NFTs // console.log('Arbitrum Goerli Velocimeter Instruments deployed') diff --git a/deploy/13_redemptionReceiver.ts b/removed/_____13_redemptionReceiver.ts similarity index 100% rename from deploy/13_redemptionReceiver.ts rename to removed/_____13_redemptionReceiver.ts diff --git a/deploy/14_merkleClaim.ts b/removed/_____14_merkleClaim.ts similarity index 100% rename from deploy/14_merkleClaim.ts rename to removed/_____14_merkleClaim.ts diff --git a/deploy/12_veloGovernor.ts b/removed/_______12_veloGovernor.ts similarity index 100% rename from deploy/12_veloGovernor.ts rename to removed/_______12_veloGovernor.ts From ef83476380c76391692c56d3b3fbade3477d1698 Mon Sep 17 00:00:00 2001 From: 0xmotto <0xmotto@protonmail.com> Date: Sat, 4 Feb 2023 17:23:44 +0800 Subject: [PATCH 28/43] feat: add create lock for script --- hardhat.config.ts | 1 + tasks/createLockFor.ts | 56 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 tasks/createLockFor.ts diff --git a/hardhat.config.ts b/hardhat.config.ts index b8699f90..d117f4c1 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -13,6 +13,7 @@ import { resolve } from 'path' import './tasks/accounts' import './tasks/deploy' +import './tasks/createLockFor' dotenvConfig({ path: resolve(__dirname, './.env') }) import './checkEnv' diff --git a/tasks/createLockFor.ts b/tasks/createLockFor.ts new file mode 100644 index 00000000..825631bb --- /dev/null +++ b/tasks/createLockFor.ts @@ -0,0 +1,56 @@ +import { task } from 'hardhat/config' + +// SAMPLE command +// npx hardhat create-lock-for --network arbitrumOne --token 0xC33f7f83CbB021846Cb9c58f2d8E3df428dbC8C1 --contract 0x10Df81252069C1095F541FAca61646cb9Ae76703 --recipient 0x069e85D4F1010DD961897dC8C095FBB5FF297434 --amount 1 --duration 4 +task('create-lock-for', 'Creates lock for a recipient address') + .addParam("token", "The flow token address") + .addParam("contract", "The Voting Escrow's contract address") + .addParam("recipient", "The recipient's address") + .addParam("amount", "The amount to lock (in MILLION)") + .addParam("duration", "The lock duration") + .setAction(async ( + taskArguments, + { ethers } + ) => { + // Get signers + const [signer] = await ethers.getSigners() + + // Get task arguments + const { token, contract: veContract, recipient, amount: amountInMillion, duration: durationInYear } = taskArguments; + + // Validate task arguments + if (!ethers.utils.isAddress(token)) { + throw new Error("Recipient address is not valid") + } + + if (!ethers.utils.isAddress(veContract)) { + throw new Error("Voting Escrow contract address is not valid") + } + + if (!ethers.utils.isAddress(recipient)) { + throw new Error("Recipient address is not valid") + } + + // Formatting amount + const TOKEN_DECIMALS = ethers.BigNumber.from('10').pow( + ethers.BigNumber.from('18') + ); + const MILLION = ethers.BigNumber.from('10').pow( + ethers.BigNumber.from('6') + ); + const amount = ethers.BigNumber.from(amountInMillion) + .mul(MILLION) + .mul(TOKEN_DECIMALS); + + // Formatting duration + const duration = Number(durationInYear) * 365 * 86400; + + // Get contract + const flow = await ethers.getContractAt("Flow", token, signer) + const escrow = await ethers.getContractAt("VotingEscrow", veContract, signer); + + const approveTx = await (await flow.approve(veContract, amount)).wait(); + console.log(approveTx); + const createLockForTx = await (await escrow.create_lock_for(amount, duration, recipient)).wait(); + console.log(createLockForTx); + }); \ No newline at end of file From c679909740df9543430fb70a40f1a1291cd37a95 Mon Sep 17 00:00:00 2001 From: 0xmotto <0xmotto@protonmail.com> Date: Sat, 4 Feb 2023 18:22:58 +0800 Subject: [PATCH 29/43] feat: add batch create lock script --- hardhat.config.ts | 1 + package.json | 4 ++ tasks/batchCreateLockFor.ts | 119 ++++++++++++++++++++++++++++++++++++ tasks/log/failed.csv | 0 tasks/log/successful.csv | 0 tasks/sample_partners.csv | 4 ++ 6 files changed, 128 insertions(+) create mode 100644 tasks/batchCreateLockFor.ts create mode 100644 tasks/log/failed.csv create mode 100644 tasks/log/successful.csv create mode 100644 tasks/sample_partners.csv diff --git a/hardhat.config.ts b/hardhat.config.ts index d117f4c1..54259b81 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -13,6 +13,7 @@ import { resolve } from 'path' import './tasks/accounts' import './tasks/deploy' +import './tasks/batchCreateLockFor' import './tasks/createLockFor' dotenvConfig({ path: resolve(__dirname, './.env') }) diff --git a/package.json b/package.json index 15e1ec54..7019b235 100644 --- a/package.json +++ b/package.json @@ -25,13 +25,17 @@ "@types/mocha": "^9.1.0", "@types/node": "^17.0.35", "chai": "^4.3.6", + "csv-parser": "^3.0.0", + "csv-writer": "^1.6.0", "dotenv": "^16.0.0", "ethereum-waffle": "^3.4.0", "ethers": "^5.0.0", + "fs": "^0.0.1-security", "hardhat": "^2.9.5", "hardhat-abi-exporter": "^2.9.0", "hardhat-deploy": "^0.11.22", "hardhat-preprocessor": "^0.1.4", + "path": "^0.12.7", "prettier": "^2.6.2", "prettier-plugin-solidity": "^1.0.0-beta.19", "ts-node": "^10.7.0", diff --git a/tasks/batchCreateLockFor.ts b/tasks/batchCreateLockFor.ts new file mode 100644 index 00000000..1ea2fdde --- /dev/null +++ b/tasks/batchCreateLockFor.ts @@ -0,0 +1,119 @@ +import { task } from 'hardhat/config' +import fs from "fs"; +import csv from "csv-parser"; +const path = require("path"); +const createCsvWriter = require('csv-writer').createObjectCsvWriter; + +// SAMPLE command +// npx hardhat batch-create-lock-for --network arbitrumOne --token 0xC33f7f83CbB021846Cb9c58f2d8E3df428dbC8C1 --contract 0x10Df81252069C1095F541FAca61646cb9Ae76703 --recipient 0x069e85D4F1010DD961897dC8C095FBB5FF297434 +type LockDetails = { + recipient: string, + amountInMillion: string, + durationInYear: string +} + +const createLockDetailsList: LockDetails[] = [] +const filePath = path.join(__dirname, "sample_partners.csv"); +fs.createReadStream(filePath) + .pipe(csv()) + .on('data', (data: LockDetails) => createLockDetailsList.push(data)) + .on('end', () => { + console.log(createLockDetailsList.length); + }); + +task('batch-create-lock-for', 'Creates lock for a recipient address') + .addParam("token", "The flow token address") + .addParam("contract", "The Voting Escrow's contract address") + .setAction(async ( + taskArguments, + { ethers } + ) => { + // Get signers + const [signer] = await ethers.getSigners() + + // Get task arguments + const { token, contract: veContract } = taskArguments; + + // Validate task arguments + if (!ethers.utils.isAddress(token)) { + throw new Error("Recipient address is not valid") + } + + if (!ethers.utils.isAddress(veContract)) { + throw new Error("Voting Escrow contract address is not valid") + } + + // Get contract + const flow = await ethers.getContractAt("Flow", token, signer) + const escrow = await ethers.getContractAt("VotingEscrow", veContract, signer); + + // Approve VE escrow + const approveTx = await (await flow.approve(veContract, ethers.constants.MaxUint256)).wait(); + console.log(approveTx); + + // Constants + const TOKEN_DECIMALS = ethers.BigNumber.from('10').pow( + ethers.BigNumber.from('18') + ); + const MILLION = ethers.BigNumber.from('10').pow( + ethers.BigNumber.from('6') + ); + + const succcessfulTxCsvWriter = createCsvWriter({ + path: path.join(__dirname, "log", "successful.csv"), + header: [ + { id: 'recipient', title: 'recipient' }, + { id: 'txHash', title: 'txHash' }, + ] + }); + + const failedLockCsvWriter = createCsvWriter({ + path: path.join(__dirname, "log", "failed.csv"), + header: [ + { id: 'recipient', title: 'recipient' }, + { id: 'amountInMillion', title: 'amountInMillion' }, + { id: 'durationInYear', title: 'durationInYear' } + ] + }); + + let successful = 0; + let failed = 0; + + for (let d of createLockDetailsList) { + const { recipient, amountInMillion, durationInYear } = d + console.log(recipient, amountInMillion, durationInYear); + + if (!ethers.utils.isAddress(d.recipient)) { + throw new Error("Recipient address is not valid") + } + + // Formatting amount + const amount = ethers.BigNumber.from(amountInMillion) + .mul(MILLION) + .mul(TOKEN_DECIMALS); + + // Formatting duration + const duration = Number(durationInYear) * 365 * 86400; + + console.log(`Creating Lock of ${amountInMillion} million for ${recipient} for ${durationInYear} years`) + + try { + const createLockForTx = await (await escrow.create_lock_for(amount, duration, recipient)).wait(); + await succcessfulTxCsvWriter.writeRecords([ + { + recipient, + txHash: createLockForTx.transactionHash + } + ]) + successful += 1; + console.log(`Successful for ${recipient}`); + } catch (e) { + failed += 1; + await failedLockCsvWriter.writeRecords(d); + console.log(`Failed for ${recipient}`); + } + } + + console.log(`Number of successful locks: ${successful}`); + console.log(`Number of failed locks: ${failed}`); + }); \ No newline at end of file diff --git a/tasks/log/failed.csv b/tasks/log/failed.csv new file mode 100644 index 00000000..e69de29b diff --git a/tasks/log/successful.csv b/tasks/log/successful.csv new file mode 100644 index 00000000..e69de29b diff --git a/tasks/sample_partners.csv b/tasks/sample_partners.csv new file mode 100644 index 00000000..afd5c297 --- /dev/null +++ b/tasks/sample_partners.csv @@ -0,0 +1,4 @@ +recipient,amountInMillion,durationInYear +0xBD2Ca4c6481b9C4BefAA06172149Bf502D5eF827,1,4 +0x500E720b2BE2d04cAc33541E30bf88887554E14b,2,2 +0xc8EeFd78e1d29B28100413bB3204c952Cb36604E,4,4 \ No newline at end of file From aa935ebfbb9667c3f0a551824bf11de37dee99bc Mon Sep 17 00:00:00 2001 From: 0xmotto <0xmotto@protonmail.com> Date: Sat, 4 Feb 2023 18:23:18 +0800 Subject: [PATCH 30/43] feat: add batch create lock script --- tasks/log/successful.csv | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tasks/log/successful.csv b/tasks/log/successful.csv index e69de29b..f4fb964c 100644 --- a/tasks/log/successful.csv +++ b/tasks/log/successful.csv @@ -0,0 +1,4 @@ +recipient,txHash +0xBD2Ca4c6481b9C4BefAA06172149Bf502D5eF827,0xab1728dff933790245fcaaf1a4b38562c30b9562f8a71ebbc57e1bdd254870ab +0x500E720b2BE2d04cAc33541E30bf88887554E14b,0x8ce5df602c1b962516f8f3b047bb3048a85ad47bc34cb6082471da724e107fc8 +0xc8EeFd78e1d29B28100413bB3204c952Cb36604E,0xd98e98081a727e2abe3768091efd523891c314c03e29bb0cb599aa4c011f3826 From 4b05baf03a3cb780e3d196991a31e8d1cc829901 Mon Sep 17 00:00:00 2001 From: 0xmotto <0xmotto@protonmail.com> Date: Sat, 4 Feb 2023 18:25:34 +0800 Subject: [PATCH 31/43] chore: amend sample commad --- tasks/batchCreateLockFor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/batchCreateLockFor.ts b/tasks/batchCreateLockFor.ts index 1ea2fdde..fec8d75b 100644 --- a/tasks/batchCreateLockFor.ts +++ b/tasks/batchCreateLockFor.ts @@ -5,7 +5,7 @@ const path = require("path"); const createCsvWriter = require('csv-writer').createObjectCsvWriter; // SAMPLE command -// npx hardhat batch-create-lock-for --network arbitrumOne --token 0xC33f7f83CbB021846Cb9c58f2d8E3df428dbC8C1 --contract 0x10Df81252069C1095F541FAca61646cb9Ae76703 --recipient 0x069e85D4F1010DD961897dC8C095FBB5FF297434 +// npx hardhat batch-create-lock-for --network arbitrumOne --token 0xC33f7f83CbB021846Cb9c58f2d8E3df428dbC8C1 --contract 0x10Df81252069C1095F541FAca61646cb9Ae76703 type LockDetails = { recipient: string, amountInMillion: string, From 2d26235cf3a700b5a1f3252815026b31ba9a7aab Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Sun, 5 Feb 2023 00:27:39 +1100 Subject: [PATCH 32/43] merge prep --- contracts/Flow.sol | 43 +- dist/deploy/17_dist.js | 113 +- tasks/log/successful.csv | 6 +- yarn.lock | 8641 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 8731 insertions(+), 72 deletions(-) create mode 100644 yarn.lock diff --git a/contracts/Flow.sol b/contracts/Flow.sol index 9b77a5bc..e0d00b1d 100644 --- a/contracts/Flow.sol +++ b/contracts/Flow.sol @@ -4,22 +4,25 @@ pragma solidity 0.8.13; import "contracts/interfaces/IFlow.sol"; contract Flow is IFlow { - string public constant name = "Velocimeter"; string public constant symbol = "FLOW"; uint8 public constant decimals = 18; - uint public totalSupply = 0; + uint256 public totalSupply = 0; - mapping(address => uint) public balanceOf; - mapping(address => mapping(address => uint)) public allowance; + mapping(address => uint256) public balanceOf; + mapping(address => mapping(address => uint256)) public allowance; bool public initialMinted; address public minter; address public redemptionReceiver; address public merkleClaim; - event Transfer(address indexed from, address indexed to, uint value); - event Approval(address indexed owner, address indexed spender, uint value); + event Transfer(address indexed from, address indexed to, uint256 value); + event Approval( + address indexed owner, + address indexed spender, + uint256 value + ); constructor() { minter = msg.sender; @@ -49,16 +52,16 @@ contract Flow is IFlow { function initialMint(address _recipient) external { require(msg.sender == minter && !initialMinted); initialMinted = true; - _mint(_recipient, 82 * 1e6 * 1e18); + _mint(_recipient, 400 * 1e6 * 1e18); } - function approve(address _spender, uint _value) external returns (bool) { + function approve(address _spender, uint256 _value) external returns (bool) { allowance[msg.sender][_spender] = _value; emit Approval(msg.sender, _spender, _value); return true; } - function _mint(address _to, uint _amount) internal returns (bool) { + function _mint(address _to, uint256 _amount) internal returns (bool) { totalSupply += _amount; unchecked { balanceOf[_to] += _amount; @@ -67,7 +70,11 @@ contract Flow is IFlow { return true; } - function _transfer(address _from, address _to, uint _value) internal returns (bool) { + function _transfer( + address _from, + address _to, + uint256 _value + ) internal returns (bool) { balanceOf[_from] -= _value; unchecked { balanceOf[_to] += _value; @@ -76,25 +83,29 @@ contract Flow is IFlow { return true; } - function transfer(address _to, uint _value) external returns (bool) { + function transfer(address _to, uint256 _value) external returns (bool) { return _transfer(msg.sender, _to, _value); } - function transferFrom(address _from, address _to, uint _value) external returns (bool) { - uint allowed_from = allowance[_from][msg.sender]; - if (allowed_from != type(uint).max) { + function transferFrom( + address _from, + address _to, + uint256 _value + ) external returns (bool) { + uint256 allowed_from = allowance[_from][msg.sender]; + if (allowed_from != type(uint256).max) { allowance[_from][msg.sender] -= _value; } return _transfer(_from, _to, _value); } - function mint(address account, uint amount) external returns (bool) { + function mint(address account, uint256 amount) external returns (bool) { require(msg.sender == minter); _mint(account, amount); return true; } - function claim(address account, uint amount) external returns (bool) { + function claim(address account, uint256 amount) external returns (bool) { require(msg.sender == redemptionReceiver || msg.sender == merkleClaim); _mint(account, amount); return true; diff --git a/dist/deploy/17_dist.js b/dist/deploy/17_dist.js index 456f8b5f..15bc6799 100644 --- a/dist/deploy/17_dist.js +++ b/dist/deploy/17_dist.js @@ -1,54 +1,61 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const arbConfig_1 = __importDefault(require("../tasks/deploy/constants/arbConfig")); -const ARB_TEST_CONFIG = arbConfig_1.default; +'use strict' +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod } + } +Object.defineProperty(exports, '__esModule', { value: true }) +const arbConfig_1 = __importDefault( + require('../tasks/deploy/constants/arbConfig') +) +const ARB_TEST_CONFIG = arbConfig_1.default const func = async function (hre) { - const { ethers } = hre; - const minter = await ethers.getContract('Minter'); - const { deployments, getNamedAccounts } = hre; - const { deploy } = deployments; - const { deployer } = await getNamedAccounts(); - const flow = await deployments.get('Flow'); - // Initial veVELO distro // this is not inside dist lets see if its being used for deploys?? - // await minter.initialize( - // ARB_TEST_CONFIG.partnerAddrs, - // ARB_TEST_CONFIG.partnerAmts, - // ARB_TEST_CONFIG.partnerMax - // ) - console.log('veVELO distributed'); - // - console.log('Arbitrum Goerli Velocimeter Instruments deployed'); - return true; - // Initialize - console.log('deployer', deployer); - // await flow.initialMint(ARB_CONFIG.teamEOA) - // console.log('Initial minted') - // await flow.setRedemptionReceiver(receiver.address) - // console.log('RedemptionReceiver set') - // await flow.setMerkleClaim(claim.address) - // console.log('MerkleClaim set') - // await flow.setMinter(minter.address) - // console.log('Minter set') - // await pairFactory.setPauser(ARB_CONFIG.teamMultisig) - // console.log('Pauser set') - // await escrow.setVoter(voter.address) - // console.log('Voter set') - // await escrow.setTeam(ARB_CONFIG.teamMultisig) - // console.log('Team set for escrow') - // await voter.setGovernor(ARB_CONFIG.teamMultisig) - // console.log('Governor set') - // await voter.setEmergencyCouncil(ARB_CONFIG.teamMultisig) - // console.log('Emergency Council set') - // await distributor.setDepositor(minter.address) - // console.log('Depositor set') - // await receiver.setTeam(ARB_CONFIG.teamMultisig) - // console.log('Team set for receiver') - // await governor.setTeam(ARB_CONFIG.teamMultisig) - // console.log('Team set for governor') -}; -exports.default = func; -func.tags = ['initial_dist']; -func.id = 'initial_dist'; + const { ethers } = hre + const minter = await ethers.getContract('Minter') + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments + const { deployer } = await getNamedAccounts() + const flow = await deployments.get('Flow') + + // skip this completely till initialise day + + // Initial veVELO distro // this is not inside dist lets see if its being used for deploys?? + // await minter.initialize( + // ARB_TEST_CONFIG.partnerAddrs, + // ARB_TEST_CONFIG.partnerAmts, + // ARB_TEST_CONFIG.partnerMax + // ) + console.log('veVELO distributed') + // + console.log('Arbitrum Goerli Velocimeter Instruments deployed') + return true + // Initialize + console.log('deployer', deployer) + // await flow.initialMint(ARB_CONFIG.teamEOA) + // console.log('Initial minted') + // await flow.setRedemptionReceiver(receiver.address) + // console.log('RedemptionReceiver set') + // await flow.setMerkleClaim(claim.address) + // console.log('MerkleClaim set') + // await flow.setMinter(minter.address) + // console.log('Minter set') + // await pairFactory.setPauser(ARB_CONFIG.teamMultisig) + // console.log('Pauser set') + // await escrow.setVoter(voter.address) + // console.log('Voter set') + // await escrow.setTeam(ARB_CONFIG.teamMultisig) + // console.log('Team set for escrow') + // await voter.setGovernor(ARB_CONFIG.teamMultisig) + // console.log('Governor set') + // await voter.setEmergencyCouncil(ARB_CONFIG.teamMultisig) + // console.log('Emergency Council set') + // await distributor.setDepositor(minter.address) + // console.log('Depositor set') + // await receiver.setTeam(ARB_CONFIG.teamMultisig) + // console.log('Team set for receiver') + // await governor.setTeam(ARB_CONFIG.teamMultisig) + // console.log('Team set for governor') +} +exports.default = func +func.tags = ['initial_dist'] +func.id = 'initial_dist' diff --git a/tasks/log/successful.csv b/tasks/log/successful.csv index f4fb964c..76d71ed8 100644 --- a/tasks/log/successful.csv +++ b/tasks/log/successful.csv @@ -1,4 +1,4 @@ recipient,txHash -0xBD2Ca4c6481b9C4BefAA06172149Bf502D5eF827,0xab1728dff933790245fcaaf1a4b38562c30b9562f8a71ebbc57e1bdd254870ab -0x500E720b2BE2d04cAc33541E30bf88887554E14b,0x8ce5df602c1b962516f8f3b047bb3048a85ad47bc34cb6082471da724e107fc8 -0xc8EeFd78e1d29B28100413bB3204c952Cb36604E,0xd98e98081a727e2abe3768091efd523891c314c03e29bb0cb599aa4c011f3826 +0xBD2Ca4c6481b9C4BefAA06172149Bf502D5eF827,0x2c2ceb71decba8a60cc2dc14480822e73dfbd1de1fa0387db42980733e4deb87 +0x500E720b2BE2d04cAc33541E30bf88887554E14b,0xd7e94edb5b8e0f6b7be771276703f9b22522c2895a3d1e555462c0f23a663493 +0xc8EeFd78e1d29B28100413bB3204c952Cb36604E,0x3a93d8bbe4d13875d52c3d384a13364d43403db2808c8e615794db1747fc48b3 diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 00000000..7220a8cf --- /dev/null +++ b/yarn.lock @@ -0,0 +1,8641 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@ensdomains/ens@^0.4.4": + version "0.4.5" + resolved "https://registry.yarnpkg.com/@ensdomains/ens/-/ens-0.4.5.tgz#e0aebc005afdc066447c6e22feb4eda89a5edbfc" + integrity sha512-JSvpj1iNMFjK6K+uVl4unqMoa9rf5jopb8cya5UGBWz23Nw8hSNT7efgUx4BTlAPAgpNlEioUfeTyQ6J9ZvTVw== + dependencies: + bluebird "^3.5.2" + eth-ens-namehash "^2.0.8" + solc "^0.4.20" + testrpc "0.0.1" + web3-utils "^1.0.0-beta.31" + +"@ensdomains/resolver@^0.2.4": + version "0.2.4" + resolved "https://registry.yarnpkg.com/@ensdomains/resolver/-/resolver-0.2.4.tgz#c10fe28bf5efbf49bff4666d909aed0265efbc89" + integrity sha512-bvaTH34PMCbv6anRa9I/0zjLJgY4EuznbEMgbV77JBCQ9KNC46rzi0avuxpOfu+xDjPEtSFGqVEOr5GlUSGudA== + +"@ethereum-waffle/chai@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/chai/-/chai-3.4.4.tgz#16c4cc877df31b035d6d92486dfdf983df9138ff" + integrity sha512-/K8czydBtXXkcM9X6q29EqEkc5dN3oYenyH2a9hF7rGAApAJUpH8QBtojxOY/xQ2up5W332jqgxwp0yPiYug1g== + dependencies: + "@ethereum-waffle/provider" "^3.4.4" + ethers "^5.5.2" + +"@ethereum-waffle/compiler@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/compiler/-/compiler-3.4.4.tgz#d568ee0f6029e68b5c645506079fbf67d0dfcf19" + integrity sha512-RUK3axJ8IkD5xpWjWoJgyHclOeEzDLQFga6gKpeGxiS/zBu+HB0W2FvsrrLalTFIaPw/CGYACRBSIxqiCqwqTQ== + dependencies: + "@resolver-engine/imports" "^0.3.3" + "@resolver-engine/imports-fs" "^0.3.3" + "@typechain/ethers-v5" "^2.0.0" + "@types/mkdirp" "^0.5.2" + "@types/node-fetch" "^2.5.5" + ethers "^5.0.1" + mkdirp "^0.5.1" + node-fetch "^2.6.1" + solc "^0.6.3" + ts-generator "^0.1.1" + typechain "^3.0.0" + +"@ethereum-waffle/ens@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/ens/-/ens-3.4.4.tgz#db97ea2c9decbb70b9205d53de2ccbd6f3182ba1" + integrity sha512-0m4NdwWxliy3heBYva1Wr4WbJKLnwXizmy5FfSSr5PMbjI7SIGCdCB59U7/ZzY773/hY3bLnzLwvG5mggVjJWg== + dependencies: + "@ensdomains/ens" "^0.4.4" + "@ensdomains/resolver" "^0.2.4" + ethers "^5.5.2" + +"@ethereum-waffle/mock-contract@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/mock-contract/-/mock-contract-3.4.4.tgz#fc6ffa18813546f4950a69f5892d4dd54b2c685a" + integrity sha512-Mp0iB2YNWYGUV+VMl5tjPsaXKbKo8MDH9wSJ702l9EBjdxFf/vBvnMBAC1Fub1lLtmD0JHtp1pq+mWzg/xlLnA== + dependencies: + "@ethersproject/abi" "^5.5.0" + ethers "^5.5.2" + +"@ethereum-waffle/provider@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/provider/-/provider-3.4.4.tgz#398fc1f7eb91cc2df7d011272eacba8af0c7fffb" + integrity sha512-GK8oKJAM8+PKy2nK08yDgl4A80mFuI8zBkE0C9GqTRYQqvuxIyXoLmJ5NZU9lIwyWVv5/KsoA11BgAv2jXE82g== + dependencies: + "@ethereum-waffle/ens" "^3.4.4" + ethers "^5.5.2" + ganache-core "^2.13.2" + patch-package "^6.2.2" + postinstall-postinstall "^2.1.0" + +"@ethersproject/abi@5.0.0-beta.153": + version "5.0.0-beta.153" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.0-beta.153.tgz#43a37172b33794e4562999f6e2d555b7599a8eee" + integrity sha512-aXweZ1Z7vMNzJdLpR1CZUAIgnwjrZeUSvN9syCwlBaEBUFJmFY+HHnfuTI5vIhVs/mRkfJVrbEyl51JZQqyjAg== + dependencies: + "@ethersproject/address" ">=5.0.0-beta.128" + "@ethersproject/bignumber" ">=5.0.0-beta.130" + "@ethersproject/bytes" ">=5.0.0-beta.129" + "@ethersproject/constants" ">=5.0.0-beta.128" + "@ethersproject/hash" ">=5.0.0-beta.128" + "@ethersproject/keccak256" ">=5.0.0-beta.127" + "@ethersproject/logger" ">=5.0.0-beta.129" + "@ethersproject/properties" ">=5.0.0-beta.131" + "@ethersproject/strings" ">=5.0.0-beta.130" + +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.5.0", "@ethersproject/abi@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" + integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" + integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + +"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" + integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/address@5.7.0", "@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" + integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + +"@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" + integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + +"@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" + integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" + integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + bn.js "^5.2.1" + +"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" + integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/constants@5.7.0", "@ethersproject/constants@>=5.0.0-beta.128", "@ethersproject/constants@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" + integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + +"@ethersproject/contracts@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" + integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== + dependencies: + "@ethersproject/abi" "^5.7.0" + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + +"@ethersproject/hash@5.7.0", "@ethersproject/hash@>=5.0.0-beta.128", "@ethersproject/hash@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" + integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" + integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" + integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + aes-js "3.0.0" + scrypt-js "3.0.1" + +"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@>=5.0.0-beta.127", "@ethersproject/keccak256@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" + integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + js-sha3 "0.8.0" + +"@ethersproject/logger@5.7.0", "@ethersproject/logger@>=5.0.0-beta.129", "@ethersproject/logger@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" + integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== + +"@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" + integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" + integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + +"@ethersproject/properties@5.7.0", "@ethersproject/properties@>=5.0.0-beta.131", "@ethersproject/properties@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" + integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/providers@5.7.2": + version "5.7.2" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" + integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + bech32 "1.1.4" + ws "7.4.6" + +"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" + integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" + integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" + integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + hash.js "1.1.7" + +"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" + integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + bn.js "^5.2.1" + elliptic "6.5.4" + hash.js "1.1.7" + +"@ethersproject/solidity@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" + integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/strings@5.7.0", "@ethersproject/strings@>=5.0.0-beta.130", "@ethersproject/strings@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" + integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.0.0-beta.135", "@ethersproject/transactions@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" + integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + +"@ethersproject/units@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" + integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/wallet@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" + integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/json-wallets" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" + integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== + dependencies: + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" + integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@metamask/eth-sig-util@^4.0.0": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz#3ad61f6ea9ad73ba5b19db780d40d9aae5157088" + integrity sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ== + dependencies: + ethereumjs-abi "^0.6.8" + ethereumjs-util "^6.2.1" + ethjs-util "^0.1.6" + tweetnacl "^1.0.3" + tweetnacl-util "^0.15.1" + +"@morgan-stanley/ts-mocking-bird@^0.6.2": + version "0.6.4" + resolved "https://registry.yarnpkg.com/@morgan-stanley/ts-mocking-bird/-/ts-mocking-bird-0.6.4.tgz#2e4b60d42957bab3b50b67dbf14c3da2f62a39f7" + integrity sha512-57VJIflP8eR2xXa9cD1LUawh+Gh+BVQfVu0n6GALyg/AqV/Nz25kDRvws3i9kIe1PTrbsZZOYpsYp6bXPd6nVA== + dependencies: + lodash "^4.17.16" + uuid "^7.0.3" + +"@noble/hashes@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.2.tgz#e9e035b9b166ca0af657a7848eb2718f0f22f183" + integrity sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA== + +"@noble/hashes@~1.1.1": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.5.tgz#1a0377f3b9020efe2fae03290bd2a12140c95c11" + integrity sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ== + +"@noble/secp256k1@1.6.3", "@noble/secp256k1@~1.6.0": + version "1.6.3" + resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.6.3.tgz#7eed12d9f4404b416999d0c87686836c4c5c9b94" + integrity sha512-T04e4iTurVy7I8Sw4+c5OSN9/RkPlo1uKxAomtxQNLq8j1uPAqnsqG1bqvY3Jv7c13gyr6dui0zmh/I3+f/JaQ== + +"@nomicfoundation/ethereumjs-block@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-4.0.0.tgz#fdd5c045e7baa5169abeed0e1202bf94e4481c49" + integrity sha512-bk8uP8VuexLgyIZAHExH1QEovqx0Lzhc9Ntm63nCRKLHXIZkobaFaeCVwTESV7YkPKUk7NiK11s8ryed4CS9yA== + dependencies: + "@nomicfoundation/ethereumjs-common" "^3.0.0" + "@nomicfoundation/ethereumjs-rlp" "^4.0.0" + "@nomicfoundation/ethereumjs-trie" "^5.0.0" + "@nomicfoundation/ethereumjs-tx" "^4.0.0" + "@nomicfoundation/ethereumjs-util" "^8.0.0" + ethereum-cryptography "0.1.3" + +"@nomicfoundation/ethereumjs-blockchain@^6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-6.0.0.tgz#1a8c243a46d4d3691631f139bfb3a4a157187b0c" + integrity sha512-pLFEoea6MWd81QQYSReLlLfH7N9v7lH66JC/NMPN848ySPPQA5renWnE7wPByfQFzNrPBuDDRFFULMDmj1C0xw== + dependencies: + "@nomicfoundation/ethereumjs-block" "^4.0.0" + "@nomicfoundation/ethereumjs-common" "^3.0.0" + "@nomicfoundation/ethereumjs-ethash" "^2.0.0" + "@nomicfoundation/ethereumjs-rlp" "^4.0.0" + "@nomicfoundation/ethereumjs-trie" "^5.0.0" + "@nomicfoundation/ethereumjs-util" "^8.0.0" + abstract-level "^1.0.3" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + level "^8.0.0" + lru-cache "^5.1.1" + memory-level "^1.0.0" + +"@nomicfoundation/ethereumjs-common@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-3.0.0.tgz#f6bcc7753994555e49ab3aa517fc8bcf89c280b9" + integrity sha512-WS7qSshQfxoZOpHG/XqlHEGRG1zmyjYrvmATvc4c62+gZXgre1ymYP8ZNgx/3FyZY0TWe9OjFlKOfLqmgOeYwA== + dependencies: + "@nomicfoundation/ethereumjs-util" "^8.0.0" + crc-32 "^1.2.0" + +"@nomicfoundation/ethereumjs-ethash@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-2.0.0.tgz#11539c32fe0990e1122ff987d1b84cfa34774e81" + integrity sha512-WpDvnRncfDUuXdsAXlI4lXbqUDOA+adYRQaEezIkxqDkc+LDyYDbd/xairmY98GnQzo1zIqsIL6GB5MoMSJDew== + dependencies: + "@nomicfoundation/ethereumjs-block" "^4.0.0" + "@nomicfoundation/ethereumjs-rlp" "^4.0.0" + "@nomicfoundation/ethereumjs-util" "^8.0.0" + abstract-level "^1.0.3" + bigint-crypto-utils "^3.0.23" + ethereum-cryptography "0.1.3" + +"@nomicfoundation/ethereumjs-evm@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-1.0.0.tgz#99cd173c03b59107c156a69c5e215409098a370b" + integrity sha512-hVS6qRo3V1PLKCO210UfcEQHvlG7GqR8iFzp0yyjTg2TmJQizcChKgWo8KFsdMw6AyoLgLhHGHw4HdlP8a4i+Q== + dependencies: + "@nomicfoundation/ethereumjs-common" "^3.0.0" + "@nomicfoundation/ethereumjs-util" "^8.0.0" + "@types/async-eventemitter" "^0.2.1" + async-eventemitter "^0.2.4" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + mcl-wasm "^0.7.1" + rustbn.js "~0.2.0" + +"@nomicfoundation/ethereumjs-rlp@^4.0.0", "@nomicfoundation/ethereumjs-rlp@^4.0.0-beta.2": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-4.0.0.tgz#d9a9c5f0f10310c8849b6525101de455a53e771d" + integrity sha512-GaSOGk5QbUk4eBP5qFbpXoZoZUj/NrW7MRa0tKY4Ew4c2HAS0GXArEMAamtFrkazp0BO4K5p2ZCG3b2FmbShmw== + +"@nomicfoundation/ethereumjs-statemanager@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-1.0.0.tgz#14a9d4e1c828230368f7ab520c144c34d8721e4b" + integrity sha512-jCtqFjcd2QejtuAMjQzbil/4NHf5aAWxUc+CvS0JclQpl+7M0bxMofR2AJdtz+P3u0ke2euhYREDiE7iSO31vQ== + dependencies: + "@nomicfoundation/ethereumjs-common" "^3.0.0" + "@nomicfoundation/ethereumjs-rlp" "^4.0.0" + "@nomicfoundation/ethereumjs-trie" "^5.0.0" + "@nomicfoundation/ethereumjs-util" "^8.0.0" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + functional-red-black-tree "^1.0.1" + +"@nomicfoundation/ethereumjs-trie@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-5.0.0.tgz#dcfbe3be53a94bc061c9767a396c16702bc2f5b7" + integrity sha512-LIj5XdE+s+t6WSuq/ttegJzZ1vliwg6wlb+Y9f4RlBpuK35B9K02bO7xU+E6Rgg9RGptkWd6TVLdedTI4eNc2A== + dependencies: + "@nomicfoundation/ethereumjs-rlp" "^4.0.0" + "@nomicfoundation/ethereumjs-util" "^8.0.0" + ethereum-cryptography "0.1.3" + readable-stream "^3.6.0" + +"@nomicfoundation/ethereumjs-tx@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-4.0.0.tgz#59dc7452b0862b30342966f7052ab9a1f7802f52" + integrity sha512-Gg3Lir2lNUck43Kp/3x6TfBNwcWC9Z1wYue9Nz3v4xjdcv6oDW9QSMJxqsKw9QEGoBBZ+gqwpW7+F05/rs/g1w== + dependencies: + "@nomicfoundation/ethereumjs-common" "^3.0.0" + "@nomicfoundation/ethereumjs-rlp" "^4.0.0" + "@nomicfoundation/ethereumjs-util" "^8.0.0" + ethereum-cryptography "0.1.3" + +"@nomicfoundation/ethereumjs-util@^8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-8.0.0.tgz#deb2b15d2c308a731e82977aefc4e61ca0ece6c5" + integrity sha512-2emi0NJ/HmTG+CGY58fa+DQuAoroFeSH9gKu9O6JnwTtlzJtgfTixuoOqLEgyyzZVvwfIpRueuePb8TonL1y+A== + dependencies: + "@nomicfoundation/ethereumjs-rlp" "^4.0.0-beta.2" + ethereum-cryptography "0.1.3" + +"@nomicfoundation/ethereumjs-vm@^6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-6.0.0.tgz#2bb50d332bf41790b01a3767ffec3987585d1de6" + integrity sha512-JMPxvPQ3fzD063Sg3Tp+UdwUkVxMoo1uML6KSzFhMH3hoQi/LMuXBoEHAoW83/vyNS9BxEe6jm6LmT5xdeEJ6w== + dependencies: + "@nomicfoundation/ethereumjs-block" "^4.0.0" + "@nomicfoundation/ethereumjs-blockchain" "^6.0.0" + "@nomicfoundation/ethereumjs-common" "^3.0.0" + "@nomicfoundation/ethereumjs-evm" "^1.0.0" + "@nomicfoundation/ethereumjs-rlp" "^4.0.0" + "@nomicfoundation/ethereumjs-statemanager" "^1.0.0" + "@nomicfoundation/ethereumjs-trie" "^5.0.0" + "@nomicfoundation/ethereumjs-tx" "^4.0.0" + "@nomicfoundation/ethereumjs-util" "^8.0.0" + "@types/async-eventemitter" "^0.2.1" + async-eventemitter "^0.2.4" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + functional-red-black-tree "^1.0.1" + mcl-wasm "^0.7.1" + rustbn.js "~0.2.0" + +"@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.0.tgz#83a7367342bd053a76d04bbcf4f373fef07cf760" + integrity sha512-vEF3yKuuzfMHsZecHQcnkUrqm8mnTWfJeEVFHpg+cO+le96xQA4lAJYdUan8pXZohQxv1fSReQsn4QGNuBNuCw== + +"@nomicfoundation/solidity-analyzer-darwin-x64@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.0.tgz#1225f7da647ae1ad25a87125664704ecc0af6ccc" + integrity sha512-dlHeIg0pTL4dB1l9JDwbi/JG6dHQaU1xpDK+ugYO8eJ1kxx9Dh2isEUtA4d02cQAl22cjOHTvifAk96A+ItEHA== + +"@nomicfoundation/solidity-analyzer-freebsd-x64@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-freebsd-x64/-/solidity-analyzer-freebsd-x64-0.1.0.tgz#dbc052dcdfd50ae50fd5ae1788b69b4e0fa40040" + integrity sha512-WFCZYMv86WowDA4GiJKnebMQRt3kCcFqHeIomW6NMyqiKqhK1kIZCxSLDYsxqlx396kKLPN1713Q1S8tu68GKg== + +"@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.0.tgz#e6b2eea633995b557e74e881d2a43eab4760903d" + integrity sha512-DTw6MNQWWlCgc71Pq7CEhEqkb7fZnS7oly13pujs4cMH1sR0JzNk90Mp1zpSCsCs4oKan2ClhMlLKtNat/XRKQ== + +"@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.0.tgz#af81107f5afa794f19988a368647727806e18dc4" + integrity sha512-wUpUnR/3GV5Da88MhrxXh/lhb9kxh9V3Jya2NpBEhKDIRCDmtXMSqPMXHZmOR9DfCwCvG6vLFPr/+YrPCnUN0w== + +"@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.0.tgz#6877e1da1a06a9f08446070ab6e0a5347109f868" + integrity sha512-lR0AxK1x/MeKQ/3Pt923kPvwigmGX3OxeU5qNtQ9pj9iucgk4PzhbS3ruUeSpYhUxG50jN4RkIGwUMoev5lguw== + +"@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.0.tgz#bb6cd83a0c259eccef4183796b6329a66cf7ebd9" + integrity sha512-A1he/8gy/JeBD3FKvmI6WUJrGrI5uWJNr5Xb9WdV+DK0F8msuOqpEByLlnTdLkXMwW7nSl3awvLezOs9xBHJEg== + +"@nomicfoundation/solidity-analyzer-win32-arm64-msvc@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-arm64-msvc/-/solidity-analyzer-win32-arm64-msvc-0.1.0.tgz#9d4bca1cc9a1333fde985675083b0b7d165f6076" + integrity sha512-7x5SXZ9R9H4SluJZZP8XPN+ju7Mx+XeUMWZw7ZAqkdhP5mK19I4vz3x0zIWygmfE8RT7uQ5xMap0/9NPsO+ykw== + +"@nomicfoundation/solidity-analyzer-win32-ia32-msvc@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-ia32-msvc/-/solidity-analyzer-win32-ia32-msvc-0.1.0.tgz#0db5bfc6aa952bea4098d8d2c8947b4e5c4337ee" + integrity sha512-m7w3xf+hnE774YRXu+2mGV7RiF3QJtUoiYU61FascCkQhX3QMQavh7saH/vzb2jN5D24nT/jwvaHYX/MAM9zUw== + +"@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.0.tgz#2e0f39a2924dcd77db6b419828595e984fabcb33" + integrity sha512-xCuybjY0sLJQnJhupiFAXaek2EqF0AP0eBjgzaalPXSNvCEN6ZYHvUzdA50ENDVeSYFXcUsYf3+FsD3XKaeptA== + +"@nomicfoundation/solidity-analyzer@^0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.0.tgz#e5ddc43ad5c0aab96e5054520d8e16212e125f50" + integrity sha512-xGWAiVCGOycvGiP/qrlf9f9eOn7fpNbyJygcB0P21a1MDuVPlKt0Srp7rvtBEutYQ48ouYnRXm33zlRnlTOPHg== + optionalDependencies: + "@nomicfoundation/solidity-analyzer-darwin-arm64" "0.1.0" + "@nomicfoundation/solidity-analyzer-darwin-x64" "0.1.0" + "@nomicfoundation/solidity-analyzer-freebsd-x64" "0.1.0" + "@nomicfoundation/solidity-analyzer-linux-arm64-gnu" "0.1.0" + "@nomicfoundation/solidity-analyzer-linux-arm64-musl" "0.1.0" + "@nomicfoundation/solidity-analyzer-linux-x64-gnu" "0.1.0" + "@nomicfoundation/solidity-analyzer-linux-x64-musl" "0.1.0" + "@nomicfoundation/solidity-analyzer-win32-arm64-msvc" "0.1.0" + "@nomicfoundation/solidity-analyzer-win32-ia32-msvc" "0.1.0" + "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.0" + +"@nomiclabs/hardhat-ethers@yarn:hardhat-deploy-ethers": + version "0.3.0-beta.13" + resolved "https://registry.yarnpkg.com/hardhat-deploy-ethers/-/hardhat-deploy-ethers-0.3.0-beta.13.tgz#b96086ff768ddf69928984d5eb0a8d78cfca9366" + integrity sha512-PdWVcKB9coqWV1L7JTpfXRCI91Cgwsm7KLmBcwZ8f0COSm1xtABHZTyz3fvF6p42cTnz1VM0QnfDvMFlIRkSNw== + +"@nomiclabs/hardhat-etherscan@^3.1.4": + version "3.1.5" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.1.5.tgz#24f3f3272d3c79acdc933b557810ca85caef0fee" + integrity sha512-PxPX28AGBAlxgXLU27NB3oiMsklxbNhM75SDC4v1QPCyPeAxGm4xV0WpYbR10W7sxY2WF3Ek7u7GhjbQWa2Fcg== + dependencies: + "@ethersproject/abi" "^5.1.2" + "@ethersproject/address" "^5.0.2" + cbor "^8.1.0" + chalk "^2.4.2" + debug "^4.1.1" + fs-extra "^7.0.1" + lodash "^4.17.11" + semver "^6.3.0" + table "^6.8.0" + undici "^5.14.0" + +"@nomiclabs/hardhat-waffle@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.3.tgz#9c538a09c5ed89f68f5fd2dc3f78f16ed1d6e0b1" + integrity sha512-049PHSnI1CZq6+XTbrMbMv5NaL7cednTfPenx02k3cEh8wBMLa6ys++dBETJa6JjfwgA9nBhhHQ173LJv6k2Pg== + dependencies: + "@types/sinon-chai" "^3.2.3" + "@types/web3" "1.0.19" + +"@resolver-engine/core@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/core/-/core-0.3.3.tgz#590f77d85d45bc7ecc4e06c654f41345db6ca967" + integrity sha512-eB8nEbKDJJBi5p5SrvrvILn4a0h42bKtbCTri3ZxCGt6UvoQyp7HnGOfki944bUjBSHKK3RvgfViHn+kqdXtnQ== + dependencies: + debug "^3.1.0" + is-url "^1.2.4" + request "^2.85.0" + +"@resolver-engine/fs@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/fs/-/fs-0.3.3.tgz#fbf83fa0c4f60154a82c817d2fe3f3b0c049a973" + integrity sha512-wQ9RhPUcny02Wm0IuJwYMyAG8fXVeKdmhm8xizNByD4ryZlx6PP6kRen+t/haF43cMfmaV7T3Cx6ChOdHEhFUQ== + dependencies: + "@resolver-engine/core" "^0.3.3" + debug "^3.1.0" + +"@resolver-engine/imports-fs@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/imports-fs/-/imports-fs-0.3.3.tgz#4085db4b8d3c03feb7a425fbfcf5325c0d1e6c1b" + integrity sha512-7Pjg/ZAZtxpeyCFlZR5zqYkz+Wdo84ugB5LApwriT8XFeQoLwGUj4tZFFvvCuxaNCcqZzCYbonJgmGObYBzyCA== + dependencies: + "@resolver-engine/fs" "^0.3.3" + "@resolver-engine/imports" "^0.3.3" + debug "^3.1.0" + +"@resolver-engine/imports@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/imports/-/imports-0.3.3.tgz#badfb513bb3ff3c1ee9fd56073e3144245588bcc" + integrity sha512-anHpS4wN4sRMwsAbMXhMfOD/y4a4Oo0Cw/5+rue7hSwGWsDOQaAU1ClK1OxjUC35/peazxEl8JaSRRS+Xb8t3Q== + dependencies: + "@resolver-engine/core" "^0.3.3" + debug "^3.1.0" + hosted-git-info "^2.6.0" + path-browserify "^1.0.0" + url "^0.11.0" + +"@scure/base@~1.1.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" + integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA== + +"@scure/bip32@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.0.tgz#dea45875e7fbc720c2b4560325f1cf5d2246d95b" + integrity sha512-ftTW3kKX54YXLCxH6BB7oEEoJfoE2pIgw7MINKAs5PsS6nqKPuKk1haTF/EuHmYqG330t5GSrdmtRuHaY1a62Q== + dependencies: + "@noble/hashes" "~1.1.1" + "@noble/secp256k1" "~1.6.0" + "@scure/base" "~1.1.0" + +"@scure/bip39@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.0.tgz#92f11d095bae025f166bef3defcc5bf4945d419a" + integrity sha512-pwrPOS16VeTKg98dYXQyIjJEcWfz7/1YJIwxUEPFfQPtc86Ym/1sVgQ2RLoD43AazMk2l/unK4ITySSpW2+82w== + dependencies: + "@noble/hashes" "~1.1.1" + "@scure/base" "~1.1.0" + +"@sentry/core@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" + integrity sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/minimal" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/hub@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.30.0.tgz#2453be9b9cb903404366e198bd30c7ca74cdc100" + integrity sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ== + dependencies: + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/minimal@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.30.0.tgz#ce3d3a6a273428e0084adcb800bc12e72d34637b" + integrity sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/types" "5.30.0" + tslib "^1.9.3" + +"@sentry/node@^5.18.1": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.30.0.tgz#4ca479e799b1021285d7fe12ac0858951c11cd48" + integrity sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg== + dependencies: + "@sentry/core" "5.30.0" + "@sentry/hub" "5.30.0" + "@sentry/tracing" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + cookie "^0.4.1" + https-proxy-agent "^5.0.0" + lru_map "^0.3.3" + tslib "^1.9.3" + +"@sentry/tracing@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-5.30.0.tgz#501d21f00c3f3be7f7635d8710da70d9419d4e1f" + integrity sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/minimal" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/types@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.30.0.tgz#19709bbe12a1a0115bc790b8942917da5636f402" + integrity sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw== + +"@sentry/utils@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.30.0.tgz#9a5bd7ccff85ccfe7856d493bffa64cabc41e980" + integrity sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww== + dependencies: + "@sentry/types" "5.30.0" + tslib "^1.9.3" + +"@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + +"@sindresorhus/is@^4.0.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" + integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== + +"@solidity-parser/parser@^0.14.5": + version "0.14.5" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.14.5.tgz#87bc3cc7b068e08195c219c91cd8ddff5ef1a804" + integrity sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg== + dependencies: + antlr4ts "^0.5.0-alpha.4" + +"@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + dependencies: + defer-to-connect "^1.0.1" + +"@szmarczak/http-timer@^4.0.5": + version "4.0.6" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807" + integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w== + dependencies: + defer-to-connect "^2.0.0" + +"@tsconfig/node10@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" + integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" + integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== + +"@typechain/ethers-v5@^10.0.0": + version "10.2.0" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-10.2.0.tgz#68f5963efb5214cb2d881477228e4b5b315473e1" + integrity sha512-ikaq0N/w9fABM+G01OFmU3U3dNnyRwEahkdvi9mqy1a3XwKiPZaF/lu54OcNaEWnpvEYyhhS0N7buCtLQqC92w== + dependencies: + lodash "^4.17.15" + ts-essentials "^7.0.1" + +"@typechain/ethers-v5@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-2.0.0.tgz#cd3ca1590240d587ca301f4c029b67bfccd08810" + integrity sha512-0xdCkyGOzdqh4h5JSf+zoWx85IusEjDcPIwNEHP8mrWSnCae4rvrqB+/gtpdNfX7zjlFlZiMeePn2r63EI3Lrw== + dependencies: + ethers "^5.0.2" + +"@typechain/hardhat@^6.0.0": + version "6.1.5" + resolved "https://registry.yarnpkg.com/@typechain/hardhat/-/hardhat-6.1.5.tgz#caad58a1d3e9cd88061a584eb4f4fa763d5dcad1" + integrity sha512-lg7LW4qDZpxFMknp3Xool61Fg6Lays8F8TXdFGBG+MxyYcYU5795P1U2XdStuzGq9S2Dzdgh+1jGww9wvZ6r4Q== + dependencies: + fs-extra "^9.1.0" + +"@types/async-eventemitter@^0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@types/async-eventemitter/-/async-eventemitter-0.2.1.tgz#f8e6280e87e8c60b2b938624b0a3530fb3e24712" + integrity sha512-M2P4Ng26QbAeITiH7w1d7OxtldgfAe0wobpyJzVK/XOb0cUGKU2R4pfAhqcJBXAe2ife5ZOhSv4wk7p+ffURtg== + +"@types/bn.js@*", "@types/bn.js@^5.1.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" + integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== + dependencies: + "@types/node" "*" + +"@types/bn.js@^4.11.3", "@types/bn.js@^4.11.5": + version "4.11.6" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" + integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== + dependencies: + "@types/node" "*" + +"@types/cacheable-request@^6.0.1": + version "6.0.3" + resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183" + integrity sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw== + dependencies: + "@types/http-cache-semantics" "*" + "@types/keyv" "^3.1.4" + "@types/node" "*" + "@types/responselike" "^1.0.0" + +"@types/chai@*", "@types/chai@^4.3.0": + version "4.3.4" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.4.tgz#e913e8175db8307d78b4e8fa690408ba6b65dee4" + integrity sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw== + +"@types/http-cache-semantics@*": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812" + integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ== + +"@types/keyv@^3.1.4": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6" + integrity sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg== + dependencies: + "@types/node" "*" + +"@types/lru-cache@^5.1.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" + integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw== + +"@types/mkdirp@^0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-0.5.2.tgz#503aacfe5cc2703d5484326b1b27efa67a339c1f" + integrity sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg== + dependencies: + "@types/node" "*" + +"@types/mocha@^9.1.0": + version "9.1.1" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4" + integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== + +"@types/node-fetch@^2.5.5": + version "2.6.2" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.2.tgz#d1a9c5fd049d9415dce61571557104dec3ec81da" + integrity sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + +"@types/node@*": + version "18.11.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.18.tgz#8dfb97f0da23c2293e554c5a50d61ef134d7697f" + integrity sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA== + +"@types/node@^12.12.6": + version "12.20.55" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" + integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== + +"@types/node@^17.0.35": + version "17.0.45" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190" + integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw== + +"@types/pbkdf2@^3.0.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.0.tgz#039a0e9b67da0cdc4ee5dab865caa6b267bb66b1" + integrity sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ== + dependencies: + "@types/node" "*" + +"@types/prettier@^2.1.1": + version "2.7.2" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.2.tgz#6c2324641cc4ba050a8c710b2b251b377581fbf0" + integrity sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg== + +"@types/qs@^6.9.7": + version "6.9.7" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" + integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + +"@types/resolve@^0.0.8": + version "0.0.8" + resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194" + integrity sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ== + dependencies: + "@types/node" "*" + +"@types/responselike@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" + integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA== + dependencies: + "@types/node" "*" + +"@types/secp256k1@^4.0.1": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.3.tgz#1b8e55d8e00f08ee7220b4d59a6abe89c37a901c" + integrity sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w== + dependencies: + "@types/node" "*" + +"@types/sinon-chai@^3.2.3": + version "3.2.9" + resolved "https://registry.yarnpkg.com/@types/sinon-chai/-/sinon-chai-3.2.9.tgz#71feb938574bbadcb176c68e5ff1a6014c5e69d4" + integrity sha512-/19t63pFYU0ikrdbXKBWj9PCdnKyTd0Qkz0X91Ta081cYsq90OxYdcWwK/dwEoDa6dtXgj2HJfmzgq+QZTHdmQ== + dependencies: + "@types/chai" "*" + "@types/sinon" "*" + +"@types/sinon@*": + version "10.0.13" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.13.tgz#60a7a87a70d9372d0b7b38cc03e825f46981fb83" + integrity sha512-UVjDqJblVNQYvVNUsj0PuYYw0ELRmgt1Nt5Vk0pT5f16ROGfcKJY8o1HVuMOJOpD727RrGB9EGvoaTQE5tgxZQ== + dependencies: + "@types/sinonjs__fake-timers" "*" + +"@types/sinonjs__fake-timers@*": + version "8.1.2" + resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz#bf2e02a3dbd4aecaf95942ecd99b7402e03fad5e" + integrity sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA== + +"@types/underscore@*": + version "1.11.4" + resolved "https://registry.yarnpkg.com/@types/underscore/-/underscore-1.11.4.tgz#62e393f8bc4bd8a06154d110c7d042a93751def3" + integrity sha512-uO4CD2ELOjw8tasUrAhvnn2W4A0ZECOvMjCivJr4gA9pGgjv+qxKWY9GLTMVEK8ej85BxQOocUyE7hImmSQYcg== + +"@types/web3@1.0.19": + version "1.0.19" + resolved "https://registry.yarnpkg.com/@types/web3/-/web3-1.0.19.tgz#46b85d91d398ded9ab7c85a5dd57cb33ac558924" + integrity sha512-fhZ9DyvDYDwHZUp5/STa9XW2re0E8GxoioYJ4pEUZ13YHpApSagixj7IAdoYH5uAK+UalGq6Ml8LYzmgRA/q+A== + dependencies: + "@types/bn.js" "*" + "@types/underscore" "*" + +"@yarnpkg/lockfile@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" + integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== + +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + +abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/abstract-level/-/abstract-level-1.0.3.tgz#78a67d3d84da55ee15201486ab44c09560070741" + integrity sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA== + dependencies: + buffer "^6.0.3" + catering "^2.1.0" + is-buffer "^2.0.5" + level-supports "^4.0.0" + level-transcoder "^1.0.1" + module-error "^1.0.1" + queue-microtask "^1.2.3" + +abstract-leveldown@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-3.0.0.tgz#5cb89f958a44f526779d740d1440e743e0c30a57" + integrity sha512-KUWx9UWGQD12zsmLNj64/pndaz4iJh/Pj7nopgkfDG6RlCcbMZvT6+9l7dchK4idog2Is8VdC/PvNbFuFmalIQ== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@^2.4.1, abstract-leveldown@~2.7.1: + version "2.7.2" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz#87a44d7ebebc341d59665204834c8b7e0932cc93" + integrity sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@^5.0.0, abstract-leveldown@~5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz#f7128e1f86ccabf7d2893077ce5d06d798e386c6" + integrity sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@~2.6.0: + version "2.6.3" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz#1c5e8c6a5ef965ae8c35dfb3a8770c476b82c4b8" + integrity sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA== + dependencies: + xtend "~4.0.0" + +accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +acorn-walk@^8.1.1: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + +acorn@^8.4.1: + version "8.8.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" + integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== + +adm-zip@^0.4.16: + version "0.4.16" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365" + integrity sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg== + +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== + +aes-js@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" + integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ajv@^6.12.3: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.0.1: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +ansi-colors@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-colors@^4.1.0, ansi-colors@^4.1.1: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== + +ansi-escapes@^4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +antlr4ts@^0.5.0-alpha.4: + version "0.5.0-alpha.4" + resolved "https://registry.yarnpkg.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz#71702865a87478ed0b40c0709f422cf14d51652a" + integrity sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ== + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA== + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q== + +array-back@^1.0.3, array-back@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-1.0.4.tgz#644ba7f095f7ffcf7c43b5f0dc39d3c1f03c063b" + integrity sha512-1WxbZvrmyhkNoeYcizokbmh5oiOCIfyvGtcqbK3Ls1v1fKcquzxnQSceOx6tzq7jmai2kFLWIpGND2cLhH6TPw== + dependencies: + typical "^2.6.0" + +array-back@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-2.0.0.tgz#6877471d51ecc9c9bfa6136fb6c7d5fe69748022" + integrity sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw== + dependencies: + typical "^2.6.1" + +array-back@^3.0.1, array-back@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" + integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== + +array-back@^4.0.1, array-back@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e" + integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg== + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ== + +array.prototype.reduce@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz#6b20b0daa9d9734dd6bc7ea66b5bbce395471eac" + integrity sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-array-method-boxes-properly "^1.0.0" + is-string "^1.0.7" + +asn1.js@^5.2.0: + version "5.4.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" + integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + safer-buffer "^2.1.0" + +asn1@~0.2.3: + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== + +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw== + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + +async-eventemitter@^0.2.2, async-eventemitter@^0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" + integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw== + dependencies: + async "^2.4.0" + +async-limiter@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" + integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + +async@2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381" + integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg== + dependencies: + lodash "^4.17.11" + +async@^1.4.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + integrity sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w== + +async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.5.0, async@^2.6.1: + version "2.6.4" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" + integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== + dependencies: + lodash "^4.17.14" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + +atob@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +available-typed-arrays@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" + integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== + +aws4@^1.8.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3" + integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== + +axios@^0.21.1: + version "0.21.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" + integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== + dependencies: + follow-redirects "^1.14.0" + +babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + integrity sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g== + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-core@^6.0.14, babel-core@^6.26.0: + version "6.26.3" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" + integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== + dependencies: + babel-code-frame "^6.26.0" + babel-generator "^6.26.0" + babel-helpers "^6.24.1" + babel-messages "^6.23.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + convert-source-map "^1.5.1" + debug "^2.6.9" + json5 "^0.5.1" + lodash "^4.17.4" + minimatch "^3.0.4" + path-is-absolute "^1.0.1" + private "^0.1.8" + slash "^1.0.0" + source-map "^0.5.7" + +babel-generator@^6.26.0: + version "6.26.1" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" + integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.17.4" + source-map "^0.5.7" + trim-right "^1.0.1" + +babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" + integrity sha512-gCtfYORSG1fUMX4kKraymq607FWgMWg+j42IFPc18kFQEsmtaibP4UrqsXt8FlEJle25HUd4tsoDR7H2wDhe9Q== + dependencies: + babel-helper-explode-assignable-expression "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-call-delegate@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" + integrity sha512-RL8n2NiEj+kKztlrVJM9JT1cXzzAdvWFh76xh/H1I4nKwunzE4INBXn8ieCZ+wh4zWszZk7NBS1s/8HR5jDkzQ== + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-define-map@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" + integrity sha512-bHkmjcC9lM1kmZcVpA5t2om2nzT/xiZpo6TJq7UlZ3wqKfzia4veeXbIhKvJXAMzhhEBd3cR1IElL5AenWEUpA== + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-explode-assignable-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" + integrity sha512-qe5csbhbvq6ccry9G7tkXbzNtcDiH4r51rrPUbwwoTzZ18AqxWYRZT6AOmxrpxKnQBW0pYlBI/8vh73Z//78nQ== + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-function-name@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" + integrity sha512-Oo6+e2iX+o9eVvJ9Y5eKL5iryeRdsIkwRYheCuhYdVHsdEQysbc2z2QkqCLIYnNxkT5Ss3ggrHdXiDI7Dhrn4Q== + dependencies: + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-get-function-arity@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" + integrity sha512-WfgKFX6swFB1jS2vo+DwivRN4NB8XUdM3ij0Y1gnC21y1tdBoe6xjVnd7NSI6alv+gZXCtJqvrTeMW3fR/c0ng== + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-hoist-variables@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" + integrity sha512-zAYl3tqerLItvG5cKYw7f1SpvIxS9zi7ohyGHaI9cgDUjAT6YcY9jIEH5CstetP5wHIVSceXwNS7Z5BpJg+rOw== + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-optimise-call-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" + integrity sha512-Op9IhEaxhbRT8MDXx2iNuMgciu2V8lDvYCNQbDGjdBNCjaMvyLf4wl4A3b8IgndCyQF8TwfgsQ8T3VD8aX1/pA== + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-regex@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" + integrity sha512-VlPiWmqmGJp0x0oK27Out1D+71nVVCTSdlbhIVoaBAj2lUgrNjBCRR9+llO4lTSb2O4r7PJg+RobRkhBrf6ofg== + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-remap-async-to-generator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" + integrity sha512-RYqaPD0mQyQIFRu7Ho5wE2yvA/5jxqCIj/Lv4BXNq23mHYu/vxikOy2JueLiBxQknwapwrJeNCesvY0ZcfnlHg== + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-replace-supers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" + integrity sha512-sLI+u7sXJh6+ToqDr57Bv973kCepItDhMou0xCP2YPVmR1jkHSCY+p1no8xErbV1Siz5QE8qKT1WIwybSWlqjw== + dependencies: + babel-helper-optimise-call-expression "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helpers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" + integrity sha512-n7pFrqQm44TCYvrCDb0MqabAF+JUBq+ijBvNMUxpkLjJaAu32faIexewMumrH5KLLJ1HDyT0PTEqRyAe/GwwuQ== + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + integrity sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-check-es2015-constants@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" + integrity sha512-B1M5KBP29248dViEo1owyY32lk1ZSH2DaNNrXLGt8lyjjHm7pBqAdQ7VKUPR6EEDO323+OvT3MQXbCin8ooWdA== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-syntax-async-functions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" + integrity sha512-4Zp4unmHgw30A1eWI5EpACji2qMocisdXhAftfhXoSV9j0Tvj6nRFE3tOmRY912E0FMRm/L5xWE7MGVT2FoLnw== + +babel-plugin-syntax-exponentiation-operator@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" + integrity sha512-Z/flU+T9ta0aIEKl1tGEmN/pZiI1uXmCiGFRegKacQfEJzp7iNsKloZmyJlQr+75FCJtiFfGIK03SiCvCt9cPQ== + +babel-plugin-syntax-trailing-function-commas@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" + integrity sha512-Gx9CH3Q/3GKbhs07Bszw5fPTlU+ygrOGfAhEt7W2JICwufpC4SuO0mG0+4NykPBSYPMJhqvVlDBU17qB1D+hMQ== + +babel-plugin-transform-async-to-generator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" + integrity sha512-7BgYJujNCg0Ti3x0c/DL3tStvnKS6ktIYOmo9wginv/dfZOrbSZ+qG4IRRHMBOzZ5Awb1skTiAsQXg/+IWkZYw== + dependencies: + babel-helper-remap-async-to-generator "^6.24.1" + babel-plugin-syntax-async-functions "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-arrow-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" + integrity sha512-PCqwwzODXW7JMrzu+yZIaYbPQSKjDTAsNNlK2l5Gg9g4rz2VzLnZsStvp/3c46GfXpwkyufb3NCyG9+50FF1Vg== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" + integrity sha512-2+ujAT2UMBzYFm7tidUsYh+ZoIutxJ3pN9IYrF1/H6dCKtECfhmB8UkHVpyxDwkj0CYbQG35ykoz925TUnBc3A== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoping@^6.23.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" + integrity sha512-YiN6sFAQ5lML8JjCmr7uerS5Yc/EMbgg9G8ZNmk2E3nYX4ckHR01wrkeeMijEf5WHNK5TW0Sl0Uu3pv3EdOJWw== + dependencies: + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-plugin-transform-es2015-classes@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" + integrity sha512-5Dy7ZbRinGrNtmWpquZKZ3EGY8sDgIVB4CU8Om8q8tnMLrD/m94cKglVcHps0BCTdZ0TJeeAWOq2TK9MIY6cag== + dependencies: + babel-helper-define-map "^6.24.1" + babel-helper-function-name "^6.24.1" + babel-helper-optimise-call-expression "^6.24.1" + babel-helper-replace-supers "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-computed-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" + integrity sha512-C/uAv4ktFP/Hmh01gMTvYvICrKze0XVX9f2PdIXuriCSvUmV9j+u+BB9f5fJK3+878yMK6dkdcq+Ymr9mrcLzw== + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-destructuring@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" + integrity sha512-aNv/GDAW0j/f4Uy1OEPZn1mqD+Nfy9viFGBfQ5bZyT35YqOiqx7/tXdyfZkJ1sC21NyEsBdfDY6PYmLHF4r5iA== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-duplicate-keys@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" + integrity sha512-ossocTuPOssfxO2h+Z3/Ea1Vo1wWx31Uqy9vIiJusOP4TbF7tPs9U0sJ9pX9OJPf4lXRGj5+6Gkl/HHKiAP5ug== + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-for-of@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" + integrity sha512-DLuRwoygCoXx+YfxHLkVx5/NpeSbVwfoTeBykpJK7JhYWlL/O8hgAK/reforUnZDlxasOrVPPJVI/guE3dCwkw== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-function-name@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" + integrity sha512-iFp5KIcorf11iBqu/y/a7DK3MN5di3pNCzto61FqCNnUX4qeBwcV1SLqe10oXNnCaxBUImX3SckX2/o1nsrTcg== + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" + integrity sha512-tjFl0cwMPpDYyoqYA9li1/7mGFit39XiNX5DKC/uCNjBctMxyL1/PT/l4rSlbvBG1pOKI88STRdUsWXB3/Q9hQ== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" + integrity sha512-LnIIdGWIKdw7zwckqx+eGjcS8/cl8D74A3BpJbGjKTFFNJSMrjN4bIh22HY1AlkUbeLG6X6OZj56BDvWD+OeFA== + dependencies: + babel-plugin-transform-es2015-modules-commonjs "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: + version "6.26.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" + integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== + dependencies: + babel-plugin-transform-strict-mode "^6.24.1" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-types "^6.26.0" + +babel-plugin-transform-es2015-modules-systemjs@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" + integrity sha512-ONFIPsq8y4bls5PPsAWYXH/21Hqv64TBxdje0FvU3MhIV6QM2j5YS7KvAzg/nTIVLot2D2fmFQrFWCbgHlFEjg== + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-umd@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" + integrity sha512-LpVbiT9CLsuAIp3IG0tfbVo81QIhn6pE8xBJ7XSeCtFlMltuar5VuBV6y6Q45tpui9QWcy5i0vLQfCfrnF7Kiw== + dependencies: + babel-plugin-transform-es2015-modules-amd "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-object-super@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" + integrity sha512-8G5hpZMecb53vpD3mjs64NhI1au24TAmokQ4B+TBFBjN9cVoGoOvotdrMMRmHvVZUEvqGUPWL514woru1ChZMA== + dependencies: + babel-helper-replace-supers "^6.24.1" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-parameters@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" + integrity sha512-8HxlW+BB5HqniD+nLkQ4xSAVq3bR/pcYW9IigY+2y0dI+Y7INFeTbfAQr+63T3E4UDsZGjyb+l9txUnABWxlOQ== + dependencies: + babel-helper-call-delegate "^6.24.1" + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-shorthand-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" + integrity sha512-mDdocSfUVm1/7Jw/FIRNw9vPrBQNePy6wZJlR8HAUBLybNp1w/6lr6zZ2pjMShee65t/ybR5pT8ulkLzD1xwiw== + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-spread@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" + integrity sha512-3Ghhi26r4l3d0Js933E5+IhHwk0A1yiutj9gwvzmFbVV0sPMYk2lekhOufHBswX7NCoSeF4Xrl3sCIuSIa+zOg== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-sticky-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" + integrity sha512-CYP359ADryTo3pCsH0oxRo/0yn6UsEZLqYohHmvLQdfS9xkf+MbCzE3/Kolw9OYIY4ZMilH25z/5CbQbwDD+lQ== + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-template-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" + integrity sha512-x8b9W0ngnKzDMHimVtTfn5ryimars1ByTqsfBDwAqLibmuuQY6pgBQi5z1ErIsUOWBdw1bW9FSz5RZUojM4apg== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-typeof-symbol@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" + integrity sha512-fz6J2Sf4gYN6gWgRZaoFXmq93X+Li/8vf+fb0sGDVtdeWvxC9y5/bTD7bvfWMEq6zetGEHpWjtzRGSugt5kNqw== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-unicode-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" + integrity sha512-v61Dbbihf5XxnYjtBN04B/JBvsScY37R1cZT5r9permN1cp+b70DY3Ib3fIkgn1DI9U3tGgBJZVD8p/mE/4JbQ== + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + regexpu-core "^2.0.0" + +babel-plugin-transform-exponentiation-operator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" + integrity sha512-LzXDmbMkklvNhprr20//RStKVcT8Cu+SQtX18eMHLhjHf2yFzwtQ0S2f0jQ+89rokoNdmwoSqYzAhq86FxlLSQ== + dependencies: + babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" + babel-plugin-syntax-exponentiation-operator "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-regenerator@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" + integrity sha512-LS+dBkUGlNR15/5WHKe/8Neawx663qttS6AGqoOUhICc9d1KciBvtrQSuc0PI+CxQ2Q/S1aKuJ+u64GtLdcEZg== + dependencies: + regenerator-transform "^0.10.0" + +babel-plugin-transform-strict-mode@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" + integrity sha512-j3KtSpjyLSJxNoCDrhwiJad8kw0gJ9REGj8/CqL0HeRyLnvUNYV9zcqluL6QJSXh3nfsLEmSLvwRfGzrgR96Pw== + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-preset-env@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" + integrity sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg== + dependencies: + babel-plugin-check-es2015-constants "^6.22.0" + babel-plugin-syntax-trailing-function-commas "^6.22.0" + babel-plugin-transform-async-to-generator "^6.22.0" + babel-plugin-transform-es2015-arrow-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoping "^6.23.0" + babel-plugin-transform-es2015-classes "^6.23.0" + babel-plugin-transform-es2015-computed-properties "^6.22.0" + babel-plugin-transform-es2015-destructuring "^6.23.0" + babel-plugin-transform-es2015-duplicate-keys "^6.22.0" + babel-plugin-transform-es2015-for-of "^6.23.0" + babel-plugin-transform-es2015-function-name "^6.22.0" + babel-plugin-transform-es2015-literals "^6.22.0" + babel-plugin-transform-es2015-modules-amd "^6.22.0" + babel-plugin-transform-es2015-modules-commonjs "^6.23.0" + babel-plugin-transform-es2015-modules-systemjs "^6.23.0" + babel-plugin-transform-es2015-modules-umd "^6.23.0" + babel-plugin-transform-es2015-object-super "^6.22.0" + babel-plugin-transform-es2015-parameters "^6.23.0" + babel-plugin-transform-es2015-shorthand-properties "^6.22.0" + babel-plugin-transform-es2015-spread "^6.22.0" + babel-plugin-transform-es2015-sticky-regex "^6.22.0" + babel-plugin-transform-es2015-template-literals "^6.22.0" + babel-plugin-transform-es2015-typeof-symbol "^6.23.0" + babel-plugin-transform-es2015-unicode-regex "^6.22.0" + babel-plugin-transform-exponentiation-operator "^6.22.0" + babel-plugin-transform-regenerator "^6.22.0" + browserslist "^3.2.6" + invariant "^2.2.2" + semver "^5.3.0" + +babel-register@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" + integrity sha512-veliHlHX06wjaeY8xNITbveXSiI+ASFnOqvne/LaIJIqOWi2Ogmj91KOugEz/hoh/fwMhXNBJPCv8Xaz5CyM4A== + dependencies: + babel-core "^6.26.0" + babel-runtime "^6.26.0" + core-js "^2.5.0" + home-or-tmp "^2.0.0" + lodash "^4.17.4" + mkdirp "^0.5.1" + source-map-support "^0.4.15" + +babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + integrity sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g== + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-template@^6.24.1, babel-template@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + integrity sha512-PCOcLFW7/eazGUKIoqH97sO9A2UYMahsn/yRQ7uOk37iutwjq7ODtcTNF+iFDSHNfkctqsLRjLP7URnOx0T1fg== + dependencies: + babel-runtime "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + lodash "^4.17.4" + +babel-traverse@^6.24.1, babel-traverse@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + integrity sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA== + dependencies: + babel-code-frame "^6.26.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + debug "^2.6.8" + globals "^9.18.0" + invariant "^2.2.2" + lodash "^4.17.4" + +babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + integrity sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g== + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babelify@^7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/babelify/-/babelify-7.3.0.tgz#aa56aede7067fd7bd549666ee16dc285087e88e5" + integrity sha512-vID8Fz6pPN5pJMdlUnNFSfrlcx5MUule4k9aKs/zbZPyXxMTcRrB0M4Tarw22L8afr8eYSWxDPYCob3TdrqtlA== + dependencies: + babel-core "^6.0.14" + object-assign "^4.0.0" + +babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== + +backoff@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f" + integrity sha512-wC5ihrnUXmR2douXmXLCe5O3zg3GKIyvRi/hi58a/XyRxVI+3/yM0PYueQOZXPXQ9pxBislYkw+sF9b7C/RuMA== + dependencies: + precond "0.2" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base-x@^3.0.2, base-x@^3.0.8: + version "3.0.9" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" + integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== + dependencies: + safe-buffer "^5.0.1" + +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== + dependencies: + tweetnacl "^0.14.3" + +bech32@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== + +bigint-crypto-utils@^3.0.23: + version "3.1.8" + resolved "https://registry.yarnpkg.com/bigint-crypto-utils/-/bigint-crypto-utils-3.1.8.tgz#e2e0f40cf45488f9d7f0e32ff84152aa73819d5d" + integrity sha512-+VMV9Laq8pXLBKKKK49nOoq9bfR3j7NNQAtbA617a4nw9bVLo8rsqkKMBgM2AJWlNX9fEIyYaYX+d0laqYV4tw== + dependencies: + bigint-mod-arith "^3.1.0" + +bigint-mod-arith@^3.1.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bigint-mod-arith/-/bigint-mod-arith-3.1.2.tgz#658e416bc593a463d97b59766226d0a3021a76b1" + integrity sha512-nx8J8bBeiRR+NlsROFH9jHswW5HO8mgfOSqW0AmjicMMvaONDa8AO+5ViKDUUNytBPWiwfvZP4/Bj4Y3lUfvgQ== + +bignumber.js@^9.0.0: + version "9.1.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.1.tgz#c4df7dc496bd849d4c9464344c1aa74228b4dac6" + integrity sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +bip39@2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.5.0.tgz#51cbd5179460504a63ea3c000db3f787ca051235" + integrity sha512-xwIx/8JKoT2+IPJpFEfXoWdYwP7UVAoUxxLNfGCfVowaJE7yg1Y5B1BVPqlUNsBq5/nGwmFkwRJ8xDW4sX8OdA== + dependencies: + create-hash "^1.1.0" + pbkdf2 "^3.0.9" + randombytes "^2.0.1" + safe-buffer "^5.0.1" + unorm "^1.3.3" + +blakejs@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" + integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== + +bluebird@^3.5.0, bluebird@^3.5.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + +bn.js@4.11.6: + version "4.11.6" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" + integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA== + +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.11.9, bn.js@^4.8.0: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^5.0.0, bn.js@^5.1.1, bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + +body-parser@1.20.1, body-parser@^1.16.0: + version "1.20.1" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" + integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== + dependencies: + bytes "3.1.2" + content-type "~1.0.4" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.11.0" + raw-body "2.5.1" + type-is "~1.6.18" + unpipe "1.0.0" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +braces@^3.0.2, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +brorand@^1.0.1, brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== + +browser-level@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browser-level/-/browser-level-1.0.1.tgz#36e8c3183d0fe1c405239792faaab5f315871011" + integrity sha512-XECYKJ+Dbzw0lbydyQuJzwNXtOpbMSq737qxJN11sIRTErOMShvDpbzTlgju7orJKvx4epULolZAuJGLzCmWRQ== + dependencies: + abstract-level "^1.0.2" + catering "^2.1.1" + module-error "^1.0.2" + run-parallel-limit "^1.1.0" + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" + integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== + dependencies: + bn.js "^5.0.0" + randombytes "^2.0.1" + +browserify-sign@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" + integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== + dependencies: + bn.js "^5.1.1" + browserify-rsa "^4.0.1" + create-hash "^1.2.0" + create-hmac "^1.1.7" + elliptic "^6.5.3" + inherits "^2.0.4" + parse-asn1 "^5.1.5" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +browserslist@^3.2.6: + version "3.2.8" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" + integrity sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ== + dependencies: + caniuse-lite "^1.0.30000844" + electron-to-chromium "^1.3.47" + +bs58@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" + integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== + dependencies: + base-x "^3.0.2" + +bs58check@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" + integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== + dependencies: + bs58 "^4.0.0" + create-hash "^1.1.0" + safe-buffer "^5.1.2" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer-to-arraybuffer@^0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz#6064a40fa76eb43c723aba9ef8f6e1216d10511a" + integrity sha512-3dthu5CYiVB1DEJp61FtApNnNndTckcqe4pFcLdvHtrpG+kcyekCJKg4MRiDcFW7A6AODnXB9U4dwQiCW5kzJQ== + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== + +buffer-xor@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-2.0.2.tgz#34f7c64f04c777a1f8aac5e661273bb9dd320289" + integrity sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ== + dependencies: + safe-buffer "^5.1.1" + +buffer@^5.0.5, buffer@^5.2.1, buffer@^5.5.0, buffer@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + +bufferutil@^4.0.1: + version "4.0.7" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.7.tgz#60c0d19ba2c992dd8273d3f73772ffc894c153ad" + integrity sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw== + dependencies: + node-gyp-build "^4.3.0" + +busboy@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" + integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== + dependencies: + streamsearch "^1.1.0" + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +bytewise-core@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/bytewise-core/-/bytewise-core-1.2.3.tgz#3fb410c7e91558eb1ab22a82834577aa6bd61d42" + integrity sha512-nZD//kc78OOxeYtRlVk8/zXqTB4gf/nlguL1ggWA8FuchMyOxcyHR4QPQZMUmA7czC+YnaBrPUCubqAWe50DaA== + dependencies: + typewise-core "^1.2" + +bytewise@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/bytewise/-/bytewise-1.1.0.tgz#1d13cbff717ae7158094aa881b35d081b387253e" + integrity sha512-rHuuseJ9iQ0na6UDhnrRVDh8YnWVlU6xM3VH6q/+yHDeUH2zIhUzP+2/h3LIrhLDBtTqzWpE3p3tP/boefskKQ== + dependencies: + bytewise-core "^1.2.2" + typewise "^1.0.3" + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +cacheable-lookup@^5.0.3: + version "5.0.4" + resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" + integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA== + +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" + integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^1.0.2" + +cacheable-request@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.2.tgz#ea0d0b889364a25854757301ca12b2da77f91d27" + integrity sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^4.0.0" + lowercase-keys "^2.0.0" + normalize-url "^6.0.1" + responselike "^2.0.0" + +cachedown@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cachedown/-/cachedown-1.0.0.tgz#d43f036e4510696b31246d7db31ebf0f7ac32d15" + integrity sha512-t+yVk82vQWCJF3PsWHMld+jhhjkkWjcAzz8NbFx1iULOXWl8Tm/FdM4smZNVw3MRr0X+lVTx9PKzvEn4Ng19RQ== + dependencies: + abstract-leveldown "^2.4.1" + lru-cache "^3.2.0" + +call-bind@^1.0.0, call-bind@^1.0.2, call-bind@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +camelcase@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" + integrity sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg== + +camelcase@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-lite@^1.0.30000844: + version "1.0.30001450" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001450.tgz#022225b91200589196b814b51b1bbe45144cf74f" + integrity sha512-qMBmvmQmFXaSxexkjjfMvD5rnDL0+m+dUMZKoDYsGG8iZN29RuYh9eRoMvKsT6uMAWlyUUGDEQGJJYjzCIO9ew== + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== + +catering@^2.1.0, catering@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/catering/-/catering-2.1.1.tgz#66acba06ed5ee28d5286133982a927de9a04b510" + integrity sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w== + +cbor@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/cbor/-/cbor-8.1.0.tgz#cfc56437e770b73417a2ecbfc9caf6b771af60d5" + integrity sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg== + dependencies: + nofilter "^3.1.0" + +chai@^4.3.6: + version "4.3.7" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" + integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^4.1.2" + get-func-name "^2.0.0" + loupe "^2.3.1" + pathval "^1.1.1" + type-detect "^4.0.5" + +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.4.1, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.1.0, chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +check-error@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== + +checkpoint-store@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06" + integrity sha512-J/NdY2WvIx654cc6LWSq/IYFFCUf75fFTgwzFnmbqyORH4MwgiQCgswLLKBGzmsyTI5V7i5bp/So6sMbDWhedg== + dependencies: + functional-red-black-tree "^1.0.1" + +chokidar@3.5.3, chokidar@^3.4.0, chokidar@^3.5.2: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chownr@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +cids@^0.7.1: + version "0.7.5" + resolved "https://registry.yarnpkg.com/cids/-/cids-0.7.5.tgz#60a08138a99bfb69b6be4ceb63bfef7a396b28b2" + integrity sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA== + dependencies: + buffer "^5.5.0" + class-is "^1.1.0" + multibase "~0.6.0" + multicodec "^1.0.0" + multihashes "~0.4.15" + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +class-is@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/class-is/-/class-is-1.1.0.tgz#9d3c0fba0440d211d843cec3dedfa48055005825" + integrity sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw== + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +classic-level@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/classic-level/-/classic-level-1.2.0.tgz#2d52bdec8e7a27f534e67fdeb890abef3e643c27" + integrity sha512-qw5B31ANxSluWz9xBzklRWTUAJ1SXIdaVKTVS7HcTGKOAmExx65Wo5BUICW+YGORe2FOUaDghoI9ZDxj82QcFg== + dependencies: + abstract-level "^1.0.2" + catering "^2.1.0" + module-error "^1.0.1" + napi-macros "~2.0.0" + node-gyp-build "^4.3.0" + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cliui@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + integrity sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w== + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +clone-response@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3" + integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA== + dependencies: + mimic-response "^1.0.0" + +clone@2.1.2, clone@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w== + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA== + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw== + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +command-exists@^1.2.8: + version "1.2.9" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== + +command-line-args@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-4.0.7.tgz#f8d1916ecb90e9e121eda6428e41300bfb64cc46" + integrity sha512-aUdPvQRAyBvQd2n7jXcsMDz68ckBJELXNzBybCHOibUWEg0mWTnaYCSRU8h9R+aNRSvDihJtssSRCiDRpLaezA== + dependencies: + array-back "^2.0.0" + find-replace "^1.0.3" + typical "^2.6.1" + +command-line-args@^5.1.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.1.tgz#c44c32e437a57d7c51157696893c5909e9cec42e" + integrity sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg== + dependencies: + array-back "^3.1.0" + find-replace "^3.0.0" + lodash.camelcase "^4.3.0" + typical "^4.0.0" + +command-line-usage@^6.1.0: + version "6.1.3" + resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-6.1.3.tgz#428fa5acde6a838779dfa30e44686f4b6761d957" + integrity sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw== + dependencies: + array-back "^4.0.2" + chalk "^2.4.2" + table-layout "^1.0.2" + typical "^5.2.0" + +commander@3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" + integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== + +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +concat-stream@^1.5.1: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-hash@^2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/content-hash/-/content-hash-2.5.2.tgz#bbc2655e7c21f14fd3bfc7b7d4bfe6e454c9e211" + integrity sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw== + dependencies: + cids "^0.7.1" + multicodec "^0.5.5" + multihashes "^0.4.15" + +content-type@~1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + +convert-source-map@^1.5.1: + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + +cookie@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== + +cookie@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + +cookiejar@^2.1.1: + version "2.1.4" + resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.4.tgz#ee669c1fea2cf42dc31585469d193fef0d65771b" + integrity sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw== + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== + +core-js-pure@^3.0.1: + version "3.27.2" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.27.2.tgz#47e9cc96c639eefc910da03c3ece26c5067c7553" + integrity sha512-Cf2jqAbXgWH3VVzjyaaFkY1EBazxugUepGymDoeteyYr9ByX51kD2jdHZlsEF/xnJMyN3Prua7mQuzwMg6Zc9A== + +core-js@^2.4.0, core-js@^2.5.0: + version "2.6.12" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" + integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== + +core-util-is@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cors@^2.8.1: + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + +crc-32@^1.2.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" + integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== + +create-ecdh@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" + integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== + dependencies: + bn.js "^4.1.0" + elliptic "^6.5.3" + +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +cross-fetch@^2.1.0, cross-fetch@^2.1.1: + version "2.2.6" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-2.2.6.tgz#2ef0bb39a24ac034787965c457368a28730e220a" + integrity sha512-9JZz+vXCmfKUZ68zAptS7k4Nu8e2qcibe7WVZYps7sAgk5R8GYTc+T1WR0v1rlP9HxgARmOX1UTIJZFytajpNA== + dependencies: + node-fetch "^2.6.7" + whatwg-fetch "^2.0.4" + +cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +crypto-browserify@3.12.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== + dependencies: + browserify-cipher "^1.0.0" + browserify-sign "^4.0.0" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "^3.0.3" + public-encrypt "^4.0.0" + randombytes "^2.0.0" + randomfill "^1.0.3" + +csv-parser@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/csv-parser/-/csv-parser-3.0.0.tgz#b88a6256d79e090a97a1b56451f9327b01d710e7" + integrity sha512-s6OYSXAK3IdKqYO33y09jhypG/bSDHPuyCme/IdEHfWpLf/jKcpitVFyOC6UemgGk8v7Q5u2XE0vvwmanxhGlQ== + dependencies: + minimist "^1.2.0" + +csv-writer@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/csv-writer/-/csv-writer-1.6.0.tgz#d0cea44b6b4d7d3baa2ecc6f3f7209233514bcf9" + integrity sha512-NOx7YDFWEsM/fTRAJjRpPp8t+MKRVvniAg9wQlUKx20MFrPs73WLJhFf5iteqrxNYnsy924K3Iroh3yNHeYd2g== + +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== + dependencies: + assert-plus "^1.0.0" + +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +debug@4, debug@4.3.4, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +debug@^3.1.0: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +decamelize@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +decode-uri-component@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== + +decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA== + dependencies: + mimic-response "^1.0.0" + +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== + dependencies: + mimic-response "^3.1.0" + +deep-eql@^4.1.2: + version "4.1.3" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" + integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== + dependencies: + type-detect "^4.0.0" + +deep-equal@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" + integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== + dependencies: + is-arguments "^1.0.4" + is-date-object "^1.0.1" + is-regex "^1.0.4" + object-is "^1.0.1" + object-keys "^1.1.1" + regexp.prototype.flags "^1.2.0" + +deep-extend@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +defer-to-connect@^1.0.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" + integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== + +defer-to-connect@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" + integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== + +deferred-leveldown@~1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz#3acd2e0b75d1669924bc0a4b642851131173e1eb" + integrity sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA== + dependencies: + abstract-leveldown "~2.6.0" + +deferred-leveldown@~4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz#0b0570087827bf480a23494b398f04c128c19a20" + integrity sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww== + dependencies: + abstract-leveldown "~5.0.0" + inherits "^2.0.3" + +define-properties@^1.1.3, define-properties@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" + integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== + dependencies: + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA== + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA== + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +defined@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.1.tgz#c0b9db27bfaffd95d6f61399419b893df0f91ebf" + integrity sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q== + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +delete-empty@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/delete-empty/-/delete-empty-3.0.0.tgz#f8040f2669f26fa7060bc2304e9859c593b685e8" + integrity sha512-ZUyiwo76W+DYnKsL3Kim6M/UOavPdBJgDYWOmuQhYaZvJH0AXAHbUNyEDtRbBra8wqqr686+63/0azfEk1ebUQ== + dependencies: + ansi-colors "^4.1.0" + minimist "^1.2.0" + path-starts-with "^2.0.0" + rimraf "^2.6.2" + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +des.js@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" + integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + integrity sha512-BDKtmHlOzwI7iRuEkhzsnPoi5ypEhWAJB5RvHWe1kMr06js3uK5B3734i3ui5Yd+wOJV1cpE4JnivPD283GU/A== + dependencies: + repeating "^2.0.0" + +diff@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +diffie-hellman@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +dom-walk@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" + integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w== + +dotenv@^16.0.0: + version "16.0.3" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" + integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== + +dotignore@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/dotignore/-/dotignore-0.1.2.tgz#f942f2200d28c3a76fbdd6f0ee9f3257c8a2e905" + integrity sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw== + dependencies: + minimatch "^3.0.4" + +duplexer3@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e" + integrity sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA== + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +electron-to-chromium@^1.3.47: + version "1.4.286" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.286.tgz#0e039de59135f44ab9a8ec9025e53a9135eba11f" + integrity sha512-Vp3CVhmYpgf4iXNKAucoQUDcCrBQX3XLBtwgFqP9BUXuucgvAV9zWp1kYU7LL9j4++s9O+12cb3wMtN4SJy6UQ== + +elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5.4: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +encode-utf8@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda" + integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +encoding-down@5.0.4, encoding-down@~5.0.0: + version "5.0.4" + resolved "https://registry.yarnpkg.com/encoding-down/-/encoding-down-5.0.4.tgz#1e477da8e9e9d0f7c8293d320044f8b2cd8e9614" + integrity sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw== + dependencies: + abstract-leveldown "^5.0.0" + inherits "^2.0.3" + level-codec "^9.0.0" + level-errors "^2.0.0" + xtend "^4.0.1" + +encoding@^0.1.11: + version "0.1.13" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" + integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== + dependencies: + iconv-lite "^0.6.2" + +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +enquirer@^2.3.0, enquirer@^2.3.6: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + +env-paths@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + +errno@~0.1.1: + version "0.1.8" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" + integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== + dependencies: + prr "~1.0.1" + +error-ex@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.19.0, es-abstract@^1.20.4: + version "1.21.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.1.tgz#e6105a099967c08377830a0c9cb589d570dd86c6" + integrity sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + es-set-tostringtag "^2.0.1" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + function.prototype.name "^1.1.5" + get-intrinsic "^1.1.3" + get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" + has "^1.0.3" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.4" + is-array-buffer "^3.0.1" + is-callable "^1.2.7" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-typed-array "^1.1.10" + is-weakref "^1.0.2" + object-inspect "^1.12.2" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.4.3" + safe-regex-test "^1.0.0" + string.prototype.trimend "^1.0.6" + string.prototype.trimstart "^1.0.6" + typed-array-length "^1.0.4" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.9" + +es-array-method-boxes-properly@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" + integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== + +es-set-tostringtag@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" + integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + has-tostringtag "^1.0.0" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +es5-ext@^0.10.35, es5-ext@^0.10.50: + version "0.10.62" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.62.tgz#5e6adc19a6da524bf3d1e02bbc8960e5eb49a9a5" + integrity sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA== + dependencies: + es6-iterator "^2.0.3" + es6-symbol "^3.1.3" + next-tick "^1.1.0" + +es6-iterator@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@^3.1.1, es6-symbol@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" + integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== + dependencies: + d "^1.0.1" + ext "^1.1.2" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +escape-string-regexp@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +eth-block-tracker@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-3.0.1.tgz#95cd5e763c7293e0b1b2790a2a39ac2ac188a5e1" + integrity sha512-WUVxWLuhMmsfenfZvFO5sbl1qFY2IqUlw/FPVmjjdElpqLsZtSG+wPe9Dz7W/sB6e80HgFKknOmKk2eNlznHug== + dependencies: + eth-query "^2.1.0" + ethereumjs-tx "^1.3.3" + ethereumjs-util "^5.1.3" + ethjs-util "^0.1.3" + json-rpc-engine "^3.6.0" + pify "^2.3.0" + tape "^4.6.3" + +eth-ens-namehash@2.0.8, eth-ens-namehash@^2.0.8: + version "2.0.8" + resolved "https://registry.yarnpkg.com/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz#229ac46eca86d52e0c991e7cb2aef83ff0f68bcf" + integrity sha512-VWEI1+KJfz4Km//dadyvBBoBeSQ0MHTXPvr8UIXiLW6IanxvAV+DmlZAijZwAyggqGUfwQBeHf7tc9wzc1piSw== + dependencies: + idna-uts46-hx "^2.3.1" + js-sha3 "^0.5.7" + +eth-json-rpc-infura@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/eth-json-rpc-infura/-/eth-json-rpc-infura-3.2.1.tgz#26702a821067862b72d979c016fd611502c6057f" + integrity sha512-W7zR4DZvyTn23Bxc0EWsq4XGDdD63+XPUCEhV2zQvQGavDVC4ZpFDK4k99qN7bd7/fjj37+rxmuBOBeIqCA5Mw== + dependencies: + cross-fetch "^2.1.1" + eth-json-rpc-middleware "^1.5.0" + json-rpc-engine "^3.4.0" + json-rpc-error "^2.0.0" + +eth-json-rpc-middleware@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz#5c9d4c28f745ccb01630f0300ba945f4bef9593f" + integrity sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q== + dependencies: + async "^2.5.0" + eth-query "^2.1.2" + eth-tx-summary "^3.1.2" + ethereumjs-block "^1.6.0" + ethereumjs-tx "^1.3.3" + ethereumjs-util "^5.1.2" + ethereumjs-vm "^2.1.0" + fetch-ponyfill "^4.0.0" + json-rpc-engine "^3.6.0" + json-rpc-error "^2.0.0" + json-stable-stringify "^1.0.1" + promise-to-callback "^1.0.0" + tape "^4.6.3" + +eth-lib@0.2.8: + version "0.2.8" + resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.8.tgz#b194058bef4b220ad12ea497431d6cb6aa0623c8" + integrity sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw== + dependencies: + bn.js "^4.11.6" + elliptic "^6.4.0" + xhr-request-promise "^0.1.2" + +eth-lib@^0.1.26: + version "0.1.29" + resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.29.tgz#0c11f5060d42da9f931eab6199084734f4dbd1d9" + integrity sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ== + dependencies: + bn.js "^4.11.6" + elliptic "^6.4.0" + nano-json-stream-parser "^0.1.2" + servify "^0.1.12" + ws "^3.0.0" + xhr-request-promise "^0.1.2" + +eth-query@^2.0.2, eth-query@^2.1.0, eth-query@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/eth-query/-/eth-query-2.1.2.tgz#d6741d9000106b51510c72db92d6365456a6da5e" + integrity sha512-srES0ZcvwkR/wd5OQBRA1bIJMww1skfGS0s8wlwK3/oNP4+wnds60krvu5R1QbpRQjMmpG5OMIWro5s7gvDPsA== + dependencies: + json-rpc-random-id "^1.0.0" + xtend "^4.0.1" + +eth-sig-util@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-3.0.0.tgz#75133b3d7c20a5731af0690c385e184ab942b97e" + integrity sha512-4eFkMOhpGbTxBQ3AMzVf0haUX2uTur7DpWiHzWyTURa28BVJJtOkcb9Ok5TV0YvEPG61DODPW7ZUATbJTslioQ== + dependencies: + buffer "^5.2.1" + elliptic "^6.4.0" + ethereumjs-abi "0.6.5" + ethereumjs-util "^5.1.1" + tweetnacl "^1.0.0" + tweetnacl-util "^0.15.0" + +eth-sig-util@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.2.tgz#8d958202c7edbaae839707fba6f09ff327606210" + integrity sha512-iNZ576iTOGcfllftB73cPB5AN+XUQAT/T8xzsILsghXC1o8gJUqe3RHlcDqagu+biFpYQ61KQrZZJza8eRSYqw== + dependencies: + ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" + ethereumjs-util "^5.1.1" + +eth-tx-summary@^3.1.2: + version "3.2.4" + resolved "https://registry.yarnpkg.com/eth-tx-summary/-/eth-tx-summary-3.2.4.tgz#e10eb95eb57cdfe549bf29f97f1e4f1db679035c" + integrity sha512-NtlDnaVZah146Rm8HMRUNMgIwG/ED4jiqk0TME9zFheMl1jOp6jL1m0NKGjJwehXQ6ZKCPr16MTr+qspKpEXNg== + dependencies: + async "^2.1.2" + clone "^2.0.0" + concat-stream "^1.5.1" + end-of-stream "^1.1.0" + eth-query "^2.0.2" + ethereumjs-block "^1.4.1" + ethereumjs-tx "^1.1.1" + ethereumjs-util "^5.0.1" + ethereumjs-vm "^2.6.0" + through2 "^2.0.3" + +ethashjs@~0.0.7: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ethashjs/-/ethashjs-0.0.8.tgz#227442f1bdee409a548fb04136e24c874f3aa6f9" + integrity sha512-/MSbf/r2/Ld8o0l15AymjOTlPqpN8Cr4ByUEA9GtR4x0yAh3TdtDzEg29zMjXCNPI7u6E5fOQdj/Cf9Tc7oVNw== + dependencies: + async "^2.1.2" + buffer-xor "^2.0.1" + ethereumjs-util "^7.0.2" + miller-rabin "^4.0.0" + +ethereum-bloom-filters@^1.0.6: + version "1.0.10" + resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz#3ca07f4aed698e75bd134584850260246a5fed8a" + integrity sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA== + dependencies: + js-sha3 "^0.8.0" + +ethereum-common@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.2.0.tgz#13bf966131cce1eeade62a1b434249bb4cb120ca" + integrity sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA== + +ethereum-common@^0.0.18: + version "0.0.18" + resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" + integrity sha512-EoltVQTRNg2Uy4o84qpa2aXymXDJhxm7eos/ACOg0DG4baAbMjhbdAEsx9GeE8sC3XCxnYvrrzZDH8D8MtA2iQ== + +ethereum-cryptography@0.1.3, ethereum-cryptography@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" + integrity sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ== + dependencies: + "@types/pbkdf2" "^3.0.0" + "@types/secp256k1" "^4.0.1" + blakejs "^1.1.0" + browserify-aes "^1.2.0" + bs58check "^2.1.2" + create-hash "^1.2.0" + create-hmac "^1.1.7" + hash.js "^1.1.7" + keccak "^3.0.0" + pbkdf2 "^3.0.17" + randombytes "^2.1.0" + safe-buffer "^5.1.2" + scrypt-js "^3.0.0" + secp256k1 "^4.0.1" + setimmediate "^1.0.5" + +ethereum-cryptography@^1.0.3: + version "1.1.2" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-1.1.2.tgz#74f2ac0f0f5fe79f012c889b3b8446a9a6264e6d" + integrity sha512-XDSJlg4BD+hq9N2FjvotwUET9Tfxpxc3kWGE2AqUG5vcbeunnbImVk3cj6e/xT3phdW21mE8R5IugU4fspQDcQ== + dependencies: + "@noble/hashes" "1.1.2" + "@noble/secp256k1" "1.6.3" + "@scure/bip32" "1.1.0" + "@scure/bip39" "1.1.0" + +ethereum-waffle@^3.4.0: + version "3.4.4" + resolved "https://registry.yarnpkg.com/ethereum-waffle/-/ethereum-waffle-3.4.4.tgz#1378b72040697857b7f5e8f473ca8f97a37b5840" + integrity sha512-PA9+jCjw4WC3Oc5ocSMBj5sXvueWQeAbvCA+hUlb6oFgwwKyq5ka3bWQ7QZcjzIX+TdFkxP4IbFmoY2D8Dkj9Q== + dependencies: + "@ethereum-waffle/chai" "^3.4.4" + "@ethereum-waffle/compiler" "^3.4.4" + "@ethereum-waffle/mock-contract" "^3.4.4" + "@ethereum-waffle/provider" "^3.4.4" + ethers "^5.0.1" + +ethereumjs-abi@0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz#5a637ef16ab43473fa72a29ad90871405b3f5241" + integrity sha512-rCjJZ/AE96c/AAZc6O3kaog4FhOsAViaysBxqJNy2+LHP0ttH0zkZ7nXdVHOAyt6lFwLO0nlCwWszysG/ao1+g== + dependencies: + bn.js "^4.10.0" + ethereumjs-util "^4.3.0" + +ethereumjs-abi@0.6.8, ethereumjs-abi@^0.6.8: + version "0.6.8" + resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae" + integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== + dependencies: + bn.js "^4.11.8" + ethereumjs-util "^6.0.0" + +"ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git": + version "0.6.8" + resolved "git+https://github.com/ethereumjs/ethereumjs-abi.git#ee3994657fa7a427238e6ba92a84d0b529bbcde0" + dependencies: + bn.js "^4.11.8" + ethereumjs-util "^6.0.0" + +ethereumjs-account@3.0.0, ethereumjs-account@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-3.0.0.tgz#728f060c8e0c6e87f1e987f751d3da25422570a9" + integrity sha512-WP6BdscjiiPkQfF9PVfMcwx/rDvfZTjFKY0Uwc09zSQr9JfIVH87dYIJu0gNhBhpmovV4yq295fdllS925fnBA== + dependencies: + ethereumjs-util "^6.0.0" + rlp "^2.2.1" + safe-buffer "^5.1.1" + +ethereumjs-account@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz#eeafc62de544cb07b0ee44b10f572c9c49e00a84" + integrity sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA== + dependencies: + ethereumjs-util "^5.0.0" + rlp "^2.0.0" + safe-buffer "^5.1.1" + +ethereumjs-block@2.2.2, ethereumjs-block@^2.2.2, ethereumjs-block@~2.2.0, ethereumjs-block@~2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz#c7654be7e22df489fda206139ecd63e2e9c04965" + integrity sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg== + dependencies: + async "^2.0.1" + ethereumjs-common "^1.5.0" + ethereumjs-tx "^2.1.1" + ethereumjs-util "^5.0.0" + merkle-patricia-tree "^2.1.2" + +ethereumjs-block@^1.2.2, ethereumjs-block@^1.4.1, ethereumjs-block@^1.6.0: + version "1.7.1" + resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz#78b88e6cc56de29a6b4884ee75379b6860333c3f" + integrity sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg== + dependencies: + async "^2.0.1" + ethereum-common "0.2.0" + ethereumjs-tx "^1.2.2" + ethereumjs-util "^5.0.0" + merkle-patricia-tree "^2.1.2" + +ethereumjs-blockchain@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/ethereumjs-blockchain/-/ethereumjs-blockchain-4.0.4.tgz#30f2228dc35f6dcf94423692a6902604ae34960f" + integrity sha512-zCxaRMUOzzjvX78DTGiKjA+4h2/sF0OYL1QuPux0DHpyq8XiNoF5GYHtb++GUxVlMsMfZV7AVyzbtgcRdIcEPQ== + dependencies: + async "^2.6.1" + ethashjs "~0.0.7" + ethereumjs-block "~2.2.2" + ethereumjs-common "^1.5.0" + ethereumjs-util "^6.1.0" + flow-stoplight "^1.0.0" + level-mem "^3.0.1" + lru-cache "^5.1.1" + rlp "^2.2.2" + semaphore "^1.1.0" + +ethereumjs-common@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.0.tgz#d3e82fc7c47c0cef95047f431a99485abc9bb1cd" + integrity sha512-SZOjgK1356hIY7MRj3/ma5qtfr/4B5BL+G4rP/XSMYr2z1H5el4RX5GReYCKmQmYI/nSBmRnwrZ17IfHuG0viQ== + +ethereumjs-common@^1.1.0, ethereumjs-common@^1.3.2, ethereumjs-common@^1.5.0: + version "1.5.2" + resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz#2065dbe9214e850f2e955a80e650cb6999066979" + integrity sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA== + +ethereumjs-tx@2.1.2, ethereumjs-tx@^2.1.1, ethereumjs-tx@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz#5dfe7688bf177b45c9a23f86cf9104d47ea35fed" + integrity sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw== + dependencies: + ethereumjs-common "^1.5.0" + ethereumjs-util "^6.0.0" + +ethereumjs-tx@^1.1.1, ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.3: + version "1.3.7" + resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a" + integrity sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA== + dependencies: + ethereum-common "^0.0.18" + ethereumjs-util "^5.0.0" + +ethereumjs-util@6.2.1, ethereumjs-util@^6.0.0, ethereumjs-util@^6.1.0, ethereumjs-util@^6.2.0, ethereumjs-util@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" + integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== + dependencies: + "@types/bn.js" "^4.11.3" + bn.js "^4.11.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + ethjs-util "0.1.6" + rlp "^2.2.3" + +ethereumjs-util@^4.3.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.1.tgz#f4bf9b3b515a484e3cc8781d61d9d980f7c83bd0" + integrity sha512-WrckOZ7uBnei4+AKimpuF1B3Fv25OmoRgmYCpGsP7u8PFxXAmAgiJSYT2kRWnt6fVIlKaQlZvuwXp7PIrmn3/w== + dependencies: + bn.js "^4.8.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + rlp "^2.0.0" + +ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.2, ethereumjs-util@^5.1.3, ethereumjs-util@^5.1.5, ethereumjs-util@^5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz#a833f0e5fca7e5b361384dc76301a721f537bf65" + integrity sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ== + dependencies: + bn.js "^4.11.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + ethjs-util "^0.1.3" + rlp "^2.0.0" + safe-buffer "^5.1.1" + +ethereumjs-util@^7.0.2, ethereumjs-util@^7.1.0: + version "7.1.5" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" + integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== + dependencies: + "@types/bn.js" "^5.1.0" + bn.js "^5.1.2" + create-hash "^1.1.2" + ethereum-cryptography "^0.1.3" + rlp "^2.2.4" + +ethereumjs-vm@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-4.2.0.tgz#e885e861424e373dbc556278f7259ff3fca5edab" + integrity sha512-X6qqZbsY33p5FTuZqCnQ4+lo957iUJMM6Mpa6bL4UW0dxM6WmDSHuI4j/zOp1E2TDKImBGCJA9QPfc08PaNubA== + dependencies: + async "^2.1.2" + async-eventemitter "^0.2.2" + core-js-pure "^3.0.1" + ethereumjs-account "^3.0.0" + ethereumjs-block "^2.2.2" + ethereumjs-blockchain "^4.0.3" + ethereumjs-common "^1.5.0" + ethereumjs-tx "^2.1.2" + ethereumjs-util "^6.2.0" + fake-merkle-patricia-tree "^1.0.1" + functional-red-black-tree "^1.0.1" + merkle-patricia-tree "^2.3.2" + rustbn.js "~0.2.0" + safe-buffer "^5.1.1" + util.promisify "^1.0.0" + +ethereumjs-vm@^2.1.0, ethereumjs-vm@^2.3.4, ethereumjs-vm@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz#76243ed8de031b408793ac33907fb3407fe400c6" + integrity sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw== + dependencies: + async "^2.1.2" + async-eventemitter "^0.2.2" + ethereumjs-account "^2.0.3" + ethereumjs-block "~2.2.0" + ethereumjs-common "^1.1.0" + ethereumjs-util "^6.0.0" + fake-merkle-patricia-tree "^1.0.1" + functional-red-black-tree "^1.0.1" + merkle-patricia-tree "^2.3.2" + rustbn.js "~0.2.0" + safe-buffer "^5.1.1" + +ethereumjs-wallet@0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.5.tgz#685e9091645cee230ad125c007658833991ed474" + integrity sha512-MDwjwB9VQVnpp/Dc1XzA6J1a3wgHQ4hSvA1uWNatdpOrtCbPVuQSKSyRnjLvS0a+KKMw2pvQ9Ybqpb3+eW8oNA== + dependencies: + aes-js "^3.1.1" + bs58check "^2.1.2" + ethereum-cryptography "^0.1.3" + ethereumjs-util "^6.0.0" + randombytes "^2.0.6" + safe-buffer "^5.1.2" + scryptsy "^1.2.1" + utf8 "^3.0.0" + uuid "^3.3.2" + +ethers@^5.0.0, ethers@^5.0.1, ethers@^5.0.2, ethers@^5.5.2, ethers@^5.5.3: + version "5.7.2" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" + integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/abstract-signer" "5.7.0" + "@ethersproject/address" "5.7.0" + "@ethersproject/base64" "5.7.0" + "@ethersproject/basex" "5.7.0" + "@ethersproject/bignumber" "5.7.0" + "@ethersproject/bytes" "5.7.0" + "@ethersproject/constants" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/hash" "5.7.0" + "@ethersproject/hdnode" "5.7.0" + "@ethersproject/json-wallets" "5.7.0" + "@ethersproject/keccak256" "5.7.0" + "@ethersproject/logger" "5.7.0" + "@ethersproject/networks" "5.7.1" + "@ethersproject/pbkdf2" "5.7.0" + "@ethersproject/properties" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@ethersproject/random" "5.7.0" + "@ethersproject/rlp" "5.7.0" + "@ethersproject/sha2" "5.7.0" + "@ethersproject/signing-key" "5.7.0" + "@ethersproject/solidity" "5.7.0" + "@ethersproject/strings" "5.7.0" + "@ethersproject/transactions" "5.7.0" + "@ethersproject/units" "5.7.0" + "@ethersproject/wallet" "5.7.0" + "@ethersproject/web" "5.7.1" + "@ethersproject/wordlists" "5.7.0" + +ethjs-unit@0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" + integrity sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw== + dependencies: + bn.js "4.11.6" + number-to-bn "1.7.0" + +ethjs-util@0.1.6, ethjs-util@^0.1.3, ethjs-util@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" + integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== + dependencies: + is-hex-prefixed "1.0.0" + strip-hex-prefix "1.0.0" + +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + +eventemitter3@4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" + integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== + +events@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA== + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +express@^4.14.0: + version "4.18.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" + integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.20.1" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.5.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "2.0.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.2.0" + fresh "0.5.2" + http-errors "2.0.0" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "2.4.1" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.7" + qs "6.11.0" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.18.0" + serve-static "1.15.0" + setprototypeof "1.2.0" + statuses "2.0.1" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +ext@^1.1.2: + version "1.7.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" + integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== + dependencies: + type "^2.7.2" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q== + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== + +extsprintf@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== + +fake-merkle-patricia-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz#4b8c3acfb520afadf9860b1f14cd8ce3402cddd3" + integrity sha512-Tgq37lkc9pUIgIKw5uitNUKcgcYL3R6JvXtKQbOf/ZSavXbidsksgp/pAY6p//uhw0I4yoMsvTSovvVIsk/qxA== + dependencies: + checkpoint-store "^1.1.0" + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fetch-ponyfill@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz#ae3ce5f732c645eab87e4ae8793414709b239893" + integrity sha512-knK9sGskIg2T7OnYLdZ2hZXn0CtDrAIBxYQLpmEf0BqfdWnwmM1weccUl5+4EdA44tzNSFAuxITPbXtPehUB3g== + dependencies: + node-fetch "~1.7.1" + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ== + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" + +find-replace@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-1.0.3.tgz#b88e7364d2d9c959559f388c66670d6130441fa0" + integrity sha512-KrUnjzDCD9426YnCP56zGYy/eieTnhtK6Vn++j+JJzmlsWWwEkDnsyVF575spT6HJ6Ow9tlbT3TQTDsa+O4UWA== + dependencies: + array-back "^1.0.4" + test-value "^2.1.0" + +find-replace@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" + integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ== + dependencies: + array-back "^3.0.1" + +find-up@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + integrity sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA== + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== + dependencies: + locate-path "^2.0.0" + +find-yarn-workspace-root@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz#40eb8e6e7c2502ddfaa2577c176f221422f860db" + integrity sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q== + dependencies: + fs-extra "^4.0.3" + micromatch "^3.1.4" + +find-yarn-workspace-root@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" + integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ== + dependencies: + micromatch "^4.0.2" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +flow-stoplight@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/flow-stoplight/-/flow-stoplight-1.0.0.tgz#4a292c5bcff8b39fa6cc0cb1a853d86f27eeff7b" + integrity sha512-rDjbZUKpN8OYhB0IE/vY/I8UWO/602IIJEU/76Tv4LvYnwHCk0BCsvz4eRr9n+FQcri7L5cyaXOo0+/Kh4HisA== + +fmix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/fmix/-/fmix-0.1.0.tgz#c7bbf124dec42c9d191cfb947d0a9778dd986c0c" + integrity sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w== + dependencies: + imul "^1.0.0" + +follow-redirects@^1.12.1, follow-redirects@^1.14.0: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + +for-each@^0.3.3, for-each@~0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ== + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== + +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fp-ts@1.19.3: + version "1.19.3" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.3.tgz#261a60d1088fbff01f91256f91d21d0caaaaa96f" + integrity sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg== + +fp-ts@^1.0.0: + version "1.19.5" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a" + integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A== + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA== + dependencies: + map-cache "^0.2.2" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +fs-extra@^0.30.0: + version "0.30.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" + integrity sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + klaw "^1.0.0" + path-is-absolute "^1.0.0" + rimraf "^2.2.8" + +fs-extra@^10.0.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-extra@^4.0.2, fs-extra@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" + integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^7.0.0, fs-extra@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^9.0.0, fs-extra@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-minipass@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" + integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== + dependencies: + minipass "^2.6.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fs@^0.0.1-security: + version "0.0.1-security" + resolved "https://registry.yarnpkg.com/fs/-/fs-0.0.1-security.tgz#8a7bd37186b6dddf3813f23858b57ecaaf5e41d4" + integrity sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w== + +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +function.prototype.name@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" + integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + functions-have-names "^1.2.2" + +functional-red-black-tree@^1.0.1, functional-red-black-tree@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== + +functions-have-names@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + +ganache-core@^2.13.2: + version "2.13.2" + resolved "https://registry.yarnpkg.com/ganache-core/-/ganache-core-2.13.2.tgz#27e6fc5417c10e6e76e2e646671869d7665814a3" + integrity sha512-tIF5cR+ANQz0+3pHWxHjIwHqFXcVo0Mb+kcsNhglNFALcYo49aQpnS9dqHartqPfMFjiHh/qFoD3mYK0d/qGgw== + dependencies: + abstract-leveldown "3.0.0" + async "2.6.2" + bip39 "2.5.0" + cachedown "1.0.0" + clone "2.1.2" + debug "3.2.6" + encoding-down "5.0.4" + eth-sig-util "3.0.0" + ethereumjs-abi "0.6.8" + ethereumjs-account "3.0.0" + ethereumjs-block "2.2.2" + ethereumjs-common "1.5.0" + ethereumjs-tx "2.1.2" + ethereumjs-util "6.2.1" + ethereumjs-vm "4.2.0" + heap "0.2.6" + keccak "3.0.1" + level-sublevel "6.6.4" + levelup "3.1.1" + lodash "4.17.20" + lru-cache "5.1.1" + merkle-patricia-tree "3.0.0" + patch-package "6.2.2" + seedrandom "3.0.1" + source-map-support "0.5.12" + tmp "0.1.0" + web3-provider-engine "14.2.1" + websocket "1.0.32" + optionalDependencies: + ethereumjs-wallet "0.6.5" + web3 "1.2.11" + +get-caller-file@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig== + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f" + integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.3" + +get-stream@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + +get-symbol-description@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" + integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== + dependencies: + assert-plus "^1.0.0" + +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@7.1.7: + version "7.1.7" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" + integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.2, glob@^7.1.3, glob@~7.2.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global@~4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" + integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w== + dependencies: + min-document "^2.19.0" + process "^0.11.10" + +globals@^9.18.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== + +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +got@9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" + integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + dependencies: + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" + +got@^11.8.5: + version "11.8.6" + resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a" + integrity sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g== + dependencies: + "@sindresorhus/is" "^4.0.0" + "@szmarczak/http-timer" "^4.0.5" + "@types/cacheable-request" "^6.0.1" + "@types/responselike" "^1.0.0" + cacheable-lookup "^5.0.3" + cacheable-request "^7.0.2" + decompress-response "^6.0.0" + http2-wrapper "^1.0.0-beta.5.2" + lowercase-keys "^2.0.0" + p-cancelable "^2.0.0" + responselike "^2.0.0" + +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== + +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + +hardhat-abi-exporter@^2.9.0: + version "2.10.1" + resolved "https://registry.yarnpkg.com/hardhat-abi-exporter/-/hardhat-abi-exporter-2.10.1.tgz#b14884e233c73fe3f43360f014ad7fd6df4b6d25" + integrity sha512-X8GRxUTtebMAd2k4fcPyVnCdPa6dYK4lBsrwzKP5yiSq4i+WadWPIumaLfce53TUf/o2TnLpLOduyO1ylE2NHQ== + dependencies: + "@ethersproject/abi" "^5.5.0" + delete-empty "^3.0.0" + +hardhat-deploy@^0.11.22: + version "0.11.23" + resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.11.23.tgz#7c5d11ba32acfd7c5730490bf6af8815b435c996" + integrity sha512-9F+sDRX79D/oV1cUEE0k2h5LiccrnzXEtrMofL5PTVDCJfUnRvhQqCRi4NhcYmxf2+MBkOIJv5KyzP0lz6ojTw== + dependencies: + "@types/qs" "^6.9.7" + axios "^0.21.1" + chalk "^4.1.2" + chokidar "^3.5.2" + debug "^4.3.2" + enquirer "^2.3.6" + ethers "^5.5.3" + form-data "^4.0.0" + fs-extra "^10.0.0" + match-all "^1.2.6" + murmur-128 "^0.2.1" + qs "^6.9.4" + zksync-web3 "^0.8.1" + +hardhat-preprocessor@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/hardhat-preprocessor/-/hardhat-preprocessor-0.1.5.tgz#75b22641fd6a680739c995d03bd5f7868eb72144" + integrity sha512-j8m44mmPxpxAAd0G8fPHRHOas/INZdzptSur0TNJvMEGcFdLDhbHHxBcqZVQ/bmiW42q4gC60AP4CXn9EF018g== + dependencies: + murmur-128 "^0.2.1" + +hardhat@^2.9.5: + version "2.12.6" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.12.6.tgz#ea3c058bbd81850867389d10f76037cfa52a0019" + integrity sha512-0Ent1O5DsPgvaVb5sxEgsQ3bJRt/Ex92tsoO+xjoNH2Qc4bFmhI5/CHVlFikulalxOPjNmw5XQ2vJFuVQFESAA== + dependencies: + "@ethersproject/abi" "^5.1.2" + "@metamask/eth-sig-util" "^4.0.0" + "@nomicfoundation/ethereumjs-block" "^4.0.0" + "@nomicfoundation/ethereumjs-blockchain" "^6.0.0" + "@nomicfoundation/ethereumjs-common" "^3.0.0" + "@nomicfoundation/ethereumjs-evm" "^1.0.0" + "@nomicfoundation/ethereumjs-rlp" "^4.0.0" + "@nomicfoundation/ethereumjs-statemanager" "^1.0.0" + "@nomicfoundation/ethereumjs-trie" "^5.0.0" + "@nomicfoundation/ethereumjs-tx" "^4.0.0" + "@nomicfoundation/ethereumjs-util" "^8.0.0" + "@nomicfoundation/ethereumjs-vm" "^6.0.0" + "@nomicfoundation/solidity-analyzer" "^0.1.0" + "@sentry/node" "^5.18.1" + "@types/bn.js" "^5.1.0" + "@types/lru-cache" "^5.1.0" + abort-controller "^3.0.0" + adm-zip "^0.4.16" + aggregate-error "^3.0.0" + ansi-escapes "^4.3.0" + chalk "^2.4.2" + chokidar "^3.4.0" + ci-info "^2.0.0" + debug "^4.1.1" + enquirer "^2.3.0" + env-paths "^2.2.0" + ethereum-cryptography "^1.0.3" + ethereumjs-abi "^0.6.8" + find-up "^2.1.0" + fp-ts "1.19.3" + fs-extra "^7.0.1" + glob "7.2.0" + immutable "^4.0.0-rc.12" + io-ts "1.10.4" + keccak "^3.0.2" + lodash "^4.17.11" + mnemonist "^0.38.0" + mocha "^10.0.0" + p-map "^4.0.0" + qs "^6.7.0" + raw-body "^2.4.1" + resolve "1.17.0" + semver "^6.3.0" + solc "0.7.3" + source-map-support "^0.5.13" + stacktrace-parser "^0.1.10" + tsort "0.0.1" + undici "^5.14.0" + uuid "^8.3.2" + ws "^7.4.6" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg== + dependencies: + ansi-regex "^2.0.0" + +has-bigints@^1.0.1, has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + +has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q== + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw== + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ== + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ== + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has@^1.0.3, has@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +heap@0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.6.tgz#087e1f10b046932fc8594dd9e6d378afc9d1e5ac" + integrity sha512-MzzWcnfB1e4EG2vHi3dXHoBupmuXNZzx6pY6HldVS55JKKBoq3xOyzfSaZRkJp37HIhEYC78knabHff3zc4dQQ== + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +home-or-tmp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" + integrity sha512-ycURW7oUxE2sNiPVw1HVEFsW+ecOpJ5zaj7eC0RlwhibhRBod20muUN8qu/gzx956YrLolVvs1MTXwKgC2rVEg== + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.1" + +hosted-git-info@^2.1.4, hosted-git-info@^2.6.0: + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + +http-cache-semantics@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" + integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +http-https@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" + integrity sha512-o0PWwVCSp3O0wS6FvNr6xfBCHgt0m1tvPLFOCc2iFDKTRAXhB7m8klDf7ErowFH8POa6dVdGatKU5I1YYwzUyg== + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +http2-wrapper@^1.0.0-beta.5.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d" + integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg== + dependencies: + quick-lru "^5.1.1" + resolve-alpn "^1.0.0" + +https-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +iconv-lite@^0.6.2: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +idna-uts46-hx@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz#a1dc5c4df37eee522bf66d969cc980e00e8711f9" + integrity sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA== + dependencies: + punycode "2.1.0" + +ieee754@^1.1.13, ieee754@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +immediate@^3.2.3: + version "3.3.0" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" + integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q== + +immediate@~3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" + integrity sha512-RrGCXRm/fRVqMIhqXrGEX9rRADavPiDFSoMb/k64i9XMk8uH4r/Omi5Ctierj6XzNecwDbO4WuFbDD1zmpl3Tg== + +immutable@^4.0.0-rc.12: + version "4.2.3" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.2.3.tgz#a203cdda37a5a30bc351b982a1794c1930198815" + integrity sha512-IHpmvaOIX4VLJwPOuQr1NpeBr2ZG6vpIj3blsLVxXRWJscLioaJRStqC+NcBsLeCDsnGlPpXd5/WZmnE7MbsKA== + +imul@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/imul/-/imul-1.0.1.tgz#9d5867161e8b3de96c2c38d5dc7cb102f35e2ac9" + integrity sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA== + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== + +internal-slot@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.4.tgz#8551e7baf74a7a6ba5f749cfb16aa60722f0d6f3" + integrity sha512-tA8URYccNzMo94s5MQZgH8NB/XTa6HsOo0MLfXTKKEnHVVdegzaQoFZ7Jp44bdvLvY2waT5dc+j5ICEswhi7UQ== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + side-channel "^1.0.4" + +invariant@^2.2.2: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + integrity sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ== + +io-ts@1.10.4: + version "1.10.4" + resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-1.10.4.tgz#cd5401b138de88e4f920adbcb7026e2d1967e6e2" + integrity sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g== + dependencies: + fp-ts "^1.0.0" + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A== + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-arguments@^1.0.4: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" + integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-array-buffer@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.1.tgz#deb1db4fcae48308d54ef2442706c0393997052a" + integrity sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-typed-array "^1.1.10" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-buffer@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== + +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + +is-core-module@^2.9.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" + integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== + dependencies: + has "^1.0.3" + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg== + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-date-object@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-docker@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-finite@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" + integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== + +is-fn@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fn/-/is-fn-1.0.0.tgz#9543d5de7bcf5b08a22ec8a20bae6e286d510d8c" + integrity sha512-XoFPJQmsAShb3jEQRfzf2rqXavq7fIqF/jOekp308JlThqrODnMpweVSGilKTCXELfLhltGP2AGgbQGVP8F1dg== + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw== + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-function@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.2.tgz#4f097f30abf6efadac9833b17ca5dc03f8144e08" + integrity sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ== + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-hex-prefixed@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" + integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA== + +is-negative-zero@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + +is-number-object@^1.0.4: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" + integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== + dependencies: + has-tostringtag "^1.0.0" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg== + dependencies: + kind-of "^3.0.2" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-regex@^1.0.4, is-regex@^1.1.4, is-regex@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-shared-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" + integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== + dependencies: + call-bind "^1.0.2" + +is-stream@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ== + +is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + +is-symbol@^1.0.2, is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + +is-typed-array@^1.1.10, is-typed-array@^1.1.9: + version "1.1.10" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" + integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + +is-typedarray@^1.0.0, is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +is-url@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" + integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + integrity sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q== + +is-weakref@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +is-wsl@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== + +isarray@1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA== + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== + +js-sha3@0.8.0, js-sha3@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + +js-sha3@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" + integrity sha512-GII20kjaPX0zJ8wzkTbNDYMY7msuZcTWk8S5UOh6806Jq/wz1J8/bnr8uGU0DAUmYDjj2Mr4X1cW8v/GLYnR+g== + +"js-tokens@^3.0.0 || ^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + integrity sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg== + +js-yaml@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== + +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + integrity sha512-Mke0DA0QjUWuJlhsE0ZPPhYiJkRap642SmI/4ztCFaUs6V2AiH1sfecc+57NgaryfAA2VR3v6O+CSjC1jZJKOA== + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== + +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + integrity sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ== + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz#9d4ff447241792e1d0a232f6ef927302bb0c62a9" + integrity sha512-6QNcvm2gFuuK4TKU1uwfH0Qd/cOSb9c1lls0gbnIhciktIUQJwz6NQNAW4B1KiGPenv7IKu97V222Yo1bNhGuA== + dependencies: + async "^2.0.1" + babel-preset-env "^1.7.0" + babelify "^7.3.0" + json-rpc-error "^2.0.0" + promise-to-callback "^1.0.0" + safe-event-emitter "^1.0.1" + +json-rpc-error@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02" + integrity sha512-EwUeWP+KgAZ/xqFpaP6YDAXMtCJi+o/QQpCQFIYyxr01AdADi2y413eM8hSqJcoQym9WMePAJWoaODEJufC4Ug== + dependencies: + inherits "^2.0.1" + +json-rpc-random-id@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8" + integrity sha512-RJ9YYNCkhVDBuP4zN5BBtYAzEl03yq/jIIsyif0JY9qyJuQQZNeDK7anAPKKlyEtLSj2s8h6hNh2F8zO5q7ScA== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== + +json-stable-stringify@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz#e06f23128e0bbe342dc996ed5a19e28b57b580e0" + integrity sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g== + dependencies: + jsonify "^0.0.1" + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + +json5@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + integrity sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw== + +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + integrity sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw== + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +jsonify@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" + integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== + +jsprim@^1.2.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" + integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.4.0" + verror "1.10.0" + +keccak@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.1.tgz#ae30a0e94dbe43414f741375cff6d64c8bea0bff" + integrity sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA== + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + +keccak@^3.0.0, keccak@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.3.tgz#4bc35ad917be1ef54ff246f904c2bbbf9ac61276" + integrity sha512-JZrLIAJWuZxKbCilMpNz5Vj7Vtb4scDG3dMXLOsbzBmQGyjwE61BbW7bJkfKKCShXiQZt3T6sBgALRtmd+nZaQ== + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + readable-stream "^3.6.0" + +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" + integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + dependencies: + json-buffer "3.0.0" + +keyv@^4.0.0: + version "4.5.2" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.2.tgz#0e310ce73bf7851ec702f2eaf46ec4e3805cce56" + integrity sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g== + dependencies: + json-buffer "3.0.1" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw== + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +klaw-sync@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c" + integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ== + dependencies: + graceful-fs "^4.1.11" + +klaw@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" + integrity sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw== + optionalDependencies: + graceful-fs "^4.1.9" + +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + integrity sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw== + dependencies: + invert-kv "^1.0.0" + +level-codec@^9.0.0: + version "9.0.2" + resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-9.0.2.tgz#fd60df8c64786a80d44e63423096ffead63d8cbc" + integrity sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ== + dependencies: + buffer "^5.6.0" + +level-codec@~7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-7.0.1.tgz#341f22f907ce0f16763f24bddd681e395a0fb8a7" + integrity sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ== + +level-errors@^1.0.3: + version "1.1.2" + resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.1.2.tgz#4399c2f3d3ab87d0625f7e3676e2d807deff404d" + integrity sha512-Sw/IJwWbPKF5Ai4Wz60B52yj0zYeqzObLh8k1Tk88jVmD51cJSKWSYpRyhVIvFzZdvsPqlH5wfhp/yxdsaQH4w== + dependencies: + errno "~0.1.1" + +level-errors@^2.0.0, level-errors@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-2.0.1.tgz#2132a677bf4e679ce029f517c2f17432800c05c8" + integrity sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw== + dependencies: + errno "~0.1.1" + +level-errors@~1.0.3: + version "1.0.5" + resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.0.5.tgz#83dbfb12f0b8a2516bdc9a31c4876038e227b859" + integrity sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig== + dependencies: + errno "~0.1.1" + +level-iterator-stream@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-2.0.3.tgz#ccfff7c046dcf47955ae9a86f46dfa06a31688b4" + integrity sha512-I6Heg70nfF+e5Y3/qfthJFexhRw/Gi3bIymCoXAlijZdAcLaPuWSJs3KXyTYf23ID6g0o2QF62Yh+grOXY3Rig== + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.5" + xtend "^4.0.0" + +level-iterator-stream@~1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz#e43b78b1a8143e6fa97a4f485eb8ea530352f2ed" + integrity sha512-1qua0RHNtr4nrZBgYlpV0qHHeHpcRRWTxEZJ8xsemoHAXNL5tbooh4tPEEqIqsbWCAJBmUmkwYK/sW5OrFjWWw== + dependencies: + inherits "^2.0.1" + level-errors "^1.0.3" + readable-stream "^1.0.33" + xtend "^4.0.0" + +level-iterator-stream@~3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz#2c98a4f8820d87cdacab3132506815419077c730" + integrity sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g== + dependencies: + inherits "^2.0.1" + readable-stream "^2.3.6" + xtend "^4.0.0" + +level-mem@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/level-mem/-/level-mem-3.0.1.tgz#7ce8cf256eac40f716eb6489654726247f5a89e5" + integrity sha512-LbtfK9+3Ug1UmvvhR2DqLqXiPW1OJ5jEh0a3m9ZgAipiwpSxGj/qaVVy54RG5vAQN1nCuXqjvprCuKSCxcJHBg== + dependencies: + level-packager "~4.0.0" + memdown "~3.0.0" + +level-packager@~4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/level-packager/-/level-packager-4.0.1.tgz#7e7d3016af005be0869bc5fa8de93d2a7f56ffe6" + integrity sha512-svCRKfYLn9/4CoFfi+d8krOtrp6RoX8+xm0Na5cgXMqSyRru0AnDYdLl+YI8u1FyS6gGZ94ILLZDE5dh2but3Q== + dependencies: + encoding-down "~5.0.0" + levelup "^3.0.0" + +level-post@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/level-post/-/level-post-1.0.7.tgz#19ccca9441a7cc527879a0635000f06d5e8f27d0" + integrity sha512-PWYqG4Q00asOrLhX7BejSajByB4EmG2GaKHfj3h5UmmZ2duciXLPGYWIjBzLECFWUGOZWlm5B20h/n3Gs3HKew== + dependencies: + ltgt "^2.1.2" + +level-sublevel@6.6.4: + version "6.6.4" + resolved "https://registry.yarnpkg.com/level-sublevel/-/level-sublevel-6.6.4.tgz#f7844ae893919cd9d69ae19d7159499afd5352ba" + integrity sha512-pcCrTUOiO48+Kp6F1+UAzF/OtWqLcQVTVF39HLdZ3RO8XBoXt+XVPKZO1vVr1aUoxHZA9OtD2e1v7G+3S5KFDA== + dependencies: + bytewise "~1.1.0" + level-codec "^9.0.0" + level-errors "^2.0.0" + level-iterator-stream "^2.0.3" + ltgt "~2.1.1" + pull-defer "^0.2.2" + pull-level "^2.0.3" + pull-stream "^3.6.8" + typewiselite "~1.0.0" + xtend "~4.0.0" + +level-supports@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-4.0.1.tgz#431546f9d81f10ff0fea0e74533a0e875c08c66a" + integrity sha512-PbXpve8rKeNcZ9C1mUicC9auIYFyGpkV9/i6g76tLgANwWhtG2v7I4xNBUlkn3lE2/dZF3Pi0ygYGtLc4RXXdA== + +level-transcoder@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/level-transcoder/-/level-transcoder-1.0.1.tgz#f8cef5990c4f1283d4c86d949e73631b0bc8ba9c" + integrity sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w== + dependencies: + buffer "^6.0.3" + module-error "^1.0.1" + +level-ws@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-0.0.0.tgz#372e512177924a00424b0b43aef2bb42496d228b" + integrity sha512-XUTaO/+Db51Uiyp/t7fCMGVFOTdtLS/NIACxE/GHsij15mKzxksZifKVjlXDF41JMUP/oM1Oc4YNGdKnc3dVLw== + dependencies: + readable-stream "~1.0.15" + xtend "~2.1.1" + +level-ws@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-1.0.0.tgz#19a22d2d4ac57b18cc7c6ecc4bd23d899d8f603b" + integrity sha512-RXEfCmkd6WWFlArh3X8ONvQPm8jNpfA0s/36M4QzLqrLEIt1iJE9WBHLZ5vZJK6haMjJPJGJCQWfjMNnRcq/9Q== + dependencies: + inherits "^2.0.3" + readable-stream "^2.2.8" + xtend "^4.0.1" + +level@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/level/-/level-8.0.0.tgz#41b4c515dabe28212a3e881b61c161ffead14394" + integrity sha512-ypf0jjAk2BWI33yzEaaotpq7fkOPALKAgDBxggO6Q9HGX2MRXn0wbP1Jn/tJv1gtL867+YOjOB49WaUF3UoJNQ== + dependencies: + browser-level "^1.0.1" + classic-level "^1.2.0" + +levelup@3.1.1, levelup@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/levelup/-/levelup-3.1.1.tgz#c2c0b3be2b4dc316647c53b42e2f559e232d2189" + integrity sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg== + dependencies: + deferred-leveldown "~4.0.0" + level-errors "~2.0.0" + level-iterator-stream "~3.0.0" + xtend "~4.0.0" + +levelup@^1.2.1: + version "1.3.9" + resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.9.tgz#2dbcae845b2bb2b6bea84df334c475533bbd82ab" + integrity sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ== + dependencies: + deferred-leveldown "~1.2.1" + level-codec "~7.0.0" + level-errors "~1.0.3" + level-iterator-stream "~1.3.0" + prr "~1.0.1" + semver "~5.4.1" + xtend "~4.0.0" + +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + integrity sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A== + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.assign@^4.0.3, lodash.assign@^4.0.6: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" + integrity sha512-hFuH8TY+Yji7Eja3mGiuAxBqLagejScbG8GbG0j6o9vzn0YL14My+ktnqtZgFTosKymC9/44wP6s7xyuLfnClw== + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== + +lodash.truncate@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" + integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== + +lodash@4.17.20: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + +lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.16, lodash@^4.17.4: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-symbols@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +looper@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/looper/-/looper-2.0.0.tgz#66cd0c774af3d4fedac53794f742db56da8f09ec" + integrity sha512-6DzMHJcjbQX/UPHc1rRCBfKlLwDkvuGZ715cIR36wSdYqWXFT35uLXq5P/2orl3tz+t+VOVPxw4yPinQlUDGDQ== + +looper@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/looper/-/looper-3.0.0.tgz#2efa54c3b1cbaba9b94aee2e5914b0be57fbb749" + integrity sha512-LJ9wplN/uSn72oJRsXTx+snxPet5c8XiZmOKCm906NVYu+ag6SB6vUcnJcWxgnl2NfbIyeobAn7Bwv6xRj2XJg== + +loose-envify@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +loupe@^2.3.1: + version "2.3.6" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53" + integrity sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA== + dependencies: + get-func-name "^2.0.0" + +lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + +lru-cache@5.1.1, lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +lru-cache@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-3.2.0.tgz#71789b3b7f5399bec8565dda38aa30d2a097efee" + integrity sha512-91gyOKTc2k66UG6kHiH4h3S2eltcPwE1STVfMYC/NG+nZwf8IIuiamfmpGZjpbbxzSyEJaLC0tNSmhjlQUTJow== + dependencies: + pseudomap "^1.0.1" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +lru_map@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" + integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== + +ltgt@^2.1.2, ltgt@~2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" + integrity sha512-AI2r85+4MquTw9ZYqabu4nMwy9Oftlfa/e/52t9IjtfG+mGBbTNdAoZ3RQKLHR6r0wQnwZnPIEh/Ya6XTWAKNA== + +ltgt@~2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.1.3.tgz#10851a06d9964b971178441c23c9e52698eece34" + integrity sha512-5VjHC5GsENtIi5rbJd+feEpDKhfr7j0odoUR2Uh978g+2p93nd5o34cTjQWohXsPsCZeqoDnIqEf88mPCe0Pfw== + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w== + dependencies: + object-visit "^1.0.0" + +match-all@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/match-all/-/match-all-1.2.6.tgz#66d276ad6b49655551e63d3a6ee53e8be0566f8d" + integrity sha512-0EESkXiTkWzrQQntBu2uzKvLu6vVkUGz40nGPbSZuegcfE5UuSzNjLaIu76zJWuaT/2I3Z/8M06OlUOZLGwLlQ== + +mcl-wasm@^0.7.1: + version "0.7.9" + resolved "https://registry.yarnpkg.com/mcl-wasm/-/mcl-wasm-0.7.9.tgz#c1588ce90042a8700c3b60e40efb339fc07ab87f" + integrity sha512-iJIUcQWA88IJB/5L15GnJVnSQJmf/YaxxV6zRavv83HILHaJQb6y0iFyDMdDO0gN8X37tdxmAOrH/P8B6RB8sQ== + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + +memdown@^1.0.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215" + integrity sha512-iVrGHZB8i4OQfM155xx8akvG9FIj+ht14DX5CQkCTG4EHzZ3d3sgckIf/Lm9ivZalEsFuEVnWv2B2WZvbrro2w== + dependencies: + abstract-leveldown "~2.7.1" + functional-red-black-tree "^1.0.1" + immediate "^3.2.3" + inherits "~2.0.1" + ltgt "~2.2.0" + safe-buffer "~5.1.1" + +memdown@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/memdown/-/memdown-3.0.0.tgz#93aca055d743b20efc37492e9e399784f2958309" + integrity sha512-tbV02LfZMWLcHcq4tw++NuqMO+FZX8tNJEiD2aNRm48ZZusVg5N8NART+dmBkepJVye986oixErf7jfXboMGMA== + dependencies: + abstract-leveldown "~5.0.0" + functional-red-black-tree "~1.0.1" + immediate "~3.2.3" + inherits "~2.0.1" + ltgt "~2.2.0" + safe-buffer "~5.1.1" + +memory-level@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/memory-level/-/memory-level-1.0.0.tgz#7323c3fd368f9af2f71c3cd76ba403a17ac41692" + integrity sha512-UXzwewuWeHBz5krr7EvehKcmLFNoXxGcvuYhC41tRnkrTbJohtS7kVn9akmgirtRygg+f7Yjsfi8Uu5SGSQ4Og== + dependencies: + abstract-level "^1.0.0" + functional-red-black-tree "^1.0.1" + module-error "^1.0.1" + +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== + +merkle-patricia-tree@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-3.0.0.tgz#448d85415565df72febc33ca362b8b614f5a58f8" + integrity sha512-soRaMuNf/ILmw3KWbybaCjhx86EYeBbD8ph0edQCTed0JN/rxDt1EBN52Ajre3VyGo+91f8+/rfPIRQnnGMqmQ== + dependencies: + async "^2.6.1" + ethereumjs-util "^5.2.0" + level-mem "^3.0.1" + level-ws "^1.0.0" + readable-stream "^3.0.6" + rlp "^2.0.0" + semaphore ">=1.0.1" + +merkle-patricia-tree@^2.1.2, merkle-patricia-tree@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz#982ca1b5a0fde00eed2f6aeed1f9152860b8208a" + integrity sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g== + dependencies: + async "^1.4.2" + ethereumjs-util "^5.0.0" + level-ws "0.0.0" + levelup "^1.2.1" + memdown "^1.0.0" + readable-stream "^2.0.0" + rlp "^2.0.0" + semaphore ">=1.0.1" + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== + +micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +micromatch@^4.0.2: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mimic-response@^1.0.0, mimic-response@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== + +min-document@^2.19.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" + integrity sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ== + dependencies: + dom-walk "^0.1.0" + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== + +minimatch@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" + integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^3.0.4, minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.0, minimist@^1.2.6, minimist@~1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" + integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== + +minipass@^2.6.0, minipass@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" + integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" + integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== + dependencies: + minipass "^2.9.0" + +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp-promise@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" + integrity sha512-Hepn5kb1lJPtVW84RFT40YG1OddBNTOVUZR2bzQUHc+Z03en8/3uX0+060JDhcEzyO08HmipsN9DcnFMxhIL9w== + dependencies: + mkdirp "*" + +mkdirp@*: + version "2.1.3" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-2.1.3.tgz#b083ff37be046fd3d6552468c1f0ff44c1545d1f" + integrity sha512-sjAkg21peAG9HS+Dkx7hlG9Ztx7HLeKnvB3NQRcu/mltCVmvkF0pisbiTSfDVYTT86XEfZrTUosLdZLStquZUw== + +mkdirp@^0.5.1, mkdirp@^0.5.5: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +mnemonist@^0.38.0: + version "0.38.5" + resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.38.5.tgz#4adc7f4200491237fe0fa689ac0b86539685cade" + integrity sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg== + dependencies: + obliterator "^2.0.0" + +mocha@^10.0.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8" + integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg== + dependencies: + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.3" + debug "4.3.4" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.2.0" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "5.0.1" + ms "2.1.3" + nanoid "3.3.3" + serialize-javascript "6.0.0" + strip-json-comments "3.1.1" + supports-color "8.1.1" + workerpool "6.2.1" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + +mock-fs@^4.1.0: + version "4.14.0" + resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.14.0.tgz#ce5124d2c601421255985e6e94da80a7357b1b18" + integrity sha512-qYvlv/exQ4+svI3UOvPUpLDF0OMX5euvUH0Ny4N5QyRyhNdgAgUrVH3iUINSzEPLvx0kbo/Bp28GJKIqvE7URw== + +module-error@^1.0.1, module-error@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/module-error/-/module-error-1.0.2.tgz#8d1a48897ca883f47a45816d4fb3e3c6ba404d86" + integrity sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3, ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +multibase@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.7.0.tgz#1adfc1c50abe05eefeb5091ac0c2728d6b84581b" + integrity sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg== + dependencies: + base-x "^3.0.8" + buffer "^5.5.0" + +multibase@~0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.6.1.tgz#b76df6298536cc17b9f6a6db53ec88f85f8cc12b" + integrity sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw== + dependencies: + base-x "^3.0.8" + buffer "^5.5.0" + +multicodec@^0.5.5: + version "0.5.7" + resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-0.5.7.tgz#1fb3f9dd866a10a55d226e194abba2dcc1ee9ffd" + integrity sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA== + dependencies: + varint "^5.0.0" + +multicodec@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-1.0.4.tgz#46ac064657c40380c28367c90304d8ed175a714f" + integrity sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg== + dependencies: + buffer "^5.6.0" + varint "^5.0.0" + +multihashes@^0.4.15, multihashes@~0.4.15: + version "0.4.21" + resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-0.4.21.tgz#dc02d525579f334a7909ade8a122dabb58ccfcb5" + integrity sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw== + dependencies: + buffer "^5.5.0" + multibase "^0.7.0" + varint "^5.0.0" + +murmur-128@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/murmur-128/-/murmur-128-0.2.1.tgz#a9f6568781d2350ecb1bf80c14968cadbeaa4b4d" + integrity sha512-WseEgiRkI6aMFBbj8Cg9yBj/y+OdipwVC7zUo3W2W1JAJITwouUOtpqsmGSg67EQmwwSyod7hsVsWY5LsrfQVg== + dependencies: + encode-utf8 "^1.0.2" + fmix "^0.1.0" + imul "^1.0.0" + +nano-json-stream-parser@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" + integrity sha512-9MqxMH/BSJC7dnLsEMPyfN5Dvoo49IsPFYMcHw3Bcfc2kN0lpHRBSzlMSVx4HGyJ7s9B31CyBTVehWJoQ8Ctew== + +nanoid@3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" + integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +napi-macros@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.0.0.tgz#2b6bae421e7b96eb687aa6c77a7858640670001b" + integrity sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg== + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +next-tick@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" + integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +node-addon-api@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" + integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== + +node-fetch@^2.6.1, node-fetch@^2.6.7: + version "2.6.9" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" + integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== + dependencies: + whatwg-url "^5.0.0" + +node-fetch@~1.7.1: + version "1.7.3" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" + integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== + dependencies: + encoding "^0.1.11" + is-stream "^1.0.1" + +node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" + integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== + +nofilter@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/nofilter/-/nofilter-3.1.0.tgz#c757ba68801d41ff930ba2ec55bab52ca184aa66" + integrity sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g== + +normalize-package-data@^2.3.2: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-url@^4.1.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" + integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== + +normalize-url@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" + integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ== + +number-to-bn@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" + integrity sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig== + dependencies: + bn.js "4.11.6" + strip-hex-prefix "1.0.0" + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +object-assign@^4, object-assign@^4.0.0, object-assign@^4.1.0, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ== + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-inspect@^1.12.2, object-inspect@^1.9.0, object-inspect@~1.12.3: + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== + +object-is@^1.0.1: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" + integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object-keys@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" + integrity sha512-ncrLw+X55z7bkl5PnUvHwFK9FcGuFYo9gtjws2XtSzL+aZ8tm830P60WJ0dSmFVaSalWieW5MD7kEdnXda9yJw== + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA== + dependencies: + isobject "^3.0.0" + +object.assign@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + has-symbols "^1.0.3" + object-keys "^1.1.1" + +object.getownpropertydescriptors@^2.1.1: + version "2.1.5" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.5.tgz#db5a9002489b64eef903df81d6623c07e5b4b4d3" + integrity sha512-yDNzckpM6ntyQiGTik1fKV1DcVDRS+w8bvpWNCBanvH5LfRX9O8WTHqQzG4RZwRAM4I0oU7TV11Lj5v0g20ibw== + dependencies: + array.prototype.reduce "^1.0.5" + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ== + dependencies: + isobject "^3.0.1" + +obliterator@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.4.tgz#fa650e019b2d075d745e44f1effeb13a2adbe816" + integrity sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ== + +oboe@2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.4.tgz#20c88cdb0c15371bb04119257d4fdd34b0aa49f6" + integrity sha512-ymBJ4xSC6GBXLT9Y7lirj+xbqBLa+jADGJldGEYG7u8sZbS9GyG+u1Xk9c5cbriKwSpCg41qUhPjvU5xOpvIyQ== + dependencies: + http-https "^1.0.0" + +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +open@^7.4.2: + version "7.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" + integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== + dependencies: + is-docker "^2.0.0" + is-wsl "^2.1.1" + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ== + +os-locale@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + integrity sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g== + dependencies: + lcid "^1.0.0" + +os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + +p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" + integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + +p-cancelable@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf" + integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg== + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== + dependencies: + p-limit "^1.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== + +parse-asn1@^5.0.0, parse-asn1@^5.1.5: + version "5.1.6" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" + integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== + dependencies: + asn1.js "^5.2.0" + browserify-aes "^1.0.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + safe-buffer "^5.1.1" + +parse-headers@^2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.5.tgz#069793f9356a54008571eb7f9761153e6c770da9" + integrity sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA== + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + integrity sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ== + dependencies: + error-ex "^1.2.0" + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw== + +patch-package@6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.2.2.tgz#71d170d650c65c26556f0d0fbbb48d92b6cc5f39" + integrity sha512-YqScVYkVcClUY0v8fF0kWOjDYopzIM8e3bj/RU1DPeEF14+dCGm6UeOYm4jvCyxqIEQ5/eJzmbWfDWnUleFNMg== + dependencies: + "@yarnpkg/lockfile" "^1.1.0" + chalk "^2.4.2" + cross-spawn "^6.0.5" + find-yarn-workspace-root "^1.2.1" + fs-extra "^7.0.1" + is-ci "^2.0.0" + klaw-sync "^6.0.0" + minimist "^1.2.0" + rimraf "^2.6.3" + semver "^5.6.0" + slash "^2.0.0" + tmp "^0.0.33" + +patch-package@^6.2.2: + version "6.5.1" + resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.5.1.tgz#3e5d00c16997e6160291fee06a521c42ac99b621" + integrity sha512-I/4Zsalfhc6bphmJTlrLoOcAF87jcxko4q0qsv4bGcurbr8IskEOtdnt9iCmsQVGL1B+iUhSQqweyTLJfCF9rA== + dependencies: + "@yarnpkg/lockfile" "^1.1.0" + chalk "^4.1.2" + cross-spawn "^6.0.5" + find-yarn-workspace-root "^2.0.0" + fs-extra "^9.0.0" + is-ci "^2.0.0" + klaw-sync "^6.0.0" + minimist "^1.2.6" + open "^7.4.2" + rimraf "^2.6.3" + semver "^5.6.0" + slash "^2.0.0" + tmp "^0.0.33" + yaml "^1.10.2" + +path-browserify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" + integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== + +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + integrity sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ== + dependencies: + pinkie-promise "^2.0.0" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== + +path-parse@^1.0.6, path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-starts-with@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-starts-with/-/path-starts-with-2.0.0.tgz#ffd6d51926cd497022b44d392196033d5451892f" + integrity sha512-3UHTHbJz5+NLkPafFR+2ycJOjoc4WV2e9qCZCnm71zHiWaFrm1XniLVTkZXvaRgxr1xFh9JsTdicpH2yM03nLA== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== + +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + integrity sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg== + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +path@^0.12.7: + version "0.12.7" + resolved "https://registry.yarnpkg.com/path/-/path-0.12.7.tgz#d4dc2a506c4ce2197eb481ebfcd5b36c0140b10f" + integrity sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q== + dependencies: + process "^0.11.1" + util "^0.10.3" + +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== + +pbkdf2@^3.0.17, pbkdf2@^3.0.3, pbkdf2@^3.0.9: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" + integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pify@^2.0.0, pify@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw== + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg== + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg== + +postinstall-postinstall@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz#4f7f77441ef539d1512c40bd04c71b06a4704ca3" + integrity sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ== + +precond@0.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" + integrity sha512-QCYG84SgGyGzqJ/vlMsxeXd/pgL/I94ixdNFyh1PusWmTCyVfPJjZ1K1jvHtsbfnXQs2TSkEP2fR7QiMZAnKFQ== + +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA== + +prettier-plugin-solidity@^1.0.0-beta.19: + version "1.1.1" + resolved "https://registry.yarnpkg.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.1.1.tgz#4d3375b85f97812ffcbe48d5a8b3fe914d69c91f" + integrity sha512-uD24KO26tAHF+zMN2nt1OUzfknzza5AgxjogQQrMLZc7j8xiQrDoNWNeOlfFC0YLTwo12CLD10b9niLyP6AqXg== + dependencies: + "@solidity-parser/parser" "^0.14.5" + semver "^7.3.8" + solidity-comments-extractor "^0.0.7" + +prettier@^2.1.2, prettier@^2.3.1, prettier@^2.6.2: + version "2.8.3" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.3.tgz#ab697b1d3dd46fb4626fbe2f543afe0cc98d8632" + integrity sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw== + +private@^0.1.6, private@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +process@^0.11.1, process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== + +promise-to-callback@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/promise-to-callback/-/promise-to-callback-1.0.0.tgz#5d2a749010bfb67d963598fcd3960746a68feef7" + integrity sha512-uhMIZmKM5ZteDMfLgJnoSq9GCwsNKrYau73Awf1jIy6/eUcuuZ3P+CD9zUv0kJsIUbU+x6uLNIhXhLHDs1pNPA== + dependencies: + is-fn "^1.0.0" + set-immediate-shim "^1.0.1" + +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw== + +pseudomap@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== + +psl@^1.1.28: + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== + +public-encrypt@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + safe-buffer "^5.1.2" + +pull-cat@^1.1.9: + version "1.1.11" + resolved "https://registry.yarnpkg.com/pull-cat/-/pull-cat-1.1.11.tgz#b642dd1255da376a706b6db4fa962f5fdb74c31b" + integrity sha512-i3w+xZ3DCtTVz8S62hBOuNLRHqVDsHMNZmgrZsjPnsxXUgbWtXEee84lo1XswE7W2a3WHyqsNuDJTjVLAQR8xg== + +pull-defer@^0.2.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/pull-defer/-/pull-defer-0.2.3.tgz#4ee09c6d9e227bede9938db80391c3dac489d113" + integrity sha512-/An3KE7mVjZCqNhZsr22k1Tx8MACnUnHZZNPSJ0S62td8JtYr/AiRG42Vz7Syu31SoTLUzVIe61jtT/pNdjVYA== + +pull-level@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pull-level/-/pull-level-2.0.4.tgz#4822e61757c10bdcc7cf4a03af04c92734c9afac" + integrity sha512-fW6pljDeUThpq5KXwKbRG3X7Ogk3vc75d5OQU/TvXXui65ykm+Bn+fiktg+MOx2jJ85cd+sheufPL+rw9QSVZg== + dependencies: + level-post "^1.0.7" + pull-cat "^1.1.9" + pull-live "^1.0.1" + pull-pushable "^2.0.0" + pull-stream "^3.4.0" + pull-window "^2.1.4" + stream-to-pull-stream "^1.7.1" + +pull-live@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/pull-live/-/pull-live-1.0.1.tgz#a4ecee01e330155e9124bbbcf4761f21b38f51f5" + integrity sha512-tkNz1QT5gId8aPhV5+dmwoIiA1nmfDOzJDlOOUpU5DNusj6neNd3EePybJ5+sITr2FwyCs/FVpx74YMCfc8YeA== + dependencies: + pull-cat "^1.1.9" + pull-stream "^3.4.0" + +pull-pushable@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/pull-pushable/-/pull-pushable-2.2.0.tgz#5f2f3aed47ad86919f01b12a2e99d6f1bd776581" + integrity sha512-M7dp95enQ2kaHvfCt2+DJfyzgCSpWVR2h2kWYnVsW6ZpxQBx5wOu0QWOvQPVoPnBLUZYitYP2y7HyHkLQNeGXg== + +pull-stream@^3.2.3, pull-stream@^3.4.0, pull-stream@^3.6.8: + version "3.7.0" + resolved "https://registry.yarnpkg.com/pull-stream/-/pull-stream-3.7.0.tgz#85de0e44ff38a4d2ad08cc43fc458e1922f9bf0b" + integrity sha512-Eco+/R004UaCK2qEDE8vGklcTG2OeZSVm1kTUQNrykEjDwcFXDZhygFDsW49DbXyJMEhHeRL3z5cRVqPAhXlIw== + +pull-window@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/pull-window/-/pull-window-2.1.4.tgz#fc3b86feebd1920c7ae297691e23f705f88552f0" + integrity sha512-cbDzN76BMlcGG46OImrgpkMf/VkCnupj8JhsrpBw3aWBM9ye345aYnqitmZCgauBkc0HbbRRn9hCnsa3k2FNUg== + dependencies: + looper "^2.0.0" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + integrity sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw== + +punycode@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" + integrity sha512-Yxz2kRwT90aPiWEMHVYnEf4+rhwF1tBmmZ4KepCP+Wkium9JxtWnUm1nqGwpiAHr/tnTSeHqr3wb++jgSkXjhA== + +punycode@^2.1.0, punycode@^2.1.1: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + +qs@6.11.0, qs@^6.7.0, qs@^6.9.4: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" + +qs@~6.5.2: + version "6.5.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== + +query-string@^5.0.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" + integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== + dependencies: + decode-uri-component "^0.2.0" + object-assign "^4.1.0" + strict-uri-encode "^1.0.0" + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g== + +queue-microtask@^1.2.2, queue-microtask@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +quick-lru@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" + integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.0.6, randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.5.1, raw-body@^2.4.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" + integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + integrity sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A== + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + integrity sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ== + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +readable-stream@^1.0.33: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + integrity sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.2.2, readable-stream@^2.2.8, readable-stream@^2.2.9, readable-stream@^2.3.6, readable-stream@~2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.0.6, readable-stream@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readable-stream@~1.0.15: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + integrity sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +reduce-flatten@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" + integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w== + +regenerate@^1.2.1: + version "1.4.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== + +regenerator-transform@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" + integrity sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q== + dependencies: + babel-runtime "^6.18.0" + babel-types "^6.19.0" + private "^0.1.6" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" + integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + functions-have-names "^1.2.2" + +regexpu-core@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" + integrity sha512-tJ9+S4oKjxY8IZ9jmjnp/mtytu1u3iyIQAfmI51IKWH6bFf7XR1ybtaO6j7INhZKXOTYADk7V5qxaqLkmNxiZQ== + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + integrity sha512-x+Y3yA24uF68m5GA+tBjbGYo64xXVJpbToBaWCoSNSc1hdk6dfctaRWrNFTVJZIIhL5GxW8zwjoixbnifnK59g== + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + integrity sha512-jlQ9gYLfk2p3V5Ag5fYhA7fv7OHzd1KUH0PRP46xc3TgwjwgROIW572AfYg/X9kaNq/LJnu6oJcFRXlIrGoTRw== + dependencies: + jsesc "~0.5.0" + +repeat-element@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" + integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + integrity sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A== + dependencies: + is-finite "^1.0.0" + +request@^2.79.0, request@^2.85.0: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-from-string@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" + integrity sha512-H7AkJWMobeskkttHyhTVtS0fxpFLjxhbfMa6Bk3wimP7sdPRGL3EyCg3sAQenFfAe+xQ+oAc85Nmtvq0ROM83Q== + +require-from-string@^2.0.0, require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + integrity sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug== + +resolve-alpn@^1.0.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" + integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== + +resolve@1.17.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" + +resolve@^1.10.0, resolve@^1.8.1, resolve@~1.22.1: + version "1.22.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== + dependencies: + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +responselike@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + integrity sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ== + dependencies: + lowercase-keys "^1.0.0" + +responselike@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.1.tgz#9a0bc8fdc252f3fb1cca68b016591059ba1422bc" + integrity sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw== + dependencies: + lowercase-keys "^2.0.0" + +resumer@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" + integrity sha512-Fn9X8rX8yYF4m81rZCK/5VmrmsSbqS/i3rDLl6ZZHAXgC2nTAx3dhwG8q8odP/RmdLa2YrybDJaAMg+X1ajY3w== + dependencies: + through "~2.3.4" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +rimraf@^2.2.8, rimraf@^2.6.2, rimraf@^2.6.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +rlp@^2.0.0, rlp@^2.2.1, rlp@^2.2.2, rlp@^2.2.3, rlp@^2.2.4: + version "2.2.7" + resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" + integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== + dependencies: + bn.js "^5.2.0" + +run-parallel-limit@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz#be80e936f5768623a38a963262d6bef8ff11e7ba" + integrity sha512-jJA7irRNM91jaKc3Hcl1npHsFLOXOoTkPCUL1JEa1R82O2miplXXRaGdjW/KM/98YQWDhJLiSs793CnXfblJUw== + dependencies: + queue-microtask "^1.2.2" + +rustbn.js@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" + integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== + +safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-event-emitter@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz#5b692ef22329ed8f69fdce607e50ca734f6f20af" + integrity sha512-e1wFe99A91XYYxoQbcq2ZJUWurxEyP8vfz7A7vuUe1s95q8r5ebraVaA1BukYJcpM6V16ugWoD9vngi8Ccu5fg== + dependencies: + events "^3.0.0" + +safe-regex-test@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" + integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-regex "^1.1.4" + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg== + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +scrypt-js@3.0.1, scrypt-js@^3.0.0, scrypt-js@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" + integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== + +scryptsy@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" + integrity sha512-aldIRgMozSJ/Gl6K6qmJZysRP82lz83Wb42vl4PWN8SaLFHIaOzLPc9nUUW2jQN88CuGm5q5HefJ9jZ3nWSmTw== + dependencies: + pbkdf2 "^3.0.3" + +secp256k1@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" + integrity sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA== + dependencies: + elliptic "^6.5.4" + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + +seedrandom@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.1.tgz#eb3dde015bcf55df05a233514e5df44ef9dce083" + integrity sha512-1/02Y/rUeU1CJBAGLebiC5Lbo5FnB22gQbIFFYTLkwvp1xdABZJH1sn4ZT1MzXmPpzv+Rf/Lu2NcsLJiK4rcDg== + +semaphore@>=1.0.1, semaphore@^1.0.3, semaphore@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" + integrity sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA== + +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@^7.3.8: + version "7.3.8" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" + integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== + dependencies: + lru-cache "^6.0.0" + +semver@~5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" + integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== + +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + +serialize-javascript@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + +serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.18.0" + +servify@^0.1.12: + version "0.1.12" + resolved "https://registry.yarnpkg.com/servify/-/servify-0.1.12.tgz#142ab7bee1f1d033b66d0707086085b17c06db95" + integrity sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw== + dependencies: + body-parser "^1.16.0" + cors "^2.8.1" + express "^4.14.0" + request "^2.79.0" + xhr "^2.3.3" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + +set-immediate-shim@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" + integrity sha512-Li5AOqrZWCVA2n5kryzEmqai6bKSIvpz5oUJHPVj6+dsbD3X1ixtsY5tEnsaNpH3pFAHmG8eIHUrtEtohrg+UQ== + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== + +simple-get@^2.7.0: + version "2.8.2" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.2.tgz#5708fb0919d440657326cd5fe7d2599d07705019" + integrity sha512-Ijd/rV5o+mSBBs4F/x9oDPtTx9Zb6X9brmnXvMW4J7IR15ngi9q5xxqWBKU744jTZiaXtxaPL7uHG6vtN8kUkw== + dependencies: + decompress-response "^3.3.0" + once "^1.3.1" + simple-concat "^1.0.0" + +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + integrity sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg== + +slash@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" + integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +solc@0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a" + integrity sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA== + dependencies: + command-exists "^1.2.8" + commander "3.0.2" + follow-redirects "^1.12.1" + fs-extra "^0.30.0" + js-sha3 "0.8.0" + memorystream "^0.3.1" + require-from-string "^2.0.0" + semver "^5.5.0" + tmp "0.0.33" + +solc@^0.4.20: + version "0.4.26" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.26.tgz#5390a62a99f40806b86258c737c1cf653cc35cb5" + integrity sha512-o+c6FpkiHd+HPjmjEVpQgH7fqZ14tJpXhho+/bQXlXbliLIS/xjXb42Vxh+qQY1WCSTMQ0+a5vR9vi0MfhU6mA== + dependencies: + fs-extra "^0.30.0" + memorystream "^0.3.1" + require-from-string "^1.1.0" + semver "^5.3.0" + yargs "^4.7.1" + +solc@^0.6.3: + version "0.6.12" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.6.12.tgz#48ac854e0c729361b22a7483645077f58cba080e" + integrity sha512-Lm0Ql2G9Qc7yPP2Ba+WNmzw2jwsrd3u4PobHYlSOxaut3TtUbj9+5ZrT6f4DUpNPEoBaFUOEg9Op9C0mk7ge9g== + dependencies: + command-exists "^1.2.8" + commander "3.0.2" + fs-extra "^0.30.0" + js-sha3 "0.8.0" + memorystream "^0.3.1" + require-from-string "^2.0.0" + semver "^5.5.0" + tmp "0.0.33" + +solidity-comments-extractor@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz#99d8f1361438f84019795d928b931f4e5c39ca19" + integrity sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw== + +source-map-resolve@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@0.5.12: + version "0.5.12" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" + integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-support@^0.4.15: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== + dependencies: + source-map "^0.5.6" + +source-map-support@^0.5.13: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" + integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== + +source-map@^0.5.6, source-map@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +spdx-correct@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.12" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz#69077835abe2710b65f03969898b6637b505a779" + integrity sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA== + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +sshpk@^1.7.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" + integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +stacktrace-parser@^0.1.10: + version "0.1.10" + resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" + integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== + dependencies: + type-fest "^0.7.1" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g== + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +stream-to-pull-stream@^1.7.1: + version "1.7.3" + resolved "https://registry.yarnpkg.com/stream-to-pull-stream/-/stream-to-pull-stream-1.7.3.tgz#4161aa2d2eb9964de60bfa1af7feaf917e874ece" + integrity sha512-6sNyqJpr5dIOQdgNy/xcDWwDuzAsAwVzhzrWlAPAQ7Lkjx/rv0wgvxEyKwTq6FmNd5rjTrELt/CLmaSw7crMGg== + dependencies: + looper "^3.0.0" + pull-stream "^3.2.3" + +streamsearch@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" + integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== + +strict-uri-encode@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + integrity sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ== + +string-format@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" + integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw== + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string.prototype.trim@~1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" + integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +string.prototype.trimend@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" + integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +string.prototype.trimstart@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" + integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + integrity sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g== + dependencies: + is-utf8 "^0.2.0" + +strip-hex-prefix@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" + integrity sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A== + dependencies: + is-hex-prefixed "1.0.0" + +strip-json-comments@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +swarm-js@^0.1.40: + version "0.1.42" + resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.42.tgz#497995c62df6696f6e22372f457120e43e727979" + integrity sha512-BV7c/dVlA3R6ya1lMlSSNPLYrntt0LUq4YMgy3iwpCIc6rZnS5W2wUoctarZ5pXlpKtxDDf9hNziEkcfrxdhqQ== + dependencies: + bluebird "^3.5.0" + buffer "^5.0.5" + eth-lib "^0.1.26" + fs-extra "^4.0.2" + got "^11.8.5" + mime-types "^2.1.16" + mkdirp-promise "^5.0.1" + mock-fs "^4.1.0" + setimmediate "^1.0.5" + tar "^4.0.2" + xhr-request "^1.0.1" + +table-layout@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.2.tgz#c4038a1853b0136d63365a734b6931cf4fad4a04" + integrity sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A== + dependencies: + array-back "^4.0.1" + deep-extend "~0.6.0" + typical "^5.2.0" + wordwrapjs "^4.0.0" + +table@^6.8.0: + version "6.8.1" + resolved "https://registry.yarnpkg.com/table/-/table-6.8.1.tgz#ea2b71359fe03b017a5fbc296204471158080bdf" + integrity sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA== + dependencies: + ajv "^8.0.1" + lodash.truncate "^4.4.2" + slice-ansi "^4.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + +tape@^4.6.3: + version "4.16.2" + resolved "https://registry.yarnpkg.com/tape/-/tape-4.16.2.tgz#7565e6af20426565557266e9dda7215869b297b6" + integrity sha512-TUChV+q0GxBBCEbfCYkGLkv8hDJYjMdSWdE0/Lr331sB389dsvFUHNV9ph5iQqKzt8Ss9drzcda/YeexclBFqg== + dependencies: + call-bind "~1.0.2" + deep-equal "~1.1.1" + defined "~1.0.1" + dotignore "~0.1.2" + for-each "~0.3.3" + glob "~7.2.3" + has "~1.0.3" + inherits "~2.0.4" + is-regex "~1.1.4" + minimist "~1.2.7" + object-inspect "~1.12.3" + resolve "~1.22.1" + resumer "~0.0.0" + string.prototype.trim "~1.2.7" + through "~2.3.8" + +tar@^4.0.2: + version "4.4.19" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" + integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA== + dependencies: + chownr "^1.1.4" + fs-minipass "^1.2.7" + minipass "^2.9.0" + minizlib "^1.3.3" + mkdirp "^0.5.5" + safe-buffer "^5.2.1" + yallist "^3.1.1" + +test-value@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/test-value/-/test-value-2.1.0.tgz#11da6ff670f3471a73b625ca4f3fdcf7bb748291" + integrity sha512-+1epbAxtKeXttkGFMTX9H42oqzOTufR1ceCF+GYA5aOmvaPq9wd4PUS8329fn2RRLGNeUkgRLnVpycjx8DsO2w== + dependencies: + array-back "^1.0.3" + typical "^2.6.0" + +testrpc@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/testrpc/-/testrpc-0.0.1.tgz#83e2195b1f5873aec7be1af8cbe6dcf39edb7aed" + integrity sha512-afH1hO+SQ/VPlmaLUFj2636QMeDvPCeQMc/9RBMW0IfjNe9gFD9Ra3ShqYkB7py0do1ZcCna/9acHyzTJ+GcNA== + +through2@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +through@~2.3.4, through@~2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== + +timed-out@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" + integrity sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA== + +tmp@0.0.33, tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +tmp@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877" + integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw== + dependencies: + rimraf "^2.6.3" + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + integrity sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og== + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg== + dependencies: + kind-of "^3.0.2" + +to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg== + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + integrity sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw== + +ts-command-line-args@^2.2.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.4.2.tgz#b4815b23c35f8a0159d4e69e01012d95690bc448" + integrity sha512-mJLQQBOdyD4XI/ZWQY44PIdYde47JhV2xl380O7twPkTQ+Y5vFDHsk8LOeXKuz7dVY5aDCfAzRarNfSqtKOkQQ== + dependencies: + "@morgan-stanley/ts-mocking-bird" "^0.6.2" + chalk "^4.1.0" + command-line-args "^5.1.1" + command-line-usage "^6.1.0" + string-format "^2.0.0" + +ts-essentials@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-1.0.4.tgz#ce3b5dade5f5d97cf69889c11bf7d2da8555b15a" + integrity sha512-q3N1xS4vZpRouhYHDPwO0bDW3EZ6SK9CrrDHxi/D6BPReSjpVgWIOpLS2o0gSBZm+7q/wyKp6RVM1AeeW7uyfQ== + +ts-essentials@^6.0.3: + version "6.0.7" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-6.0.7.tgz#5f4880911b7581a873783740ce8b94da163d18a6" + integrity sha512-2E4HIIj4tQJlIHuATRHayv0EfMGK3ris/GRk1E3CFnsZzeNV+hUmelbaTZHLtXaZppM5oLhHRtO04gINC4Jusw== + +ts-essentials@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-7.0.3.tgz#686fd155a02133eedcc5362dc8b5056cde3e5a38" + integrity sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ== + +ts-generator@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ts-generator/-/ts-generator-0.1.1.tgz#af46f2fb88a6db1f9785977e9590e7bcd79220ab" + integrity sha512-N+ahhZxTLYu1HNTQetwWcx3so8hcYbkKBHTr4b4/YgObFTIKkOSSsaa+nal12w8mfrJAyzJfETXawbNjSfP2gQ== + dependencies: + "@types/mkdirp" "^0.5.2" + "@types/prettier" "^2.1.1" + "@types/resolve" "^0.0.8" + chalk "^2.4.1" + glob "^7.1.2" + mkdirp "^0.5.1" + prettier "^2.1.2" + resolve "^1.8.1" + ts-essentials "^1.0.0" + +ts-node@^10.7.0: + version "10.9.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" + integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + +tslib@^1.9.3: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tsort@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" + integrity sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw== + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== + dependencies: + safe-buffer "^5.0.1" + +tweetnacl-util@^0.15.0, tweetnacl-util@^0.15.1: + version "0.15.1" + resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" + integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== + +tweetnacl@^1.0.0, tweetnacl@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" + integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== + +type-detect@^4.0.0, type-detect@^4.0.5: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type-fest@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" + integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== + +type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +type@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +type@^2.7.2: + version "2.7.2" + resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" + integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== + +typechain@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-3.0.0.tgz#d5a47700831f238e43f7429b987b4bb54849b92e" + integrity sha512-ft4KVmiN3zH4JUFu2WJBrwfHeDf772Tt2d8bssDTo/YcckKW2D+OwFrHXRC6hJvO3mHjFQTihoMV6fJOi0Hngg== + dependencies: + command-line-args "^4.0.7" + debug "^4.1.1" + fs-extra "^7.0.0" + js-sha3 "^0.8.0" + lodash "^4.17.15" + ts-essentials "^6.0.3" + ts-generator "^0.1.1" + +typechain@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-8.1.1.tgz#9c2e8012c2c4c586536fc18402dcd7034c4ff0bd" + integrity sha512-uF/sUvnXTOVF2FHKhQYnxHk4su4JjZR8vr4mA2mBaRwHTbwh0jIlqARz9XJr1tA0l7afJGvEa1dTSi4zt039LQ== + dependencies: + "@types/prettier" "^2.1.1" + debug "^4.3.1" + fs-extra "^7.0.0" + glob "7.1.7" + js-sha3 "^0.8.0" + lodash "^4.17.15" + mkdirp "^1.0.4" + prettier "^2.3.1" + ts-command-line-args "^2.2.0" + ts-essentials "^7.0.1" + +typed-array-length@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" + integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + is-typed-array "^1.1.9" + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== + +typescript@^4.6.4: + version "4.9.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" + integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== + +typewise-core@^1.2, typewise-core@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/typewise-core/-/typewise-core-1.2.0.tgz#97eb91805c7f55d2f941748fa50d315d991ef195" + integrity sha512-2SCC/WLzj2SbUwzFOzqMCkz5amXLlxtJqDKTICqg30x+2DZxcfZN2MvQZmGfXWKNWaKK9pBPsvkcwv8bF/gxKg== + +typewise@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typewise/-/typewise-1.0.3.tgz#1067936540af97937cc5dcf9922486e9fa284651" + integrity sha512-aXofE06xGhaQSPzt8hlTY+/YWQhm9P0jYUp1f2XtmW/3Bk0qzXcyFWAtPoo2uTGQj1ZwbDuSyuxicq+aDo8lCQ== + dependencies: + typewise-core "^1.2.0" + +typewiselite@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typewiselite/-/typewiselite-1.0.0.tgz#c8882fa1bb1092c06005a97f34ef5c8508e3664e" + integrity sha512-J9alhjVHupW3Wfz6qFRGgQw0N3gr8hOkw6zm7FZ6UR1Cse/oD9/JVok7DNE9TT9IbciDHX2Ex9+ksE6cRmtymw== + +typical@^2.6.0, typical@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/typical/-/typical-2.6.1.tgz#5c080e5d661cbbe38259d2e70a3c7253e873881d" + integrity sha512-ofhi8kjIje6npGozTip9Fr8iecmYfEbS06i0JnIg+rh51KakryWF4+jX8lLKZVhy6N+ID45WYSFCxPOdTWCzNg== + +typical@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" + integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== + +typical@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066" + integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== + +ultron@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" + integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== + +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== + dependencies: + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" + which-boxed-primitive "^1.0.2" + +underscore@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" + integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== + +undici@^5.14.0: + version "5.17.1" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.17.1.tgz#94fa53eb33d512be6c5e2bca58cbd3e6c2e26806" + integrity sha512-qMwK+1tmJ6DsMlsl/AYsZXnkIraXmQzzBuPSiQXP6q0WvNO+dwfiBAhjZWmxxW4N0PS31fzB6ulDOUS6cv8oKw== + dependencies: + busboy "^1.6.0" + +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + +unorm@^1.3.3: + version "1.6.0" + resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.6.0.tgz#029b289661fba714f1a9af439eb51d9b16c205af" + integrity sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA== + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ== + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg== + +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + integrity sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ== + dependencies: + prepend-http "^2.0.0" + +url-set-query@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" + integrity sha512-3AChu4NiXquPfeckE5R5cGdiHCMWJx1dwCWOmWIL4KHAziJNOFIYJlpGFeKDvwLPHovZRCxK3cYlwzqI9Vp+Gg== + +url@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + integrity sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ== + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +utf-8-validate@^5.0.2: + version "5.0.10" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" + integrity sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ== + dependencies: + node-gyp-build "^4.3.0" + +utf8@3.0.0, utf8@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" + integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +util.promisify@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.1.1.tgz#77832f57ced2c9478174149cae9b96e9918cd54b" + integrity sha512-/s3UsZUrIfa6xDhr7zZhnE9SLQ5RIXyYfiVnMMyMDzOc8WhWN4Nbh36H842OyurKbCDAesZOJaVyvmSl6fhGQw== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + for-each "^0.3.3" + has-symbols "^1.0.1" + object.getownpropertydescriptors "^2.1.1" + +util@^0.10.3: + version "0.10.4" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" + integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== + dependencies: + inherits "2.0.3" + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + +uuid@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== + +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +uuid@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" + integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== + +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +varint@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" + integrity sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow== + +vary@^1, vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +web3-bzz@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.11.tgz#41bc19a77444bd5365744596d778b811880f707f" + integrity sha512-XGpWUEElGypBjeFyUhTkiPXFbDVD6Nr/S5jznE3t8cWUA0FxRf1n3n/NuIZeb0H9RkN2Ctd/jNma/k8XGa3YKg== + dependencies: + "@types/node" "^12.12.6" + got "9.6.0" + swarm-js "^0.1.40" + underscore "1.9.1" + +web3-core-helpers@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.2.11.tgz#84c681ed0b942c0203f3b324a245a127e8c67a99" + integrity sha512-PEPoAoZd5ME7UfbnCZBdzIerpe74GEvlwT4AjOmHeCVZoIFk7EqvOZDejJHt+feJA6kMVTdd0xzRNN295UhC1A== + dependencies: + underscore "1.9.1" + web3-eth-iban "1.2.11" + web3-utils "1.2.11" + +web3-core-method@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.11.tgz#f880137d1507a0124912bf052534f168b8d8fbb6" + integrity sha512-ff0q76Cde94HAxLDZ6DbdmKniYCQVtvuaYh+rtOUMB6kssa5FX0q3vPmixi7NPooFnbKmmZCM6NvXg4IreTPIw== + dependencies: + "@ethersproject/transactions" "^5.0.0-beta.135" + underscore "1.9.1" + web3-core-helpers "1.2.11" + web3-core-promievent "1.2.11" + web3-core-subscriptions "1.2.11" + web3-utils "1.2.11" + +web3-core-promievent@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.11.tgz#51fe97ca0ddec2f99bf8c3306a7a8e4b094ea3cf" + integrity sha512-il4McoDa/Ox9Agh4kyfQ8Ak/9ABYpnF8poBLL33R/EnxLsJOGQG2nZhkJa3I067hocrPSjEdlPt/0bHXsln4qA== + dependencies: + eventemitter3 "4.0.4" + +web3-core-requestmanager@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.11.tgz#fe6eb603fbaee18530293a91f8cf26d8ae28c45a" + integrity sha512-oFhBtLfOiIbmfl6T6gYjjj9igOvtyxJ+fjS+byRxiwFJyJ5BQOz4/9/17gWR1Cq74paTlI7vDGxYfuvfE/mKvA== + dependencies: + underscore "1.9.1" + web3-core-helpers "1.2.11" + web3-providers-http "1.2.11" + web3-providers-ipc "1.2.11" + web3-providers-ws "1.2.11" + +web3-core-subscriptions@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.11.tgz#beca908fbfcb050c16f45f3f0f4c205e8505accd" + integrity sha512-qEF/OVqkCvQ7MPs1JylIZCZkin0aKK9lDxpAtQ1F8niEDGFqn7DT8E/vzbIa0GsOjL2fZjDhWJsaW+BSoAW1gg== + dependencies: + eventemitter3 "4.0.4" + underscore "1.9.1" + web3-core-helpers "1.2.11" + +web3-core@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.11.tgz#1043cacc1becb80638453cc5b2a14be9050288a7" + integrity sha512-CN7MEYOY5ryo5iVleIWRE3a3cZqVaLlIbIzDPsvQRUfzYnvzZQRZBm9Mq+ttDi2STOOzc1MKylspz/o3yq/LjQ== + dependencies: + "@types/bn.js" "^4.11.5" + "@types/node" "^12.12.6" + bignumber.js "^9.0.0" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-core-requestmanager "1.2.11" + web3-utils "1.2.11" + +web3-eth-abi@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.11.tgz#a887494e5d447c2926d557a3834edd66e17af9b0" + integrity sha512-PkRYc0+MjuLSgg03QVWqWlQivJqRwKItKtEpRUaxUAeLE7i/uU39gmzm2keHGcQXo3POXAbOnMqkDvOep89Crg== + dependencies: + "@ethersproject/abi" "5.0.0-beta.153" + underscore "1.9.1" + web3-utils "1.2.11" + +web3-eth-accounts@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.11.tgz#a9e3044da442d31903a7ce035a86d8fa33f90520" + integrity sha512-6FwPqEpCfKIh3nSSGeo3uBm2iFSnFJDfwL3oS9pyegRBXNsGRVpgiW63yhNzL0796StsvjHWwQnQHsZNxWAkGw== + dependencies: + crypto-browserify "3.12.0" + eth-lib "0.2.8" + ethereumjs-common "^1.3.2" + ethereumjs-tx "^2.1.1" + scrypt-js "^3.0.1" + underscore "1.9.1" + uuid "3.3.2" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-utils "1.2.11" + +web3-eth-contract@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.2.11.tgz#917065902bc27ce89da9a1da26e62ef663663b90" + integrity sha512-MzYuI/Rq2o6gn7vCGcnQgco63isPNK5lMAan2E51AJLknjSLnOxwNY3gM8BcKoy4Z+v5Dv00a03Xuk78JowFow== + dependencies: + "@types/bn.js" "^4.11.5" + underscore "1.9.1" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-core-promievent "1.2.11" + web3-core-subscriptions "1.2.11" + web3-eth-abi "1.2.11" + web3-utils "1.2.11" + +web3-eth-ens@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.2.11.tgz#26d4d7f16d6cbcfff918e39832b939edc3162532" + integrity sha512-dbW7dXP6HqT1EAPvnniZVnmw6TmQEKF6/1KgAxbo8iBBYrVTMDGFQUUnZ+C4VETGrwwaqtX4L9d/FrQhZ6SUiA== + dependencies: + content-hash "^2.5.2" + eth-ens-namehash "2.0.8" + underscore "1.9.1" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-promievent "1.2.11" + web3-eth-abi "1.2.11" + web3-eth-contract "1.2.11" + web3-utils "1.2.11" + +web3-eth-iban@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.2.11.tgz#f5f73298305bc7392e2f188bf38a7362b42144ef" + integrity sha512-ozuVlZ5jwFC2hJY4+fH9pIcuH1xP0HEFhtWsR69u9uDIANHLPQQtWYmdj7xQ3p2YT4bQLq/axKhZi7EZVetmxQ== + dependencies: + bn.js "^4.11.9" + web3-utils "1.2.11" + +web3-eth-personal@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.11.tgz#a38b3942a1d87a62070ce0622a941553c3d5aa70" + integrity sha512-42IzUtKq9iHZ8K9VN0vAI50iSU9tOA1V7XU2BhF/tb7We2iKBVdkley2fg26TxlOcKNEHm7o6HRtiiFsVK4Ifw== + dependencies: + "@types/node" "^12.12.6" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-net "1.2.11" + web3-utils "1.2.11" + +web3-eth@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.2.11.tgz#4c81fcb6285b8caf544058fba3ae802968fdc793" + integrity sha512-REvxW1wJ58AgHPcXPJOL49d1K/dPmuw4LjPLBPStOVkQjzDTVmJEIsiLwn2YeuNDd4pfakBwT8L3bz1G1/wVsQ== + dependencies: + underscore "1.9.1" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-core-subscriptions "1.2.11" + web3-eth-abi "1.2.11" + web3-eth-accounts "1.2.11" + web3-eth-contract "1.2.11" + web3-eth-ens "1.2.11" + web3-eth-iban "1.2.11" + web3-eth-personal "1.2.11" + web3-net "1.2.11" + web3-utils "1.2.11" + +web3-net@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.2.11.tgz#eda68ef25e5cdb64c96c39085cdb74669aabbe1b" + integrity sha512-sjrSDj0pTfZouR5BSTItCuZ5K/oZPVdVciPQ6981PPPIwJJkCMeVjD7I4zO3qDPCnBjBSbWvVnLdwqUBPtHxyg== + dependencies: + web3-core "1.2.11" + web3-core-method "1.2.11" + web3-utils "1.2.11" + +web3-provider-engine@14.2.1: + version "14.2.1" + resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-14.2.1.tgz#ef351578797bf170e08d529cb5b02f8751329b95" + integrity sha512-iSv31h2qXkr9vrL6UZDm4leZMc32SjWJFGOp/D92JXfcEboCqraZyuExDkpxKw8ziTufXieNM7LSXNHzszYdJw== + dependencies: + async "^2.5.0" + backoff "^2.5.0" + clone "^2.0.0" + cross-fetch "^2.1.0" + eth-block-tracker "^3.0.0" + eth-json-rpc-infura "^3.1.0" + eth-sig-util "^1.4.2" + ethereumjs-block "^1.2.2" + ethereumjs-tx "^1.2.0" + ethereumjs-util "^5.1.5" + ethereumjs-vm "^2.3.4" + json-rpc-error "^2.0.0" + json-stable-stringify "^1.0.1" + promise-to-callback "^1.0.0" + readable-stream "^2.2.9" + request "^2.85.0" + semaphore "^1.0.3" + ws "^5.1.1" + xhr "^2.2.0" + xtend "^4.0.1" + +web3-providers-http@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.2.11.tgz#1cd03442c61670572d40e4dcdf1faff8bd91e7c6" + integrity sha512-psh4hYGb1+ijWywfwpB2cvvOIMISlR44F/rJtYkRmQ5jMvG4FOCPlQJPiHQZo+2cc3HbktvvSJzIhkWQJdmvrA== + dependencies: + web3-core-helpers "1.2.11" + xhr2-cookies "1.1.0" + +web3-providers-ipc@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.11.tgz#d16d6c9be1be6e0b4f4536c4acc16b0f4f27ef21" + integrity sha512-yhc7Y/k8hBV/KlELxynWjJDzmgDEDjIjBzXK+e0rHBsYEhdCNdIH5Psa456c+l0qTEU2YzycF8VAjYpWfPnBpQ== + dependencies: + oboe "2.1.4" + underscore "1.9.1" + web3-core-helpers "1.2.11" + +web3-providers-ws@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.11.tgz#a1dfd6d9778d840561d9ec13dd453046451a96bb" + integrity sha512-ZxnjIY1Er8Ty+cE4migzr43zA/+72AF1myzsLaU5eVgdsfV7Jqx7Dix1hbevNZDKFlSoEyq/3j/jYalh3So1Zg== + dependencies: + eventemitter3 "4.0.4" + underscore "1.9.1" + web3-core-helpers "1.2.11" + websocket "^1.0.31" + +web3-shh@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.11.tgz#f5d086f9621c9a47e98d438010385b5f059fd88f" + integrity sha512-B3OrO3oG1L+bv3E1sTwCx66injW1A8hhwpknDUbV+sw3fehFazA06z9SGXUefuFI1kVs4q2vRi0n4oCcI4dZDg== + dependencies: + web3-core "1.2.11" + web3-core-method "1.2.11" + web3-core-subscriptions "1.2.11" + web3-net "1.2.11" + +web3-utils@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.11.tgz#af1942aead3fb166ae851a985bed8ef2c2d95a82" + integrity sha512-3Tq09izhD+ThqHEaWYX4VOT7dNPdZiO+c/1QMA0s5X2lDFKK/xHJb7cyTRRVzN2LvlHbR7baS1tmQhSua51TcQ== + dependencies: + bn.js "^4.11.9" + eth-lib "0.2.8" + ethereum-bloom-filters "^1.0.6" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + underscore "1.9.1" + utf8 "3.0.0" + +web3-utils@^1.0.0-beta.31: + version "1.8.2" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.8.2.tgz#c32dec5e9b955acbab220eefd7715bc540b75cc9" + integrity sha512-v7j6xhfLQfY7xQDrUP0BKbaNrmZ2/+egbqP9q3KYmOiPpnvAfol+32slgL0WX/5n8VPvKCK5EZ1HGrAVICSToA== + dependencies: + bn.js "^5.2.1" + ethereum-bloom-filters "^1.0.6" + ethereumjs-util "^7.1.0" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + utf8 "3.0.0" + +web3@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3/-/web3-1.2.11.tgz#50f458b2e8b11aa37302071c170ed61cff332975" + integrity sha512-mjQ8HeU41G6hgOYm1pmeH0mRAeNKJGnJEUzDMoerkpw7QUQT4exVREgF1MYPvL/z6vAshOXei25LE/t/Bxl8yQ== + dependencies: + web3-bzz "1.2.11" + web3-core "1.2.11" + web3-eth "1.2.11" + web3-eth-personal "1.2.11" + web3-net "1.2.11" + web3-shh "1.2.11" + web3-utils "1.2.11" + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +websocket@1.0.32: + version "1.0.32" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.32.tgz#1f16ddab3a21a2d929dec1687ab21cfdc6d3dbb1" + integrity sha512-i4yhcllSP4wrpoPMU2N0TQ/q0O94LRG/eUQjEAamRltjQ1oT1PFFKOG4i877OlJgCG8rw6LrrowJp+TYCEWF7Q== + dependencies: + bufferutil "^4.0.1" + debug "^2.2.0" + es5-ext "^0.10.50" + typedarray-to-buffer "^3.1.5" + utf-8-validate "^5.0.2" + yaeti "^0.0.6" + +websocket@^1.0.31: + version "1.0.34" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" + integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== + dependencies: + bufferutil "^4.0.1" + debug "^2.2.0" + es5-ext "^0.10.50" + typedarray-to-buffer "^3.1.5" + utf-8-validate "^5.0.2" + yaeti "^0.0.6" + +whatwg-fetch@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" + integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + +which-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + integrity sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ== + +which-typed-array@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" + integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + is-typed-array "^1.1.10" + +which@^1.2.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +window-size@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" + integrity sha512-UD7d8HFA2+PZsbKyaOCEy8gMh1oDtHgJh1LfgjQ4zVXmYjAT/kvz3PueITKuqDiIXQe7yzpPnxX3lNc+AhQMyw== + +wordwrapjs@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.1.tgz#d9790bccfb110a0fc7836b5ebce0937b37a8b98f" + integrity sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA== + dependencies: + reduce-flatten "^2.0.0" + typical "^5.2.0" + +workerpool@6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" + integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + integrity sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw== + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== + +ws@^3.0.0: + version "3.3.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" + integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== + dependencies: + async-limiter "~1.0.0" + safe-buffer "~5.1.0" + ultron "~1.1.0" + +ws@^5.1.1: + version "5.2.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.3.tgz#05541053414921bc29c63bee14b8b0dd50b07b3d" + integrity sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA== + dependencies: + async-limiter "~1.0.0" + +ws@^7.4.6: + version "7.5.9" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" + integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== + +xhr-request-promise@^0.1.2: + version "0.1.3" + resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz#2d5f4b16d8c6c893be97f1a62b0ed4cf3ca5f96c" + integrity sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg== + dependencies: + xhr-request "^1.1.0" + +xhr-request@^1.0.1, xhr-request@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/xhr-request/-/xhr-request-1.1.0.tgz#f4a7c1868b9f198723444d82dcae317643f2e2ed" + integrity sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA== + dependencies: + buffer-to-arraybuffer "^0.0.5" + object-assign "^4.1.1" + query-string "^5.0.1" + simple-get "^2.7.0" + timed-out "^4.0.1" + url-set-query "^1.0.0" + xhr "^2.0.4" + +xhr2-cookies@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" + integrity sha512-hjXUA6q+jl/bd8ADHcVfFsSPIf+tyLIjuO9TwJC9WI6JP2zKcS7C+p56I9kCLLsaCiNT035iYvEUUzdEFj/8+g== + dependencies: + cookiejar "^2.1.1" + +xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: + version "2.6.0" + resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.6.0.tgz#b69d4395e792b4173d6b7df077f0fc5e4e2b249d" + integrity sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA== + dependencies: + global "~4.4.0" + is-function "^1.0.1" + parse-headers "^2.0.0" + xtend "^4.0.0" + +xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +xtend@~2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" + integrity sha512-vMNKzr2rHP9Dp/e1NQFnLQlwlhp9L/LfvnsVdHxN1f+uggyVI3i08uD14GPvCToPkdsRfyPqIyYGmIk58V98ZQ== + dependencies: + object-keys "~0.4.0" + +y18n@^3.2.1: + version "3.2.2" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696" + integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yaeti@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" + integrity sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug== + +yallist@^3.0.0, yallist@^3.0.2, yallist@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yaml@^1.10.2: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + +yargs-parser@20.2.4: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + +yargs-parser@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" + integrity sha512-9pIKIJhnI5tonzG6OnCFlz/yln8xHYcGl+pn3xR0Vzff0vzN1PbNRaelgfgRUwZ3s4i3jvxT9WhmUGL4whnasA== + dependencies: + camelcase "^3.0.0" + lodash.assign "^4.0.6" + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yargs@^4.7.1: + version "4.8.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0" + integrity sha512-LqodLrnIDM3IFT+Hf/5sxBnEGECrfdC1uIbgZeJmESCSo4HoCAaKEus8MylXHAkdacGc0ye+Qa+dpkuom8uVYA== + dependencies: + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + lodash.assign "^4.0.3" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.1" + which-module "^1.0.0" + window-size "^0.2.0" + y18n "^3.2.1" + yargs-parser "^2.4.1" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zksync-web3@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.8.1.tgz#db289d8f6caf61f4d5ddc471fa3448d93208dc14" + integrity sha512-1A4aHPQ3MyuGjpv5X/8pVEN+MdZqMjfVmiweQSRjOlklXYu65wT9BGEOtCmMs5d3gIvLp4ssfTeuR5OCKOD2kw== + +zod@^3.20.2: + version "3.20.2" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.20.2.tgz#068606642c8f51b3333981f91c0a8ab37dfc2807" + integrity sha512-1MzNQdAvO+54H+EaK5YpyEy0T+Ejo/7YLHS93G3RnYWh5gaotGHwGeN/ZO687qEDU2y4CdStQYXVHIgrUl5UVQ== From 4841a8c0643b60d1a03f165e1ae7ae8ddbfe8d82 Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Sun, 5 Feb 2023 04:12:36 +1100 Subject: [PATCH 33/43] settings --- contracts/Flow.sol | 7 +- contracts/Minter.sol | 2 +- contracts/Voter.sol | 300 ++++++++++++------ contracts/factories/PairFactory.sol | 66 ++-- deploy/00_velo.ts | 2 + deploy/15_init.ts | 22 +- .../{arbitrumOne => arbitrumOneOLD}/.chainId | 0 .../.migrations.json | 0 .../BribeFactory.json | 0 .../GaugeFactory.json | 0 .../MerkleClaim.json | 0 .../Minter.json | 0 .../PairFactory.json | 0 .../RedemptionReceiver.json | 0 .../RewardsDistributor.json | 0 .../Router.json | 0 .../VeArtProxy.json | 0 .../{arbitrumOne => arbitrumOneOLD}/Velo.json | 0 .../VeloGovernor.json | 0 .../VelodromeLibrary.json | 0 .../Voter.json | 0 .../VotingEscrow.json | 0 .../WrappedExternalBribeFactory.json | 0 .../4e21824d68c90a2d8601cfb8f8d80414.json | 0 .../f93feb6db909c3f14d7eec3a3196fbbd.json | 0 package.json | 3 +- tasks/log/failed.csv | 2 + tasks/log/successful.csv | 5 +- tasks/sample_partners.csv | 6 +- 29 files changed, 274 insertions(+), 141 deletions(-) rename deployments/{arbitrumOne => arbitrumOneOLD}/.chainId (100%) rename deployments/{arbitrumOne => arbitrumOneOLD}/.migrations.json (100%) rename deployments/{arbitrumOne => arbitrumOneOLD}/BribeFactory.json (100%) rename deployments/{arbitrumOne => arbitrumOneOLD}/GaugeFactory.json (100%) rename deployments/{arbitrumOne => arbitrumOneOLD}/MerkleClaim.json (100%) rename deployments/{arbitrumOne => arbitrumOneOLD}/Minter.json (100%) rename deployments/{arbitrumOne => arbitrumOneOLD}/PairFactory.json (100%) rename deployments/{arbitrumOne => arbitrumOneOLD}/RedemptionReceiver.json (100%) rename deployments/{arbitrumOne => arbitrumOneOLD}/RewardsDistributor.json (100%) rename deployments/{arbitrumOne => arbitrumOneOLD}/Router.json (100%) rename deployments/{arbitrumOne => arbitrumOneOLD}/VeArtProxy.json (100%) rename deployments/{arbitrumOne => arbitrumOneOLD}/Velo.json (100%) rename deployments/{arbitrumOne => arbitrumOneOLD}/VeloGovernor.json (100%) rename deployments/{arbitrumOne => arbitrumOneOLD}/VelodromeLibrary.json (100%) rename deployments/{arbitrumOne => arbitrumOneOLD}/Voter.json (100%) rename deployments/{arbitrumOne => arbitrumOneOLD}/VotingEscrow.json (100%) rename deployments/{arbitrumOne => arbitrumOneOLD}/WrappedExternalBribeFactory.json (100%) rename deployments/{arbitrumOne => arbitrumOneOLD}/solcInputs/4e21824d68c90a2d8601cfb8f8d80414.json (100%) rename deployments/{arbitrumOne => arbitrumOneOLD}/solcInputs/f93feb6db909c3f14d7eec3a3196fbbd.json (100%) diff --git a/contracts/Flow.sol b/contracts/Flow.sol index e0d00b1d..20d75888 100644 --- a/contracts/Flow.sol +++ b/contracts/Flow.sol @@ -45,14 +45,11 @@ contract Flow is IFlow { merkleClaim = _merkleClaim; } - // Initial mint: total 82M - // 4M for "Genesis" pools - // 30M for liquid team allocation (40M excl init veNFT) - // 48M for future partners + // NFTs are minted from this amount as well now function initialMint(address _recipient) external { require(msg.sender == minter && !initialMinted); initialMinted = true; - _mint(_recipient, 400 * 1e6 * 1e18); + _mint(_recipient, 400 * 1e6 * 1e18); //#settings } function approve(address _spender, uint256 _value) external returns (bool) { diff --git a/contracts/Minter.sol b/contracts/Minter.sol index b701d2ac..4f38e9b4 100644 --- a/contracts/Minter.sol +++ b/contracts/Minter.sol @@ -27,7 +27,7 @@ contract Minter is IMinter { address public team; address public pendingTeam; uint256 public teamRate; - uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05% + uint256 public constant MAX_TEAM_RATE = 50; // 5% max event Mint( address indexed sender, diff --git a/contracts/Voter.sol b/contracts/Voter.sol index e4353dde..2fe3b5b6 100644 --- a/contracts/Voter.sol +++ b/contracts/Voter.sol @@ -1,31 +1,30 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.13; -import 'contracts/libraries/Math.sol'; -import 'contracts/interfaces/IBribe.sol'; -import 'contracts/interfaces/IBribeFactory.sol'; -import 'contracts/interfaces/IGauge.sol'; -import 'contracts/interfaces/IGaugeFactory.sol'; -import 'contracts/interfaces/IERC20.sol'; -import 'contracts/interfaces/IMinter.sol'; -import 'contracts/interfaces/IPair.sol'; -import 'contracts/interfaces/IPairFactory.sol'; -import 'contracts/interfaces/IVoter.sol'; -import 'contracts/interfaces/IVotingEscrow.sol'; +import "contracts/libraries/Math.sol"; +import "contracts/interfaces/IBribe.sol"; +import "contracts/interfaces/IBribeFactory.sol"; +import "contracts/interfaces/IGauge.sol"; +import "contracts/interfaces/IGaugeFactory.sol"; +import "contracts/interfaces/IERC20.sol"; +import "contracts/interfaces/IMinter.sol"; +import "contracts/interfaces/IPair.sol"; +import "contracts/interfaces/IPairFactory.sol"; +import "contracts/interfaces/IVoter.sol"; +import "contracts/interfaces/IVotingEscrow.sol"; contract Voter is IVoter { - address public immutable _ve; // the ve token that governs these contracts address public immutable factory; // the PairFactory address internal immutable base; address public immutable gaugefactory; address public immutable bribefactory; - uint internal constant DURATION = 7 days; // rewards are released over 7 days + uint256 internal constant DURATION = 7 days; // rewards are released over 7 days address public minter; address public governor; // should be set to an IGovernor address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO - uint public totalWeight; // total voting weight + uint256 public totalWeight; // total voting weight address[] public pools; // all pools viable for incentives mapping(address => address) public gauges; // pool => gauge @@ -33,28 +32,57 @@ contract Voter is IVoter { mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees) mapping(address => address) public external_bribes; // gauge => external bribe (real bribes) mapping(address => uint256) public weights; // pool => weight - mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes - mapping(uint => address[]) public poolVote; // nft => pools - mapping(uint => uint) public usedWeights; // nft => total voting weight of user - mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch + mapping(uint256 => mapping(address => uint256)) public votes; // nft => pool => votes + mapping(uint256 => address[]) public poolVote; // nft => pools + mapping(uint256 => uint256) public usedWeights; // nft => total voting weight of user + mapping(uint256 => uint256) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch mapping(address => bool) public isGauge; mapping(address => bool) public isWhitelisted; mapping(address => bool) public isAlive; - event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool); + event GaugeCreated( + address indexed gauge, + address creator, + address internal_bribe, + address indexed external_bribe, + address indexed pool + ); event GaugeKilled(address indexed gauge); event GaugeRevived(address indexed gauge); - event Voted(address indexed voter, uint tokenId, uint256 weight); - event Abstained(uint tokenId, uint256 weight); - event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount); - event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount); - event NotifyReward(address indexed sender, address indexed reward, uint amount); - event DistributeReward(address indexed sender, address indexed gauge, uint amount); - event Attach(address indexed owner, address indexed gauge, uint tokenId); - event Detach(address indexed owner, address indexed gauge, uint tokenId); + event Voted(address indexed voter, uint256 tokenId, uint256 weight); + event Abstained(uint256 tokenId, uint256 weight); + event Deposit( + address indexed lp, + address indexed gauge, + uint256 tokenId, + uint256 amount + ); + event Withdraw( + address indexed lp, + address indexed gauge, + uint256 tokenId, + uint256 amount + ); + event NotifyReward( + address indexed sender, + address indexed reward, + uint256 amount + ); + event DistributeReward( + address indexed sender, + address indexed gauge, + uint256 amount + ); + event Attach(address indexed owner, address indexed gauge, uint256 tokenId); + event Detach(address indexed owner, address indexed gauge, uint256 tokenId); event Whitelisted(address indexed whitelister, address indexed token); - constructor(address __ve, address _factory, address _gauges, address _bribes) { + constructor( + address __ve, + address _factory, + address _gauges, + address _bribes + ) { _ve = __ve; factory = _factory; base = IVotingEscrow(__ve).token(); @@ -66,7 +94,7 @@ contract Voter is IVoter { } // simple re-entrancy check - uint internal _unlocked = 1; + uint256 internal _unlocked = 1; modifier lock() { require(_unlocked == 1); _unlocked = 2; @@ -74,15 +102,18 @@ contract Voter is IVoter { _unlocked = 1; } - modifier onlyNewEpoch(uint _tokenId) { - // ensure new epoch since last vote - require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], "TOKEN_ALREADY_VOTED_THIS_EPOCH"); + modifier onlyNewEpoch(uint256 _tokenId) { + // ensure new epoch since last vote + require( + (block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], + "TOKEN_ALREADY_VOTED_THIS_EPOCH" + ); _; } function initialize(address[] memory _tokens, address _minter) external { require(msg.sender == minter); - for (uint i = 0; i < _tokens.length; i++) { + for (uint256 i = 0; i < _tokens.length; i++) { _whitelist(_tokens[i]); } minter = _minter; @@ -98,19 +129,19 @@ contract Voter is IVoter { emergencyCouncil = _council; } - function reset(uint _tokenId) external onlyNewEpoch(_tokenId) { + function reset(uint256 _tokenId) external onlyNewEpoch(_tokenId) { require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId)); lastVoted[_tokenId] = block.timestamp; _reset(_tokenId); IVotingEscrow(_ve).abstain(_tokenId); } - function _reset(uint _tokenId) internal { + function _reset(uint256 _tokenId) internal { address[] storage _poolVote = poolVote[_tokenId]; - uint _poolVoteCnt = _poolVote.length; + uint256 _poolVoteCnt = _poolVote.length; uint256 _totalWeight = 0; - for (uint i = 0; i < _poolVoteCnt; i ++) { + for (uint256 i = 0; i < _poolVoteCnt; i++) { address _pool = _poolVote[i]; uint256 _votes = votes[_tokenId][_pool]; @@ -119,8 +150,14 @@ contract Voter is IVoter { weights[_pool] -= _votes; votes[_tokenId][_pool] -= _votes; if (_votes > 0) { - IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId); - IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId); + IBribe(internal_bribes[gauges[_pool]])._withdraw( + uint256(_votes), + _tokenId + ); + IBribe(external_bribes[gauges[_pool]])._withdraw( + uint256(_votes), + _tokenId + ); _totalWeight += _votes; } else { _totalWeight -= _votes; @@ -133,36 +170,43 @@ contract Voter is IVoter { delete poolVote[_tokenId]; } - function poke(uint _tokenId) external { - address[] memory _poolVote = poolVote[_tokenId]; - uint _poolCnt = _poolVote.length; - uint256[] memory _weights = new uint256[](_poolCnt); + // remove poke function - for (uint i = 0; i < _poolCnt; i ++) { - _weights[i] = votes[_tokenId][_poolVote[i]]; - } + // function poke(uint _tokenId) external { + // address[] memory _poolVote = poolVote[_tokenId]; + // uint _poolCnt = _poolVote.length; + // uint256[] memory _weights = new uint256[](_poolCnt); - _vote(_tokenId, _poolVote, _weights); - } + // for (uint i = 0; i < _poolCnt; i ++) { + // _weights[i] = votes[_tokenId][_poolVote[i]]; + // } - function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal { + // _vote(_tokenId, _poolVote, _weights); + // } + + function _vote( + uint256 _tokenId, + address[] memory _poolVote, + uint256[] memory _weights + ) internal { _reset(_tokenId); - uint _poolCnt = _poolVote.length; + uint256 _poolCnt = _poolVote.length; uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId); uint256 _totalVoteWeight = 0; uint256 _totalWeight = 0; uint256 _usedWeight = 0; - for (uint i = 0; i < _poolCnt; i++) { + for (uint256 i = 0; i < _poolCnt; i++) { _totalVoteWeight += _weights[i]; } - for (uint i = 0; i < _poolCnt; i++) { + for (uint256 i = 0; i < _poolCnt; i++) { address _pool = _poolVote[i]; address _gauge = gauges[_pool]; if (isGauge[_gauge]) { - uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight; + uint256 _poolWeight = (_weights[i] * _weight) / + _totalVoteWeight; require(votes[_tokenId][_pool] == 0); require(_poolWeight != 0); _updateFor(_gauge); @@ -171,8 +215,14 @@ contract Voter is IVoter { weights[_pool] += _poolWeight; votes[_tokenId][_pool] += _poolWeight; - IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId); - IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId); + IBribe(internal_bribes[_gauge])._deposit( + uint256(_poolWeight), + _tokenId + ); + IBribe(external_bribes[_gauge])._deposit( + uint256(_poolWeight), + _tokenId + ); _usedWeight += _poolWeight; _totalWeight += _poolWeight; emit Voted(msg.sender, _tokenId, _poolWeight); @@ -183,7 +233,11 @@ contract Voter is IVoter { usedWeights[_tokenId] = uint256(_usedWeight); } - function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) { + function vote( + uint256 tokenId, + address[] calldata _poolVote, + uint256[] calldata _weights + ) external onlyNewEpoch(tokenId) { require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId)); require(_poolVote.length == _weights.length); lastVoted[tokenId] = block.timestamp; @@ -217,20 +271,33 @@ contract Voter is IVoter { internalRewards[1] = tokenB; if (base != tokenA && base != tokenB) { - allowedRewards[2] = base; + allowedRewards[2] = base; } } - if (msg.sender != governor) { // gov can create for any pool, even non-Velocimeter pairs + if (msg.sender != governor) { + // gov can create for any pool, even non-Velocimeter pairs require(isPair, "!_pool"); - require(isWhitelisted[tokenA] && isWhitelisted[tokenB], "!whitelisted"); + require( + isWhitelisted[tokenA] && isWhitelisted[tokenB], + "!whitelisted" + ); } - address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards); - address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards); - address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards); - - IERC20(base).approve(_gauge, type(uint).max); + address _internal_bribe = IBribeFactory(bribefactory) + .createInternalBribe(internalRewards); + address _external_bribe = IBribeFactory(bribefactory) + .createExternalBribe(allowedRewards); + address _gauge = IGaugeFactory(gaugefactory).createGauge( + _pool, + _internal_bribe, + _external_bribe, + _ve, + isPair, + allowedRewards + ); + + IERC20(base).approve(_gauge, type(uint256).max); internal_bribes[_gauge] = _internal_bribe; external_bribes[_gauge] = _external_bribe; gauges[_pool] = _gauge; @@ -239,7 +306,13 @@ contract Voter is IVoter { isAlive[_gauge] = true; _updateFor(_gauge); pools.push(_pool); - emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool); + emit GaugeCreated( + _gauge, + msg.sender, + _internal_bribe, + _external_bribe, + _pool + ); return _gauge; } @@ -258,41 +331,49 @@ contract Voter is IVoter { emit GaugeRevived(_gauge); } - function attachTokenToGauge(uint tokenId, address account) external { + function attachTokenToGauge(uint256 tokenId, address account) external { require(isGauge[msg.sender]); require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId); emit Attach(account, msg.sender, tokenId); } - function emitDeposit(uint tokenId, address account, uint amount) external { + function emitDeposit( + uint256 tokenId, + address account, + uint256 amount + ) external { require(isGauge[msg.sender]); require(isAlive[msg.sender]); emit Deposit(account, msg.sender, tokenId, amount); } - function detachTokenFromGauge(uint tokenId, address account) external { + function detachTokenFromGauge(uint256 tokenId, address account) external { require(isGauge[msg.sender]); if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId); emit Detach(account, msg.sender, tokenId); } - function emitWithdraw(uint tokenId, address account, uint amount) external { + function emitWithdraw( + uint256 tokenId, + address account, + uint256 amount + ) external { require(isGauge[msg.sender]); emit Withdraw(account, msg.sender, tokenId, amount); } - function length() external view returns (uint) { + function length() external view returns (uint256) { return pools.length; } - uint internal index; - mapping(address => uint) internal supplyIndex; - mapping(address => uint) public claimable; + uint256 internal index; + mapping(address => uint256) internal supplyIndex; + mapping(address => uint256) public claimable; - function notifyRewardAmount(uint amount) external { + function notifyRewardAmount(uint256 amount) external { _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in - uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim + uint256 _ratio = (amount * 1e18) / totalWeight; // 1e18 adjustment is removed during claim if (_ratio > 0) { index += _ratio; } @@ -300,13 +381,13 @@ contract Voter is IVoter { } function updateFor(address[] memory _gauges) external { - for (uint i = 0; i < _gauges.length; i++) { + for (uint256 i = 0; i < _gauges.length; i++) { _updateFor(_gauges[i]); } } - function updateForRange(uint start, uint end) public { - for (uint i = start; i < end; i++) { + function updateForRange(uint256 start, uint256 end) public { + for (uint256 i = start; i < end; i++) { _updateFor(gauges[pools[i]]); } } @@ -323,12 +404,12 @@ contract Voter is IVoter { address _pool = poolForGauge[_gauge]; uint256 _supplied = weights[_pool]; if (_supplied > 0) { - uint _supplyIndex = supplyIndex[_gauge]; - uint _index = index; // get global index0 for accumulated distro + uint256 _supplyIndex = supplyIndex[_gauge]; + uint256 _index = index; // get global index0 for accumulated distro supplyIndex[_gauge] = _index; // update _gauge current position to global position - uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued + uint256 _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued if (_delta > 0) { - uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token + uint256 _share = (uint256(_supplied) * _delta) / 1e18; // add accrued difference for each supplied token if (isAlive[_gauge]) { claimable[_gauge] += _share; } @@ -338,29 +419,39 @@ contract Voter is IVoter { } } - function claimRewards(address[] memory _gauges, address[][] memory _tokens) external { - for (uint i = 0; i < _gauges.length; i++) { + function claimRewards(address[] memory _gauges, address[][] memory _tokens) + external + { + for (uint256 i = 0; i < _gauges.length; i++) { IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]); } } - function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external { + function claimBribes( + address[] memory _bribes, + address[][] memory _tokens, + uint256 _tokenId + ) external { require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId)); - for (uint i = 0; i < _bribes.length; i++) { + for (uint256 i = 0; i < _bribes.length; i++) { IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]); } } - function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external { + function claimFees( + address[] memory _fees, + address[][] memory _tokens, + uint256 _tokenId + ) external { require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId)); - for (uint i = 0; i < _fees.length; i++) { + for (uint256 i = 0; i < _fees.length; i++) { IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]); } } function distributeFees(address[] memory _gauges) external { - for (uint i = 0; i < _gauges.length; i++) { - if (IGauge(_gauges[i]).isForPair()){ + for (uint256 i = 0; i < _gauges.length; i++) { + if (IGauge(_gauges[i]).isForPair()) { IGauge(_gauges[i]).claimFees(); } } @@ -369,8 +460,10 @@ contract Voter is IVoter { function distribute(address _gauge) public lock { IMinter(minter).update_period(); _updateFor(_gauge); // should set claimable to 0 if killed - uint _claimable = claimable[_gauge]; - if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) { + uint256 _claimable = claimable[_gauge]; + if ( + _claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0 + ) { claimable[_gauge] = 0; IGauge(_gauge).notifyRewardAmount(base, _claimable); emit DistributeReward(msg.sender, _gauge, _claimable); @@ -385,22 +478,33 @@ contract Voter is IVoter { distribute(0, pools.length); } - function distribute(uint start, uint finish) public { - for (uint x = start; x < finish; x++) { + function distribute(uint256 start, uint256 finish) public { + for (uint256 x = start; x < finish; x++) { distribute(gauges[pools[x]]); } } function distribute(address[] memory _gauges) external { - for (uint x = 0; x < _gauges.length; x++) { + for (uint256 x = 0; x < _gauges.length; x++) { distribute(_gauges[x]); } } - function _safeTransferFrom(address token, address from, address to, uint256 value) internal { + function _safeTransferFrom( + address token, + address from, + address to, + uint256 value + ) internal { require(token.code.length > 0); - (bool success, bytes memory data) = - token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value)); + (bool success, bytes memory data) = token.call( + abi.encodeWithSelector( + IERC20.transferFrom.selector, + from, + to, + value + ) + ); require(success && (data.length == 0 || abi.decode(data, (bool)))); } } diff --git a/contracts/factories/PairFactory.sol b/contracts/factories/PairFactory.sol index 752324e9..4a3175ee 100644 --- a/contracts/factories/PairFactory.sol +++ b/contracts/factories/PairFactory.sol @@ -1,22 +1,22 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.13; -import 'contracts/interfaces/IPairFactory.sol'; -import 'contracts/Pair.sol'; +import "contracts/interfaces/IPairFactory.sol"; +import "contracts/Pair.sol"; contract PairFactory is IPairFactory { - bool public isPaused; address public pauser; address public pendingPauser; uint256 public stableFee; uint256 public volatileFee; - uint256 public constant MAX_FEE = 5; // 0.05% + uint256 public constant MAX_FEE = 50; // 0.5% address public feeManager; address public pendingFeeManager; - mapping(address => mapping(address => mapping(bool => address))) public getPair; + mapping(address => mapping(address => mapping(bool => address))) + public getPair; address[] public allPairs; mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals @@ -24,17 +24,25 @@ contract PairFactory is IPairFactory { address internal _temp1; bool internal _temp; - event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint); + event PairCreated( + address indexed token0, + address indexed token1, + bool stable, + address pair, + uint256 + ); constructor() { pauser = msg.sender; isPaused = false; feeManager = msg.sender; - stableFee = 2; // 0.02% - volatileFee = 2; + // stableFee = 2; // 0.02% + // volatileFee = 2; + stableFee = 3; // 0.03% + volatileFee = 25; // 0.25% } - function allPairsLength() external view returns (uint) { + function allPairsLength() external view returns (uint256) { return allPairs.length; } @@ -54,19 +62,19 @@ contract PairFactory is IPairFactory { } function setFeeManager(address _feeManager) external { - require(msg.sender == feeManager, 'not fee manager'); + require(msg.sender == feeManager, "not fee manager"); pendingFeeManager = _feeManager; } function acceptFeeManager() external { - require(msg.sender == pendingFeeManager, 'not pending fee manager'); + require(msg.sender == pendingFeeManager, "not pending fee manager"); feeManager = pendingFeeManager; } function setFee(bool _stable, uint256 _fee) external { - require(msg.sender == feeManager, 'not fee manager'); - require(_fee <= MAX_FEE, 'fee too high'); - require(_fee != 0, 'fee must be nonzero'); + require(msg.sender == feeManager, "not fee manager"); + require(_fee <= MAX_FEE, "fee too high"); + require(_fee != 0, "fee must be nonzero"); if (_stable) { stableFee = _fee; } else { @@ -74,7 +82,7 @@ contract PairFactory is IPairFactory { } } - function getFee(bool _stable) public view returns(uint256) { + function getFee(bool _stable) public view returns (uint256) { return _stable ? stableFee : volatileFee; } @@ -82,18 +90,32 @@ contract PairFactory is IPairFactory { return keccak256(type(Pair).creationCode); } - function getInitializable() external view returns (address, address, bool) { + function getInitializable() + external + view + returns ( + address, + address, + bool + ) + { return (_temp0, _temp1, _temp); } - function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) { - require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES - (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); - require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS - require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient + function createPair( + address tokenA, + address tokenB, + bool stable + ) external returns (address pair) { + require(tokenA != tokenB, "IA"); // Pair: IDENTICAL_ADDRESSES + (address token0, address token1) = tokenA < tokenB + ? (tokenA, tokenB) + : (tokenB, tokenA); + require(token0 != address(0), "ZA"); // Pair: ZERO_ADDRESS + require(getPair[token0][token1][stable] == address(0), "PE"); // Pair: PAIR_EXISTS - single check is sufficient bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters (_temp0, _temp1, _temp) = (token0, token1, stable); - pair = address(new Pair{salt:salt}()); + pair = address(new Pair{salt: salt}()); getPair[token0][token1][stable] = pair; getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction allPairs.push(pair); diff --git a/deploy/00_velo.ts b/deploy/00_velo.ts index 7e8c676e..6f0b067c 100644 --- a/deploy/00_velo.ts +++ b/deploy/00_velo.ts @@ -1,6 +1,8 @@ import { HardhatRuntimeEnvironment } from 'hardhat/types' import { DeployFunction } from 'hardhat-deploy/types' +// ok + const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, getNamedAccounts } = hre const { deploy } = deployments diff --git a/deploy/15_init.ts b/deploy/15_init.ts index bb14f259..d5749c52 100644 --- a/deploy/15_init.ts +++ b/deploy/15_init.ts @@ -21,7 +21,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { // Initialize await flow.initialMint(ARB_TEST_CONFIG.teamEOA) - console.log('Initial minted') + console.log('400m Initial minted') // await flow.setRedemptionReceiver(receiver.address) // console.log('RedemptionReceiver set') @@ -30,10 +30,13 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { // console.log('MerkleClaim set') await flow.setMinter(minter.address) - console.log('Minter set') + console.log('Minter set on flow contract') await pairFactory.setPauser(ARB_TEST_CONFIG.teamMultisig) - console.log('Pauser set') + console.log( + 'Pauser set on pair factory to multisig: ', + ARB_TEST_CONFIG.teamMultisig + ) await escrow.setVoter(voter.address) console.log( @@ -45,16 +48,19 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { ) await escrow.setTeam(ARB_TEST_CONFIG.teamMultisig) - console.log('Team set for escrow') + console.log('Team multisig set for escrow', ARB_TEST_CONFIG.teamMultisig) await voter.setGovernor(ARB_TEST_CONFIG.teamMultisig) - console.log('Governor set') + console.log('Governor set on voter to: ', ARB_TEST_CONFIG.teamMultisig) await voter.setEmergencyCouncil(ARB_TEST_CONFIG.teamMultisig) - console.log('Emergency Council set') + console.log( + 'Emergency Council set on voter to: ', + ARB_TEST_CONFIG.teamMultisig + ) await distributor.setDepositor(minter.address) - console.log('Depositor set') + console.log('Depositor set to minter contract address') // await receiver.setTeam(ARB_TEST_CONFIG.teamMultisig) // console.log('Team set for receiver') @@ -63,7 +69,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { // console.log('Team set for governor') await minter.setTeam(ARB_TEST_CONFIG.teamMultisig) - console.log('Team set for minter') + console.log('Team set for minter to multisig: ', ARB_TEST_CONFIG.teamMultisig) // await minter.initialize( // ARB_TEST_CONFIG.partnerAddrs, diff --git a/deployments/arbitrumOne/.chainId b/deployments/arbitrumOneOLD/.chainId similarity index 100% rename from deployments/arbitrumOne/.chainId rename to deployments/arbitrumOneOLD/.chainId diff --git a/deployments/arbitrumOne/.migrations.json b/deployments/arbitrumOneOLD/.migrations.json similarity index 100% rename from deployments/arbitrumOne/.migrations.json rename to deployments/arbitrumOneOLD/.migrations.json diff --git a/deployments/arbitrumOne/BribeFactory.json b/deployments/arbitrumOneOLD/BribeFactory.json similarity index 100% rename from deployments/arbitrumOne/BribeFactory.json rename to deployments/arbitrumOneOLD/BribeFactory.json diff --git a/deployments/arbitrumOne/GaugeFactory.json b/deployments/arbitrumOneOLD/GaugeFactory.json similarity index 100% rename from deployments/arbitrumOne/GaugeFactory.json rename to deployments/arbitrumOneOLD/GaugeFactory.json diff --git a/deployments/arbitrumOne/MerkleClaim.json b/deployments/arbitrumOneOLD/MerkleClaim.json similarity index 100% rename from deployments/arbitrumOne/MerkleClaim.json rename to deployments/arbitrumOneOLD/MerkleClaim.json diff --git a/deployments/arbitrumOne/Minter.json b/deployments/arbitrumOneOLD/Minter.json similarity index 100% rename from deployments/arbitrumOne/Minter.json rename to deployments/arbitrumOneOLD/Minter.json diff --git a/deployments/arbitrumOne/PairFactory.json b/deployments/arbitrumOneOLD/PairFactory.json similarity index 100% rename from deployments/arbitrumOne/PairFactory.json rename to deployments/arbitrumOneOLD/PairFactory.json diff --git a/deployments/arbitrumOne/RedemptionReceiver.json b/deployments/arbitrumOneOLD/RedemptionReceiver.json similarity index 100% rename from deployments/arbitrumOne/RedemptionReceiver.json rename to deployments/arbitrumOneOLD/RedemptionReceiver.json diff --git a/deployments/arbitrumOne/RewardsDistributor.json b/deployments/arbitrumOneOLD/RewardsDistributor.json similarity index 100% rename from deployments/arbitrumOne/RewardsDistributor.json rename to deployments/arbitrumOneOLD/RewardsDistributor.json diff --git a/deployments/arbitrumOne/Router.json b/deployments/arbitrumOneOLD/Router.json similarity index 100% rename from deployments/arbitrumOne/Router.json rename to deployments/arbitrumOneOLD/Router.json diff --git a/deployments/arbitrumOne/VeArtProxy.json b/deployments/arbitrumOneOLD/VeArtProxy.json similarity index 100% rename from deployments/arbitrumOne/VeArtProxy.json rename to deployments/arbitrumOneOLD/VeArtProxy.json diff --git a/deployments/arbitrumOne/Velo.json b/deployments/arbitrumOneOLD/Velo.json similarity index 100% rename from deployments/arbitrumOne/Velo.json rename to deployments/arbitrumOneOLD/Velo.json diff --git a/deployments/arbitrumOne/VeloGovernor.json b/deployments/arbitrumOneOLD/VeloGovernor.json similarity index 100% rename from deployments/arbitrumOne/VeloGovernor.json rename to deployments/arbitrumOneOLD/VeloGovernor.json diff --git a/deployments/arbitrumOne/VelodromeLibrary.json b/deployments/arbitrumOneOLD/VelodromeLibrary.json similarity index 100% rename from deployments/arbitrumOne/VelodromeLibrary.json rename to deployments/arbitrumOneOLD/VelodromeLibrary.json diff --git a/deployments/arbitrumOne/Voter.json b/deployments/arbitrumOneOLD/Voter.json similarity index 100% rename from deployments/arbitrumOne/Voter.json rename to deployments/arbitrumOneOLD/Voter.json diff --git a/deployments/arbitrumOne/VotingEscrow.json b/deployments/arbitrumOneOLD/VotingEscrow.json similarity index 100% rename from deployments/arbitrumOne/VotingEscrow.json rename to deployments/arbitrumOneOLD/VotingEscrow.json diff --git a/deployments/arbitrumOne/WrappedExternalBribeFactory.json b/deployments/arbitrumOneOLD/WrappedExternalBribeFactory.json similarity index 100% rename from deployments/arbitrumOne/WrappedExternalBribeFactory.json rename to deployments/arbitrumOneOLD/WrappedExternalBribeFactory.json diff --git a/deployments/arbitrumOne/solcInputs/4e21824d68c90a2d8601cfb8f8d80414.json b/deployments/arbitrumOneOLD/solcInputs/4e21824d68c90a2d8601cfb8f8d80414.json similarity index 100% rename from deployments/arbitrumOne/solcInputs/4e21824d68c90a2d8601cfb8f8d80414.json rename to deployments/arbitrumOneOLD/solcInputs/4e21824d68c90a2d8601cfb8f8d80414.json diff --git a/deployments/arbitrumOne/solcInputs/f93feb6db909c3f14d7eec3a3196fbbd.json b/deployments/arbitrumOneOLD/solcInputs/f93feb6db909c3f14d7eec3a3196fbbd.json similarity index 100% rename from deployments/arbitrumOne/solcInputs/f93feb6db909c3f14d7eec3a3196fbbd.json rename to deployments/arbitrumOneOLD/solcInputs/f93feb6db909c3f14d7eec3a3196fbbd.json diff --git a/package.json b/package.json index 7019b235..66d7ac3c 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ "deployArb": "npx hardhat deploy --network arbitrumOne --tags WrappedExternalBribeFactory", "deployHardhat": "npx hardhat deploy --network hardhat", "verifyMainnet": "npx hardhat --network arbitrumOne etherscan-verify --solc-input --sleep", - "verifyGoerli": "npx hardhat --network arbitrumGoerli etherscan-verify --solc-input --sleep" + "verifyGoerli": "npx hardhat --network arbitrumGoerli etherscan-verify --solc-input --sleep", + "batchMint": "npx hardhat batch-create-lock-for --network arbitrumOne --token 0xC33f7f83CbB021846Cb9c58f2d8E3df428dbC8C1 --contract 0x10Df81252069C1095F541FAca61646cb9Ae76703" }, "devDependencies": { "@nomiclabs/hardhat-ethers": "yarn:hardhat-deploy-ethers", diff --git a/tasks/log/failed.csv b/tasks/log/failed.csv index e69de29b..9cbe67c1 100644 --- a/tasks/log/failed.csv +++ b/tasks/log/failed.csv @@ -0,0 +1,2 @@ +recipient,amountInMillion,durationInYear + diff --git a/tasks/log/successful.csv b/tasks/log/successful.csv index 76d71ed8..f42f8982 100644 --- a/tasks/log/successful.csv +++ b/tasks/log/successful.csv @@ -1,4 +1,3 @@ recipient,txHash -0xBD2Ca4c6481b9C4BefAA06172149Bf502D5eF827,0x2c2ceb71decba8a60cc2dc14480822e73dfbd1de1fa0387db42980733e4deb87 -0x500E720b2BE2d04cAc33541E30bf88887554E14b,0xd7e94edb5b8e0f6b7be771276703f9b22522c2895a3d1e555462c0f23a663493 -0xc8EeFd78e1d29B28100413bB3204c952Cb36604E,0x3a93d8bbe4d13875d52c3d384a13364d43403db2808c8e615794db1747fc48b3 +0x16ec7CD5E35682B751d0c77c41A4e6a1A3E2DE01,0x387991237fabb35fce02398147114e29115b7ee4235feb3f99274b50deab382c +0x16ec7CD5E35682B751d0c77c41A4e6a1A3E2DE01,0x3b6ff023cf2fb6e11baac5333f385bf681b825ebc842aa3fdc015d061bb55ea6 diff --git a/tasks/sample_partners.csv b/tasks/sample_partners.csv index afd5c297..8c4e7ba4 100644 --- a/tasks/sample_partners.csv +++ b/tasks/sample_partners.csv @@ -1,4 +1,4 @@ recipient,amountInMillion,durationInYear -0xBD2Ca4c6481b9C4BefAA06172149Bf502D5eF827,1,4 -0x500E720b2BE2d04cAc33541E30bf88887554E14b,2,2 -0xc8EeFd78e1d29B28100413bB3204c952Cb36604E,4,4 \ No newline at end of file +0x16ec7CD5E35682B751d0c77c41A4e6a1A3E2DE01,1,4 +0x16ec7CD5E35682B751d0c77c41A4e6a1A3E2DE01,2,2 +0x16ec7CD5E35682B751d0c77c41A4e6a1A3E2DE01,4,4 \ No newline at end of file From 78a7cbf9482dfd31398bc9d1fbce64d9f2b9b3ca Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Sun, 5 Feb 2023 05:24:19 +1100 Subject: [PATCH 34/43] rename Math --- contracts/ExternalBribe.sol | 2 +- contracts/Gauge.sol | 22 ++++++++++---------- contracts/InternalBribe.sol | 32 ++++++++++++++--------------- contracts/Minter.sol | 2 +- contracts/Pair.sol | 4 ++-- contracts/RewardsDistributor.sol | 10 ++++----- contracts/Router.sol | 6 +++--- contracts/WrappedExternalBribe.sol | 2 +- contracts/libraries/Math.sol | 2 +- deploy/17_dist.ts | 10 ++++----- scripts/k.js | 30 +++++++++++++-------------- scripts/minterSolid.js | 2 +- scripts/minterVelo.js | 2 +- tasks/deploy/constants/arbConfig.ts | 22 ++------------------ 14 files changed, 65 insertions(+), 83 deletions(-) diff --git a/contracts/ExternalBribe.sol b/contracts/ExternalBribe.sol index be4ef619..5859f360 100644 --- a/contracts/ExternalBribe.sol +++ b/contracts/ExternalBribe.sol @@ -215,7 +215,7 @@ contract ExternalBribe is IBribe { view returns (uint256) { - return MathDunks.min(block.timestamp, periodFinish[token]); + return Math.min(block.timestamp, periodFinish[token]); } // allows a user to claim rewards for a given token diff --git a/contracts/Gauge.sol b/contracts/Gauge.sol index c7bbfdb5..19ef9fc0 100644 --- a/contracts/Gauge.sol +++ b/contracts/Gauge.sol @@ -366,7 +366,7 @@ contract Gauge is IGauge { view returns (uint256) { - return MathDunks.min(block.timestamp, periodFinish[token]); + return Math.min(block.timestamp, periodFinish[token]); } function getReward(address account, address[] memory tokens) external lock { @@ -408,7 +408,7 @@ contract Gauge is IGauge { return rewardPerTokenStored[token] + (((lastTimeRewardApplicable(token) - - MathDunks.min(lastUpdateTime[token], periodFinish[token])) * + Math.min(lastUpdateTime[token], periodFinish[token])) * rewardRate[token] * PRECISION) / derivedSupply); } @@ -440,7 +440,7 @@ contract Gauge is IGauge { } uint256 _startIndex = getPriorSupplyIndex(_startTimestamp); - uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns); + uint256 _endIndex = Math.min(supplyNumCheckpoints - 1, maxRuns); for (uint256 i = _startIndex; i < _endIndex; i++) { SupplyCheckpoint memory sp0 = supplyCheckpoints[i]; @@ -469,11 +469,11 @@ contract Gauge is IGauge { uint256 supply, uint256 startTimestamp ) internal view returns (uint256, uint256) { - uint256 endTime = MathDunks.max(timestamp1, startTimestamp); + uint256 endTime = Math.max(timestamp1, startTimestamp); return ( - (((MathDunks.min(endTime, periodFinish[token]) - - MathDunks.min( - MathDunks.max(timestamp0, startTimestamp), + (((Math.min(endTime, periodFinish[token]) - + Math.min( + Math.max(timestamp0, startTimestamp), periodFinish[token] )) * rewardRate[token] * @@ -521,7 +521,7 @@ contract Gauge is IGauge { } uint256 _startIndex = getPriorSupplyIndex(_startTimestamp); - uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns); + uint256 _endIndex = Math.min(supplyNumCheckpoints - 1, maxRuns); if (_endIndex > 0) { for (uint256 i = _startIndex; i <= _endIndex - 1; i++) { @@ -549,7 +549,7 @@ contract Gauge is IGauge { (uint256 _reward, ) = _calcRewardPerToken( token, lastTimeRewardApplicable(token), - MathDunks.max(sp.timestamp, _startTimestamp), + Math.max(sp.timestamp, _startTimestamp), sp.supply, _startTimestamp ); @@ -568,7 +568,7 @@ contract Gauge is IGauge { view returns (uint256) { - uint256 _startTimestamp = MathDunks.max( + uint256 _startTimestamp = Math.max( lastEarn[token][account], rewardPerTokenCheckpoints[token][0].timestamp ); @@ -608,7 +608,7 @@ contract Gauge is IGauge { reward += (cp.balanceOf * (rewardPerToken(token) - - MathDunks.max( + Math.max( _rewardPerTokenStored, userRewardPerTokenStored[token][account] ))) / diff --git a/contracts/InternalBribe.sol b/contracts/InternalBribe.sol index 82ccd34d..25345ec8 100644 --- a/contracts/InternalBribe.sol +++ b/contracts/InternalBribe.sol @@ -13,7 +13,7 @@ contract InternalBribe is IBribe { address public immutable _ve; uint256 public constant DURATION = 7 days; // rewards are released over 7 days - uint256 public constant PRECISION = 10**18; + uint256 internal constant MAX_REWARD_TOKENS = 16; // default snx staking contract implementation @@ -293,7 +293,7 @@ contract InternalBribe is IBribe { view returns (uint256) { - return MathDunks.min(block.timestamp, periodFinish[token]); + return Math.min(block.timestamp, periodFinish[token]); } // allows a user to claim rewards for a given token @@ -347,9 +347,9 @@ contract InternalBribe is IBribe { return rewardPerTokenStored[token] + (((lastTimeRewardApplicable(token) - - MathDunks.min(lastUpdateTime[token], periodFinish[token])) * + Math.min(lastUpdateTime[token], periodFinish[token])) * rewardRate[token] * - PRECISION) / totalSupply); + 10**IERC20(token).decimals()) / totalSupply); } function batchRewardPerToken(address token, uint256 maxRuns) external { @@ -375,7 +375,7 @@ contract InternalBribe is IBribe { } uint256 _startIndex = getPriorSupplyIndex(_startTimestamp); - uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns); + uint256 _endIndex = Math.min(supplyNumCheckpoints - 1, maxRuns); for (uint256 i = _startIndex; i < _endIndex; i++) { SupplyCheckpoint memory sp0 = supplyCheckpoints[i]; @@ -404,15 +404,15 @@ contract InternalBribe is IBribe { uint256 supply, uint256 startTimestamp ) internal view returns (uint256, uint256) { - uint256 endTime = MathDunks.max(timestamp1, startTimestamp); + uint256 endTime = Math.max(timestamp1, startTimestamp); return ( - (((MathDunks.min(endTime, periodFinish[token]) - - MathDunks.min( - MathDunks.max(timestamp0, startTimestamp), + (((Math.min(endTime, periodFinish[token]) - + Math.min( + Math.max(timestamp0, startTimestamp), periodFinish[token] )) * rewardRate[token] * - PRECISION) / supply), + 10**IERC20(token).decimals()) / supply), endTime ); } @@ -456,7 +456,7 @@ contract InternalBribe is IBribe { } uint256 _startIndex = getPriorSupplyIndex(_startTimestamp); - uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns); + uint256 _endIndex = Math.min(supplyNumCheckpoints - 1, maxRuns); if (_endIndex > 0) { for (uint256 i = _startIndex; i <= _endIndex - 1; i++) { @@ -483,7 +483,7 @@ contract InternalBribe is IBribe { (uint256 _reward, ) = _calcRewardPerToken( token, lastTimeRewardApplicable(token), - MathDunks.max(sp.timestamp, _startTimestamp), + Math.max(sp.timestamp, _startTimestamp), sp.supply, _startTimestamp ); @@ -501,7 +501,7 @@ contract InternalBribe is IBribe { view returns (uint256) { - uint256 _startTimestamp = MathDunks.max( + uint256 _startTimestamp = Math.max( lastEarn[token][tokenId], rewardPerTokenCheckpoints[token][0].timestamp ); @@ -529,7 +529,7 @@ contract InternalBribe is IBribe { reward += (cp0.balanceOf * (_rewardPerTokenStored1 - _rewardPerTokenStored0)) / - PRECISION; + 10**IERC20(token).decimals(); } } @@ -541,11 +541,11 @@ contract InternalBribe is IBribe { reward += (cp.balanceOf * (rewardPerToken(token) - - MathDunks.max( + Math.max( _rewardPerTokenStored, userRewardPerTokenStored[token][tokenId] ))) / - PRECISION; + 10**IERC20(token).decimals(); return reward; } diff --git a/contracts/Minter.sol b/contracts/Minter.sol index 4f38e9b4..183b2823 100644 --- a/contracts/Minter.sol +++ b/contracts/Minter.sol @@ -94,7 +94,7 @@ contract Minter is IMinter { // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission function weekly_emission() public view returns (uint256) { - return MathDunks.max(calculate_emission(), circulating_emission()); + return Math.max(calculate_emission(), circulating_emission()); } // calculates tail end (infinity) emissions as 0.2% of total supply diff --git a/contracts/Pair.sol b/contracts/Pair.sol index d908d6a6..58667367 100644 --- a/contracts/Pair.sol +++ b/contracts/Pair.sol @@ -425,10 +425,10 @@ contract Pair is IPair { uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee if (_totalSupply == 0) { - liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY; + liquidity = Math.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY; _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens } else { - liquidity = MathDunks.min( + liquidity = Math.min( (_amount0 * _totalSupply) / _reserve0, (_amount1 * _totalSupply) / _reserve1 ); diff --git a/contracts/RewardsDistributor.sol b/contracts/RewardsDistributor.sol index 768e5e30..5a93122d 100644 --- a/contracts/RewardsDistributor.sol +++ b/contracts/RewardsDistributor.sol @@ -162,7 +162,7 @@ contract RewardsDistributor is IRewardsDistributor { epoch ); return - MathDunks.max( + Math.max( uint256( int256( pt.bias - @@ -192,7 +192,7 @@ contract RewardsDistributor is IRewardsDistributor { if (t > pt.ts) { dt = int128(int256(t - pt.ts)); } - ve_supply[t] = MathDunks.max( + ve_supply[t] = Math.max( uint256(int256(pt.bias - pt.slope * dt)), 0 ); @@ -259,7 +259,7 @@ contract RewardsDistributor is IRewardsDistributor { } } else { int128 dt = int128(int256(week_cursor - old_user_point.ts)); - uint256 balance_of = MathDunks.max( + uint256 balance_of = Math.max( uint256( int256(old_user_point.bias - dt * old_user_point.slope) ), @@ -275,7 +275,7 @@ contract RewardsDistributor is IRewardsDistributor { } } - user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1); + user_epoch = Math.min(max_user_epoch, user_epoch - 1); user_epoch_of[_tokenId] = user_epoch; time_cursor_of[_tokenId] = week_cursor; @@ -337,7 +337,7 @@ contract RewardsDistributor is IRewardsDistributor { } } else { int128 dt = int128(int256(week_cursor - old_user_point.ts)); - uint256 balance_of = MathDunks.max( + uint256 balance_of = Math.max( uint256( int256(old_user_point.bias - dt * old_user_point.slope) ), diff --git a/contracts/Router.sol b/contracts/Router.sol index d9b616b6..cc3dcfde 100644 --- a/contracts/Router.sol +++ b/contracts/Router.sol @@ -172,7 +172,7 @@ contract Router is IRouter { } if (reserveA == 0 && reserveB == 0) { (amountA, amountB) = (amountADesired, amountBDesired); - liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY; + liquidity = Math.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY; } else { uint256 amountBOptimal = quoteLiquidity( amountADesired, @@ -181,7 +181,7 @@ contract Router is IRouter { ); if (amountBOptimal <= amountBDesired) { (amountA, amountB) = (amountADesired, amountBOptimal); - liquidity = MathDunks.min( + liquidity = Math.min( (amountA * _totalSupply) / reserveA, (amountB * _totalSupply) / reserveB ); @@ -192,7 +192,7 @@ contract Router is IRouter { reserveA ); (amountA, amountB) = (amountAOptimal, amountBDesired); - liquidity = MathDunks.min( + liquidity = Math.min( (amountA * _totalSupply) / reserveA, (amountB * _totalSupply) / reserveB ); diff --git a/contracts/WrappedExternalBribe.sol b/contracts/WrappedExternalBribe.sol index 4df09a08..1b0400b0 100644 --- a/contracts/WrappedExternalBribe.sol +++ b/contracts/WrappedExternalBribe.sol @@ -87,7 +87,7 @@ contract WrappedExternalBribe { view returns (uint256) { - return MathDunks.min(block.timestamp, periodFinish[token]); + return Math.min(block.timestamp, periodFinish[token]); } // allows a user to claim rewards for a given token diff --git a/contracts/libraries/Math.sol b/contracts/libraries/Math.sol index fe5b2aa0..ee09791d 100644 --- a/contracts/libraries/Math.sol +++ b/contracts/libraries/Math.sol @@ -1,7 +1,7 @@ pragma solidity 0.8.13; // this causes issue with forge test as there is already a Math.sol in the forge repo -library MathDunks { +library Math { function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } diff --git a/deploy/17_dist.ts b/deploy/17_dist.ts index 88774cfa..c96206d4 100644 --- a/deploy/17_dist.ts +++ b/deploy/17_dist.ts @@ -19,11 +19,11 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const flow = await deployments.get('Flow') // Initial veVELO distro // this is not inside dist lets see if its being used for deploys?? - // await minter.initialize( - // ARB_TEST_CONFIG.partnerAddrs, - // ARB_TEST_CONFIG.partnerAmts, - // ARB_TEST_CONFIG.partnerMax - // ) + await minter.initialize( + ARB_TEST_CONFIG.partnerAddrs, + ARB_TEST_CONFIG.partnerAmts, + ARB_TEST_CONFIG.partnerMax + ) console.log('veVELO not distributed yet') // we will run this when we want to start the epoch and have the NFTs // console.log('Arbitrum Goerli Velocimeter Instruments deployed') diff --git a/scripts/k.js b/scripts/k.js index 652f9abb..8a3b8841 100644 --- a/scripts/k.js +++ b/scripts/k.js @@ -17,11 +17,11 @@ function get_y (xIn, a, b) { (((27 * a3 * b) / 1e18) * x2) / 1e18 + (((27 * a * b3) / 1e18) * x2) / 1e18 console.log('c0', c0) console.log('c0*c0', c0 * c0) - _c1 = MathDunks.sqrt(c0 * c0 + 108 * x ** 12) + c0 + _c1 = Math.sqrt(c0 * c0 + 108 * x ** 12) + c0 console.log(_c1) - c1 = MathDunks.cbrt(_c1) + c1 = Math.cbrt(_c1) b1 = 3 * 2 ** (1 / 3) * x - b1 = 3 * MathDunks.cbrt(2) * x + b1 = 3 * Math.cbrt(2) * x b2 = 2 ** (1 / 3) * x ** 3 console.log('c1', c1) console.log('b1', b1) @@ -34,9 +34,9 @@ function get_y (xIn, a, b) { /*function get_y(xIn, a, b) { x = xIn + a; - y0 = MathDunks.cbrt(MathDunks.sqrt(((27*(a**3)*b*(x**2)+27*a*(b**3)*(x**2))**2)+108*x**12)+27*(a**3)*b*(x**2)+27*a*(b**3)*(x**2)) - y1 = y0 / 3*MathDunks.cbrt(2)*x - y2 = MathDunks.cbrt(2)*(x**3) / y0 + y0 = Math.cbrt(Math.sqrt(((27*(a**3)*b*(x**2)+27*a*(b**3)*(x**2))**2)+108*x**12)+27*(a**3)*b*(x**2)+27*a*(b**3)*(x**2)) + y1 = y0 / 3*Math.cbrt(2)*x + y2 = Math.cbrt(2)*(x**3) / y0 y = y1 - y2 console.log(y) console.log(b-y) @@ -45,43 +45,43 @@ function get_y (xIn, a, b) { // getAmountOut gives the amount that will be returned given the amountIn for tokenIn function getAmountOut (xIn, x, y) { console.log('_k1', _k(x, y)) - _kB = MathDunks.sqrt(MathDunks.sqrt(_k(x, y))) * 2 + _kB = Math.sqrt(Math.sqrt(_k(x, y))) * 2 console.log('_kB', _kB) - _kA1 = MathDunks.sqrt(MathDunks.sqrt(_k(x + xIn, y))) * 2 + _kA1 = Math.sqrt(Math.sqrt(_k(x + xIn, y))) * 2 yOutAbove = _kA1 - _kB - _kA2 = MathDunks.sqrt(MathDunks.sqrt(_k(x + xIn, y - yOutAbove))) * 2 + _kA2 = Math.sqrt(Math.sqrt(_k(x + xIn, y - yOutAbove))) * 2 while (_kA2 < _kB) { diff = _kB - _kA2 yOutAbove = yOutAbove - diff console.log('yOutAbove', yOutAbove) - _kA2 = MathDunks.sqrt(MathDunks.sqrt(_k(x + xIn, y - yOutAbove))) * 2 + _kA2 = Math.sqrt(Math.sqrt(_k(x + xIn, y - yOutAbove))) * 2 } yOutBelow = yOutAbove - _kA2 = MathDunks.sqrt(MathDunks.sqrt(_k(x + xIn, y - yOutAbove))) * 2 + _kA2 = Math.sqrt(Math.sqrt(_k(x + xIn, y - yOutAbove))) * 2 console.log('_kA2', _kA2) while (_kA2 > _kB) { diff = _kA2 - _kB yOutBelow = yOutBelow + diff - _kA2 = MathDunks.sqrt(MathDunks.sqrt(_k(x + xIn, y - yOutBelow))) * 2 + _kA2 = Math.sqrt(Math.sqrt(_k(x + xIn, y - yOutBelow))) * 2 } console.log(yOutAbove) console.log(yOutBelow) yOut = (yOutBelow + yOutAbove) / 2 - _kA2 = MathDunks.sqrt(MathDunks.sqrt(_k(x + xIn, y - yOut))) * 2 + _kA2 = Math.sqrt(Math.sqrt(_k(x + xIn, y - yOut))) * 2 /*while (_kA2 != _kB) { diff = _kA2 - _kB; yOut = (yOutBelow+yOutAbove)/2; console.log(yOut); - _kA2 = MathDunks.sqrt(MathDunks.sqrt(_k(x+xIn, y-yOut))) * 2; + _kA2 = Math.sqrt(Math.sqrt(_k(x+xIn, y-yOut))) * 2; }*/ for (i = 0; i < 255; i++) { - _kA2 = MathDunks.sqrt(MathDunks.sqrt(_k(x + xIn, y - yOut))) * 2 + _kA2 = Math.sqrt(Math.sqrt(_k(x + xIn, y - yOut))) * 2 if (_kA2 > _kB) { yOut = (yOut + yOutBelow) / 2 } else if (_kA2 < _kB) { diff --git a/scripts/minterSolid.js b/scripts/minterSolid.js index c8a7e700..4472836f 100644 --- a/scripts/minterSolid.js +++ b/scripts/minterSolid.js @@ -15,7 +15,7 @@ function calculate_emission () { } function weekly_emission () { - return MathDunks.max(calculate_emission(), circulating_emission()) + return Math.max(calculate_emission(), circulating_emission()) } function circulating_emission () { diff --git a/scripts/minterVelo.js b/scripts/minterVelo.js index 77b6963a..aa2a5f1b 100644 --- a/scripts/minterVelo.js +++ b/scripts/minterVelo.js @@ -23,7 +23,7 @@ function calculate_emission () { // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission function weekly_emission () { - return MathDunks.max(calculate_emission(), circulating_emission()) + return Math.max(calculate_emission(), circulating_emission()) } function circulating_emission () { diff --git a/tasks/deploy/constants/arbConfig.ts b/tasks/deploy/constants/arbConfig.ts index 615fbb44..b2e48cf2 100644 --- a/tasks/deploy/constants/arbConfig.ts +++ b/tasks/deploy/constants/arbConfig.ts @@ -79,26 +79,8 @@ const arbConfig = { // // MILLION, // 10 1/4 % // // MILLION // 11 // ], - partnerAddrs: [ - TEAM_MULTISIG, - dunks, - t0rb1k, - dunks, - t0rb1k, - dunks, - t0rb1k, - dunks - ], - partnerAmts: [ - SIXTY_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - FOUR_MILLION, - ONE_MILLION - ], // MILLION Mint 0.001 WTF pls halp + partnerAddrs: [dunks], + partnerAmts: [ONE_MILLION], // MILLION Mint 0.001 WTF pls halp partnerMax: PARTNER_MAX, // Addresses From 342238f7b936568bfc9751cfe6dc262d5b9311c2 Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Sun, 5 Feb 2023 06:05:49 +1100 Subject: [PATCH 35/43] lost l2 --- contracts/ExternalBribe.sol | 3 ++- contracts/Gauge.sol | 2 +- contracts/InternalBribe.sol | 2 +- contracts/Minter.sol | 2 +- contracts/Pair.sol | 2 +- contracts/RewardsDistributor.sol | 2 +- contracts/Router.sol | 2 +- contracts/Voter.sol | 24 +++++++++++-------- contracts/WrappedExternalBribe.sol | 2 +- .../{arbitrumOneOLD => arbitrumOne}/.chainId | 0 .../.migrations.json | 0 .../BribeFactory.json | 0 .../GaugeFactory.json | 0 .../MerkleClaim.json | 0 .../Minter.json | 0 .../PairFactory.json | 0 .../RedemptionReceiver.json | 0 .../RewardsDistributor.json | 0 .../Router.json | 0 .../VeArtProxy.json | 0 .../{arbitrumOneOLD => arbitrumOne}/Velo.json | 0 .../VeloGovernor.json | 0 .../VelodromeLibrary.json | 0 .../Voter.json | 0 .../VotingEscrow.json | 0 .../WrappedExternalBribeFactory.json | 0 .../4e21824d68c90a2d8601cfb8f8d80414.json | 0 .../f93feb6db909c3f14d7eec3a3196fbbd.json | 0 28 files changed, 23 insertions(+), 18 deletions(-) rename deployments/{arbitrumOneOLD => arbitrumOne}/.chainId (100%) rename deployments/{arbitrumOneOLD => arbitrumOne}/.migrations.json (100%) rename deployments/{arbitrumOneOLD => arbitrumOne}/BribeFactory.json (100%) rename deployments/{arbitrumOneOLD => arbitrumOne}/GaugeFactory.json (100%) rename deployments/{arbitrumOneOLD => arbitrumOne}/MerkleClaim.json (100%) rename deployments/{arbitrumOneOLD => arbitrumOne}/Minter.json (100%) rename deployments/{arbitrumOneOLD => arbitrumOne}/PairFactory.json (100%) rename deployments/{arbitrumOneOLD => arbitrumOne}/RedemptionReceiver.json (100%) rename deployments/{arbitrumOneOLD => arbitrumOne}/RewardsDistributor.json (100%) rename deployments/{arbitrumOneOLD => arbitrumOne}/Router.json (100%) rename deployments/{arbitrumOneOLD => arbitrumOne}/VeArtProxy.json (100%) rename deployments/{arbitrumOneOLD => arbitrumOne}/Velo.json (100%) rename deployments/{arbitrumOneOLD => arbitrumOne}/VeloGovernor.json (100%) rename deployments/{arbitrumOneOLD => arbitrumOne}/VelodromeLibrary.json (100%) rename deployments/{arbitrumOneOLD => arbitrumOne}/Voter.json (100%) rename deployments/{arbitrumOneOLD => arbitrumOne}/VotingEscrow.json (100%) rename deployments/{arbitrumOneOLD => arbitrumOne}/WrappedExternalBribeFactory.json (100%) rename deployments/{arbitrumOneOLD => arbitrumOne}/solcInputs/4e21824d68c90a2d8601cfb8f8d80414.json (100%) rename deployments/{arbitrumOneOLD => arbitrumOne}/solcInputs/f93feb6db909c3f14d7eec3a3196fbbd.json (100%) diff --git a/contracts/ExternalBribe.sol b/contracts/ExternalBribe.sol index 5859f360..03744e84 100644 --- a/contracts/ExternalBribe.sol +++ b/contracts/ExternalBribe.sol @@ -1,7 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.13; -import "contracts/libraries/Math.sol"; +// import {Math} from "@openzeppelin-contracts/contracts/utils/math/Math.sol"; +import {Math} from "openzeppelin-contracts/contracts/utils/math/Math.sol"; import "contracts/interfaces/IBribe.sol"; import "contracts/interfaces/IERC20.sol"; import "contracts/interfaces/IGauge.sol"; diff --git a/contracts/Gauge.sol b/contracts/Gauge.sol index 19ef9fc0..11f0a93a 100644 --- a/contracts/Gauge.sol +++ b/contracts/Gauge.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.13; -import "contracts/libraries/Math.sol"; +import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; import "contracts/interfaces/IBribe.sol"; import "contracts/interfaces/IERC20.sol"; import "contracts/interfaces/IGauge.sol"; diff --git a/contracts/InternalBribe.sol b/contracts/InternalBribe.sol index 25345ec8..27fe44b5 100644 --- a/contracts/InternalBribe.sol +++ b/contracts/InternalBribe.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.13; -import "contracts/libraries/Math.sol"; +import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; import "contracts/interfaces/IBribe.sol"; import "contracts/interfaces/IERC20.sol"; import "contracts/interfaces/IVoter.sol"; diff --git a/contracts/Minter.sol b/contracts/Minter.sol index 183b2823..0c54ca84 100644 --- a/contracts/Minter.sol +++ b/contracts/Minter.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.13; -import "contracts/libraries/Math.sol"; +import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; import "contracts/interfaces/IMinter.sol"; import "contracts/interfaces/IRewardsDistributor.sol"; import "contracts/interfaces/IFlow.sol"; diff --git a/contracts/Pair.sol b/contracts/Pair.sol index 58667367..afe2142d 100644 --- a/contracts/Pair.sol +++ b/contracts/Pair.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.13; -import "contracts/libraries/Math.sol"; +import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; import "contracts/interfaces/IERC20.sol"; import "contracts/interfaces/IPair.sol"; import "contracts/interfaces/IPairCallee.sol"; diff --git a/contracts/RewardsDistributor.sol b/contracts/RewardsDistributor.sol index 5a93122d..403b6174 100644 --- a/contracts/RewardsDistributor.sol +++ b/contracts/RewardsDistributor.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.13; -import "contracts/libraries/Math.sol"; +import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; import "contracts/interfaces/IERC20.sol"; import "contracts/interfaces/IRewardsDistributor.sol"; import "contracts/interfaces/IVotingEscrow.sol"; diff --git a/contracts/Router.sol b/contracts/Router.sol index cc3dcfde..5b0491f3 100644 --- a/contracts/Router.sol +++ b/contracts/Router.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.13; -import "contracts/libraries/Math.sol"; +import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; import "contracts/interfaces/IERC20.sol"; import "contracts/interfaces/IPair.sol"; import "contracts/interfaces/IPairFactory.sol"; diff --git a/contracts/Voter.sol b/contracts/Voter.sol index 2fe3b5b6..5318e66e 100644 --- a/contracts/Voter.sol +++ b/contracts/Voter.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.13; -import "contracts/libraries/Math.sol"; +import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; import "contracts/interfaces/IBribe.sol"; import "contracts/interfaces/IBribeFactory.sol"; import "contracts/interfaces/IGauge.sol"; @@ -172,17 +172,21 @@ contract Voter is IVoter { // remove poke function - // function poke(uint _tokenId) external { - // address[] memory _poolVote = poolVote[_tokenId]; - // uint _poolCnt = _poolVote.length; - // uint256[] memory _weights = new uint256[](_poolCnt); + function poke(uint256 _tokenId) external { + require( + IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId) || + msg.sender == governor + ); + address[] memory _poolVote = poolVote[_tokenId]; + uint256 _poolCnt = _poolVote.length; + uint256[] memory _weights = new uint256[](_poolCnt); - // for (uint i = 0; i < _poolCnt; i ++) { - // _weights[i] = votes[_tokenId][_poolVote[i]]; - // } + for (uint256 i = 0; i < _poolCnt; i++) { + _weights[i] = votes[_tokenId][_poolVote[i]]; + } - // _vote(_tokenId, _poolVote, _weights); - // } + _vote(_tokenId, _poolVote, _weights); + } function _vote( uint256 _tokenId, diff --git a/contracts/WrappedExternalBribe.sol b/contracts/WrappedExternalBribe.sol index 1b0400b0..74dda19d 100644 --- a/contracts/WrappedExternalBribe.sol +++ b/contracts/WrappedExternalBribe.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.13; -import "contracts/libraries/Math.sol"; +import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; import "contracts/ExternalBribe.sol"; import "contracts/interfaces/IERC20.sol"; import "contracts/interfaces/IGauge.sol"; diff --git a/deployments/arbitrumOneOLD/.chainId b/deployments/arbitrumOne/.chainId similarity index 100% rename from deployments/arbitrumOneOLD/.chainId rename to deployments/arbitrumOne/.chainId diff --git a/deployments/arbitrumOneOLD/.migrations.json b/deployments/arbitrumOne/.migrations.json similarity index 100% rename from deployments/arbitrumOneOLD/.migrations.json rename to deployments/arbitrumOne/.migrations.json diff --git a/deployments/arbitrumOneOLD/BribeFactory.json b/deployments/arbitrumOne/BribeFactory.json similarity index 100% rename from deployments/arbitrumOneOLD/BribeFactory.json rename to deployments/arbitrumOne/BribeFactory.json diff --git a/deployments/arbitrumOneOLD/GaugeFactory.json b/deployments/arbitrumOne/GaugeFactory.json similarity index 100% rename from deployments/arbitrumOneOLD/GaugeFactory.json rename to deployments/arbitrumOne/GaugeFactory.json diff --git a/deployments/arbitrumOneOLD/MerkleClaim.json b/deployments/arbitrumOne/MerkleClaim.json similarity index 100% rename from deployments/arbitrumOneOLD/MerkleClaim.json rename to deployments/arbitrumOne/MerkleClaim.json diff --git a/deployments/arbitrumOneOLD/Minter.json b/deployments/arbitrumOne/Minter.json similarity index 100% rename from deployments/arbitrumOneOLD/Minter.json rename to deployments/arbitrumOne/Minter.json diff --git a/deployments/arbitrumOneOLD/PairFactory.json b/deployments/arbitrumOne/PairFactory.json similarity index 100% rename from deployments/arbitrumOneOLD/PairFactory.json rename to deployments/arbitrumOne/PairFactory.json diff --git a/deployments/arbitrumOneOLD/RedemptionReceiver.json b/deployments/arbitrumOne/RedemptionReceiver.json similarity index 100% rename from deployments/arbitrumOneOLD/RedemptionReceiver.json rename to deployments/arbitrumOne/RedemptionReceiver.json diff --git a/deployments/arbitrumOneOLD/RewardsDistributor.json b/deployments/arbitrumOne/RewardsDistributor.json similarity index 100% rename from deployments/arbitrumOneOLD/RewardsDistributor.json rename to deployments/arbitrumOne/RewardsDistributor.json diff --git a/deployments/arbitrumOneOLD/Router.json b/deployments/arbitrumOne/Router.json similarity index 100% rename from deployments/arbitrumOneOLD/Router.json rename to deployments/arbitrumOne/Router.json diff --git a/deployments/arbitrumOneOLD/VeArtProxy.json b/deployments/arbitrumOne/VeArtProxy.json similarity index 100% rename from deployments/arbitrumOneOLD/VeArtProxy.json rename to deployments/arbitrumOne/VeArtProxy.json diff --git a/deployments/arbitrumOneOLD/Velo.json b/deployments/arbitrumOne/Velo.json similarity index 100% rename from deployments/arbitrumOneOLD/Velo.json rename to deployments/arbitrumOne/Velo.json diff --git a/deployments/arbitrumOneOLD/VeloGovernor.json b/deployments/arbitrumOne/VeloGovernor.json similarity index 100% rename from deployments/arbitrumOneOLD/VeloGovernor.json rename to deployments/arbitrumOne/VeloGovernor.json diff --git a/deployments/arbitrumOneOLD/VelodromeLibrary.json b/deployments/arbitrumOne/VelodromeLibrary.json similarity index 100% rename from deployments/arbitrumOneOLD/VelodromeLibrary.json rename to deployments/arbitrumOne/VelodromeLibrary.json diff --git a/deployments/arbitrumOneOLD/Voter.json b/deployments/arbitrumOne/Voter.json similarity index 100% rename from deployments/arbitrumOneOLD/Voter.json rename to deployments/arbitrumOne/Voter.json diff --git a/deployments/arbitrumOneOLD/VotingEscrow.json b/deployments/arbitrumOne/VotingEscrow.json similarity index 100% rename from deployments/arbitrumOneOLD/VotingEscrow.json rename to deployments/arbitrumOne/VotingEscrow.json diff --git a/deployments/arbitrumOneOLD/WrappedExternalBribeFactory.json b/deployments/arbitrumOne/WrappedExternalBribeFactory.json similarity index 100% rename from deployments/arbitrumOneOLD/WrappedExternalBribeFactory.json rename to deployments/arbitrumOne/WrappedExternalBribeFactory.json diff --git a/deployments/arbitrumOneOLD/solcInputs/4e21824d68c90a2d8601cfb8f8d80414.json b/deployments/arbitrumOne/solcInputs/4e21824d68c90a2d8601cfb8f8d80414.json similarity index 100% rename from deployments/arbitrumOneOLD/solcInputs/4e21824d68c90a2d8601cfb8f8d80414.json rename to deployments/arbitrumOne/solcInputs/4e21824d68c90a2d8601cfb8f8d80414.json diff --git a/deployments/arbitrumOneOLD/solcInputs/f93feb6db909c3f14d7eec3a3196fbbd.json b/deployments/arbitrumOne/solcInputs/f93feb6db909c3f14d7eec3a3196fbbd.json similarity index 100% rename from deployments/arbitrumOneOLD/solcInputs/f93feb6db909c3f14d7eec3a3196fbbd.json rename to deployments/arbitrumOne/solcInputs/f93feb6db909c3f14d7eec3a3196fbbd.json From b421f652fd482516178c504a3c380abadacb5c12 Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Mon, 6 Feb 2023 05:40:34 +1100 Subject: [PATCH 36/43] push fix for math lib --- contracts/ExternalBribe.sol | 4 +- contracts/Gauge.sol | 2 +- contracts/InternalBribe.sol | 2 +- contracts/Minter.sol | 3 +- contracts/Pair.sol | 2 +- contracts/RewardsDistributor.sol | 2 +- contracts/Router.sol | 2 +- contracts/Voter.sol | 4 +- contracts/WrappedExternalBribe.sol | 2 +- deployments/arbitrumOne/.migrations.json | 6 +- deployments/arbitrumOne/BribeFactory.json | 28 +- deployments/arbitrumOne/Flow.json | 522 ++++ deployments/arbitrumOne/GaugeFactory.json | 28 +- deployments/arbitrumOne/Minter.json | 54 +- deployments/arbitrumOne/PairFactory.json | 50 +- .../arbitrumOne/RewardsDistributor.json | 62 +- deployments/arbitrumOne/Router.json | 28 +- deployments/arbitrumOne/VeArtProxy.json | 24 +- .../arbitrumOne/VelocimeterLibrary.json | 229 ++ deployments/arbitrumOne/Voter.json | 74 +- deployments/arbitrumOne/VotingEscrow.json | 158 +- .../WrappedExternalBribeFactory.json | 32 +- .../816572db58a4a8203fcf6f77728173df.json | 247 ++ deployments/arbitrumOneOLD/.chainId | 1 + deployments/arbitrumOneOLD/.migrations.json | 5 + deployments/arbitrumOneOLD/BribeFactory.json | 128 + deployments/arbitrumOneOLD/GaugeFactory.json | 113 + .../MerkleClaim.json | 0 deployments/arbitrumOneOLD/Minter.json | 427 +++ deployments/arbitrumOneOLD/PairFactory.json | 577 ++++ .../RedemptionReceiver.json | 0 .../arbitrumOneOLD/RewardsDistributor.json | 520 ++++ deployments/arbitrumOneOLD/Router.json | 1021 +++++++ deployments/arbitrumOneOLD/VeArtProxy.json | 75 + .../{arbitrumOne => arbitrumOneOLD}/Velo.json | 0 .../VeloGovernor.json | 0 .../VelodromeLibrary.json | 0 deployments/arbitrumOneOLD/Voter.json | 1418 ++++++++++ deployments/arbitrumOneOLD/VotingEscrow.json | 2339 +++++++++++++++++ .../WrappedExternalBribeFactory.json | 148 ++ .../4e21824d68c90a2d8601cfb8f8d80414.json | 0 .../f93feb6db909c3f14d7eec3a3196fbbd.json | 0 package.json | 2 +- test/PairFees.t.sol | 2 +- 44 files changed, 8056 insertions(+), 285 deletions(-) create mode 100644 deployments/arbitrumOne/Flow.json create mode 100644 deployments/arbitrumOne/VelocimeterLibrary.json create mode 100644 deployments/arbitrumOne/solcInputs/816572db58a4a8203fcf6f77728173df.json create mode 100644 deployments/arbitrumOneOLD/.chainId create mode 100644 deployments/arbitrumOneOLD/.migrations.json create mode 100644 deployments/arbitrumOneOLD/BribeFactory.json create mode 100644 deployments/arbitrumOneOLD/GaugeFactory.json rename deployments/{arbitrumOne => arbitrumOneOLD}/MerkleClaim.json (100%) create mode 100644 deployments/arbitrumOneOLD/Minter.json create mode 100644 deployments/arbitrumOneOLD/PairFactory.json rename deployments/{arbitrumOne => arbitrumOneOLD}/RedemptionReceiver.json (100%) create mode 100644 deployments/arbitrumOneOLD/RewardsDistributor.json create mode 100644 deployments/arbitrumOneOLD/Router.json create mode 100644 deployments/arbitrumOneOLD/VeArtProxy.json rename deployments/{arbitrumOne => arbitrumOneOLD}/Velo.json (100%) rename deployments/{arbitrumOne => arbitrumOneOLD}/VeloGovernor.json (100%) rename deployments/{arbitrumOne => arbitrumOneOLD}/VelodromeLibrary.json (100%) create mode 100644 deployments/arbitrumOneOLD/Voter.json create mode 100644 deployments/arbitrumOneOLD/VotingEscrow.json create mode 100644 deployments/arbitrumOneOLD/WrappedExternalBribeFactory.json rename deployments/{arbitrumOne => arbitrumOneOLD}/solcInputs/4e21824d68c90a2d8601cfb8f8d80414.json (100%) rename deployments/{arbitrumOne => arbitrumOneOLD}/solcInputs/f93feb6db909c3f14d7eec3a3196fbbd.json (100%) diff --git a/contracts/ExternalBribe.sol b/contracts/ExternalBribe.sol index 03744e84..a7a60a2d 100644 --- a/contracts/ExternalBribe.sol +++ b/contracts/ExternalBribe.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.13; -// import {Math} from "@openzeppelin-contracts/contracts/utils/math/Math.sol"; -import {Math} from "openzeppelin-contracts/contracts/utils/math/Math.sol"; +import "openzeppelin-contracts/contracts/utils/math/Math.sol"; + import "contracts/interfaces/IBribe.sol"; import "contracts/interfaces/IERC20.sol"; import "contracts/interfaces/IGauge.sol"; diff --git a/contracts/Gauge.sol b/contracts/Gauge.sol index 11f0a93a..9ecbe763 100644 --- a/contracts/Gauge.sol +++ b/contracts/Gauge.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.13; -import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; +import "openzeppelin-contracts/contracts/utils/math/Math.sol"; import "contracts/interfaces/IBribe.sol"; import "contracts/interfaces/IERC20.sol"; import "contracts/interfaces/IGauge.sol"; diff --git a/contracts/InternalBribe.sol b/contracts/InternalBribe.sol index 27fe44b5..977147ba 100644 --- a/contracts/InternalBribe.sol +++ b/contracts/InternalBribe.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.13; -import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; +import "openzeppelin-contracts/contracts/utils/math/Math.sol"; import "contracts/interfaces/IBribe.sol"; import "contracts/interfaces/IERC20.sol"; import "contracts/interfaces/IVoter.sol"; diff --git a/contracts/Minter.sol b/contracts/Minter.sol index 0c54ca84..36bde0de 100644 --- a/contracts/Minter.sol +++ b/contracts/Minter.sol @@ -1,7 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.13; -import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; +import "openzeppelin-contracts/contracts/utils/math/Math.sol"; + import "contracts/interfaces/IMinter.sol"; import "contracts/interfaces/IRewardsDistributor.sol"; import "contracts/interfaces/IFlow.sol"; diff --git a/contracts/Pair.sol b/contracts/Pair.sol index afe2142d..1c755db6 100644 --- a/contracts/Pair.sol +++ b/contracts/Pair.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.13; -import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; +import "openzeppelin-contracts/contracts/utils/math/Math.sol"; import "contracts/interfaces/IERC20.sol"; import "contracts/interfaces/IPair.sol"; import "contracts/interfaces/IPairCallee.sol"; diff --git a/contracts/RewardsDistributor.sol b/contracts/RewardsDistributor.sol index 403b6174..4b9554d7 100644 --- a/contracts/RewardsDistributor.sol +++ b/contracts/RewardsDistributor.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.13; -import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; +import "openzeppelin-contracts/contracts/utils/math/Math.sol"; import "contracts/interfaces/IERC20.sol"; import "contracts/interfaces/IRewardsDistributor.sol"; import "contracts/interfaces/IVotingEscrow.sol"; diff --git a/contracts/Router.sol b/contracts/Router.sol index 5b0491f3..008181ed 100644 --- a/contracts/Router.sol +++ b/contracts/Router.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.13; -import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; +import "openzeppelin-contracts/contracts/utils/math/Math.sol"; import "contracts/interfaces/IERC20.sol"; import "contracts/interfaces/IPair.sol"; import "contracts/interfaces/IPairFactory.sol"; diff --git a/contracts/Voter.sol b/contracts/Voter.sol index 5318e66e..69aa8e4b 100644 --- a/contracts/Voter.sol +++ b/contracts/Voter.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.13; -import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; +import "openzeppelin-contracts/contracts/utils/math/Math.sol"; import "contracts/interfaces/IBribe.sol"; import "contracts/interfaces/IBribeFactory.sol"; import "contracts/interfaces/IGauge.sol"; @@ -174,7 +174,7 @@ contract Voter is IVoter { function poke(uint256 _tokenId) external { require( - IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId) || + IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId) || msg.sender == governor ); address[] memory _poolVote = poolVote[_tokenId]; diff --git a/contracts/WrappedExternalBribe.sol b/contracts/WrappedExternalBribe.sol index 74dda19d..0b5f8d16 100644 --- a/contracts/WrappedExternalBribe.sol +++ b/contracts/WrappedExternalBribe.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.13; -import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; +import "openzeppelin-contracts/contracts/utils/math/Math.sol"; import "contracts/ExternalBribe.sol"; import "contracts/interfaces/IERC20.sol"; import "contracts/interfaces/IGauge.sol"; diff --git a/deployments/arbitrumOne/.migrations.json b/deployments/arbitrumOne/.migrations.json index 92ece6a3..9b57fb51 100644 --- a/deployments/arbitrumOne/.migrations.json +++ b/deployments/arbitrumOne/.migrations.json @@ -1,5 +1,5 @@ { - "init_deploy": 1673992762, - "whitelist": 1673992764, - "initial_dist": 1673992767 + "init_deploy": 1675539307, + "whitelist": 1675539310, + "initial_dist": 1675539312 } \ No newline at end of file diff --git a/deployments/arbitrumOne/BribeFactory.json b/deployments/arbitrumOne/BribeFactory.json index 5986839d..c3551454 100644 --- a/deployments/arbitrumOne/BribeFactory.json +++ b/deployments/arbitrumOne/BribeFactory.json @@ -1,5 +1,5 @@ { - "address": "0xBcC3c06e1D22E44Ac807D76A887fFB40765e0D16", + "address": "0xf4F344Cfa1A82eDD37C96E879f01D9CA03f385b9", "abi": [ { "inputs": [ @@ -66,28 +66,28 @@ "type": "function" } ], - "transactionHash": "0x7354518e1e037b7664110bd3a0f7ef13b1ee4eadbe7d059b4b536bf86b6250fa", + "transactionHash": "0xbf242241c92ba4fe4c8c398fb59ba800f65487e29c50dddc5199b54763cffee9", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xBcC3c06e1D22E44Ac807D76A887fFB40765e0D16", + "contractAddress": "0xf4F344Cfa1A82eDD37C96E879f01D9CA03f385b9", "transactionIndex": 1, - "gasUsed": "26207536", + "gasUsed": "26772550", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfa162f78feb20b053135d6fb2f86d54a4dacf3af0fb526b6dd495cccbeb6e593", - "transactionHash": "0x7354518e1e037b7664110bd3a0f7ef13b1ee4eadbe7d059b4b536bf86b6250fa", + "blockHash": "0x6f3249adc0248d06500dda140b6f84fa675bf831f30e5a226917ffa5d23c4923", + "transactionHash": "0xbf242241c92ba4fe4c8c398fb59ba800f65487e29c50dddc5199b54763cffee9", "logs": [], - "blockNumber": 53774033, - "cumulativeGasUsed": "26207536", + "blockNumber": 58032009, + "cumulativeGasUsed": "26772550", "status": 1, "byzantium": true }, "args": [], "numDeployments": 1, - "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createExternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createInternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_external_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_internal_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/BribeFactory.sol\":\"BribeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/ExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract ExternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve; // \\u5929\\u4f7f\\u306e\\u305f\\u307e\\u3054\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balanceOf;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n _prevSupply = supplyCheckpoints[\\n getPriorSupplyIndex(_nextEpochStart + DURATION)\\n ].supply;\\n prevRewards.balanceOf =\\n (cp0.balanceOf *\\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (block.timestamp > _lastEpochEnd) {\\n reward +=\\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\\n }\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0xfe1e53dea8a63ce448c5856a740ed73038ad29a9dcd0f2a2752049b146bb4eb0\",\"license\":\"MIT\"},\"contracts/InternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract InternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve;\\n\\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 public constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n mapping(address => mapping(uint256 => uint256))\\n public userRewardPerTokenStored;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (totalSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / totalSupply);\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\\n _startTimestamp = endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][tokenId],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][tokenId]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n require(isReward[token]);\\n\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2dc302de5dfd95018d1fba7a3a1916d2c1fcf32859d19d38648767f13422a694\",\"license\":\"MIT\"},\"contracts/factories/BribeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IBribeFactory.sol\\\";\\nimport 'contracts/InternalBribe.sol';\\nimport 'contracts/ExternalBribe.sol';\\n\\ncontract BribeFactory is IBribeFactory {\\n address public last_internal_bribe;\\n address public last_external_bribe;\\n\\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\\n return last_internal_bribe;\\n }\\n\\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\\n return last_external_bribe;\\n }\\n}\\n\\n// if this imports int and ext bribe why is the the gauge factory asking for those address as if they are deployed to an address.\\n\",\"keccak256\":\"0xd107fb5a520bae9b655bec4ad2eb11d598e74d0eeda0db547e2526a907dea7ec\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50614cca806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea26469706673582212205fdc0cbedbaeaa0ba11c8120c027b2bca65c182779d5bf888b06502050a1f54a64736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea2646970667358221220d5f0eaed47ec9cb0f7332a517560bcb420138d14d674caf3674831366bf225f464736f6c634300080d0033a264697066735822122050c7efc34434eca9041cf3c63b65797031e5608706da7fccb31aad9274a6c62c64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea26469706673582212205fdc0cbedbaeaa0ba11c8120c027b2bca65c182779d5bf888b06502050a1f54a64736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea2646970667358221220d5f0eaed47ec9cb0f7332a517560bcb420138d14d674caf3674831366bf225f464736f6c634300080d0033a264697066735822122050c7efc34434eca9041cf3c63b65797031e5608706da7fccb31aad9274a6c62c64736f6c634300080d0033", + "solcInputHash": "816572db58a4a8203fcf6f77728173df", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createExternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createInternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_external_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_internal_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/BribeFactory.sol\":\"BribeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735353339323034313033\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/ExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\\\";\\n\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract ExternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve; // \\u5929\\u4f7f\\u306e\\u305f\\u307e\\u3054\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return Math.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balanceOf;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n _prevSupply = supplyCheckpoints[\\n getPriorSupplyIndex(_nextEpochStart + DURATION)\\n ].supply;\\n prevRewards.balanceOf =\\n (cp0.balanceOf *\\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (block.timestamp > _lastEpochEnd) {\\n reward +=\\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\\n }\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x0026916e62de3e8d8c183fb2baea5512ef16c50760bf8e0f98a69de1e763a03f\",\"license\":\"MIT\"},\"contracts/InternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract InternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve;\\n\\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\\n\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n mapping(address => mapping(uint256 => uint256))\\n public userRewardPerTokenStored;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return Math.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (totalSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n Math.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n 10**IERC20(token).decimals()) / totalSupply);\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = Math.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\\n _startTimestamp = endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = Math.max(timestamp1, startTimestamp);\\n return (\\n (((Math.min(endTime, periodFinish[token]) -\\n Math.min(\\n Math.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n 10**IERC20(token).decimals()) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = Math.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n Math.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = Math.max(\\n lastEarn[token][tokenId],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n 10**IERC20(token).decimals();\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n Math.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][tokenId]\\n ))) /\\n 10**IERC20(token).decimals();\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n require(isReward[token]);\\n\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x520960e0665eab7dd1f9ff52bcd3c3e08b19ee98eff1ba8b4fae7d9e2f1eca8c\",\"license\":\"MIT\"},\"contracts/factories/BribeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IBribeFactory.sol\\\";\\nimport \\\"contracts/InternalBribe.sol\\\";\\nimport \\\"contracts/ExternalBribe.sol\\\";\\n\\ncontract BribeFactory is IBribeFactory {\\n address public last_internal_bribe;\\n address public last_external_bribe;\\n\\n function createInternalBribe(address[] memory allowedRewards)\\n external\\n returns (address)\\n {\\n last_internal_bribe = address(\\n new InternalBribe(msg.sender, allowedRewards)\\n );\\n return last_internal_bribe;\\n }\\n\\n function createExternalBribe(address[] memory allowedRewards)\\n external\\n returns (address)\\n {\\n last_external_bribe = address(\\n new ExternalBribe(msg.sender, allowedRewards)\\n );\\n return last_external_bribe;\\n }\\n}\\n\",\"keccak256\":\"0x8c40b8537b65c9a412a22d707e5a160bf2310c128705dcb0a80f968bc072c39f\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3546b156d97633f7f8cad536d5454c81d1d604687c02b2eb105fdc33cb962b41\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50614f4f806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612db6806102e183390190565b611e838061309783390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002db638038062002db68339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051612a22620003946000396000818161041801528181610aae01528181610f2e015261175201526000818161030601528181610cb901528181610eeb015261165c0152612a226000f3fe608060405234801561001057600080fd5b50600436106102115760003560e01c806399bcc05211610125578063e6886396116100ad578063f301af421161007c578063f301af421461057b578063f32077231461058e578063f5f8d365146105a1578063f7412baf146105b4578063fd314098146105db57600080fd5b8063e68863961461052c578063e8111a1214610534578063f12297771461053d578063f25e55a51461055057600080fd5b8063a28d4c9c116100f4578063a28d4c9c146104b3578063a7852afa146104c6578063aa479652146104d9578063b66503cf146104f9578063da09d19d1461050c57600080fd5b806399bcc0521461044d5780639cc7f708146104605780639ce43f90146104805780639e2bf22c146104a057600080fd5b806349dcc204116101a8578063638634ee11610177578063638634ee146103da57806368fcee1a146103ed57806376f4be36146104005780638dd598fb146104135780639418f9391461043a57600080fd5b806349dcc204146103405780634d5ce0381461037257806350589793146103a55780635a45d052146103c557600080fd5b80632ce9aead116101e45780632ce9aead146102a35780633b881999146102c35780633e491d47146102ee57806346c96aac1461030157600080fd5b806301316ddf1461021657806318160ddd146102625780631be0528914610279578063221ca18c14610283575b600080fd5b6102486102243660046125e1565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61026b60085481565b604051908152602001610259565b61026b62093a8081565b61026b61029136600461260d565b60006020819052908152604090205481565b61026b6102b136600461260d565b60026020526000908152604090205481565b61026b6102d13660046125e1565b600560209081526000928352604080842090915290825290205481565b61026b6102fc3660046125e1565b6105ee565b6103287f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610259565b61024861034e36600461262a565b600a6020908152600092835260408084209091529082529020805460019091015482565b61039561038036600461260d565b60076020526000908152604090205460ff1681565b6040519015158152602001610259565b61026b6103b336600461264c565b600b6020526000908152604090205481565b6103d86103d33660046125e1565b610910565b005b61026b6103e836600461260d565b610948565b6103d86103fb3660046125e1565b61096c565b61026b61040e36600461264c565b610978565b6103287f000000000000000000000000000000000000000000000000000000000000000081565b6103d8610448366004612665565b610aac565b61026b61045b36600461260d565b610c3d565b61026b61046e36600461264c565b60096020526000908152604090205481565b61026b61048e36600461260d565b60036020526000908152604090205481565b6103d86104ae36600461262a565b610cae565b61026b6104c136600461262a565b610d87565b6103d86104d43660046126bd565b610ecc565b61026b6104e736600461260d565b600f6020526000908152604090205481565b6103d86105073660046125e1565b611211565b61026b61051a36600461260d565b60016020526000908152604090205481565b60065461026b565b61026b600d5481565b61026b61054b36600461260d565b611507565b61026b61055e3660046125e1565b600460209081526000928352604080842090915290825290205481565b61032861058936600461264c565b611627565b6103d861059c36600461262a565b611651565b6103d86105af3660046126bd565b611722565b6102486105c236600461264c565b600c602052600090815260409020805460019091015482565b6102486105e93660046125e1565b611a29565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e8252808320838052909152812054909182916106339190611c4a565b6000848152600b60205260408120549192500361065457600091505061090a565b60006106608483610d87565b6000858152600b60205260408120549192509061067f906001906127a4565b9050600081156107ec57825b6106966001846127a4565b81116107ea576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106e29086906127bb565b815260200190815260200160002060405180604001604052908160008201548152602001600182015481525050905060006107218b8460000151611a29565b50905060006107348c8460000151611a29565b5090508b6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610775573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061079991906127d3565b6107a490600a6128da565b6107ae83836127a4565b85602001516107bd91906128e9565b6107c79190612908565b6107d190876127bb565b95505050505080806107e29061292a565b91505061068b565b505b6000868152600a6020908152604080832085845282528083208151808301909252805480835260019091015492820192909252919061082c908a90611a29565b509050886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561086d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061089191906127d3565b61089c90600a6128da565b6001600160a01b038a1660009081526005602090815260408083208c84529091529020546108cb908390611c4a565b6108d48b611507565b6108de91906127a4565b83602001516108ed91906128e9565b6108f79190612908565b61090190846127bb565b96505050505050505b92915050565b61091a8282611c60565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461090a904290611dc3565b61091a82826000611dd2565b600d5460009080820361098e5750600092915050565b82600c600061099e6001856127a4565b815260200190815260200160002060000154116109c7576109c06001826127a4565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e854831015610a025750600092915050565b600080610a106001846127a4565b90505b81811115610aa45760006002610a2984846127a4565b610a339190612908565b610a3d90836127a4565b6000818152600c6020908152604091829020825180840190935280548084526001909101549183019190915291925090879003610a7e575095945050505050565b8051871115610a8f57819350610a9d565b610a9a6001836127a4565b92505b5050610a13565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610b0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b309190612943565b6001600160a01b0316336001600160a01b031614610b815760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610b9e57610b9e612960565b6000918252602090912001546001600160a01b031614610bbd57600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610c0a57610c0a612960565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610c6457506000919050565b6001600160a01b038216600090815260016020526040812054610c889042906127a4565b6001600160a01b0384166000908152602081905260409020549091506109c090826128e9565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610ce357600080fd5b610ceb611fc2565b8160086000828254610cfd91906127a4565b909155505060008181526009602052604081208054849290610d209084906127a4565b9091555050600081815260096020526040902054610d3f90829061204a565b610d47612123565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610da757600091505061090a565b6000848152600a602052604081208491610dc26001856127a4565b81526020019081526020016000206000015411610dec57610de46001826127a4565b91505061090a565b6000848152600a60209081526040808320838052909152902054831015610e1757600091505061090a565b600080610e256001846127a4565b90505b81811115610ec35760006002610e3e84846127a4565b610e489190612908565b610e5290836127a4565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610e9d5750935061090a92505050565b8051871115610eae57819350610ebc565b610eb96001836127a4565b92505b5050610e28565b50949350505050565b601054600114610edb57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610f1557600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610f7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa19190612943565b905060005b825181101561120657610fd6838281518110610fc457610fc4612960565b60200260200101516000196001611dd2565b60036000868581518110610fec57610fec612960565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006002600088878151811061102c5761102c612960565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000849190505583919050555050600061108784838151811061107957611079612960565b6020026020010151866105ee565b905042600460008685815181106110a0576110a0612960565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600087815260200190815260200160002081905550600360008584815181106110f3576110f3612960565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600086858151811061113257611132612960565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120898252909252902055801561118d5761118d84838151811061117e5761117e612960565b602002602001015184836121c7565b83828151811061119f5761119f612960565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516111eb91815260200190565b60405180910390a350806111fe8161292a565b915050610fa6565b505060016010555050565b60105460011461122057600080fd5b60026010558061122f57600080fd5b6001600160a01b03821660009081526007602052604090205460ff1661125457600080fd5b6001600160a01b038216600090815260208190526040812054900361127f5761127f826000426122b6565b61128d826000196001611dd2565b6001600160a01b03841660009081526003602090815260408083206002835281842094909455939092556001909152205442106112fb576112d0823330846123a5565b6112dd62093a8082612908565b6001600160a01b038316600090815260208190526040902055611394565b6001600160a01b03821660009081526001602052604081205461131f9042906127a4565b6001600160a01b0384166000908152602081905260408120549192509061134690836128e9565b905080831161135457600080fd5b611360843330866123a5565b62093a8061136e82856127bb565b6113789190612908565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b0382166000908152602081905260409020546113b657600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156113fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114219190612976565b905061143062093a8082612908565b6001600160a01b03841660009081526020819052604090205411156114975760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610b78565b6114a462093a80426127bb565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114f59086815260200190565b60405180910390a35050600160105550565b600060085460000361152f57506001600160a01b031660009081526003602052604090205490565b600854826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611570573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061159491906127d3565b61159f90600a6128da565b6001600160a01b03841660009081526020818152604080832054600283528184205460019093529220546115d39190611dc3565b6115dc86610948565b6115e691906127a4565b6115f091906128e9565b6115fa91906128e9565b6116049190612908565b6001600160a01b03831660009081526003602052604090205461090a91906127bb565b6006818154811061163757600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461168657600080fd5b61168e611fc2565b81600860008282546116a091906127bb565b9091555050600081815260096020526040812080548492906116c39084906127bb565b90915550506000818152600960205260409020546116e290829061204a565b6116ea612123565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610d7b565b60105460011461173157600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156117a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c5919061298f565b6117ce57600080fd5b60005b8151811015611a1f576117ef828281518110610fc457610fc4612960565b6003600085858151811061180557611805612960565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006002600087878151811061184557611845612960565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600084919050558391905055505060006118a083838151811061189257611892612960565b6020026020010151856105ee565b905042600460008585815181106118b9576118b9612960565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000868152602001908152602001600020819055506003600084848151811061190c5761190c612960565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061194b5761194b612960565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812088825290925290205580156119a6576119a683838151811061199757611997612960565b602002602001015133836121c7565b8282815181106119b8576119b8612960565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051611a0491815260200190565b60405180910390a35080611a178161292a565b9150506117d1565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611a58576000809250925050611c43565b6001600160a01b0385166000908152600e602052604081208591611a7d6001856127a4565b81526020019081526020016000206000015411611b1a576001600160a01b0385166000908152600e6020526040812090611ab86001846127a4565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611afe91906127a4565b8152602001908152602001600020600001549250925050611c43565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611b52576000809250925050611c43565b600080611b606001846127a4565b90505b81811115611c125760006002611b7984846127a4565b611b839190612908565b611b8d90836127a4565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611bec57602081015190519096509450611c439350505050565b8051881115611bfd57819350611c0b565b611c086001836127a4565b92505b5050611b63565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b6000818311611c5957816109c0565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611c9a5792509050611c43565b6001600160a01b0386166000908152602081905260408120549003611cc5579250429150611c439050565b6000611cd083610978565b90506000611cec6001600d54611ce691906127a4565b88611dc3565b9050815b81811015611db4576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611da1576000600c81611d358560016127bb565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611d808d8460000151866000015187602001518d61249d565b9092509050611d8f82896127bb565b9750611d9c8d89836122b6565b975050505b5080611dac8161292a565b915050611cf0565b50919792965091945050505050565b6000818310611c5957816109c0565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611e0c5792509050611fba565b6001600160a01b0387166000908152602081905260408120549003611e37579250429150611fba9050565b6000611e4283610978565b90506000611e5e6001600d54611e5891906127a4565b89611dc3565b90508015611f3757815b611e736001836127a4565b8111611f35576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611f22576000600c81611eb68560016127bb565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611f018e8460000151866000015187602001518d61249d565b9092509050611f1082896127bb565b9750611f1d8e89836122b6565b975050505b5080611f2d8161292a565b915050611e68565b505b8615611fb1576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611faf576000611f908b611f798d610948565b8451611f85908a611c4a565b85602001518a61249d565b509050611f9d81866127bb565b9450611faa8b86426122b6565b429550505b505b50909350909150505b935093915050565b60065460005b8181101561204657600060068281548110611fe557611fe5612960565b6000918252602090912001546001600160a01b0316905061200a816000196001611dd2565b6001600160a01b03909216600090815260036020908152604080832060029092529091209290925590558061203e8161292a565b915050611fc8565b5050565b6000828152600b60205260409020544290801580159061209457506000848152600a6020526040812083916120806001856127a4565b815260200190815260200160002060000154145b156120cd576000848152600a6020526040812084916120b46001856127a4565b815260208101919091526040016000206001015561211d565b60408051808201825283815260208082018681526000888152600a835284812086825290925292902090518155905160019182015561210d9082906127bb565b6000858152600b60205260409020555b50505050565b600d54428115801590612155575080600c60006121416001866127a4565b815260200190815260200160002060000154145b1561218457600854600c600061216c6001866127a4565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556121c09083906127bb565b600d555050565b6000836001600160a01b03163b116121de57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161223a91906129b1565b6000604051808303816000865af19150503d8060008114612277576040519150601f19603f3d011682016040523d82523d6000602084013e61227c565b606091505b50915091508180156122a65750805115806122a65750808060200190518101906122a6919061298f565b6122af57600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061231257506001600160a01b0384166000908152600e6020526040812083916122fe6001856127a4565b815260200190815260200160002060000154145b1561233c576001600160a01b0384166000908152600e6020526040812084916120b46001856127a4565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556123869082906127bb565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116123bc57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b179052915160009283929088169161242091906129b1565b6000604051808303816000865af19150503d806000811461245d576040519150601f19603f3d011682016040523d82523d6000602084013e612462565b606091505b509150915081801561248c57508051158061248c57508080602001905181019061248c919061298f565b61249557600080fd5b505050505050565b60008060006124ac8785611c4a565b905084886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156124ed573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061251191906127d3565b61251c90600a6128da565b6001600160a01b038a166000908152602081905260409020546125606125428a89611c4a565b6001600160a01b038d16600090815260016020526040902054611dc3565b6001600160a01b038c16600090815260016020526040902054612584908690611dc3565b61258e91906127a4565b61259891906128e9565b6125a291906128e9565b6125ac9190612908565b9890975095505050505050565b6001600160a01b03811681146125ce57600080fd5b50565b80356125dc816125b9565b919050565b600080604083850312156125f457600080fd5b82356125ff816125b9565b946020939093013593505050565b60006020828403121561261f57600080fd5b81356109c0816125b9565b6000806040838503121561263d57600080fd5b50508035926020909101359150565b60006020828403121561265e57600080fd5b5035919050565b60008060006060848603121561267a57600080fd5b83359250602084013561268c816125b9565b9150604084013561269c816125b9565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156126d057600080fd5b8235915060208084013567ffffffffffffffff808211156126f057600080fd5b818601915086601f83011261270457600080fd5b813581811115612716576127166126a7565b8060051b604051601f19603f8301168101818110858211171561273b5761273b6126a7565b60405291825284820192508381018501918983111561275957600080fd5b938501935b8285101561277e5761276f856125d1565b8452938501939285019261275e565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156127b6576127b661278e565b500390565b600082198211156127ce576127ce61278e565b500190565b6000602082840312156127e557600080fd5b815160ff811681146109c057600080fd5b600181815b808511156128315781600019048211156128175761281761278e565b8085161561282457918102915b93841c93908002906127fb565b509250929050565b6000826128485750600161090a565b816128555750600061090a565b816001811461286b576002811461287557612891565b600191505061090a565b60ff8411156128865761288661278e565b50506001821b61090a565b5060208310610133831016604e8410600b84101617156128b4575081810a61090a565b6128be83836127f6565b80600019048211156128d2576128d261278e565b029392505050565b60006109c060ff841683612839565b60008160001904831182151516156129035761290361278e565b500290565b60008261292557634e487b7160e01b600052601260045260246000fd5b500490565b60006001820161293c5761293c61278e565b5060010190565b60006020828403121561295557600080fd5b81516109c0816125b9565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561298857600080fd5b5051919050565b6000602082840312156129a157600080fd5b815180151581146109c057600080fd5b6000825160005b818110156129d257602081860181015185830152016129b8565b818111156129e1576000828501525b50919091019291505056fea264697066735822122016172e022d6946333f4325de38fe84762d1ef9f5bc1abbd8f51a6908eb1c138064736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea26469706673582212209d8eb9055c16ee5d95fa4b560f1c94c676f2a031fe0222ec062a8c1738e12d0064736f6c634300080d0033a26469706673582212201f60e040b09d3baead88ccddcde9fbf38fa4b0df6d1520678203c2eadff9e4b964736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612db6806102e183390190565b611e838061309783390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002db638038062002db68339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051612a22620003946000396000818161041801528181610aae01528181610f2e015261175201526000818161030601528181610cb901528181610eeb015261165c0152612a226000f3fe608060405234801561001057600080fd5b50600436106102115760003560e01c806399bcc05211610125578063e6886396116100ad578063f301af421161007c578063f301af421461057b578063f32077231461058e578063f5f8d365146105a1578063f7412baf146105b4578063fd314098146105db57600080fd5b8063e68863961461052c578063e8111a1214610534578063f12297771461053d578063f25e55a51461055057600080fd5b8063a28d4c9c116100f4578063a28d4c9c146104b3578063a7852afa146104c6578063aa479652146104d9578063b66503cf146104f9578063da09d19d1461050c57600080fd5b806399bcc0521461044d5780639cc7f708146104605780639ce43f90146104805780639e2bf22c146104a057600080fd5b806349dcc204116101a8578063638634ee11610177578063638634ee146103da57806368fcee1a146103ed57806376f4be36146104005780638dd598fb146104135780639418f9391461043a57600080fd5b806349dcc204146103405780634d5ce0381461037257806350589793146103a55780635a45d052146103c557600080fd5b80632ce9aead116101e45780632ce9aead146102a35780633b881999146102c35780633e491d47146102ee57806346c96aac1461030157600080fd5b806301316ddf1461021657806318160ddd146102625780631be0528914610279578063221ca18c14610283575b600080fd5b6102486102243660046125e1565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61026b60085481565b604051908152602001610259565b61026b62093a8081565b61026b61029136600461260d565b60006020819052908152604090205481565b61026b6102b136600461260d565b60026020526000908152604090205481565b61026b6102d13660046125e1565b600560209081526000928352604080842090915290825290205481565b61026b6102fc3660046125e1565b6105ee565b6103287f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610259565b61024861034e36600461262a565b600a6020908152600092835260408084209091529082529020805460019091015482565b61039561038036600461260d565b60076020526000908152604090205460ff1681565b6040519015158152602001610259565b61026b6103b336600461264c565b600b6020526000908152604090205481565b6103d86103d33660046125e1565b610910565b005b61026b6103e836600461260d565b610948565b6103d86103fb3660046125e1565b61096c565b61026b61040e36600461264c565b610978565b6103287f000000000000000000000000000000000000000000000000000000000000000081565b6103d8610448366004612665565b610aac565b61026b61045b36600461260d565b610c3d565b61026b61046e36600461264c565b60096020526000908152604090205481565b61026b61048e36600461260d565b60036020526000908152604090205481565b6103d86104ae36600461262a565b610cae565b61026b6104c136600461262a565b610d87565b6103d86104d43660046126bd565b610ecc565b61026b6104e736600461260d565b600f6020526000908152604090205481565b6103d86105073660046125e1565b611211565b61026b61051a36600461260d565b60016020526000908152604090205481565b60065461026b565b61026b600d5481565b61026b61054b36600461260d565b611507565b61026b61055e3660046125e1565b600460209081526000928352604080842090915290825290205481565b61032861058936600461264c565b611627565b6103d861059c36600461262a565b611651565b6103d86105af3660046126bd565b611722565b6102486105c236600461264c565b600c602052600090815260409020805460019091015482565b6102486105e93660046125e1565b611a29565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e8252808320838052909152812054909182916106339190611c4a565b6000848152600b60205260408120549192500361065457600091505061090a565b60006106608483610d87565b6000858152600b60205260408120549192509061067f906001906127a4565b9050600081156107ec57825b6106966001846127a4565b81116107ea576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106e29086906127bb565b815260200190815260200160002060405180604001604052908160008201548152602001600182015481525050905060006107218b8460000151611a29565b50905060006107348c8460000151611a29565b5090508b6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610775573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061079991906127d3565b6107a490600a6128da565b6107ae83836127a4565b85602001516107bd91906128e9565b6107c79190612908565b6107d190876127bb565b95505050505080806107e29061292a565b91505061068b565b505b6000868152600a6020908152604080832085845282528083208151808301909252805480835260019091015492820192909252919061082c908a90611a29565b509050886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561086d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061089191906127d3565b61089c90600a6128da565b6001600160a01b038a1660009081526005602090815260408083208c84529091529020546108cb908390611c4a565b6108d48b611507565b6108de91906127a4565b83602001516108ed91906128e9565b6108f79190612908565b61090190846127bb565b96505050505050505b92915050565b61091a8282611c60565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461090a904290611dc3565b61091a82826000611dd2565b600d5460009080820361098e5750600092915050565b82600c600061099e6001856127a4565b815260200190815260200160002060000154116109c7576109c06001826127a4565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e854831015610a025750600092915050565b600080610a106001846127a4565b90505b81811115610aa45760006002610a2984846127a4565b610a339190612908565b610a3d90836127a4565b6000818152600c6020908152604091829020825180840190935280548084526001909101549183019190915291925090879003610a7e575095945050505050565b8051871115610a8f57819350610a9d565b610a9a6001836127a4565b92505b5050610a13565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610b0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b309190612943565b6001600160a01b0316336001600160a01b031614610b815760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610b9e57610b9e612960565b6000918252602090912001546001600160a01b031614610bbd57600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610c0a57610c0a612960565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610c6457506000919050565b6001600160a01b038216600090815260016020526040812054610c889042906127a4565b6001600160a01b0384166000908152602081905260409020549091506109c090826128e9565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610ce357600080fd5b610ceb611fc2565b8160086000828254610cfd91906127a4565b909155505060008181526009602052604081208054849290610d209084906127a4565b9091555050600081815260096020526040902054610d3f90829061204a565b610d47612123565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610da757600091505061090a565b6000848152600a602052604081208491610dc26001856127a4565b81526020019081526020016000206000015411610dec57610de46001826127a4565b91505061090a565b6000848152600a60209081526040808320838052909152902054831015610e1757600091505061090a565b600080610e256001846127a4565b90505b81811115610ec35760006002610e3e84846127a4565b610e489190612908565b610e5290836127a4565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610e9d5750935061090a92505050565b8051871115610eae57819350610ebc565b610eb96001836127a4565b92505b5050610e28565b50949350505050565b601054600114610edb57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610f1557600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610f7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa19190612943565b905060005b825181101561120657610fd6838281518110610fc457610fc4612960565b60200260200101516000196001611dd2565b60036000868581518110610fec57610fec612960565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006002600088878151811061102c5761102c612960565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000849190505583919050555050600061108784838151811061107957611079612960565b6020026020010151866105ee565b905042600460008685815181106110a0576110a0612960565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600087815260200190815260200160002081905550600360008584815181106110f3576110f3612960565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600086858151811061113257611132612960565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120898252909252902055801561118d5761118d84838151811061117e5761117e612960565b602002602001015184836121c7565b83828151811061119f5761119f612960565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516111eb91815260200190565b60405180910390a350806111fe8161292a565b915050610fa6565b505060016010555050565b60105460011461122057600080fd5b60026010558061122f57600080fd5b6001600160a01b03821660009081526007602052604090205460ff1661125457600080fd5b6001600160a01b038216600090815260208190526040812054900361127f5761127f826000426122b6565b61128d826000196001611dd2565b6001600160a01b03841660009081526003602090815260408083206002835281842094909455939092556001909152205442106112fb576112d0823330846123a5565b6112dd62093a8082612908565b6001600160a01b038316600090815260208190526040902055611394565b6001600160a01b03821660009081526001602052604081205461131f9042906127a4565b6001600160a01b0384166000908152602081905260408120549192509061134690836128e9565b905080831161135457600080fd5b611360843330866123a5565b62093a8061136e82856127bb565b6113789190612908565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b0382166000908152602081905260409020546113b657600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156113fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114219190612976565b905061143062093a8082612908565b6001600160a01b03841660009081526020819052604090205411156114975760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610b78565b6114a462093a80426127bb565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114f59086815260200190565b60405180910390a35050600160105550565b600060085460000361152f57506001600160a01b031660009081526003602052604090205490565b600854826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611570573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061159491906127d3565b61159f90600a6128da565b6001600160a01b03841660009081526020818152604080832054600283528184205460019093529220546115d39190611dc3565b6115dc86610948565b6115e691906127a4565b6115f091906128e9565b6115fa91906128e9565b6116049190612908565b6001600160a01b03831660009081526003602052604090205461090a91906127bb565b6006818154811061163757600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461168657600080fd5b61168e611fc2565b81600860008282546116a091906127bb565b9091555050600081815260096020526040812080548492906116c39084906127bb565b90915550506000818152600960205260409020546116e290829061204a565b6116ea612123565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610d7b565b60105460011461173157600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156117a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c5919061298f565b6117ce57600080fd5b60005b8151811015611a1f576117ef828281518110610fc457610fc4612960565b6003600085858151811061180557611805612960565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006002600087878151811061184557611845612960565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600084919050558391905055505060006118a083838151811061189257611892612960565b6020026020010151856105ee565b905042600460008585815181106118b9576118b9612960565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000868152602001908152602001600020819055506003600084848151811061190c5761190c612960565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061194b5761194b612960565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812088825290925290205580156119a6576119a683838151811061199757611997612960565b602002602001015133836121c7565b8282815181106119b8576119b8612960565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051611a0491815260200190565b60405180910390a35080611a178161292a565b9150506117d1565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611a58576000809250925050611c43565b6001600160a01b0385166000908152600e602052604081208591611a7d6001856127a4565b81526020019081526020016000206000015411611b1a576001600160a01b0385166000908152600e6020526040812090611ab86001846127a4565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611afe91906127a4565b8152602001908152602001600020600001549250925050611c43565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611b52576000809250925050611c43565b600080611b606001846127a4565b90505b81811115611c125760006002611b7984846127a4565b611b839190612908565b611b8d90836127a4565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611bec57602081015190519096509450611c439350505050565b8051881115611bfd57819350611c0b565b611c086001836127a4565b92505b5050611b63565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b6000818311611c5957816109c0565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611c9a5792509050611c43565b6001600160a01b0386166000908152602081905260408120549003611cc5579250429150611c439050565b6000611cd083610978565b90506000611cec6001600d54611ce691906127a4565b88611dc3565b9050815b81811015611db4576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611da1576000600c81611d358560016127bb565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611d808d8460000151866000015187602001518d61249d565b9092509050611d8f82896127bb565b9750611d9c8d89836122b6565b975050505b5080611dac8161292a565b915050611cf0565b50919792965091945050505050565b6000818310611c5957816109c0565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611e0c5792509050611fba565b6001600160a01b0387166000908152602081905260408120549003611e37579250429150611fba9050565b6000611e4283610978565b90506000611e5e6001600d54611e5891906127a4565b89611dc3565b90508015611f3757815b611e736001836127a4565b8111611f35576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611f22576000600c81611eb68560016127bb565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611f018e8460000151866000015187602001518d61249d565b9092509050611f1082896127bb565b9750611f1d8e89836122b6565b975050505b5080611f2d8161292a565b915050611e68565b505b8615611fb1576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611faf576000611f908b611f798d610948565b8451611f85908a611c4a565b85602001518a61249d565b509050611f9d81866127bb565b9450611faa8b86426122b6565b429550505b505b50909350909150505b935093915050565b60065460005b8181101561204657600060068281548110611fe557611fe5612960565b6000918252602090912001546001600160a01b0316905061200a816000196001611dd2565b6001600160a01b03909216600090815260036020908152604080832060029092529091209290925590558061203e8161292a565b915050611fc8565b5050565b6000828152600b60205260409020544290801580159061209457506000848152600a6020526040812083916120806001856127a4565b815260200190815260200160002060000154145b156120cd576000848152600a6020526040812084916120b46001856127a4565b815260208101919091526040016000206001015561211d565b60408051808201825283815260208082018681526000888152600a835284812086825290925292902090518155905160019182015561210d9082906127bb565b6000858152600b60205260409020555b50505050565b600d54428115801590612155575080600c60006121416001866127a4565b815260200190815260200160002060000154145b1561218457600854600c600061216c6001866127a4565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556121c09083906127bb565b600d555050565b6000836001600160a01b03163b116121de57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161223a91906129b1565b6000604051808303816000865af19150503d8060008114612277576040519150601f19603f3d011682016040523d82523d6000602084013e61227c565b606091505b50915091508180156122a65750805115806122a65750808060200190518101906122a6919061298f565b6122af57600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061231257506001600160a01b0384166000908152600e6020526040812083916122fe6001856127a4565b815260200190815260200160002060000154145b1561233c576001600160a01b0384166000908152600e6020526040812084916120b46001856127a4565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556123869082906127bb565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116123bc57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b179052915160009283929088169161242091906129b1565b6000604051808303816000865af19150503d806000811461245d576040519150601f19603f3d011682016040523d82523d6000602084013e612462565b606091505b509150915081801561248c57508051158061248c57508080602001905181019061248c919061298f565b61249557600080fd5b505050505050565b60008060006124ac8785611c4a565b905084886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156124ed573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061251191906127d3565b61251c90600a6128da565b6001600160a01b038a166000908152602081905260409020546125606125428a89611c4a565b6001600160a01b038d16600090815260016020526040902054611dc3565b6001600160a01b038c16600090815260016020526040902054612584908690611dc3565b61258e91906127a4565b61259891906128e9565b6125a291906128e9565b6125ac9190612908565b9890975095505050505050565b6001600160a01b03811681146125ce57600080fd5b50565b80356125dc816125b9565b919050565b600080604083850312156125f457600080fd5b82356125ff816125b9565b946020939093013593505050565b60006020828403121561261f57600080fd5b81356109c0816125b9565b6000806040838503121561263d57600080fd5b50508035926020909101359150565b60006020828403121561265e57600080fd5b5035919050565b60008060006060848603121561267a57600080fd5b83359250602084013561268c816125b9565b9150604084013561269c816125b9565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156126d057600080fd5b8235915060208084013567ffffffffffffffff808211156126f057600080fd5b818601915086601f83011261270457600080fd5b813581811115612716576127166126a7565b8060051b604051601f19603f8301168101818110858211171561273b5761273b6126a7565b60405291825284820192508381018501918983111561275957600080fd5b938501935b8285101561277e5761276f856125d1565b8452938501939285019261275e565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156127b6576127b661278e565b500390565b600082198211156127ce576127ce61278e565b500190565b6000602082840312156127e557600080fd5b815160ff811681146109c057600080fd5b600181815b808511156128315781600019048211156128175761281761278e565b8085161561282457918102915b93841c93908002906127fb565b509250929050565b6000826128485750600161090a565b816128555750600061090a565b816001811461286b576002811461287557612891565b600191505061090a565b60ff8411156128865761288661278e565b50506001821b61090a565b5060208310610133831016604e8410600b84101617156128b4575081810a61090a565b6128be83836127f6565b80600019048211156128d2576128d261278e565b029392505050565b60006109c060ff841683612839565b60008160001904831182151516156129035761290361278e565b500290565b60008261292557634e487b7160e01b600052601260045260246000fd5b500490565b60006001820161293c5761293c61278e565b5060010190565b60006020828403121561295557600080fd5b81516109c0816125b9565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561298857600080fd5b5051919050565b6000602082840312156129a157600080fd5b815180151581146109c057600080fd5b6000825160005b818110156129d257602081860181015185830152016129b8565b818111156129e1576000828501525b50919091019291505056fea264697066735822122016172e022d6946333f4325de38fe84762d1ef9f5bc1abbd8f51a6908eb1c138064736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea26469706673582212209d8eb9055c16ee5d95fa4b560f1c94c676f2a031fe0222ec062a8c1738e12d0064736f6c634300080d0033a26469706673582212201f60e040b09d3baead88ccddcde9fbf38fa4b0df6d1520678203c2eadff9e4b964736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, @@ -101,7 +101,7 @@ "storageLayout": { "storage": [ { - "astId": 21321, + "astId": 21361, "contract": "contracts/factories/BribeFactory.sol:BribeFactory", "label": "last_internal_bribe", "offset": 0, @@ -109,7 +109,7 @@ "type": "t_address" }, { - "astId": 21323, + "astId": 21363, "contract": "contracts/factories/BribeFactory.sol:BribeFactory", "label": "last_external_bribe", "offset": 0, diff --git a/deployments/arbitrumOne/Flow.json b/deployments/arbitrumOne/Flow.json new file mode 100644 index 00000000..a050bebe --- /dev/null +++ b/deployments/arbitrumOne/Flow.json @@ -0,0 +1,522 @@ +{ + "address": "0x944AF7785d57bcfC00e95388453B93DAD373216e", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "claim", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_recipient", + "type": "address" + } + ], + "name": "initialMint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initialMinted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "merkleClaim", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "minter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "redemptionReceiver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_merkleClaim", + "type": "address" + } + ], + "name": "setMerkleClaim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_minter", + "type": "address" + } + ], + "name": "setMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_receiver", + "type": "address" + } + ], + "name": "setRedemptionReceiver", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xfbef1c0e0b922b2c420135c2e7a45369ddb4b68905fc17c359453f82ad01eb11", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x944AF7785d57bcfC00e95388453B93DAD373216e", + "transactionIndex": 3, + "gasUsed": "4613767", + "logsBloom": "0x00000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000010000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000002000000800000000000000000000000000080000000000000000020000000000000000000000000080000000000000000000000000000000000000000", + "blockHash": "0x899067a5f05d1d9bdd910915fe507905882b7c56a07df51cd2736a939d73c628", + "transactionHash": "0xfbef1c0e0b922b2c420135c2e7a45369ddb4b68905fc17c359453f82ad01eb11", + "logs": [ + { + "transactionIndex": 3, + "blockNumber": 58031985, + "transactionHash": "0xfbef1c0e0b922b2c420135c2e7a45369ddb4b68905fc17c359453f82ad01eb11", + "address": "0x944AF7785d57bcfC00e95388453B93DAD373216e", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000053f3b51fd7f327e1ec4e6eaa3a049149cb2acad2" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000", + "logIndex": 7, + "blockHash": "0x899067a5f05d1d9bdd910915fe507905882b7c56a07df51cd2736a939d73c628" + } + ], + "blockNumber": 58031985, + "cumulativeGasUsed": "6369681", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "816572db58a4a8203fcf6f77728173df", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"initialMint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialMinted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleClaim\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redemptionReceiver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_merkleClaim\",\"type\":\"address\"}],\"name\":\"setMerkleClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"setMinter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_receiver\",\"type\":\"address\"}],\"name\":\"setRedemptionReceiver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Flow.sol\":\"Flow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735353339323034313033\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Flow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\n\\ncontract Flow is IFlow {\\n string public constant name = \\\"Velocimeter\\\";\\n string public constant symbol = \\\"FLOW\\\";\\n uint8 public constant decimals = 18;\\n uint256 public totalSupply = 0;\\n\\n mapping(address => uint256) public balanceOf;\\n mapping(address => mapping(address => uint256)) public allowance;\\n\\n bool public initialMinted;\\n address public minter;\\n address public redemptionReceiver;\\n address public merkleClaim;\\n\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 value\\n );\\n\\n constructor() {\\n minter = msg.sender;\\n _mint(msg.sender, 0);\\n }\\n\\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\\n function setMinter(address _minter) external {\\n require(msg.sender == minter);\\n minter = _minter;\\n }\\n\\n function setRedemptionReceiver(address _receiver) external {\\n require(msg.sender == minter);\\n redemptionReceiver = _receiver;\\n }\\n\\n function setMerkleClaim(address _merkleClaim) external {\\n require(msg.sender == minter);\\n merkleClaim = _merkleClaim;\\n }\\n\\n // NFTs are minted from this amount as well now\\n function initialMint(address _recipient) external {\\n require(msg.sender == minter && !initialMinted);\\n initialMinted = true;\\n _mint(_recipient, 400 * 1e6 * 1e18); //#settings\\n }\\n\\n function approve(address _spender, uint256 _value) external returns (bool) {\\n allowance[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n function _mint(address _to, uint256 _amount) internal returns (bool) {\\n totalSupply += _amount;\\n unchecked {\\n balanceOf[_to] += _amount;\\n }\\n emit Transfer(address(0x0), _to, _amount);\\n return true;\\n }\\n\\n function _transfer(\\n address _from,\\n address _to,\\n uint256 _value\\n ) internal returns (bool) {\\n balanceOf[_from] -= _value;\\n unchecked {\\n balanceOf[_to] += _value;\\n }\\n emit Transfer(_from, _to, _value);\\n return true;\\n }\\n\\n function transfer(address _to, uint256 _value) external returns (bool) {\\n return _transfer(msg.sender, _to, _value);\\n }\\n\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) external returns (bool) {\\n uint256 allowed_from = allowance[_from][msg.sender];\\n if (allowed_from != type(uint256).max) {\\n allowance[_from][msg.sender] -= _value;\\n }\\n return _transfer(_from, _to, _value);\\n }\\n\\n function mint(address account, uint256 amount) external returns (bool) {\\n require(msg.sender == minter);\\n _mint(account, amount);\\n return true;\\n }\\n\\n function claim(address account, uint256 amount) external returns (bool) {\\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\\n _mint(account, amount);\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x69c9717363b336f8674b2f170b77071a6894b883bd08fafc805b391921a412a6\",\"license\":\"MIT\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"}},\"version\":1}", + "bytecode": "0x60806040526000805534801561001457600080fd5b5060038054610100600160a81b0319163361010081029190911790915561003c906000610042565b506100d9565b60008160008082825461005591906100b3565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a350600192915050565b600082198211156100d457634e487b7160e01b600052601160045260246000fd5b500190565b61082f806100e86000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ae578063dd62ed3e146102c1578063e752c44a146102ec578063ec676a25146102ff578063fca3b5aa1461031257600080fd5b806395d89b4114610243578063a9059cbb14610266578063aad3ec9614610279578063c268f9ba1461028c578063ca1c4de9146102a157600080fd5b806323b872dd116100f457806323b872dd146101d0578063313ce567146101e357806340c10f19146101fd5780635e05fe501461021057806370a082311461022357600080fd5b806306fdde03146101265780630754617214610166578063095ea7b31461019657806318160ddd146101b9575b600080fd5b6101506040518060400160405280600b81526020016a2b32b637b1b4b6b2ba32b960a91b81525081565b60405161015d919061068f565b60405180910390f35b60035461017e9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015d565b6101a96101a4366004610700565b610325565b604051901515815260200161015d565b6101c260005481565b60405190815260200161015d565b6101a96101de36600461072a565b610391565b6101eb601281565b60405160ff909116815260200161015d565b6101a961020b366004610700565b61040b565b60045461017e906001600160a01b031681565b6101c2610231366004610766565b60016020526000908152604090205481565b61015060405180604001604052806004815260200163464c4f5760e01b81525081565b6101a9610274366004610700565b61043e565b6101a9610287366004610700565b610452565b61029f61029a366004610766565b610481565b005b6003546101a99060ff1681565b61029f6102bc366004610766565b6104d3565b6101c26102cf366004610781565b600260209081526000928352604080842090915290825290205481565b60055461017e906001600160a01b031681565b61029f61030d366004610766565b610511565b61029f610320366004610766565b61054f565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103809086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f7576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103f19084906107ca565b90915550505b610402858585610593565b95945050505050565b60035460009061010090046001600160a01b0316331461042a57600080fd5b610434838361062a565b5060019392505050565b600061044b338484610593565b9392505050565b6004546000906001600160a01b031633148061047857506005546001600160a01b031633145b61042a57600080fd5b60035461010090046001600160a01b0316331480156104a3575060035460ff16155b6104ac57600080fd5b6003805460ff191660011790556104cf816b014adf4b7320334b9000000061062a565b5050565b60035461010090046001600160a01b031633146104ef57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052d57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056b57600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105bd9084906107ca565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106189086815260200190565b60405180910390a35060019392505050565b60008160008082825461063d91906107e1565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610380565b600060208083528351808285015260005b818110156106bc578581018301518582016040015282016106a0565b818111156106ce576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106fb57600080fd5b919050565b6000806040838503121561071357600080fd5b61071c836106e4565b946020939093013593505050565b60008060006060848603121561073f57600080fd5b610748846106e4565b9250610756602085016106e4565b9150604084013590509250925092565b60006020828403121561077857600080fd5b61044b826106e4565b6000806040838503121561079457600080fd5b61079d836106e4565b91506107ab602084016106e4565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107dc576107dc6107b4565b500390565b600082198211156107f4576107f46107b4565b50019056fea2646970667358221220a5ae3bb638496085d1b59cf15baa7d05a0030da5f1aa65c9923d3d59e531405164736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c806395d89b41116100ad578063d9b2e35511610071578063d9b2e355146102ae578063dd62ed3e146102c1578063e752c44a146102ec578063ec676a25146102ff578063fca3b5aa1461031257600080fd5b806395d89b4114610243578063a9059cbb14610266578063aad3ec9614610279578063c268f9ba1461028c578063ca1c4de9146102a157600080fd5b806323b872dd116100f457806323b872dd146101d0578063313ce567146101e357806340c10f19146101fd5780635e05fe501461021057806370a082311461022357600080fd5b806306fdde03146101265780630754617214610166578063095ea7b31461019657806318160ddd146101b9575b600080fd5b6101506040518060400160405280600b81526020016a2b32b637b1b4b6b2ba32b960a91b81525081565b60405161015d919061068f565b60405180910390f35b60035461017e9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161015d565b6101a96101a4366004610700565b610325565b604051901515815260200161015d565b6101c260005481565b60405190815260200161015d565b6101a96101de36600461072a565b610391565b6101eb601281565b60405160ff909116815260200161015d565b6101a961020b366004610700565b61040b565b60045461017e906001600160a01b031681565b6101c2610231366004610766565b60016020526000908152604090205481565b61015060405180604001604052806004815260200163464c4f5760e01b81525081565b6101a9610274366004610700565b61043e565b6101a9610287366004610700565b610452565b61029f61029a366004610766565b610481565b005b6003546101a99060ff1681565b61029f6102bc366004610766565b6104d3565b6101c26102cf366004610781565b600260209081526000928352604080842090915290825290205481565b60055461017e906001600160a01b031681565b61029f61030d366004610766565b610511565b61029f610320366004610766565b61054f565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103809086815260200190565b60405180910390a350600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146103f7576001600160a01b0385166000908152600260209081526040808320338452909152812080548592906103f19084906107ca565b90915550505b610402858585610593565b95945050505050565b60035460009061010090046001600160a01b0316331461042a57600080fd5b610434838361062a565b5060019392505050565b600061044b338484610593565b9392505050565b6004546000906001600160a01b031633148061047857506005546001600160a01b031633145b61042a57600080fd5b60035461010090046001600160a01b0316331480156104a3575060035460ff16155b6104ac57600080fd5b6003805460ff191660011790556104cf816b014adf4b7320334b9000000061062a565b5050565b60035461010090046001600160a01b031633146104ef57600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461052d57600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60035461010090046001600160a01b0316331461056b57600080fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b0383166000908152600160205260408120805483919083906105bd9084906107ca565b90915550506001600160a01b03808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106189086815260200190565b60405180910390a35060019392505050565b60008160008082825461063d91906107e1565b90915550506001600160a01b0383166000818152600160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610380565b600060208083528351808285015260005b818110156106bc578581018301518582016040015282016106a0565b818111156106ce576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146106fb57600080fd5b919050565b6000806040838503121561071357600080fd5b61071c836106e4565b946020939093013593505050565b60008060006060848603121561073f57600080fd5b610748846106e4565b9250610756602085016106e4565b9150604084013590509250925092565b60006020828403121561077857600080fd5b61044b826106e4565b6000806040838503121561079457600080fd5b61079d836106e4565b91506107ab602084016106e4565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107dc576107dc6107b4565b500390565b600082198211156107f4576107f46107b4565b50019056fea2646970667358221220a5ae3bb638496085d1b59cf15baa7d05a0030da5f1aa65c9923d3d59e531405164736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 1343, + "contract": "contracts/Flow.sol:Flow", + "label": "totalSupply", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 1347, + "contract": "contracts/Flow.sol:Flow", + "label": "balanceOf", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 1353, + "contract": "contracts/Flow.sol:Flow", + "label": "allowance", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 1355, + "contract": "contracts/Flow.sol:Flow", + "label": "initialMinted", + "offset": 0, + "slot": "3", + "type": "t_bool" + }, + { + "astId": 1357, + "contract": "contracts/Flow.sol:Flow", + "label": "minter", + "offset": 1, + "slot": "3", + "type": "t_address" + }, + { + "astId": 1359, + "contract": "contracts/Flow.sol:Flow", + "label": "redemptionReceiver", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 1361, + "contract": "contracts/Flow.sol:Flow", + "label": "merkleClaim", + "offset": 0, + "slot": "5", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumOne/GaugeFactory.json b/deployments/arbitrumOne/GaugeFactory.json index 06d3737d..d47bf99b 100644 --- a/deployments/arbitrumOne/GaugeFactory.json +++ b/deployments/arbitrumOne/GaugeFactory.json @@ -1,5 +1,5 @@ { - "address": "0x2CCb061AD1b50211cF79f33e690452497941a2fe", + "address": "0x2B0BB6962e89bD5FE9510Ff09Af8D709be21AAD7", "abi": [ { "inputs": [ @@ -59,28 +59,28 @@ "type": "function" } ], - "transactionHash": "0x7ce753e4c58de4050464cc91803d46e3f6e11979f35747b219de8ced642739a6", + "transactionHash": "0x09f6670bba024fa701ea9d9b3063e28841cf575d2835f1cf7b62e001ba978aef", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x2CCb061AD1b50211cF79f33e690452497941a2fe", - "transactionIndex": 2, - "gasUsed": "22465566", + "contractAddress": "0x2B0BB6962e89bD5FE9510Ff09Af8D709be21AAD7", + "transactionIndex": 1, + "gasUsed": "22312361", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x8411daf7bf6b95ca73cd5501cf340f0ad5b197b0b98168e0e20a0bf9a5405d66", - "transactionHash": "0x7ce753e4c58de4050464cc91803d46e3f6e11979f35747b219de8ced642739a6", + "blockHash": "0x9549973db6314c602849799444ad26a0d1adc452c46b8d6a18749a87566b018b", + "transactionHash": "0x09f6670bba024fa701ea9d9b3063e28841cf575d2835f1cf7b62e001ba978aef", "logs": [], - "blockNumber": 53774021, - "cumulativeGasUsed": "23230219", + "blockNumber": 58031998, + "cumulativeGasUsed": "22312361", "status": 1, "byzantium": true }, "args": [], "numDeployments": 1, - "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_internal_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_external_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_ve\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isPair\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_gauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/GaugeFactory.sol\":\"GaugeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Gauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\\ncontract Gauge is IGauge {\\n address public immutable stake; // the LP token that needs to be staked for rewards\\n address public immutable _ve; // the ve token used for gauges\\n address public immutable internal_bribe;\\n address public immutable external_bribe;\\n address public immutable voter;\\n\\n uint256 public derivedSupply;\\n mapping(address => uint256) public derivedBalances;\\n\\n bool public isForPair;\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 internal constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(address => uint256)) public lastEarn;\\n mapping(address => mapping(address => uint256))\\n public userRewardPerTokenStored;\\n\\n mapping(address => uint256) public tokenIds;\\n\\n uint256 public totalSupply;\\n mapping(address => uint256) public balanceOf;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n uint256 public fees0;\\n uint256 public fees1;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(\\n address _stake,\\n address _internal_bribe,\\n address _external_bribe,\\n address __ve,\\n address _voter,\\n bool _forPair,\\n address[] memory _allowedRewardTokens\\n ) {\\n stake = _stake;\\n internal_bribe = _internal_bribe;\\n external_bribe = _external_bribe;\\n _ve = __ve;\\n voter = _voter;\\n isForPair = _forPair;\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function claimFees()\\n external\\n lock\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n return _claimFees();\\n }\\n\\n function _claimFees()\\n internal\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n if (!isForPair) {\\n return (0, 0);\\n }\\n (claimed0, claimed1) = IPair(stake).claimFees();\\n if (claimed0 > 0 || claimed1 > 0) {\\n uint256 _fees0 = fees0 + claimed0;\\n uint256 _fees1 = fees1 + claimed1;\\n (address _token0, address _token1) = IPair(stake).tokens();\\n if (\\n _fees0 > IBribe(internal_bribe).left(_token0) &&\\n _fees0 / DURATION > 0\\n ) {\\n fees0 = 0;\\n _safeApprove(_token0, internal_bribe, _fees0);\\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\\n } else {\\n fees0 = _fees0;\\n }\\n if (\\n _fees1 > IBribe(internal_bribe).left(_token1) &&\\n _fees1 / DURATION > 0\\n ) {\\n fees1 = 0;\\n _safeApprove(_token1, internal_bribe, _fees1);\\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\\n } else {\\n fees1 = _fees1;\\n }\\n\\n emit ClaimFees(msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(address account, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(address account, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[account][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[account] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n derivedSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n function getReward(address account, address[] memory tokens) external lock {\\n require(msg.sender == account || msg.sender == voter);\\n _unlocked = 1;\\n IVoter(voter).distribute(address(this));\\n _unlocked = 2;\\n\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], account);\\n lastEarn[tokens[i]][account] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n\\n uint256 _derivedBalance = derivedBalances[account];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(account);\\n derivedBalances[account] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(account, derivedBalances[account]);\\n _writeSupplyCheckpoint();\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (derivedSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / derivedSupply);\\n }\\n\\n function derivedBalance(address account) public view returns (uint256) {\\n return balanceOf[account];\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\\n function earned(address token, address account)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][account],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[account] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[account] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[account][i];\\n Checkpoint memory cp1 = checkpoints[account][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[account][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][account]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n function depositAll(uint256 tokenId) external {\\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\\n }\\n\\n function deposit(uint256 amount, uint256 tokenId) public lock {\\n require(amount > 0);\\n _updateRewardForAllTokens();\\n\\n _safeTransferFrom(stake, msg.sender, address(this), amount);\\n totalSupply += amount;\\n balanceOf[msg.sender] += amount;\\n\\n if (tokenId > 0) {\\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\\n if (tokenIds[msg.sender] == 0) {\\n tokenIds[msg.sender] = tokenId;\\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\\n }\\n require(tokenIds[msg.sender] == tokenId);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, _derivedBalance);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function withdrawAll() external {\\n withdraw(balanceOf[msg.sender]);\\n }\\n\\n function withdraw(uint256 amount) public {\\n uint256 tokenId = 0;\\n if (amount == balanceOf[msg.sender]) {\\n tokenId = tokenIds[msg.sender];\\n }\\n withdrawToken(amount, tokenId);\\n }\\n\\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[msg.sender] -= amount;\\n _safeTransfer(stake, msg.sender, amount);\\n\\n if (tokenId > 0) {\\n require(tokenId == tokenIds[msg.sender]);\\n tokenIds[msg.sender] = 0;\\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(token != stake);\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"rewards tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n _claimFees();\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeApprove(\\n address token,\\n address spender,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x38cc0284dd60d8a1418d9c34e6be84911ca4a1b479dc129f19b9027e4c670e1f\",\"license\":\"MIT\"},\"contracts/factories/GaugeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/Gauge.sol';\\n\\ncontract GaugeFactory is IGaugeFactory {\\n address public last_gauge;\\n\\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\\n return last_gauge;\\n }\\n}\\n\",\"keccak256\":\"0x34f6ac4bdace9ef01d8cffda9b45842efae88b519230c67759b9936aee6acc9b\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50613b19806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea2646970667358221220656ccf09ce656ea8ebfb044a59e62cffea98cb78d8b1c3228ccdcceab4e0aee364736f6c634300080d0033a2646970667358221220b102ed748ff42223948c2bba31684751618fee0a65b5917ca364d53fe7ff82cd64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea2646970667358221220656ccf09ce656ea8ebfb044a59e62cffea98cb78d8b1c3228ccdcceab4e0aee364736f6c634300080d0033a2646970667358221220b102ed748ff42223948c2bba31684751618fee0a65b5917ca364d53fe7ff82cd64736f6c634300080d0033", + "solcInputHash": "816572db58a4a8203fcf6f77728173df", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_internal_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_external_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_ve\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isPair\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_gauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/GaugeFactory.sol\":\"GaugeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735353339323034313033\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Gauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\\ncontract Gauge is IGauge {\\n address public immutable stake; // the LP token that needs to be staked for rewards\\n address public immutable _ve; // the ve token used for gauges\\n address public immutable internal_bribe;\\n address public immutable external_bribe;\\n address public immutable voter;\\n\\n uint256 public derivedSupply;\\n mapping(address => uint256) public derivedBalances;\\n\\n bool public isForPair;\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 internal constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(address => uint256)) public lastEarn;\\n mapping(address => mapping(address => uint256))\\n public userRewardPerTokenStored;\\n\\n mapping(address => uint256) public tokenIds;\\n\\n uint256 public totalSupply;\\n mapping(address => uint256) public balanceOf;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n uint256 public fees0;\\n uint256 public fees1;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(\\n address _stake,\\n address _internal_bribe,\\n address _external_bribe,\\n address __ve,\\n address _voter,\\n bool _forPair,\\n address[] memory _allowedRewardTokens\\n ) {\\n stake = _stake;\\n internal_bribe = _internal_bribe;\\n external_bribe = _external_bribe;\\n _ve = __ve;\\n voter = _voter;\\n isForPair = _forPair;\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function claimFees()\\n external\\n lock\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n return _claimFees();\\n }\\n\\n function _claimFees()\\n internal\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n if (!isForPair) {\\n return (0, 0);\\n }\\n (claimed0, claimed1) = IPair(stake).claimFees();\\n if (claimed0 > 0 || claimed1 > 0) {\\n uint256 _fees0 = fees0 + claimed0;\\n uint256 _fees1 = fees1 + claimed1;\\n (address _token0, address _token1) = IPair(stake).tokens();\\n if (\\n _fees0 > IBribe(internal_bribe).left(_token0) &&\\n _fees0 / DURATION > 0\\n ) {\\n fees0 = 0;\\n _safeApprove(_token0, internal_bribe, _fees0);\\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\\n } else {\\n fees0 = _fees0;\\n }\\n if (\\n _fees1 > IBribe(internal_bribe).left(_token1) &&\\n _fees1 / DURATION > 0\\n ) {\\n fees1 = 0;\\n _safeApprove(_token1, internal_bribe, _fees1);\\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\\n } else {\\n fees1 = _fees1;\\n }\\n\\n emit ClaimFees(msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(address account, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(address account, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[account][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[account] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n derivedSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return Math.min(block.timestamp, periodFinish[token]);\\n }\\n\\n function getReward(address account, address[] memory tokens) external lock {\\n require(msg.sender == account || msg.sender == voter);\\n _unlocked = 1;\\n IVoter(voter).distribute(address(this));\\n _unlocked = 2;\\n\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], account);\\n lastEarn[tokens[i]][account] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n\\n uint256 _derivedBalance = derivedBalances[account];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(account);\\n derivedBalances[account] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(account, derivedBalances[account]);\\n _writeSupplyCheckpoint();\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (derivedSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n Math.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / derivedSupply);\\n }\\n\\n function derivedBalance(address account) public view returns (uint256) {\\n return balanceOf[account];\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = Math.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = Math.max(timestamp1, startTimestamp);\\n return (\\n (((Math.min(endTime, periodFinish[token]) -\\n Math.min(\\n Math.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = Math.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n Math.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\\n function earned(address token, address account)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = Math.max(\\n lastEarn[token][account],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[account] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[account] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[account][i];\\n Checkpoint memory cp1 = checkpoints[account][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[account][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n Math.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][account]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n function depositAll(uint256 tokenId) external {\\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\\n }\\n\\n function deposit(uint256 amount, uint256 tokenId) public lock {\\n require(amount > 0);\\n _updateRewardForAllTokens();\\n\\n _safeTransferFrom(stake, msg.sender, address(this), amount);\\n totalSupply += amount;\\n balanceOf[msg.sender] += amount;\\n\\n if (tokenId > 0) {\\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\\n if (tokenIds[msg.sender] == 0) {\\n tokenIds[msg.sender] = tokenId;\\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\\n }\\n require(tokenIds[msg.sender] == tokenId);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, _derivedBalance);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function withdrawAll() external {\\n withdraw(balanceOf[msg.sender]);\\n }\\n\\n function withdraw(uint256 amount) public {\\n uint256 tokenId = 0;\\n if (amount == balanceOf[msg.sender]) {\\n tokenId = tokenIds[msg.sender];\\n }\\n withdrawToken(amount, tokenId);\\n }\\n\\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[msg.sender] -= amount;\\n _safeTransfer(stake, msg.sender, amount);\\n\\n if (tokenId > 0) {\\n require(tokenId == tokenIds[msg.sender]);\\n tokenIds[msg.sender] = 0;\\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(token != stake);\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"rewards tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n _claimFees();\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeApprove(\\n address token,\\n address spender,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x83f617441300319e41d821f84d4d4d2d2ddf16dbbc70e7a362b1c7d75a50c299\",\"license\":\"MIT\"},\"contracts/factories/GaugeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/Gauge.sol';\\n\\ncontract GaugeFactory is IGaugeFactory {\\n address public last_gauge;\\n\\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\\n return last_gauge;\\n }\\n}\\n\",\"keccak256\":\"0x34f6ac4bdace9ef01d8cffda9b45842efae88b519230c67759b9936aee6acc9b\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3546b156d97633f7f8cad536d5454c81d1d604687c02b2eb105fdc33cb962b41\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50613b18806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613812806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003812380380620038128339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fc620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa301528181612b3a01528181612b8501528181612c0b01528181612ca00152612ceb0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293b01526129fd01526133fc6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303c565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303c565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303c565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613068565b610900565b61036a6103a23660046130a1565b60036020526000908152604090205481565b61036a6103c23660046130a1565b60056020526000908152604090205481565b6103e76103e23660046130be565b610b84565b005b6103e76103f73660046130ed565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613068565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a1565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303c565b610fba565b61036a6104d23660046130a1565b610ff2565b61036a6104e53660046130a1565b60016020526000908152604090205481565b6103e761050536600461303c565b611016565b61036a6105183660046130a1565b600f6020526000908152604090205481565b61036a6105383660046130a1565b600b6020526000908152604090205481565b61036a6105583660046130be565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c7565b611171565b61036a6105dd3660046130a1565b611302565b61036a6105f03660046130a1565b60066020526000908152604090205481565b61036a610610366004613068565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a1565b60136020526000908152604090205481565b6103e761065b36600461303c565b611373565b6103e761066e3660046130be565b611865565b6102cc6118fa565b61036a6106893660046130a1565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a1565b60046020526000908152604090205481565b6103e76106db366004613209565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a1565b611c73565b61030d61071f3660046130be565b611d32565b6102cc6107323660046130be565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a1565b60096020526000908152604090205481565b6102cc61077936600461303c565b611d5c565b6103e761078c366004613209565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613241565b8152602001908152602001600020600001541161080a57610802600182613241565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613241565b90505b818111156108f557600060026108668484613241565b6108709190613258565b61087a9083613241565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613241565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613241565b905060008115610ab857825b6109bd600184613241565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327a565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613241565b8560200151610a899190613292565b610a939190613258565b610a9d908761327a565b9550505050508080610aae906132b1565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613241565b8360200151610b639190613292565b610b6d9190613258565b610b77908461327a565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132ca565b60200260200101516000196001612222565b60066000858581518110610ce357610ce36132ca565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132ca565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132ca565b602002602001015185610900565b90504260076000858581518110610d9757610d976132ca565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132ca565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132ca565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132ca565b60200260200101518583612412565b828281518110610eac57610eac6132ca565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b1565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613241565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327a565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612512565b610fb061261d565b5050600160165550565b610fc482826126c0565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612823565b610fc482826000612222565b6011546000908082036110385750600092915050565b8260106000611048600185613241565b815260200190815260200160002060000154116110715761106a600182613241565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613241565b90505b8181111561114e57600060026110d38484613241565b6110dd9190613258565b6110e79083613241565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613241565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e0565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132ca565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132ca565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613241565b6001600160a01b03841660009081526003602052604090205490915061106a9082613292565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fd565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612832565b611558826000196001612222565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612921565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d96565b6115c262093a8082613258565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613241565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613292565b905080831161163957600080fd5b61164584333086612d96565b62093a80611653828561327a565b61165d9190613258565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611706919061331f565b905061171562093a8082613258565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327a565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f1919061331f565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612921565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8e565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d96565b81600a600082825461198a919061327a565b9091555050336000908152600b6020526040812080548492906119ae90849061327a565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e0565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613241565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327a565b90915550611b9e90503382612512565b611ba661261d565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612823565b611ce786610ff2565b611cf19190613241565b611cfb9190613292565b611d059190613292565b611d0f9190613258565b6001600160a01b0383166000908152600660205260409020546108fa919061327a565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613241565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613241565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613241565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613241565b90505b81811115611f455760006002611eac8484613241565b611eb69190613258565b611ec09083613241565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613241565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8e565b81600a6000828254611fab9190613241565b9091555050336000908152600b602052604081208054849290611fcf908490613241565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612412565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613241565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327a565b9091555050336000818152600160205260409020546121459190612512565b61214d61261d565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b600081831161221b578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225c579250905061240a565b6001600160a01b038716600090815260036020526040812054900361228757925042915061240a9050565b600061229283611022565b905060006122ae60016011546122a89190613241565b89612823565b9050801561238757815b6122c3600183613241565b811161238557600081815260106020908152604091829020825180840190935280548352600101549082018190521561237257600060108161230685600161327a565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123518e8460000151866000015187602001518d612f12565b9092509050612360828961327a565b975061236d8e8983612832565b975050505b508061237d816132b1565b9150506122b8565b505b86156124015760008181526010602090815260409182902082518084019093528054835260010154908201819052156123ff5760006123e08b6123c98d610ff2565b84516123d5908a61220c565b85602001518a612f12565b5090506123ed818661327a565b94506123fa8b8642612832565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242957600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124969190613338565b6000604051808303816000865af19150503d80600081146124d3576040519150601f19603f3d011682016040523d82523d6000602084013e6124d8565b606091505b509150915081801561250257508051158061250257508080602001905181019061250291906132fd565b61250b57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257057506001600160a01b0384166000908152600e60205260408120839161255c600185613241565b815260200190815260200160002060000154145b156125b3576001600160a01b0384166000908152600e60205260408120849161259a600185613241565b8152602081019190915260400160002060010155612617565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fd90829061327a565b6001600160a01b0385166000908152600f60205260409020555b50505050565b60115442811580159061264f5750806010600061263b600186613241565b815260200190815260200160002060000154145b1561268057600054601060006001856126689190613241565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126b990839061327a565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fa5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612725579250429150611f769050565b600061273083611022565b9050600061274c60016011546127469190613241565b88612823565b9050815b8181101561281457600081815260106020908152604091829020825180840190935280548352600101549082018190521561280157600060108161279585600161327a565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e08d8460000151866000015187602001518d612f12565b90925090506127ef828961327a565b97506127fc8d8983612832565b975050505b508061280c816132b1565b915050612750565b50919792965091945050505050565b600081831061221b578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288e57506001600160a01b0384166000908152601260205260408120839161287a600185613241565b815260200190815260200160002060000154145b156128b8576001600160a01b0384166000908152601260205260408120849161259a600185613241565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290290829061327a565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff166129395750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612998573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bc9190613373565b9092509050811515806129cf5750600081115b15612d92576000826014546129e4919061327a565b90506000826015546129f6919061327a565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7e9190613397565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b10919061331f565b84118015612b2a57506000612b2862093a8086613258565b115b15612be6576000601455612b5f827f000000000000000000000000000000000000000000000000000000000000000086612fcd565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bc957600080fd5b505af1158015612bdd573d6000803e3d6000fd5b50505050612bec565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c76919061331f565b83118015612c9057506000612c8e62093a8085613258565b115b15612d4c576000601555612cc5817f000000000000000000000000000000000000000000000000000000000000000085612fcd565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d2f57600080fd5b505af1158015612d43573d6000803e3d6000fd5b50505050612d52565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dad57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e119190613338565b6000604051808303816000865af19150503d8060008114612e4e576040519150601f19603f3d011682016040523d82523d6000602084013e612e53565b606091505b5091509150818015612e7d575080511580612e7d575080806020019051810190612e7d91906132fd565b612e8657600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb157612eb16132ca565b6000918252602090912001546001600160a01b03169050612ed6816000196001612222565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0a816132b1565b915050612e94565b6000806000612f21878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f74612f568a8961220c565b6001600160a01b038d16600090815260046020526040902054612823565b6001600160a01b038c16600090815260046020526040902054612f98908690612823565b612fa29190613241565b612fac9190613292565b612fb69190613292565b612fc09190613258565b9890975095505050505050565b6000836001600160a01b03163b11612fe457600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612458565b6001600160a01b03811681146118f757600080fd5b803561303781613017565b919050565b6000806040838503121561304f57600080fd5b823561305a81613017565b946020939093013593505050565b6000806040838503121561307b57600080fd5b823561308681613017565b9150602083013561309681613017565b809150509250929050565b6000602082840312156130b357600080fd5b813561106a81613017565b6000602082840312156130d057600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310057600080fd5b823561310b81613017565b915060208381013567ffffffffffffffff8082111561312957600080fd5b818601915086601f83011261313d57600080fd5b81358181111561314f5761314f6130d7565b8060051b604051601f19603f83011681018181108582111715613174576131746130d7565b60405291825284820192508381018501918983111561319257600080fd5b938501935b828510156131b7576131a88561302c565b84529385019392850192613197565b8096505050505050509250929050565b6000806000606084860312156131dc57600080fd5b8335925060208401356131ee81613017565b915060408401356131fe81613017565b809150509250925092565b6000806040838503121561321c57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132535761325361322b565b500390565b60008261327557634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328d5761328d61322b565b500190565b60008160001904831182151516156132ac576132ac61322b565b500290565b6000600182016132c3576132c361322b565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f257600080fd5b815161106a81613017565b60006020828403121561330f57600080fd5b8151801515811461106a57600080fd5b60006020828403121561333157600080fd5b5051919050565b6000825160005b81811015613359576020818601810151858301520161333f565b81811115613368576000828501525b509190910192915050565b6000806040838503121561338657600080fd5b505080516020909101519092909150565b600080604083850312156133aa57600080fd5b82516133b581613017565b60208401519092506130968161301756fea2646970667358221220d3d5846418c8a989d07a62131dbd9fbd6198a140718eb6845440fdb0e3af1de564736f6c634300080d0033a264697066735822122033bb32f75eb748f30d848ded2119eaa78f2bd974bb37bd01b17846c6040fa11364736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613812806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003812380380620038128339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fc620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa301528181612b3a01528181612b8501528181612c0b01528181612ca00152612ceb0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293b01526129fd01526133fc6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303c565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303c565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303c565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613068565b610900565b61036a6103a23660046130a1565b60036020526000908152604090205481565b61036a6103c23660046130a1565b60056020526000908152604090205481565b6103e76103e23660046130be565b610b84565b005b6103e76103f73660046130ed565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613068565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a1565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303c565b610fba565b61036a6104d23660046130a1565b610ff2565b61036a6104e53660046130a1565b60016020526000908152604090205481565b6103e761050536600461303c565b611016565b61036a6105183660046130a1565b600f6020526000908152604090205481565b61036a6105383660046130a1565b600b6020526000908152604090205481565b61036a6105583660046130be565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c7565b611171565b61036a6105dd3660046130a1565b611302565b61036a6105f03660046130a1565b60066020526000908152604090205481565b61036a610610366004613068565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a1565b60136020526000908152604090205481565b6103e761065b36600461303c565b611373565b6103e761066e3660046130be565b611865565b6102cc6118fa565b61036a6106893660046130a1565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a1565b60046020526000908152604090205481565b6103e76106db366004613209565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a1565b611c73565b61030d61071f3660046130be565b611d32565b6102cc6107323660046130be565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a1565b60096020526000908152604090205481565b6102cc61077936600461303c565b611d5c565b6103e761078c366004613209565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613241565b8152602001908152602001600020600001541161080a57610802600182613241565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613241565b90505b818111156108f557600060026108668484613241565b6108709190613258565b61087a9083613241565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613241565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613241565b905060008115610ab857825b6109bd600184613241565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327a565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613241565b8560200151610a899190613292565b610a939190613258565b610a9d908761327a565b9550505050508080610aae906132b1565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613241565b8360200151610b639190613292565b610b6d9190613258565b610b77908461327a565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132ca565b60200260200101516000196001612222565b60066000858581518110610ce357610ce36132ca565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132ca565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132ca565b602002602001015185610900565b90504260076000858581518110610d9757610d976132ca565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132ca565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132ca565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132ca565b60200260200101518583612412565b828281518110610eac57610eac6132ca565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b1565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613241565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327a565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612512565b610fb061261d565b5050600160165550565b610fc482826126c0565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612823565b610fc482826000612222565b6011546000908082036110385750600092915050565b8260106000611048600185613241565b815260200190815260200160002060000154116110715761106a600182613241565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613241565b90505b8181111561114e57600060026110d38484613241565b6110dd9190613258565b6110e79083613241565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613241565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e0565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132ca565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132ca565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613241565b6001600160a01b03841660009081526003602052604090205490915061106a9082613292565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fd565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612832565b611558826000196001612222565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612921565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d96565b6115c262093a8082613258565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613241565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613292565b905080831161163957600080fd5b61164584333086612d96565b62093a80611653828561327a565b61165d9190613258565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611706919061331f565b905061171562093a8082613258565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327a565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f1919061331f565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612921565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8e565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d96565b81600a600082825461198a919061327a565b9091555050336000908152600b6020526040812080548492906119ae90849061327a565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e0565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613241565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327a565b90915550611b9e90503382612512565b611ba661261d565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612823565b611ce786610ff2565b611cf19190613241565b611cfb9190613292565b611d059190613292565b611d0f9190613258565b6001600160a01b0383166000908152600660205260409020546108fa919061327a565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613241565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613241565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613241565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613241565b90505b81811115611f455760006002611eac8484613241565b611eb69190613258565b611ec09083613241565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613241565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8e565b81600a6000828254611fab9190613241565b9091555050336000908152600b602052604081208054849290611fcf908490613241565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612412565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613241565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327a565b9091555050336000818152600160205260409020546121459190612512565b61214d61261d565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b600081831161221b578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225c579250905061240a565b6001600160a01b038716600090815260036020526040812054900361228757925042915061240a9050565b600061229283611022565b905060006122ae60016011546122a89190613241565b89612823565b9050801561238757815b6122c3600183613241565b811161238557600081815260106020908152604091829020825180840190935280548352600101549082018190521561237257600060108161230685600161327a565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123518e8460000151866000015187602001518d612f12565b9092509050612360828961327a565b975061236d8e8983612832565b975050505b508061237d816132b1565b9150506122b8565b505b86156124015760008181526010602090815260409182902082518084019093528054835260010154908201819052156123ff5760006123e08b6123c98d610ff2565b84516123d5908a61220c565b85602001518a612f12565b5090506123ed818661327a565b94506123fa8b8642612832565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242957600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124969190613338565b6000604051808303816000865af19150503d80600081146124d3576040519150601f19603f3d011682016040523d82523d6000602084013e6124d8565b606091505b509150915081801561250257508051158061250257508080602001905181019061250291906132fd565b61250b57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257057506001600160a01b0384166000908152600e60205260408120839161255c600185613241565b815260200190815260200160002060000154145b156125b3576001600160a01b0384166000908152600e60205260408120849161259a600185613241565b8152602081019190915260400160002060010155612617565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fd90829061327a565b6001600160a01b0385166000908152600f60205260409020555b50505050565b60115442811580159061264f5750806010600061263b600186613241565b815260200190815260200160002060000154145b1561268057600054601060006001856126689190613241565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126b990839061327a565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fa5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612725579250429150611f769050565b600061273083611022565b9050600061274c60016011546127469190613241565b88612823565b9050815b8181101561281457600081815260106020908152604091829020825180840190935280548352600101549082018190521561280157600060108161279585600161327a565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e08d8460000151866000015187602001518d612f12565b90925090506127ef828961327a565b97506127fc8d8983612832565b975050505b508061280c816132b1565b915050612750565b50919792965091945050505050565b600081831061221b578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288e57506001600160a01b0384166000908152601260205260408120839161287a600185613241565b815260200190815260200160002060000154145b156128b8576001600160a01b0384166000908152601260205260408120849161259a600185613241565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290290829061327a565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff166129395750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612998573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bc9190613373565b9092509050811515806129cf5750600081115b15612d92576000826014546129e4919061327a565b90506000826015546129f6919061327a565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7e9190613397565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b10919061331f565b84118015612b2a57506000612b2862093a8086613258565b115b15612be6576000601455612b5f827f000000000000000000000000000000000000000000000000000000000000000086612fcd565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bc957600080fd5b505af1158015612bdd573d6000803e3d6000fd5b50505050612bec565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c76919061331f565b83118015612c9057506000612c8e62093a8085613258565b115b15612d4c576000601555612cc5817f000000000000000000000000000000000000000000000000000000000000000085612fcd565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d2f57600080fd5b505af1158015612d43573d6000803e3d6000fd5b50505050612d52565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dad57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e119190613338565b6000604051808303816000865af19150503d8060008114612e4e576040519150601f19603f3d011682016040523d82523d6000602084013e612e53565b606091505b5091509150818015612e7d575080511580612e7d575080806020019051810190612e7d91906132fd565b612e8657600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb157612eb16132ca565b6000918252602090912001546001600160a01b03169050612ed6816000196001612222565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0a816132b1565b915050612e94565b6000806000612f21878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f74612f568a8961220c565b6001600160a01b038d16600090815260046020526040902054612823565b6001600160a01b038c16600090815260046020526040902054612f98908690612823565b612fa29190613241565b612fac9190613292565b612fb69190613292565b612fc09190613258565b9890975095505050505050565b6000836001600160a01b03163b11612fe457600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612458565b6001600160a01b03811681146118f757600080fd5b803561303781613017565b919050565b6000806040838503121561304f57600080fd5b823561305a81613017565b946020939093013593505050565b6000806040838503121561307b57600080fd5b823561308681613017565b9150602083013561309681613017565b809150509250929050565b6000602082840312156130b357600080fd5b813561106a81613017565b6000602082840312156130d057600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310057600080fd5b823561310b81613017565b915060208381013567ffffffffffffffff8082111561312957600080fd5b818601915086601f83011261313d57600080fd5b81358181111561314f5761314f6130d7565b8060051b604051601f19603f83011681018181108582111715613174576131746130d7565b60405291825284820192508381018501918983111561319257600080fd5b938501935b828510156131b7576131a88561302c565b84529385019392850192613197565b8096505050505050509250929050565b6000806000606084860312156131dc57600080fd5b8335925060208401356131ee81613017565b915060408401356131fe81613017565b809150509250925092565b6000806040838503121561321c57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132535761325361322b565b500390565b60008261327557634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328d5761328d61322b565b500190565b60008160001904831182151516156132ac576132ac61322b565b500290565b6000600182016132c3576132c361322b565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f257600080fd5b815161106a81613017565b60006020828403121561330f57600080fd5b8151801515811461106a57600080fd5b60006020828403121561333157600080fd5b5051919050565b6000825160005b81811015613359576020818601810151858301520161333f565b81811115613368576000828501525b509190910192915050565b6000806040838503121561338657600080fd5b505080516020909101519092909150565b600080604083850312156133aa57600080fd5b82516133b581613017565b60208401519092506130968161301756fea2646970667358221220d3d5846418c8a989d07a62131dbd9fbd6198a140718eb6845440fdb0e3af1de564736f6c634300080d0033a264697066735822122033bb32f75eb748f30d848ded2119eaa78f2bd974bb37bd01b17846c6040fa11364736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, @@ -94,7 +94,7 @@ "storageLayout": { "storage": [ { - "astId": 21380, + "astId": 21420, "contract": "contracts/factories/GaugeFactory.sol:GaugeFactory", "label": "last_gauge", "offset": 0, diff --git a/deployments/arbitrumOne/Minter.json b/deployments/arbitrumOne/Minter.json index 200f1a09..ffa42aa3 100644 --- a/deployments/arbitrumOne/Minter.json +++ b/deployments/arbitrumOne/Minter.json @@ -1,5 +1,5 @@ { - "address": "0x68352C1560B43AFE60413E6caf9900d77988E44f", + "address": "0xA9ee0C9f59Cf387859c8E9e3b333F9e8c2ea51F4", "abi": [ { "inputs": [ @@ -68,10 +68,10 @@ }, { "inputs": [], - "name": "_rewards_distributor", + "name": "_flow", "outputs": [ { - "internalType": "contract IRewardsDistributor", + "internalType": "contract IFlow", "name": "", "type": "address" } @@ -81,10 +81,10 @@ }, { "inputs": [], - "name": "_ve", + "name": "_rewards_distributor", "outputs": [ { - "internalType": "contract IVotingEscrow", + "internalType": "contract IRewardsDistributor", "name": "", "type": "address" } @@ -94,10 +94,10 @@ }, { "inputs": [], - "name": "_velo", + "name": "_ve", "outputs": [ { - "internalType": "contract IVelo", + "internalType": "contract IVotingEscrow", "name": "", "type": "address" } @@ -324,32 +324,32 @@ "type": "function" } ], - "transactionHash": "0x47bfaf1e72075b00d5a115b9f499c65033c3e758846fc068abae3d30ebe58f6b", + "transactionHash": "0x9f4423eed3e5dbb799714e6f2c6deefbf9229630f1a821c03649730155b199ed", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x68352C1560B43AFE60413E6caf9900d77988E44f", + "contractAddress": "0xA9ee0C9f59Cf387859c8E9e3b333F9e8c2ea51F4", "transactionIndex": 1, - "gasUsed": "8497822", + "gasUsed": "8439331", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x182dfc9178650a0120d8627568d8f4bbd2cff0a2dd095e6931def59f5761e34b", - "transactionHash": "0x47bfaf1e72075b00d5a115b9f499c65033c3e758846fc068abae3d30ebe58f6b", + "blockHash": "0x686c7d9ee125145ef07f8d91dbbf258c59b1ea893818bad00d5cfeb689dd1dbb", + "transactionHash": "0x9f4423eed3e5dbb799714e6f2c6deefbf9229630f1a821c03649730155b199ed", "logs": [], - "blockNumber": 53774119, - "cumulativeGasUsed": "8497822", + "blockNumber": 58032111, + "cumulativeGasUsed": "8439331", "status": 1, "byzantium": true }, "args": [ - "0x29C487a354D11315059204Df4F7d8AB1aa008ebb", - "0x10Df81252069C1095F541FAca61646cb9Ae76703", - "0xd9891738458A5b1F1EfB5f82183b77c666d9064E" + "0x2862Bf1ADC96d485B6E85C062b170903DE9A2Bd5", + "0xfa01adbAA40f0EEeCEA76b7B18AC8bE064536787", + "0xffCC209120a8fb388140689ea1235e4eD78620d5" ], "numDeployments": 1, - "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__voter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__rewards_distributor\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weekly\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_supply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_emission\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_TEAM_RATE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_rewards_distributor\",\"outputs\":[{\"internalType\":\"contract IRewardsDistributor\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"contract IVotingEscrow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_velo\",\"outputs\":[{\"internalType\":\"contract IVelo\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_voter\",\"outputs\":[{\"internalType\":\"contract IVoter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"active_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"calculate_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minted\",\"type\":\"uint256\"}],\"name\":\"calculate_growth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"claimants\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingTeam\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_teamRate\",\"type\":\"uint256\"}],\"name\":\"setTeamRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"teamRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"update_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Minter.sol\":\"Minter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Minter.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IMinter.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVelo.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\\n\\ncontract Minter is IMinter {\\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\\n uint256 internal constant EMISSION = 990;\\n uint256 internal constant TAIL_EMISSION = 2;\\n uint256 internal constant PRECISION = 1000;\\n IVelo public immutable _velo;\\n IVoter public immutable _voter;\\n IVotingEscrow public immutable _ve;\\n IRewardsDistributor public immutable _rewards_distributor;\\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\\n uint256 public active_period;\\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\\n\\n address internal initializer;\\n address public team;\\n address public pendingTeam;\\n uint256 public teamRate;\\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\\n\\n event Mint(\\n address indexed sender,\\n uint256 weekly,\\n uint256 circulating_supply,\\n uint256 circulating_emission\\n );\\n\\n constructor(\\n address __voter, // the voting & distribution system\\n address __ve, // the ve(3,3) system that will be locked into\\n address __rewards_distributor // the distribution system that ensures users aren't diluted\\n ) {\\n initializer = msg.sender;\\n team = msg.sender;\\n teamRate = 30; // 30 bps = 0.03%\\n _velo = IVelo(IVotingEscrow(__ve).token());\\n _voter = IVoter(__voter);\\n _ve = IVotingEscrow(__ve);\\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\\n }\\n\\n function initialize(\\n address[] memory claimants,\\n uint256[] memory amounts,\\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\\n ) external {\\n require(initializer == msg.sender);\\n _velo.mint(address(this), max);\\n _velo.approve(address(_ve), type(uint256).max);\\n for (uint256 i = 0; i < claimants.length; i++) {\\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\\n }\\n initializer = address(0);\\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\\n }\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team, \\\"not team\\\");\\n pendingTeam = _team;\\n }\\n\\n function acceptTeam() external {\\n require(msg.sender == pendingTeam, \\\"not pending team\\\");\\n team = pendingTeam;\\n }\\n\\n function setTeamRate(uint256 _teamRate) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(_teamRate <= MAX_TEAM_RATE, \\\"rate too high\\\");\\n teamRate = _teamRate;\\n }\\n\\n // calculate circulating supply as total token supply - locked supply\\n function circulating_supply() public view returns (uint256) {\\n return _velo.totalSupply() - _ve.totalSupply();\\n }\\n\\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\\n function calculate_emission() public view returns (uint256) {\\n return (weekly * EMISSION) / PRECISION;\\n }\\n\\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\\n function weekly_emission() public view returns (uint256) {\\n return MathDunks.max(calculate_emission(), circulating_emission());\\n }\\n\\n // calculates tail end (infinity) emissions as 0.2% of total supply\\n function circulating_emission() public view returns (uint256) {\\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\\n }\\n\\n // calculate inflation and adjust ve balances accordingly\\n function calculate_growth(uint256 _minted) public view returns (uint256) {\\n uint256 _veTotal = _ve.totalSupply();\\n uint256 _veloTotal = _velo.totalSupply();\\n return\\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\\n _veTotal) /\\n _veloTotal /\\n 2;\\n }\\n\\n // update period can only be called once per cycle (1 week)\\n function update_period() external returns (uint256) {\\n uint256 _period = active_period;\\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\\n // only trigger if new week\\n _period = (block.timestamp / WEEK) * WEEK;\\n active_period = _period;\\n weekly = weekly_emission();\\n\\n uint256 _growth = calculate_growth(weekly);\\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\\n (PRECISION - teamRate);\\n uint256 _required = _growth + weekly + _teamEmissions;\\n uint256 _balanceOf = _velo.balanceOf(address(this));\\n if (_balanceOf < _required) {\\n _velo.mint(address(this), _required - _balanceOf);\\n }\\n\\n require(_velo.transfer(team, _teamEmissions));\\n require(_velo.transfer(address(_rewards_distributor), _growth));\\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\\n\\n _velo.approve(address(_voter), weekly);\\n _voter.notifyRewardAmount(weekly);\\n\\n emit Mint(\\n msg.sender,\\n weekly,\\n circulating_supply(),\\n circulating_emission()\\n );\\n }\\n return _period;\\n }\\n}\\n\",\"keccak256\":\"0x8dce50c09815e53982006f9ddc46cd52cf7ac86b0c1b7bb15c817f86fb990580\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x6101006040526a0c685fa11e01ec6f0000006000553480156200002157600080fd5b506040516200158938038062001589833981016040819052620000449162000156565b60028054336001600160a01b03199182168117909255600380549091169091179055601e60055560408051637e062a3560e11b815290516001600160a01b0384169163fc0c546a9160048083019260209291908290030181865afa158015620000b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d79190620001a0565b6001600160a01b0390811660805283811660a05282811660c052811660e05262093a808062000108816002620001db565b620001149042620001fd565b62000120919062000218565b6200012c9190620001db565b600155506200023b915050565b80516001600160a01b03811681146200015157600080fd5b919050565b6000806000606084860312156200016c57600080fd5b620001778462000139565b9250620001876020850162000139565b9150620001976040850162000139565b90509250925092565b600060208284031215620001b357600080fd5b620001be8262000139565b9392505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620001f857620001f8620001c5565b500290565b60008219821115620002135762000213620001c5565b500190565b6000826200023657634e487b7160e01b600052601260045260246000fd5b500490565b60805160a05160c05160e051611296620002f3600039600081816101f801528181610c3701528181610cde0152610d51015260008181610261015281816104b30152818161055f0152818161068901526108750152600081816101d101528181610e090152610ea301526000818161015101528181610426015281816104e30152818161070f015281816108f701528181610a5f01528181610ade01528181610ba801528181610c660152610dda01526112966000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c806378ef7f02116100ad578063b5cc143a11610071578063b5cc143a14610296578063cfc6c8ff1461029e578063d1399608146102a6578063e038c75a146102af578063ed29fc11146102b757600080fd5b806378ef7f021461022d578063851708131461023657806385f2aef2146102495780638dd598fb1461025c5780638e01fbfa1461028357600080fd5b80632e8f7b1f116100f45780632e8f7b1f146101b157806336d96faf146101c45780633db9b42a146101cc5780634b1cd5da146101f357806359d46ffc1461021a57600080fd5b806301c8e6fd1461013157806308aa44581461014c578063095cf5c61461018b5780631eebae80146101a057806326cfc17b146101a8575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b61019e610199366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61019e6101bf366004610fb8565b610353565b6101396103de565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b600454610173906001600160a01b031681565b61013960055481565b61019e6102443660046110a7565b6103f3565b600354610173906001600160a01b031681565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b610139610291366004610fb8565b610684565b61019e6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea2646970667358221220ca2234c7f93e2440b9fbf0fec3a7db175caf6e9740b210ee968450b35cc8333b64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c806378ef7f02116100ad578063b5cc143a11610071578063b5cc143a14610296578063cfc6c8ff1461029e578063d1399608146102a6578063e038c75a146102af578063ed29fc11146102b757600080fd5b806378ef7f021461022d578063851708131461023657806385f2aef2146102495780638dd598fb1461025c5780638e01fbfa1461028357600080fd5b80632e8f7b1f116100f45780632e8f7b1f146101b157806336d96faf146101c45780633db9b42a146101cc5780634b1cd5da146101f357806359d46ffc1461021a57600080fd5b806301c8e6fd1461013157806308aa44581461014c578063095cf5c61461018b5780631eebae80146101a057806326cfc17b146101a8575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b61019e610199366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61019e6101bf366004610fb8565b610353565b6101396103de565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b600454610173906001600160a01b031681565b61013960055481565b61019e6102443660046110a7565b6103f3565b600354610173906001600160a01b031681565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b610139610291366004610fb8565b610684565b61019e6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea2646970667358221220ca2234c7f93e2440b9fbf0fec3a7db175caf6e9740b210ee968450b35cc8333b64736f6c634300080d0033", + "solcInputHash": "816572db58a4a8203fcf6f77728173df", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__voter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__rewards_distributor\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weekly\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_supply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_emission\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_TEAM_RATE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_flow\",\"outputs\":[{\"internalType\":\"contract IFlow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_rewards_distributor\",\"outputs\":[{\"internalType\":\"contract IRewardsDistributor\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"contract IVotingEscrow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_voter\",\"outputs\":[{\"internalType\":\"contract IVoter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"active_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"calculate_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minted\",\"type\":\"uint256\"}],\"name\":\"calculate_growth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"claimants\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingTeam\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_teamRate\",\"type\":\"uint256\"}],\"name\":\"setTeamRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"teamRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"update_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Minter.sol\":\"Minter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735353339323034313033\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Minter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\\\";\\n\\nimport \\\"contracts/interfaces/IMinter.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IFlow.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\\n\\ncontract Minter is IMinter {\\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\\n uint256 internal constant EMISSION = 990;\\n uint256 internal constant TAIL_EMISSION = 2;\\n uint256 internal constant PRECISION = 1000;\\n IFlow public immutable _flow;\\n IVoter public immutable _voter;\\n IVotingEscrow public immutable _ve;\\n IRewardsDistributor public immutable _rewards_distributor;\\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M FLOW (FLOW has 18 decimals)\\n uint256 public active_period;\\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\\n\\n address internal initializer;\\n address public team;\\n address public pendingTeam;\\n uint256 public teamRate;\\n uint256 public constant MAX_TEAM_RATE = 50; // 5% max\\n\\n event Mint(\\n address indexed sender,\\n uint256 weekly,\\n uint256 circulating_supply,\\n uint256 circulating_emission\\n );\\n\\n constructor(\\n address __voter, // the voting & distribution system\\n address __ve, // the ve(3,3) system that will be locked into\\n address __rewards_distributor // the distribution system that ensures users aren't diluted\\n ) {\\n initializer = msg.sender;\\n team = msg.sender;\\n teamRate = 30; // 30 bps = 3%\\n _flow = IFlow(IVotingEscrow(__ve).token());\\n _voter = IVoter(__voter);\\n _ve = IVotingEscrow(__ve);\\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\\n }\\n\\n function initialize(\\n address[] memory claimants, // partnerAddrs\\n uint256[] memory amounts, // partnerAmounts\\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\\n ) external {\\n require(initializer == msg.sender);\\n _flow.mint(address(this), max);\\n _flow.approve(address(_ve), type(uint256).max);\\n for (uint256 i = 0; i < claimants.length; i++) {\\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\\n }\\n initializer = address(0);\\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\\n }\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team, \\\"not team\\\");\\n pendingTeam = _team;\\n }\\n\\n function acceptTeam() external {\\n require(msg.sender == pendingTeam, \\\"not pending team\\\");\\n team = pendingTeam;\\n }\\n\\n function setTeamRate(uint256 _teamRate) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(_teamRate <= MAX_TEAM_RATE, \\\"rate too high\\\");\\n teamRate = _teamRate;\\n }\\n\\n // calculate circulating supply as total token supply - locked supply\\n function circulating_supply() public view returns (uint256) {\\n return _flow.totalSupply() - _ve.totalSupply();\\n }\\n\\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\\n function calculate_emission() public view returns (uint256) {\\n return (weekly * EMISSION) / PRECISION;\\n }\\n\\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\\n function weekly_emission() public view returns (uint256) {\\n return Math.max(calculate_emission(), circulating_emission());\\n }\\n\\n // calculates tail end (infinity) emissions as 0.2% of total supply\\n function circulating_emission() public view returns (uint256) {\\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\\n }\\n\\n // calculate inflation and adjust ve balances accordingly\\n function calculate_growth(uint256 _minted) public view returns (uint256) {\\n uint256 _veTotal = _ve.totalSupply();\\n uint256 _flowTotal = _flow.totalSupply();\\n return\\n (((((_minted * _veTotal) / _flowTotal) * _veTotal) / _flowTotal) *\\n _veTotal) /\\n _flowTotal /\\n 2;\\n }\\n\\n // update period can only be called once per cycle (1 week)\\n function update_period() external returns (uint256) {\\n uint256 _period = active_period;\\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\\n // only trigger if new week\\n _period = (block.timestamp / WEEK) * WEEK;\\n active_period = _period;\\n weekly = weekly_emission();\\n\\n uint256 _growth = calculate_growth(weekly);\\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\\n (PRECISION - teamRate);\\n uint256 _required = _growth + weekly + _teamEmissions;\\n uint256 _balanceOf = _flow.balanceOf(address(this));\\n if (_balanceOf < _required) {\\n _flow.mint(address(this), _required - _balanceOf);\\n }\\n\\n require(_flow.transfer(team, _teamEmissions));\\n require(_flow.transfer(address(_rewards_distributor), _growth));\\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\\n\\n _flow.approve(address(_voter), weekly);\\n _voter.notifyRewardAmount(weekly);\\n\\n emit Mint(\\n msg.sender,\\n weekly,\\n circulating_supply(),\\n circulating_emission()\\n );\\n }\\n return _period;\\n }\\n}\\n\",\"keccak256\":\"0x727eea05351dc27cf7dec9d1dd31ea84bfdff68f0cfd20f94c5db9770f7b849e\",\"license\":\"MIT\"},\"contracts/interfaces/IFlow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IFlow {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x957c4997b5ac464df3484317f7526b8425008684147ab08af5e4bd10d5a60d8d\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3546b156d97633f7f8cad536d5454c81d1d604687c02b2eb105fdc33cb962b41\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x6101006040526a0c685fa11e01ec6f0000006000553480156200002157600080fd5b506040516200158838038062001588833981016040819052620000449162000156565b60028054336001600160a01b03199182168117909255600380549091169091179055601e60055560408051637e062a3560e11b815290516001600160a01b0384169163fc0c546a9160048083019260209291908290030181865afa158015620000b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d79190620001a0565b6001600160a01b0390811660805283811660a05282811660c052811660e05262093a808062000108816002620001db565b620001149042620001fd565b62000120919062000218565b6200012c9190620001db565b600155506200023b915050565b80516001600160a01b03811681146200015157600080fd5b919050565b6000806000606084860312156200016c57600080fd5b620001778462000139565b9250620001876020850162000139565b9150620001976040850162000139565b90509250925092565b600060208284031215620001b357600080fd5b620001be8262000139565b9392505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620001f857620001f8620001c5565b500290565b60008219821115620002135762000213620001c5565b500190565b6000826200023657634e487b7160e01b600052601260045260246000fd5b500490565b60805160a05160c05160e051611295620002f3600039600081816101d101528181610c3701528181610cde0152610d5101526000818161023a015281816104b30152818161055f01528181610689015261087501526000818161019201528181610e090152610ea301526000818161029d01528181610426015281816104e30152818161070f015281816108f701528181610a5f01528181610ade01528181610ba801528181610c660152610dda01526112956000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c806385170813116100ad578063cfc6c8ff11610071578063cfc6c8ff14610277578063d13996081461027f578063e038c75a14610288578063ed29fc1114610290578063fe75cac51461029857600080fd5b8063851708131461020f57806385f2aef2146102225780638dd598fb146102355780638e01fbfa1461025c578063b5cc143a1461026f57600080fd5b806336d96faf116100f457806336d96faf146101855780633db9b42a1461018d5780634b1cd5da146101cc57806359d46ffc146101f357806378ef7f021461020657600080fd5b806301c8e6fd14610131578063095cf5c61461014c5780631eebae801461016157806326cfc17b146101695780632e8f7b1f14610172575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b61015f61015a366004610f9c565b6102bf565b005b61013961032b565b61013960005481565b61015f610180366004610fb7565b610353565b6101396103de565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6004546101b4906001600160a01b031681565b61013960055481565b61015f61021d3660046110a6565b6103f3565b6003546101b4906001600160a01b031681565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b61013961026a366004610fb7565b610684565b61015f6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611185565b61034e91906111a4565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611185565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c6565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c6565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e8565b602002602001015163077f88008785815181106105bd576105bd6111e8565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111fe565b508061064b81611217565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a4565b61067c9190611185565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111fe565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111fe565b9050600281838181816107a2828b611185565b6107ac91906111a4565b6107b69190611185565b6107c091906111a4565b6107ca9190611185565b6107d491906111a4565b6107de91906111a4565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111fe565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111fe565b61034e9190611230565b60015460009061099462093a8082611247565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a4565b6109c99190611185565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611230565b600054610a089084611247565b600554610a159190611185565b610a1f91906111a4565b905060008160005484610a329190611247565b610a3c9190611247565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111fe565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611230565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c6565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c6565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c6565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c6565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b6000818311610f7c5781610f7e565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610fae57600080fd5b610f7e82610f85565b600060208284031215610fc957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561100f5761100f610fd0565b604052919050565b600067ffffffffffffffff82111561103157611031610fd0565b5060051b60200190565b600082601f83011261104c57600080fd5b8135602061106161105c83611017565b610fe6565b82815260059290921b8401810191818101908684111561108057600080fd5b8286015b8481101561109b5780358352918301918301611084565b509695505050505050565b6000806000606084860312156110bb57600080fd5b833567ffffffffffffffff808211156110d357600080fd5b818601915086601f8301126110e757600080fd5b813560206110f761105c83611017565b82815260059290921b8401810191818101908a84111561111657600080fd5b948201945b8386101561113b5761112c86610f85565b8252948201949082019061111b565b9750508701359250508082111561115157600080fd5b5061115e8682870161103b565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b600081600019048311821515161561119f5761119f61116f565b500290565b6000826111c157634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d857600080fd5b81518015158114610f7e57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121057600080fd5b5051919050565b6000600182016112295761122961116f565b5060010190565b6000828210156112425761124261116f565b500390565b6000821982111561125a5761125a61116f565b50019056fea26469706673582212208bc003ee39b765b48d66a36d4a2baae464b369a0037feb8b7982ba6c0ef980c164736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c806385170813116100ad578063cfc6c8ff11610071578063cfc6c8ff14610277578063d13996081461027f578063e038c75a14610288578063ed29fc1114610290578063fe75cac51461029857600080fd5b8063851708131461020f57806385f2aef2146102225780638dd598fb146102355780638e01fbfa1461025c578063b5cc143a1461026f57600080fd5b806336d96faf116100f457806336d96faf146101855780633db9b42a1461018d5780634b1cd5da146101cc57806359d46ffc146101f357806378ef7f021461020657600080fd5b806301c8e6fd14610131578063095cf5c61461014c5780631eebae801461016157806326cfc17b146101695780632e8f7b1f14610172575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b61015f61015a366004610f9c565b6102bf565b005b61013961032b565b61013960005481565b61015f610180366004610fb7565b610353565b6101396103de565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6004546101b4906001600160a01b031681565b61013960055481565b61015f61021d3660046110a6565b6103f3565b6003546101b4906001600160a01b031681565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b61013961026a366004610fb7565b610684565b61015f6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6101b47f000000000000000000000000000000000000000000000000000000000000000081565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611185565b61034e91906111a4565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611185565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c6565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c6565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e8565b602002602001015163077f88008785815181106105bd576105bd6111e8565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111fe565b508061064b81611217565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a4565b61067c9190611185565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111fe565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111fe565b9050600281838181816107a2828b611185565b6107ac91906111a4565b6107b69190611185565b6107c091906111a4565b6107ca9190611185565b6107d491906111a4565b6107de91906111a4565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111fe565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111fe565b61034e9190611230565b60015460009061099462093a8082611247565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a4565b6109c99190611185565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611230565b600054610a089084611247565b600554610a159190611185565b610a1f91906111a4565b905060008160005484610a329190611247565b610a3c9190611247565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111fe565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611230565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c6565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c6565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c6565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c6565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b6000818311610f7c5781610f7e565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610fae57600080fd5b610f7e82610f85565b600060208284031215610fc957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561100f5761100f610fd0565b604052919050565b600067ffffffffffffffff82111561103157611031610fd0565b5060051b60200190565b600082601f83011261104c57600080fd5b8135602061106161105c83611017565b610fe6565b82815260059290921b8401810191818101908684111561108057600080fd5b8286015b8481101561109b5780358352918301918301611084565b509695505050505050565b6000806000606084860312156110bb57600080fd5b833567ffffffffffffffff808211156110d357600080fd5b818601915086601f8301126110e757600080fd5b813560206110f761105c83611017565b82815260059290921b8401810191818101908a84111561111657600080fd5b948201945b8386101561113b5761112c86610f85565b8252948201949082019061111b565b9750508701359250508082111561115157600080fd5b5061115e8682870161103b565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b600081600019048311821515161561119f5761119f61116f565b500290565b6000826111c157634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d857600080fd5b81518015158114610f7e57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121057600080fd5b5051919050565b6000600182016112295761122961116f565b5060010190565b6000828210156112425761124261116f565b500390565b6000821982111561125a5761125a61116f565b50019056fea26469706673582212208bc003ee39b765b48d66a36d4a2baae464b369a0037feb8b7982ba6c0ef980c164736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, @@ -363,7 +363,7 @@ "storageLayout": { "storage": [ { - "astId": 6187, + "astId": 6699, "contract": "contracts/Minter.sol:Minter", "label": "weekly", "offset": 0, @@ -371,7 +371,7 @@ "type": "t_uint256" }, { - "astId": 6189, + "astId": 6701, "contract": "contracts/Minter.sol:Minter", "label": "active_period", "offset": 0, @@ -379,7 +379,7 @@ "type": "t_uint256" }, { - "astId": 6200, + "astId": 6712, "contract": "contracts/Minter.sol:Minter", "label": "initializer", "offset": 0, @@ -387,7 +387,7 @@ "type": "t_address" }, { - "astId": 6202, + "astId": 6714, "contract": "contracts/Minter.sol:Minter", "label": "team", "offset": 0, @@ -395,7 +395,7 @@ "type": "t_address" }, { - "astId": 6204, + "astId": 6716, "contract": "contracts/Minter.sol:Minter", "label": "pendingTeam", "offset": 0, @@ -403,7 +403,7 @@ "type": "t_address" }, { - "astId": 6206, + "astId": 6718, "contract": "contracts/Minter.sol:Minter", "label": "teamRate", "offset": 0, diff --git a/deployments/arbitrumOne/PairFactory.json b/deployments/arbitrumOne/PairFactory.json index c724ba2f..83e26eff 100644 --- a/deployments/arbitrumOne/PairFactory.json +++ b/deployments/arbitrumOne/PairFactory.json @@ -1,5 +1,5 @@ { - "address": "0xA2db791281CdeeBb1EEDc78a34989df2Bfd479bE", + "address": "0x9f7fdaB9317f1442808B90B819Ed0a4eF4f74994", "abi": [ { "inputs": [], @@ -383,28 +383,28 @@ "type": "function" } ], - "transactionHash": "0x306e2d821d9c59dcbab8293e7535aa6a69903b449e099338d70dd1634e6e431f", + "transactionHash": "0x806f757dba4c1e4adee2d353b31c86b731de7f0f1928fa007e126b9f2c830303", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xA2db791281CdeeBb1EEDc78a34989df2Bfd479bE", + "contractAddress": "0x9f7fdaB9317f1442808B90B819Ed0a4eF4f74994", "transactionIndex": 1, - "gasUsed": "30339230", + "gasUsed": "30447801", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x9a41d528ac53283549a72da1405ffe146c73ff66abf7986ace7249bf7cd5fc1c", - "transactionHash": "0x306e2d821d9c59dcbab8293e7535aa6a69903b449e099338d70dd1634e6e431f", + "blockHash": "0xcd403376b36713664b24f1b8f61efb3b435076d8ab533c85ddefbe114c0a33d0", + "transactionHash": "0x806f757dba4c1e4adee2d353b31c86b731de7f0f1928fa007e126b9f2c830303", "logs": [], - "blockNumber": 53774047, - "cumulativeGasUsed": "30339230", + "blockNumber": 58032024, + "cumulativeGasUsed": "30447801", "status": 1, "byzantium": true }, "args": [], "numDeployments": 1, - "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"PairCreated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_FEE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allPairs\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"allPairsLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"createPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getInitializable\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"name\":\"getPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pairCodeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingFeeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingPauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_feeManager\",\"type\":\"address\"}],\"name\":\"setFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_state\",\"type\":\"bool\"}],\"name\":\"setPause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pauser\",\"type\":\"address\"}],\"name\":\"setPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stableFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"volatileFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/PairFactory.sol\":\"PairFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Pair.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairCallee.sol\\\";\\nimport \\\"contracts/factories/PairFactory.sol\\\";\\nimport \\\"contracts/PairFees.sol\\\";\\n\\n// The base pair of pools, either stable or volatile\\ncontract Pair is IPair {\\n string public name;\\n string public symbol;\\n uint8 public constant decimals = 18;\\n\\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\\n bool public immutable stable;\\n\\n uint256 public totalSupply = 0;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n mapping(address => uint256) public balanceOf;\\n\\n bytes32 internal DOMAIN_SEPARATOR;\\n // keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 internal constant PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n mapping(address => uint256) public nonces;\\n\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n\\n address public immutable token0;\\n address public immutable token1;\\n address public immutable fees;\\n address immutable factory;\\n\\n // Structure to capture time period obervations every 30 minutes, used for local oracles\\n struct Observation {\\n uint256 timestamp;\\n uint256 reserve0Cumulative;\\n uint256 reserve1Cumulative;\\n }\\n\\n // Capture oracle reading every 30 minutes\\n uint256 constant periodSize = 1800;\\n\\n Observation[] public observations;\\n\\n uint256 internal immutable decimals0;\\n uint256 internal immutable decimals1;\\n\\n uint256 public reserve0;\\n uint256 public reserve1;\\n uint256 public blockTimestampLast;\\n\\n uint256 public reserve0CumulativeLast;\\n uint256 public reserve1CumulativeLast;\\n\\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \\\"clean\\\"\\n // this further allows LP holders to easily claim fees for tokens they have/staked\\n uint256 public index0 = 0;\\n uint256 public index1 = 0;\\n\\n // position assigned to each LP to track their current index0 & index1 vs the global position\\n mapping(address => uint256) public supplyIndex0;\\n mapping(address => uint256) public supplyIndex1;\\n\\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\\n mapping(address => uint256) public claimable0;\\n mapping(address => uint256) public claimable1;\\n\\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\\n event Burn(\\n address indexed sender,\\n uint256 amount0,\\n uint256 amount1,\\n address indexed to\\n );\\n event Swap(\\n address indexed sender,\\n uint256 amount0In,\\n uint256 amount1In,\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address indexed to\\n );\\n event Sync(uint256 reserve0, uint256 reserve1);\\n event Claim(\\n address indexed sender,\\n address indexed recipient,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 amount\\n );\\n\\n constructor() {\\n factory = msg.sender;\\n (address _token0, address _token1, bool _stable) = PairFactory(\\n msg.sender\\n ).getInitializable();\\n (token0, token1, stable) = (_token0, _token1, _stable);\\n fees = address(new PairFees(_token0, _token1));\\n if (_stable) {\\n name = string(\\n abi.encodePacked(\\n \\\"StableV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"sAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n } else {\\n name = string(\\n abi.encodePacked(\\n \\\"VolatileV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"vAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n }\\n\\n decimals0 = 10**IERC20(_token0).decimals();\\n decimals1 = 10**IERC20(_token1).decimals();\\n\\n observations.push(Observation(block.timestamp, 0, 0));\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function observationLength() external view returns (uint256) {\\n return observations.length;\\n }\\n\\n function lastObservation() public view returns (Observation memory) {\\n return observations[observations.length - 1];\\n }\\n\\n function metadata()\\n external\\n view\\n returns (\\n uint256 dec0,\\n uint256 dec1,\\n uint256 r0,\\n uint256 r1,\\n bool st,\\n address t0,\\n address t1\\n )\\n {\\n return (\\n decimals0,\\n decimals1,\\n reserve0,\\n reserve1,\\n stable,\\n token0,\\n token1\\n );\\n }\\n\\n function tokens() external view returns (address, address) {\\n return (token0, token1);\\n }\\n\\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\\n _updateFor(msg.sender);\\n\\n claimed0 = claimable0[msg.sender];\\n claimed1 = claimable1[msg.sender];\\n\\n if (claimed0 > 0 || claimed1 > 0) {\\n claimable0[msg.sender] = 0;\\n claimable1[msg.sender] = 0;\\n\\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\\n\\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n // Accrue fees on token0\\n function _update0(uint256 amount) internal {\\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index0 += _ratio;\\n }\\n emit Fees(msg.sender, amount, 0);\\n }\\n\\n // Accrue fees on token1\\n function _update1(uint256 amount) internal {\\n _safeTransfer(token1, fees, amount);\\n uint256 _ratio = (amount * 1e18) / totalSupply;\\n if (_ratio > 0) {\\n index1 += _ratio;\\n }\\n emit Fees(msg.sender, 0, amount);\\n }\\n\\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\\n // Fees are segregated from core funds, so fees can never put liquidity at risk\\n function _updateFor(address recipient) internal {\\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\\n if (_supplied > 0) {\\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\\n uint256 _supplyIndex1 = supplyIndex1[recipient];\\n uint256 _index0 = index0; // get global index0 for accumulated fees\\n uint256 _index1 = index1;\\n supplyIndex0[recipient] = _index0; // update user current position to global position\\n supplyIndex1[recipient] = _index1;\\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\\n uint256 _delta1 = _index1 - _supplyIndex1;\\n if (_delta0 > 0) {\\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\\n claimable0[recipient] += _share;\\n }\\n if (_delta1 > 0) {\\n uint256 _share = (_supplied * _delta1) / 1e18;\\n claimable1[recipient] += _share;\\n }\\n } else {\\n supplyIndex0[recipient] = index0; // new users are set to the default global state\\n supplyIndex1[recipient] = index1;\\n }\\n }\\n\\n function getReserves()\\n public\\n view\\n returns (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n )\\n {\\n _reserve0 = reserve0;\\n _reserve1 = reserve1;\\n _blockTimestampLast = blockTimestampLast;\\n }\\n\\n // update reserves and, on the first call per block, price accumulators\\n function _update(\\n uint256 balance0,\\n uint256 balance1,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal {\\n uint256 blockTimestamp = block.timestamp;\\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\\n reserve0CumulativeLast += _reserve0 * timeElapsed;\\n reserve1CumulativeLast += _reserve1 * timeElapsed;\\n }\\n\\n Observation memory _point = lastObservation();\\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\\n if (timeElapsed > periodSize) {\\n observations.push(\\n Observation(\\n blockTimestamp,\\n reserve0CumulativeLast,\\n reserve1CumulativeLast\\n )\\n );\\n }\\n reserve0 = balance0;\\n reserve1 = balance1;\\n blockTimestampLast = blockTimestamp;\\n emit Sync(reserve0, reserve1);\\n }\\n\\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\\n function currentCumulativePrices()\\n public\\n view\\n returns (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n uint256 blockTimestamp\\n )\\n {\\n blockTimestamp = block.timestamp;\\n reserve0Cumulative = reserve0CumulativeLast;\\n reserve1Cumulative = reserve1CumulativeLast;\\n\\n // if time has elapsed since the last update on the pair, mock the accumulated price values\\n (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n ) = getReserves();\\n if (_blockTimestampLast != blockTimestamp) {\\n // subtraction overflow is desired\\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\\n reserve0Cumulative += _reserve0 * timeElapsed;\\n reserve1Cumulative += _reserve1 * timeElapsed;\\n }\\n }\\n\\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\\n function current(address tokenIn, uint256 amountIn)\\n external\\n view\\n returns (uint256 amountOut)\\n {\\n Observation memory _observation = lastObservation();\\n (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n\\n ) = currentCumulativePrices();\\n if (block.timestamp == _observation.timestamp) {\\n _observation = observations[observations.length - 2];\\n }\\n\\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\\n uint256 _reserve0 = (reserve0Cumulative -\\n _observation.reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (reserve1Cumulative -\\n _observation.reserve1Cumulative) / timeElapsed;\\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n // as per `current`, however allows user configured granularity, up to the full window size\\n function quote(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 granularity\\n ) external view returns (uint256 amountOut) {\\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\\n uint256 priceAverageCumulative;\\n for (uint256 i = 0; i < _prices.length; i++) {\\n priceAverageCumulative += _prices[i];\\n }\\n return priceAverageCumulative / granularity;\\n }\\n\\n // returns a memory set of twap prices\\n function prices(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points\\n ) external view returns (uint256[] memory) {\\n return sample(tokenIn, amountIn, points, 1);\\n }\\n\\n function sample(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points,\\n uint256 window\\n ) public view returns (uint256[] memory) {\\n uint256[] memory _prices = new uint256[](points);\\n\\n uint256 length = observations.length - 1;\\n uint256 i = length - (points * window);\\n uint256 nextIndex = 0;\\n uint256 index = 0;\\n\\n for (; i < length; i += window) {\\n nextIndex = i + window;\\n uint256 timeElapsed = observations[nextIndex].timestamp -\\n observations[i].timestamp;\\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\\n observations[i].reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\\n observations[i].reserve1Cumulative) / timeElapsed;\\n _prices[index] = _getAmountOut(\\n amountIn,\\n tokenIn,\\n _reserve0,\\n _reserve1\\n );\\n // index < length; length cannot overflow\\n unchecked {\\n index = index + 1;\\n }\\n }\\n return _prices;\\n }\\n\\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\\n // standard uniswap v2 implementation\\n function mint(address to) external lock returns (uint256 liquidity) {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\\n uint256 _amount0 = _balance0 - _reserve0;\\n uint256 _amount1 = _balance1 - _reserve1;\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n if (_totalSupply == 0) {\\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\\n } else {\\n liquidity = MathDunks.min(\\n (_amount0 * _totalSupply) / _reserve0,\\n (_amount1 * _totalSupply) / _reserve1\\n );\\n }\\n require(liquidity > 0, \\\"ILM\\\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\\n _mint(to, liquidity);\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Mint(msg.sender, _amount0, _amount1);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n // standard uniswap v2 implementation\\n function burn(address to)\\n external\\n lock\\n returns (uint256 amount0, uint256 amount1)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n (address _token0, address _token1) = (token0, token1);\\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\\n uint256 _liquidity = balanceOf[address(this)];\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\\n require(amount0 > 0 && amount1 > 0, \\\"ILB\\\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\\n _burn(address(this), _liquidity);\\n _safeTransfer(_token0, to, amount0);\\n _safeTransfer(_token1, to, amount1);\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Burn(msg.sender, amount0, amount1, to);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n function swap(\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address to,\\n bytes calldata data\\n ) external lock {\\n require(!PairFactory(factory).isPaused());\\n require(amount0Out > 0 || amount1Out > 0, \\\"IOA\\\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \\\"IL\\\"); // Pair: INSUFFICIENT_LIQUIDITY\\n\\n uint256 _balance0;\\n uint256 _balance1;\\n {\\n // scope for _token{0,1}, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n require(to != _token0 && to != _token1, \\\"IT\\\"); // Pair: INVALID_TO\\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\\n if (data.length > 0)\\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n }\\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\\n ? _balance0 - (_reserve0 - amount0Out)\\n : 0;\\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\\n ? _balance1 - (_reserve1 - amount1Out)\\n : 0;\\n require(amount0In > 0 || amount1In > 0, \\\"IIA\\\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\\n {\\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n if (amount0In > 0)\\n _update0(\\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token0 and move them out of pool\\n if (amount1In > 0)\\n _update1(\\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token1 and move them out of pool\\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \\\"K\\\"); // Pair: K\\n }\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\\n }\\n\\n // force balances to match reserves\\n function skim(address to) external lock {\\n (address _token0, address _token1) = (token0, token1);\\n _safeTransfer(\\n _token0,\\n to,\\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\\n );\\n _safeTransfer(\\n _token1,\\n to,\\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\\n );\\n }\\n\\n // force reserves to match balances\\n function sync() external lock {\\n _update(\\n IERC20(token0).balanceOf(address(this)),\\n IERC20(token1).balanceOf(address(this)),\\n reserve0,\\n reserve1\\n );\\n }\\n\\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\\n 1e18 +\\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\\n 1e18;\\n }\\n\\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (3 * x0 * ((y * y) / 1e18)) /\\n 1e18 +\\n ((((x0 * x0) / 1e18) * x0) / 1e18);\\n }\\n\\n function _get_y(\\n uint256 x0,\\n uint256 xy,\\n uint256 y\\n ) internal pure returns (uint256) {\\n for (uint256 i = 0; i < 255; i++) {\\n uint256 y_prev = y;\\n uint256 k = _f(x0, y);\\n if (k < xy) {\\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\\n y = y + dy;\\n } else {\\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getAmountOut(uint256 amountIn, address tokenIn)\\n external\\n view\\n returns (uint256)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n function _getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal view returns (uint256) {\\n if (stable) {\\n uint256 xy = _k(_reserve0, _reserve1);\\n _reserve0 = (_reserve0 * 1e18) / decimals0;\\n _reserve1 = (_reserve1 * 1e18) / decimals1;\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0\\n ? (amountIn * 1e18) / decimals0\\n : (amountIn * 1e18) / decimals1;\\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\\n } else {\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n return (amountIn * reserveB) / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\\n if (stable) {\\n uint256 _x = (x * 1e18) / decimals0;\\n uint256 _y = (y * 1e18) / decimals1;\\n uint256 _a = (_x * _y) / 1e18;\\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return (_a * _b) / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n\\n function _mint(address dst, uint256 amount) internal {\\n _updateFor(dst); // balances must be updated on mint/burn/transfer\\n totalSupply += amount;\\n balanceOf[dst] += amount;\\n emit Transfer(address(0), dst, amount);\\n }\\n\\n function _burn(address dst, uint256 amount) internal {\\n _updateFor(dst);\\n totalSupply -= amount;\\n balanceOf[dst] -= amount;\\n emit Transfer(dst, address(0), amount);\\n }\\n\\n function approve(address spender, uint256 amount) external returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external {\\n require(deadline >= block.timestamp, \\\"Pair: EXPIRED\\\");\\n DOMAIN_SEPARATOR = keccak256(\\n abi.encode(\\n keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n ),\\n keccak256(bytes(name)),\\n keccak256(bytes(\\\"1\\\")),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR,\\n keccak256(\\n abi.encode(\\n PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n );\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n require(\\n recoveredAddress != address(0) && recoveredAddress == owner,\\n \\\"Pair: INVALID_SIGNATURE\\\"\\n );\\n allowance[owner][spender] = value;\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function transfer(address dst, uint256 amount) external returns (bool) {\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 amount\\n ) external returns (bool) {\\n address spender = msg.sender;\\n uint256 spenderAllowance = allowance[src][spender];\\n\\n if (spender != src && spenderAllowance != type(uint256).max) {\\n uint256 newAllowance = spenderAllowance - amount;\\n allowance[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n function _transferTokens(\\n address src,\\n address dst,\\n uint256 amount\\n ) internal {\\n _updateFor(src); // update fee position for src\\n _updateFor(dst); // update fee position for dst\\n\\n balanceOf[src] -= amount;\\n balanceOf[dst] += amount;\\n\\n emit Transfer(src, dst, amount);\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x4f508747645f4480e0b0f23d952fa9b82af1d9bc60b15b8cd1f542ee136043d1\",\"license\":\"MIT\"},\"contracts/PairFees.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IERC20.sol';\\n\\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\\ncontract PairFees {\\n\\n address internal immutable pair; // The pair it is bonded to\\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\\n\\n constructor(address _token0, address _token1) {\\n pair = msg.sender;\\n token0 = _token0;\\n token1 = _token1;\\n }\\n\\n function _safeTransfer(address token,address to,uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n // Allow the pair to transfer fees to users\\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\\n require(msg.sender == pair);\\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\\n }\\n\\n}\\n\",\"keccak256\":\"0xb772e192bab353f8642e89a95ef4ef0255d1caef08444101d7fe34469c1000ca\",\"license\":\"MIT\"},\"contracts/factories/PairFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/Pair.sol';\\n\\ncontract PairFactory is IPairFactory {\\n\\n bool public isPaused;\\n address public pauser;\\n address public pendingPauser;\\n\\n uint256 public stableFee;\\n uint256 public volatileFee;\\n uint256 public constant MAX_FEE = 5; // 0.05%\\n address public feeManager;\\n address public pendingFeeManager;\\n\\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\\n address[] public allPairs;\\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\\n\\n address internal _temp0;\\n address internal _temp1;\\n bool internal _temp;\\n\\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\\n\\n constructor() {\\n pauser = msg.sender;\\n isPaused = false;\\n feeManager = msg.sender;\\n stableFee = 2; // 0.02%\\n volatileFee = 2;\\n }\\n\\n function allPairsLength() external view returns (uint) {\\n return allPairs.length;\\n }\\n\\n function setPauser(address _pauser) external {\\n require(msg.sender == pauser);\\n pendingPauser = _pauser;\\n }\\n\\n function acceptPauser() external {\\n require(msg.sender == pendingPauser);\\n pauser = pendingPauser;\\n }\\n\\n function setPause(bool _state) external {\\n require(msg.sender == pauser);\\n isPaused = _state;\\n }\\n\\n function setFeeManager(address _feeManager) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n pendingFeeManager = _feeManager;\\n }\\n\\n function acceptFeeManager() external {\\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\\n feeManager = pendingFeeManager;\\n }\\n\\n function setFee(bool _stable, uint256 _fee) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n require(_fee <= MAX_FEE, 'fee too high');\\n require(_fee != 0, 'fee must be nonzero');\\n if (_stable) {\\n stableFee = _fee;\\n } else {\\n volatileFee = _fee;\\n }\\n }\\n\\n function getFee(bool _stable) public view returns(uint256) {\\n return _stable ? stableFee : volatileFee;\\n }\\n\\n function pairCodeHash() external pure returns (bytes32) {\\n return keccak256(type(Pair).creationCode);\\n }\\n\\n function getInitializable() external view returns (address, address, bool) {\\n return (_temp0, _temp1, _temp);\\n }\\n\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\\n (_temp0, _temp1, _temp) = (token0, token1, stable);\\n pair = address(new Pair{salt:salt}());\\n getPair[token0][token1][stable] = pair;\\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\\n allPairs.push(pair);\\n isPair[pair] = true;\\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\\n }\\n}\\n\",\"keccak256\":\"0x9b7984117a5a32188aa9ddf42b6cff024240579ab30f3776f7a201285d813e4f\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairCallee.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairCallee {\\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x3ac2de2c7a08bf59fd1006e4d108b247916369de15fbd048b72ca2b7814023ca\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50600080546001600160a81b03191633610100810260ff1916919091178255600480546001600160a01b0319169091179055600280805560035561519190819061005a90396000f3fe60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea2646970667358221220270f4e3352962d1c128c52f446c9e0a94cfd4293f1f3d44b28a148af57736d1a64736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea26469706673582212204d9e84053035e063a46827cca65ab59fad4e23ed0078ae98f8e2cc371de9f9ef64736f6c634300080d0033a2646970667358221220dfffcd46a9d232648bdc2dd9222c658d5554eef6a609556964e00d872e0d720d64736f6c634300080d0033", - "deployedBytecode": "0x60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea2646970667358221220270f4e3352962d1c128c52f446c9e0a94cfd4293f1f3d44b28a148af57736d1a64736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea26469706673582212204d9e84053035e063a46827cca65ab59fad4e23ed0078ae98f8e2cc371de9f9ef64736f6c634300080d0033a2646970667358221220dfffcd46a9d232648bdc2dd9222c658d5554eef6a609556964e00d872e0d720d64736f6c634300080d0033", + "solcInputHash": "816572db58a4a8203fcf6f77728173df", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"PairCreated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_FEE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allPairs\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"allPairsLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"createPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getInitializable\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"name\":\"getPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pairCodeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingFeeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingPauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_feeManager\",\"type\":\"address\"}],\"name\":\"setFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_state\",\"type\":\"bool\"}],\"name\":\"setPause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pauser\",\"type\":\"address\"}],\"name\":\"setPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stableFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"volatileFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/PairFactory.sol\":\"PairFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735353339323034313033\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Pair.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairCallee.sol\\\";\\nimport \\\"contracts/factories/PairFactory.sol\\\";\\nimport \\\"contracts/PairFees.sol\\\";\\n\\n// The base pair of pools, either stable or volatile\\ncontract Pair is IPair {\\n string public name;\\n string public symbol;\\n uint8 public constant decimals = 18;\\n\\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\\n bool public immutable stable;\\n\\n uint256 public totalSupply = 0;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n mapping(address => uint256) public balanceOf;\\n\\n bytes32 internal DOMAIN_SEPARATOR;\\n // keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 internal constant PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n mapping(address => uint256) public nonces;\\n\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n\\n address public immutable token0;\\n address public immutable token1;\\n address public immutable fees;\\n address immutable factory;\\n\\n // Structure to capture time period obervations every 30 minutes, used for local oracles\\n struct Observation {\\n uint256 timestamp;\\n uint256 reserve0Cumulative;\\n uint256 reserve1Cumulative;\\n }\\n\\n // Capture oracle reading every 30 minutes\\n uint256 constant periodSize = 1800;\\n\\n Observation[] public observations;\\n\\n uint256 internal immutable decimals0;\\n uint256 internal immutable decimals1;\\n\\n uint256 public reserve0;\\n uint256 public reserve1;\\n uint256 public blockTimestampLast;\\n\\n uint256 public reserve0CumulativeLast;\\n uint256 public reserve1CumulativeLast;\\n\\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \\\"clean\\\"\\n // this further allows LP holders to easily claim fees for tokens they have/staked\\n uint256 public index0 = 0;\\n uint256 public index1 = 0;\\n\\n // position assigned to each LP to track their current index0 & index1 vs the global position\\n mapping(address => uint256) public supplyIndex0;\\n mapping(address => uint256) public supplyIndex1;\\n\\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\\n mapping(address => uint256) public claimable0;\\n mapping(address => uint256) public claimable1;\\n\\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\\n event Burn(\\n address indexed sender,\\n uint256 amount0,\\n uint256 amount1,\\n address indexed to\\n );\\n event Swap(\\n address indexed sender,\\n uint256 amount0In,\\n uint256 amount1In,\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address indexed to\\n );\\n event Sync(uint256 reserve0, uint256 reserve1);\\n event Claim(\\n address indexed sender,\\n address indexed recipient,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 amount\\n );\\n\\n constructor() {\\n factory = msg.sender;\\n (address _token0, address _token1, bool _stable) = PairFactory(\\n msg.sender\\n ).getInitializable();\\n (token0, token1, stable) = (_token0, _token1, _stable);\\n fees = address(new PairFees(_token0, _token1));\\n if (_stable) {\\n name = string(\\n abi.encodePacked(\\n \\\"StableV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"sAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n } else {\\n name = string(\\n abi.encodePacked(\\n \\\"VolatileV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"vAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n }\\n\\n decimals0 = 10**IERC20(_token0).decimals();\\n decimals1 = 10**IERC20(_token1).decimals();\\n\\n observations.push(Observation(block.timestamp, 0, 0));\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function observationLength() external view returns (uint256) {\\n return observations.length;\\n }\\n\\n function lastObservation() public view returns (Observation memory) {\\n return observations[observations.length - 1];\\n }\\n\\n function metadata()\\n external\\n view\\n returns (\\n uint256 dec0,\\n uint256 dec1,\\n uint256 r0,\\n uint256 r1,\\n bool st,\\n address t0,\\n address t1\\n )\\n {\\n return (\\n decimals0,\\n decimals1,\\n reserve0,\\n reserve1,\\n stable,\\n token0,\\n token1\\n );\\n }\\n\\n function tokens() external view returns (address, address) {\\n return (token0, token1);\\n }\\n\\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\\n _updateFor(msg.sender);\\n\\n claimed0 = claimable0[msg.sender];\\n claimed1 = claimable1[msg.sender];\\n\\n if (claimed0 > 0 || claimed1 > 0) {\\n claimable0[msg.sender] = 0;\\n claimable1[msg.sender] = 0;\\n\\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\\n\\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n // Accrue fees on token0\\n function _update0(uint256 amount) internal {\\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index0 += _ratio;\\n }\\n emit Fees(msg.sender, amount, 0);\\n }\\n\\n // Accrue fees on token1\\n function _update1(uint256 amount) internal {\\n _safeTransfer(token1, fees, amount);\\n uint256 _ratio = (amount * 1e18) / totalSupply;\\n if (_ratio > 0) {\\n index1 += _ratio;\\n }\\n emit Fees(msg.sender, 0, amount);\\n }\\n\\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\\n // Fees are segregated from core funds, so fees can never put liquidity at risk\\n function _updateFor(address recipient) internal {\\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\\n if (_supplied > 0) {\\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\\n uint256 _supplyIndex1 = supplyIndex1[recipient];\\n uint256 _index0 = index0; // get global index0 for accumulated fees\\n uint256 _index1 = index1;\\n supplyIndex0[recipient] = _index0; // update user current position to global position\\n supplyIndex1[recipient] = _index1;\\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\\n uint256 _delta1 = _index1 - _supplyIndex1;\\n if (_delta0 > 0) {\\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\\n claimable0[recipient] += _share;\\n }\\n if (_delta1 > 0) {\\n uint256 _share = (_supplied * _delta1) / 1e18;\\n claimable1[recipient] += _share;\\n }\\n } else {\\n supplyIndex0[recipient] = index0; // new users are set to the default global state\\n supplyIndex1[recipient] = index1;\\n }\\n }\\n\\n function getReserves()\\n public\\n view\\n returns (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n )\\n {\\n _reserve0 = reserve0;\\n _reserve1 = reserve1;\\n _blockTimestampLast = blockTimestampLast;\\n }\\n\\n // update reserves and, on the first call per block, price accumulators\\n function _update(\\n uint256 balance0,\\n uint256 balance1,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal {\\n uint256 blockTimestamp = block.timestamp;\\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\\n reserve0CumulativeLast += _reserve0 * timeElapsed;\\n reserve1CumulativeLast += _reserve1 * timeElapsed;\\n }\\n\\n Observation memory _point = lastObservation();\\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\\n if (timeElapsed > periodSize) {\\n observations.push(\\n Observation(\\n blockTimestamp,\\n reserve0CumulativeLast,\\n reserve1CumulativeLast\\n )\\n );\\n }\\n reserve0 = balance0;\\n reserve1 = balance1;\\n blockTimestampLast = blockTimestamp;\\n emit Sync(reserve0, reserve1);\\n }\\n\\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\\n function currentCumulativePrices()\\n public\\n view\\n returns (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n uint256 blockTimestamp\\n )\\n {\\n blockTimestamp = block.timestamp;\\n reserve0Cumulative = reserve0CumulativeLast;\\n reserve1Cumulative = reserve1CumulativeLast;\\n\\n // if time has elapsed since the last update on the pair, mock the accumulated price values\\n (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n ) = getReserves();\\n if (_blockTimestampLast != blockTimestamp) {\\n // subtraction overflow is desired\\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\\n reserve0Cumulative += _reserve0 * timeElapsed;\\n reserve1Cumulative += _reserve1 * timeElapsed;\\n }\\n }\\n\\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\\n function current(address tokenIn, uint256 amountIn)\\n external\\n view\\n returns (uint256 amountOut)\\n {\\n Observation memory _observation = lastObservation();\\n (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n\\n ) = currentCumulativePrices();\\n if (block.timestamp == _observation.timestamp) {\\n _observation = observations[observations.length - 2];\\n }\\n\\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\\n uint256 _reserve0 = (reserve0Cumulative -\\n _observation.reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (reserve1Cumulative -\\n _observation.reserve1Cumulative) / timeElapsed;\\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n // as per `current`, however allows user configured granularity, up to the full window size\\n function quote(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 granularity\\n ) external view returns (uint256 amountOut) {\\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\\n uint256 priceAverageCumulative;\\n for (uint256 i = 0; i < _prices.length; i++) {\\n priceAverageCumulative += _prices[i];\\n }\\n return priceAverageCumulative / granularity;\\n }\\n\\n // returns a memory set of twap prices\\n function prices(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points\\n ) external view returns (uint256[] memory) {\\n return sample(tokenIn, amountIn, points, 1);\\n }\\n\\n function sample(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points,\\n uint256 window\\n ) public view returns (uint256[] memory) {\\n uint256[] memory _prices = new uint256[](points);\\n\\n uint256 length = observations.length - 1;\\n uint256 i = length - (points * window);\\n uint256 nextIndex = 0;\\n uint256 index = 0;\\n\\n for (; i < length; i += window) {\\n nextIndex = i + window;\\n uint256 timeElapsed = observations[nextIndex].timestamp -\\n observations[i].timestamp;\\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\\n observations[i].reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\\n observations[i].reserve1Cumulative) / timeElapsed;\\n _prices[index] = _getAmountOut(\\n amountIn,\\n tokenIn,\\n _reserve0,\\n _reserve1\\n );\\n // index < length; length cannot overflow\\n unchecked {\\n index = index + 1;\\n }\\n }\\n return _prices;\\n }\\n\\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\\n // standard uniswap v2 implementation\\n function mint(address to) external lock returns (uint256 liquidity) {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\\n uint256 _amount0 = _balance0 - _reserve0;\\n uint256 _amount1 = _balance1 - _reserve1;\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n if (_totalSupply == 0) {\\n liquidity = Math.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\\n } else {\\n liquidity = Math.min(\\n (_amount0 * _totalSupply) / _reserve0,\\n (_amount1 * _totalSupply) / _reserve1\\n );\\n }\\n require(liquidity > 0, \\\"ILM\\\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\\n _mint(to, liquidity);\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Mint(msg.sender, _amount0, _amount1);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n // standard uniswap v2 implementation\\n function burn(address to)\\n external\\n lock\\n returns (uint256 amount0, uint256 amount1)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n (address _token0, address _token1) = (token0, token1);\\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\\n uint256 _liquidity = balanceOf[address(this)];\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\\n require(amount0 > 0 && amount1 > 0, \\\"ILB\\\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\\n _burn(address(this), _liquidity);\\n _safeTransfer(_token0, to, amount0);\\n _safeTransfer(_token1, to, amount1);\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Burn(msg.sender, amount0, amount1, to);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n function swap(\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address to,\\n bytes calldata data\\n ) external lock {\\n require(!PairFactory(factory).isPaused());\\n require(amount0Out > 0 || amount1Out > 0, \\\"IOA\\\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \\\"IL\\\"); // Pair: INSUFFICIENT_LIQUIDITY\\n\\n uint256 _balance0;\\n uint256 _balance1;\\n {\\n // scope for _token{0,1}, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n require(to != _token0 && to != _token1, \\\"IT\\\"); // Pair: INVALID_TO\\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\\n if (data.length > 0)\\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n }\\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\\n ? _balance0 - (_reserve0 - amount0Out)\\n : 0;\\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\\n ? _balance1 - (_reserve1 - amount1Out)\\n : 0;\\n require(amount0In > 0 || amount1In > 0, \\\"IIA\\\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\\n {\\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n if (amount0In > 0)\\n _update0(\\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token0 and move them out of pool\\n if (amount1In > 0)\\n _update1(\\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token1 and move them out of pool\\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \\\"K\\\"); // Pair: K\\n }\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\\n }\\n\\n // force balances to match reserves\\n function skim(address to) external lock {\\n (address _token0, address _token1) = (token0, token1);\\n _safeTransfer(\\n _token0,\\n to,\\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\\n );\\n _safeTransfer(\\n _token1,\\n to,\\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\\n );\\n }\\n\\n // force reserves to match balances\\n function sync() external lock {\\n _update(\\n IERC20(token0).balanceOf(address(this)),\\n IERC20(token1).balanceOf(address(this)),\\n reserve0,\\n reserve1\\n );\\n }\\n\\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\\n 1e18 +\\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\\n 1e18;\\n }\\n\\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (3 * x0 * ((y * y) / 1e18)) /\\n 1e18 +\\n ((((x0 * x0) / 1e18) * x0) / 1e18);\\n }\\n\\n function _get_y(\\n uint256 x0,\\n uint256 xy,\\n uint256 y\\n ) internal pure returns (uint256) {\\n for (uint256 i = 0; i < 255; i++) {\\n uint256 y_prev = y;\\n uint256 k = _f(x0, y);\\n if (k < xy) {\\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\\n y = y + dy;\\n } else {\\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getAmountOut(uint256 amountIn, address tokenIn)\\n external\\n view\\n returns (uint256)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n function _getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal view returns (uint256) {\\n if (stable) {\\n uint256 xy = _k(_reserve0, _reserve1);\\n _reserve0 = (_reserve0 * 1e18) / decimals0;\\n _reserve1 = (_reserve1 * 1e18) / decimals1;\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0\\n ? (amountIn * 1e18) / decimals0\\n : (amountIn * 1e18) / decimals1;\\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\\n } else {\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n return (amountIn * reserveB) / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\\n if (stable) {\\n uint256 _x = (x * 1e18) / decimals0;\\n uint256 _y = (y * 1e18) / decimals1;\\n uint256 _a = (_x * _y) / 1e18;\\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return (_a * _b) / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n\\n function _mint(address dst, uint256 amount) internal {\\n _updateFor(dst); // balances must be updated on mint/burn/transfer\\n totalSupply += amount;\\n balanceOf[dst] += amount;\\n emit Transfer(address(0), dst, amount);\\n }\\n\\n function _burn(address dst, uint256 amount) internal {\\n _updateFor(dst);\\n totalSupply -= amount;\\n balanceOf[dst] -= amount;\\n emit Transfer(dst, address(0), amount);\\n }\\n\\n function approve(address spender, uint256 amount) external returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external {\\n require(deadline >= block.timestamp, \\\"Pair: EXPIRED\\\");\\n DOMAIN_SEPARATOR = keccak256(\\n abi.encode(\\n keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n ),\\n keccak256(bytes(name)),\\n keccak256(bytes(\\\"1\\\")),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR,\\n keccak256(\\n abi.encode(\\n PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n );\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n require(\\n recoveredAddress != address(0) && recoveredAddress == owner,\\n \\\"Pair: INVALID_SIGNATURE\\\"\\n );\\n allowance[owner][spender] = value;\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function transfer(address dst, uint256 amount) external returns (bool) {\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 amount\\n ) external returns (bool) {\\n address spender = msg.sender;\\n uint256 spenderAllowance = allowance[src][spender];\\n\\n if (spender != src && spenderAllowance != type(uint256).max) {\\n uint256 newAllowance = spenderAllowance - amount;\\n allowance[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n function _transferTokens(\\n address src,\\n address dst,\\n uint256 amount\\n ) internal {\\n _updateFor(src); // update fee position for src\\n _updateFor(dst); // update fee position for dst\\n\\n balanceOf[src] -= amount;\\n balanceOf[dst] += amount;\\n\\n emit Transfer(src, dst, amount);\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x5974c07deac137349ce692ca582cd6be6d341166613ff6964d997ab6abe0b3ef\",\"license\":\"MIT\"},\"contracts/PairFees.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IERC20.sol';\\n\\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\\ncontract PairFees {\\n\\n address internal immutable pair; // The pair it is bonded to\\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\\n\\n constructor(address _token0, address _token1) {\\n pair = msg.sender;\\n token0 = _token0;\\n token1 = _token1;\\n }\\n\\n function _safeTransfer(address token,address to,uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n // Allow the pair to transfer fees to users\\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\\n require(msg.sender == pair);\\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\\n }\\n\\n}\\n\",\"keccak256\":\"0xb772e192bab353f8642e89a95ef4ef0255d1caef08444101d7fe34469c1000ca\",\"license\":\"MIT\"},\"contracts/factories/PairFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IPairFactory.sol\\\";\\nimport \\\"contracts/Pair.sol\\\";\\n\\ncontract PairFactory is IPairFactory {\\n bool public isPaused;\\n address public pauser;\\n address public pendingPauser;\\n\\n uint256 public stableFee;\\n uint256 public volatileFee;\\n uint256 public constant MAX_FEE = 50; // 0.5%\\n address public feeManager;\\n address public pendingFeeManager;\\n\\n mapping(address => mapping(address => mapping(bool => address)))\\n public getPair;\\n address[] public allPairs;\\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\\n\\n address internal _temp0;\\n address internal _temp1;\\n bool internal _temp;\\n\\n event PairCreated(\\n address indexed token0,\\n address indexed token1,\\n bool stable,\\n address pair,\\n uint256\\n );\\n\\n constructor() {\\n pauser = msg.sender;\\n isPaused = false;\\n feeManager = msg.sender;\\n // stableFee = 2; // 0.02%\\n // volatileFee = 2;\\n stableFee = 3; // 0.03%\\n volatileFee = 25; // 0.25%\\n }\\n\\n function allPairsLength() external view returns (uint256) {\\n return allPairs.length;\\n }\\n\\n function setPauser(address _pauser) external {\\n require(msg.sender == pauser);\\n pendingPauser = _pauser;\\n }\\n\\n function acceptPauser() external {\\n require(msg.sender == pendingPauser);\\n pauser = pendingPauser;\\n }\\n\\n function setPause(bool _state) external {\\n require(msg.sender == pauser);\\n isPaused = _state;\\n }\\n\\n function setFeeManager(address _feeManager) external {\\n require(msg.sender == feeManager, \\\"not fee manager\\\");\\n pendingFeeManager = _feeManager;\\n }\\n\\n function acceptFeeManager() external {\\n require(msg.sender == pendingFeeManager, \\\"not pending fee manager\\\");\\n feeManager = pendingFeeManager;\\n }\\n\\n function setFee(bool _stable, uint256 _fee) external {\\n require(msg.sender == feeManager, \\\"not fee manager\\\");\\n require(_fee <= MAX_FEE, \\\"fee too high\\\");\\n require(_fee != 0, \\\"fee must be nonzero\\\");\\n if (_stable) {\\n stableFee = _fee;\\n } else {\\n volatileFee = _fee;\\n }\\n }\\n\\n function getFee(bool _stable) public view returns (uint256) {\\n return _stable ? stableFee : volatileFee;\\n }\\n\\n function pairCodeHash() external pure returns (bytes32) {\\n return keccak256(type(Pair).creationCode);\\n }\\n\\n function getInitializable()\\n external\\n view\\n returns (\\n address,\\n address,\\n bool\\n )\\n {\\n return (_temp0, _temp1, _temp);\\n }\\n\\n function createPair(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) external returns (address pair) {\\n require(tokenA != tokenB, \\\"IA\\\"); // Pair: IDENTICAL_ADDRESSES\\n (address token0, address token1) = tokenA < tokenB\\n ? (tokenA, tokenB)\\n : (tokenB, tokenA);\\n require(token0 != address(0), \\\"ZA\\\"); // Pair: ZERO_ADDRESS\\n require(getPair[token0][token1][stable] == address(0), \\\"PE\\\"); // Pair: PAIR_EXISTS - single check is sufficient\\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\\n (_temp0, _temp1, _temp) = (token0, token1, stable);\\n pair = address(new Pair{salt: salt}());\\n getPair[token0][token1][stable] = pair;\\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\\n allPairs.push(pair);\\n isPair[pair] = true;\\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\\n }\\n}\\n\",\"keccak256\":\"0x110c99d6ec3d32fe341faf2ac02bd881a144c62403e4436a712d9e77ab760690\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairCallee.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairCallee {\\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x3ac2de2c7a08bf59fd1006e4d108b247916369de15fbd048b72ca2b7814023ca\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3546b156d97633f7f8cad536d5454c81d1d604687c02b2eb105fdc33cb962b41\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50600080546001600160a81b03191633610100810260ff1916919091178255600480546001600160a01b031916909117905560036002819055601990556152be90819061005d90396000f3fe60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3603281565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6032811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6147fd8062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200448d83390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161373862000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae01526137386000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461319f565b61079f565b005b610296610eec565b6040516102a39190613263565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613296565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046132c0565b610fe7565b6040516102a391906132f9565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461333d565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613358565b611252565b6102b66103da366004613394565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461333d565b60116020526000908152604090205481565b61035c61051f366004613296565b61134e565b6103466105323660046133ad565b611436565b61035c60095481565b61035c61054e36600461333d565b611445565b61035c61056136600461333d565b60046020526000908152604090205481565b61035c61058136600461333d565b60066020526000908152604090205481565b6105a66105a136600461333d565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c6106803660046133ad565b611a50565b61035c61069336600461333d565b600f6020526000908152604090205481565b61035c6106b336600461333d565b60126020526000908152604090205481565b6102e46106d3366004613296565b611abd565b61028c6106e636600461333d565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046133e0565b611d18565b61035c61075f366004613453565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613486565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061083891906134a9565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016134cb565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613517565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613517565b9250505060008985610ae59190613546565b8311610af2576000610b06565b610afc8a86613546565b610b069084613546565b90506000610b148a86613546565b8311610b21576000610b35565b610b2b8a86613546565b610b359084613546565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613517565b610c7c908761355d565b610c869190613592565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613517565b610d4d908661355d565b610d579190613592565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613517565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613517565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef9906135b4565b80601f0160208091040260200160405190810160405280929190818152602001828054610f25906135b4565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046135ee565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613546565b90506000611051858761355d565b61105b9083613546565b90506000805b838310156111d3576110738784613604565b915060006007848154811061108a5761108a61361c565b906000526020600020906003020160000154600784815481106110af576110af61361c565b9060005260206000209060030201600001546110cb9190613546565b9050600081600786815481106110e3576110e361361c565b906000526020600020906003020160010154600786815481106111085761110861361c565b9060005260206000209060030201600101546111249190613546565b61112e9190613592565b9050600082600787815481106111465761114661361c565b9060005260206000209060030201600201546007878154811061116b5761116b61361c565b9060005260206000209060030201600201546111879190613546565b6111919190613592565b905061119f8c8e84846127aa565b8885815181106111b1576111b161361c565b60209081029190910101525050506001016111cc8784613604565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613546565b9050611226818561355d565b6112309088613604565b965061123c818461355d565b6112469087613604565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613546565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613546565b815481106113945761139461361c565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613546565b90506000818560200151856113f29190613546565b6113fc9190613592565b90506000828660400151856114119190613546565b61141b9190613592565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613517565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613517565b905060006115888584613546565b905060006115968584613546565b60025490915060008190036115d8576103e86115ba6115b5848661355d565b612b5f565b6115c49190613546565b97506115d360006103e8612c47565b61160d565b61160a876115e6838661355d565b6115f09190613592565b876115fb848661355d565b6116059190613592565b612cda565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612c47565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613517565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613517565b306000908152600460205260409020546002549192509080611802858461355d565b61180c9190613592565b995080611819848461355d565b6118239190613592565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612cf0565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613517565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613517565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613546565b81548110611a0757611a0761361c565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef9906135b4565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a8161361c565b602002602001015182611a949190613604565b915080611aa081613632565b915050611a66565b50611ab38482613592565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613517565b611baa9190613546565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d7b565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061364b565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613632565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613517565b6120e3908761355d565b6120ed9190613592565b6120f79086613546565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613517565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613517565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906136e6565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b509150915081801561232757508051158061232757508080602001905181019061232791906134a9565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061355d565b6123a49190613592565b905080156123c45780600d60008282546123be9190613604565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061355d565b6124719190613592565b905080156124915780600e600082825461248b9190613604565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061355d565b6125319190613592565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061355d565b6125729190613592565b90506000670de0b6b3a7640000612589838561355d565b6125939190613592565b90506000670de0b6b3a76400006125aa848061355d565b6125b49190613592565b670de0b6b3a76400006125c7868061355d565b6125d19190613592565b6125db9190613604565b9050670de0b6b3a76400006125f0828461355d565b6125fa9190613592565b945050505050610fe1565b61260f828461355d565b9050610fe1565b600a5442906000906126289083613546565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561355d565b600b60008282546126649190613604565b909155506126749050818461355d565b600c60008282546126859190613604565b90915550505b60006126956119c3565b80519091506126a49084613546565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061355d565b61281d9190613592565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061355d565b61285c9190613592565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061355d565b61291e9190613592565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061355d565b6129609190613592565b97506000612978612971848b613604565b8584612edb565b6129829083613546565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361355d565b612a229190613592565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a828783613604565b612a8c828961355d565b612a969190613592565b925050506111db565b612aa883612d7b565b612ab182612d7b565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613546565b90915550506001600160a01b03821660009081526004602052604081208054839290612b06908490613604565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b600081600003612b7157506000919050565b60006001612b7e84612fea565b901c6001901b90506001818481612b9757612b9761357c565b048201901c90506001818481612baf57612baf61357c565b048201901c90506001818481612bc757612bc761357c565b048201901c90506001818481612bdf57612bdf61357c565b048201901c90506001818481612bf757612bf761357c565b048201901c90506001818481612c0f57612c0f61357c565b048201901c90506001818481612c2757612c2761357c565b048201901c905061131481828581612c4157612c4161357c565b04612cda565b612c5082612d7b565b8060026000828254612c629190613604565b90915550506001600160a01b03821660009081526004602052604081208054839290612c8f908490613604565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612ce95781611314565b5090919050565b612cf982612d7b565b8060026000828254612d0b9190613546565b90915550506001600160a01b03821660009081526004602052604081208054839290612d38908490613546565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612cce565b6001600160a01b0381166000908152600460205260409020548015612ea9576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612ddd8584613546565b90506000612deb8584613546565b90508115612e46576000670de0b6b3a7640000612e08848a61355d565b612e129190613592565b6001600160a01b038a16600090815260116020526040812080549293508392909190612e3f908490613604565b9091555050505b8015612e9f576000670de0b6b3a7640000612e61838a61355d565b612e6b9190613592565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e98908490613604565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612fe157826000612ef5878361307e565b905085811015612f45576000612f0b888761311b565b612f158389613546565b612f2790670de0b6b3a764000061355d565b612f319190613592565b9050612f3d8187613604565b955050612f87565b6000612f51888761311b565b612f5b8884613546565b612f6d90670de0b6b3a764000061355d565b612f779190613592565b9050612f838187613546565b9550505b81851115612fb0576001612f9b8387613546565b11612fab57849350505050611314565b612fcc565b6001612fbc8684613546565b11612fcc57849350505050611314565b50508080612fd990613632565b915050612edf565b50909392505050565b600080608083901c15612fff57608092831c92015b604083901c1561301157604092831c92015b602083901c1561302357602092831c92015b601083901c1561303557601092831c92015b600883901c1561304757600892831c92015b600483901c1561305957600492831c92015b600283901c1561306b57600292831c92015b600183901c15610fe15760010192915050565b6000670de0b6b3a764000082818581613097828061355d565b6130a19190613592565b6130ab919061355d565b6130b59190613592565b6130bf919061355d565b6130c99190613592565b670de0b6b3a76400008084816130df828061355d565b6130e99190613592565b6130f3919061355d565b6130fd9190613592565b613107908661355d565b6131119190613592565b6113149190613604565b6000670de0b6b3a76400008381613132828061355d565b61313c9190613592565b613146919061355d565b6131509190613592565b670de0b6b3a764000080613164858061355d565b61316e9190613592565b61317986600361355d565b613107919061355d565b80356001600160a01b038116811461319a57600080fd5b919050565b6000806000806000608086880312156131b757600080fd5b85359450602086013593506131ce60408701613183565b9250606086013567ffffffffffffffff808211156131eb57600080fd5b818801915088601f8301126131ff57600080fd5b81358181111561320e57600080fd5b89602082850101111561322057600080fd5b9699959850939650602001949392505050565b60005b8381101561324e578181015183820152602001613236565b8381111561325d576000848401525b50505050565b6020815260008251806020840152613282816040850160208701613233565b601f01601f19169190910160400192915050565b600080604083850312156132a957600080fd5b6132b283613183565b946020939093013593505050565b600080600080608085870312156132d657600080fd5b6132df85613183565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561333157835183529284019291840191600101613315565b50909695505050505050565b60006020828403121561334f57600080fd5b61131482613183565b60008060006060848603121561336d57600080fd5b61337684613183565b925061338460208501613183565b9150604084013590509250925092565b6000602082840312156133a657600080fd5b5035919050565b6000806000606084860312156133c257600080fd5b6133cb84613183565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156133fb57600080fd5b61340488613183565b965061341260208901613183565b95506040880135945060608801359350608088013560ff8116811461343657600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561346657600080fd5b61346f83613183565b915061347d60208401613183565b90509250929050565b6000806040838503121561349957600080fd5b8235915061347d60208401613183565b6000602082840312156134bb57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561352957600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b60008282101561355857613558613530565b500390565b600081600019048311821515161561357757613577613530565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826135af57634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806135c857607f821691505b6020821081036135e857634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b6000821982111561361757613617613530565b500190565b634e487b7160e01b600052603260045260246000fd5b60006001820161364457613644613530565b5060010190565b600080835481600182811c91508083168061366757607f831692505b6020808410820361368657634e487b7160e01b86526022600452602486fd5b81801561369a57600181146136ab576136d8565b60ff198616895284890196506136d8565b60008a81526020902060005b868110156136d05781548b8201529085019083016136b7565b505084890196505b509498975050505050505050565b600082516136f8818460208701613233565b919091019291505056fea2646970667358221220fed5970654bb21f25b14400905f28cdb4c08d63db9c047612259d5629314a09764736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea2646970667358221220c9406c901a625cf7448e9a91f1b84e0d0c3f2f34da3016610507d3d734e058d664736f6c634300080d0033a2646970667358221220ac4c70e05741ea9f1ea02a315d61660a77dfd80b0473d3b2469a49038e9f479664736f6c634300080d0033", + "deployedBytecode": "0x60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3603281565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6032811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6147fd8062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200448d83390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161373862000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae01526137386000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461319f565b61079f565b005b610296610eec565b6040516102a39190613263565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613296565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046132c0565b610fe7565b6040516102a391906132f9565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461333d565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613358565b611252565b6102b66103da366004613394565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461333d565b60116020526000908152604090205481565b61035c61051f366004613296565b61134e565b6103466105323660046133ad565b611436565b61035c60095481565b61035c61054e36600461333d565b611445565b61035c61056136600461333d565b60046020526000908152604090205481565b61035c61058136600461333d565b60066020526000908152604090205481565b6105a66105a136600461333d565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c6106803660046133ad565b611a50565b61035c61069336600461333d565b600f6020526000908152604090205481565b61035c6106b336600461333d565b60126020526000908152604090205481565b6102e46106d3366004613296565b611abd565b61028c6106e636600461333d565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046133e0565b611d18565b61035c61075f366004613453565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613486565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061083891906134a9565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016134cb565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613517565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613517565b9250505060008985610ae59190613546565b8311610af2576000610b06565b610afc8a86613546565b610b069084613546565b90506000610b148a86613546565b8311610b21576000610b35565b610b2b8a86613546565b610b359084613546565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613517565b610c7c908761355d565b610c869190613592565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613517565b610d4d908661355d565b610d579190613592565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613517565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613517565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef9906135b4565b80601f0160208091040260200160405190810160405280929190818152602001828054610f25906135b4565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046135ee565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613546565b90506000611051858761355d565b61105b9083613546565b90506000805b838310156111d3576110738784613604565b915060006007848154811061108a5761108a61361c565b906000526020600020906003020160000154600784815481106110af576110af61361c565b9060005260206000209060030201600001546110cb9190613546565b9050600081600786815481106110e3576110e361361c565b906000526020600020906003020160010154600786815481106111085761110861361c565b9060005260206000209060030201600101546111249190613546565b61112e9190613592565b9050600082600787815481106111465761114661361c565b9060005260206000209060030201600201546007878154811061116b5761116b61361c565b9060005260206000209060030201600201546111879190613546565b6111919190613592565b905061119f8c8e84846127aa565b8885815181106111b1576111b161361c565b60209081029190910101525050506001016111cc8784613604565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613546565b9050611226818561355d565b6112309088613604565b965061123c818461355d565b6112469087613604565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613546565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613546565b815481106113945761139461361c565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613546565b90506000818560200151856113f29190613546565b6113fc9190613592565b90506000828660400151856114119190613546565b61141b9190613592565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613517565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613517565b905060006115888584613546565b905060006115968584613546565b60025490915060008190036115d8576103e86115ba6115b5848661355d565b612b5f565b6115c49190613546565b97506115d360006103e8612c47565b61160d565b61160a876115e6838661355d565b6115f09190613592565b876115fb848661355d565b6116059190613592565b612cda565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612c47565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613517565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613517565b306000908152600460205260409020546002549192509080611802858461355d565b61180c9190613592565b995080611819848461355d565b6118239190613592565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612cf0565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613517565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613517565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613546565b81548110611a0757611a0761361c565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef9906135b4565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a8161361c565b602002602001015182611a949190613604565b915080611aa081613632565b915050611a66565b50611ab38482613592565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613517565b611baa9190613546565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d7b565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061364b565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613632565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613517565b6120e3908761355d565b6120ed9190613592565b6120f79086613546565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613517565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613517565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906136e6565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b509150915081801561232757508051158061232757508080602001905181019061232791906134a9565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061355d565b6123a49190613592565b905080156123c45780600d60008282546123be9190613604565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061355d565b6124719190613592565b905080156124915780600e600082825461248b9190613604565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061355d565b6125319190613592565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061355d565b6125729190613592565b90506000670de0b6b3a7640000612589838561355d565b6125939190613592565b90506000670de0b6b3a76400006125aa848061355d565b6125b49190613592565b670de0b6b3a76400006125c7868061355d565b6125d19190613592565b6125db9190613604565b9050670de0b6b3a76400006125f0828461355d565b6125fa9190613592565b945050505050610fe1565b61260f828461355d565b9050610fe1565b600a5442906000906126289083613546565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561355d565b600b60008282546126649190613604565b909155506126749050818461355d565b600c60008282546126859190613604565b90915550505b60006126956119c3565b80519091506126a49084613546565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061355d565b61281d9190613592565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061355d565b61285c9190613592565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061355d565b61291e9190613592565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061355d565b6129609190613592565b97506000612978612971848b613604565b8584612edb565b6129829083613546565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361355d565b612a229190613592565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a828783613604565b612a8c828961355d565b612a969190613592565b925050506111db565b612aa883612d7b565b612ab182612d7b565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613546565b90915550506001600160a01b03821660009081526004602052604081208054839290612b06908490613604565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b600081600003612b7157506000919050565b60006001612b7e84612fea565b901c6001901b90506001818481612b9757612b9761357c565b048201901c90506001818481612baf57612baf61357c565b048201901c90506001818481612bc757612bc761357c565b048201901c90506001818481612bdf57612bdf61357c565b048201901c90506001818481612bf757612bf761357c565b048201901c90506001818481612c0f57612c0f61357c565b048201901c90506001818481612c2757612c2761357c565b048201901c905061131481828581612c4157612c4161357c565b04612cda565b612c5082612d7b565b8060026000828254612c629190613604565b90915550506001600160a01b03821660009081526004602052604081208054839290612c8f908490613604565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612ce95781611314565b5090919050565b612cf982612d7b565b8060026000828254612d0b9190613546565b90915550506001600160a01b03821660009081526004602052604081208054839290612d38908490613546565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612cce565b6001600160a01b0381166000908152600460205260409020548015612ea9576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612ddd8584613546565b90506000612deb8584613546565b90508115612e46576000670de0b6b3a7640000612e08848a61355d565b612e129190613592565b6001600160a01b038a16600090815260116020526040812080549293508392909190612e3f908490613604565b9091555050505b8015612e9f576000670de0b6b3a7640000612e61838a61355d565b612e6b9190613592565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e98908490613604565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612fe157826000612ef5878361307e565b905085811015612f45576000612f0b888761311b565b612f158389613546565b612f2790670de0b6b3a764000061355d565b612f319190613592565b9050612f3d8187613604565b955050612f87565b6000612f51888761311b565b612f5b8884613546565b612f6d90670de0b6b3a764000061355d565b612f779190613592565b9050612f838187613546565b9550505b81851115612fb0576001612f9b8387613546565b11612fab57849350505050611314565b612fcc565b6001612fbc8684613546565b11612fcc57849350505050611314565b50508080612fd990613632565b915050612edf565b50909392505050565b600080608083901c15612fff57608092831c92015b604083901c1561301157604092831c92015b602083901c1561302357602092831c92015b601083901c1561303557601092831c92015b600883901c1561304757600892831c92015b600483901c1561305957600492831c92015b600283901c1561306b57600292831c92015b600183901c15610fe15760010192915050565b6000670de0b6b3a764000082818581613097828061355d565b6130a19190613592565b6130ab919061355d565b6130b59190613592565b6130bf919061355d565b6130c99190613592565b670de0b6b3a76400008084816130df828061355d565b6130e99190613592565b6130f3919061355d565b6130fd9190613592565b613107908661355d565b6131119190613592565b6113149190613604565b6000670de0b6b3a76400008381613132828061355d565b61313c9190613592565b613146919061355d565b6131509190613592565b670de0b6b3a764000080613164858061355d565b61316e9190613592565b61317986600361355d565b613107919061355d565b80356001600160a01b038116811461319a57600080fd5b919050565b6000806000806000608086880312156131b757600080fd5b85359450602086013593506131ce60408701613183565b9250606086013567ffffffffffffffff808211156131eb57600080fd5b818801915088601f8301126131ff57600080fd5b81358181111561320e57600080fd5b89602082850101111561322057600080fd5b9699959850939650602001949392505050565b60005b8381101561324e578181015183820152602001613236565b8381111561325d576000848401525b50505050565b6020815260008251806020840152613282816040850160208701613233565b601f01601f19169190910160400192915050565b600080604083850312156132a957600080fd5b6132b283613183565b946020939093013593505050565b600080600080608085870312156132d657600080fd5b6132df85613183565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561333157835183529284019291840191600101613315565b50909695505050505050565b60006020828403121561334f57600080fd5b61131482613183565b60008060006060848603121561336d57600080fd5b61337684613183565b925061338460208501613183565b9150604084013590509250925092565b6000602082840312156133a657600080fd5b5035919050565b6000806000606084860312156133c257600080fd5b6133cb84613183565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156133fb57600080fd5b61340488613183565b965061341260208901613183565b95506040880135945060608801359350608088013560ff8116811461343657600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561346657600080fd5b61346f83613183565b915061347d60208401613183565b90509250929050565b6000806040838503121561349957600080fd5b8235915061347d60208401613183565b6000602082840312156134bb57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561352957600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b60008282101561355857613558613530565b500390565b600081600019048311821515161561357757613577613530565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826135af57634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806135c857607f821691505b6020821081036135e857634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b6000821982111561361757613617613530565b500190565b634e487b7160e01b600052603260045260246000fd5b60006001820161364457613644613530565b5060010190565b600080835481600182811c91508083168061366757607f831692505b6020808410820361368657634e487b7160e01b86526022600452602486fd5b81801561369a57600181146136ab576136d8565b60ff198616895284890196506136d8565b60008a81526020902060005b868110156136d05781548b8201529085019083016136b7565b505084890196505b509498975050505050505050565b600082516136f8818460208701613233565b919091019291505056fea2646970667358221220fed5970654bb21f25b14400905f28cdb4c08d63db9c047612259d5629314a09764736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea2646970667358221220c9406c901a625cf7448e9a91f1b84e0d0c3f2f34da3016610507d3d734e058d664736f6c634300080d0033a2646970667358221220ac4c70e05741ea9f1ea02a315d61660a77dfd80b0473d3b2469a49038e9f479664736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, @@ -418,7 +418,7 @@ "storageLayout": { "storage": [ { - "astId": 21428, + "astId": 21468, "contract": "contracts/factories/PairFactory.sol:PairFactory", "label": "isPaused", "offset": 0, @@ -426,7 +426,7 @@ "type": "t_bool" }, { - "astId": 21430, + "astId": 21470, "contract": "contracts/factories/PairFactory.sol:PairFactory", "label": "pauser", "offset": 1, @@ -434,7 +434,7 @@ "type": "t_address" }, { - "astId": 21432, + "astId": 21472, "contract": "contracts/factories/PairFactory.sol:PairFactory", "label": "pendingPauser", "offset": 0, @@ -442,7 +442,7 @@ "type": "t_address" }, { - "astId": 21434, + "astId": 21474, "contract": "contracts/factories/PairFactory.sol:PairFactory", "label": "stableFee", "offset": 0, @@ -450,7 +450,7 @@ "type": "t_uint256" }, { - "astId": 21436, + "astId": 21476, "contract": "contracts/factories/PairFactory.sol:PairFactory", "label": "volatileFee", "offset": 0, @@ -458,7 +458,7 @@ "type": "t_uint256" }, { - "astId": 21441, + "astId": 21481, "contract": "contracts/factories/PairFactory.sol:PairFactory", "label": "feeManager", "offset": 0, @@ -466,7 +466,7 @@ "type": "t_address" }, { - "astId": 21443, + "astId": 21483, "contract": "contracts/factories/PairFactory.sol:PairFactory", "label": "pendingFeeManager", "offset": 0, @@ -474,7 +474,7 @@ "type": "t_address" }, { - "astId": 21451, + "astId": 21491, "contract": "contracts/factories/PairFactory.sol:PairFactory", "label": "getPair", "offset": 0, @@ -482,7 +482,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_bool,t_address)))" }, { - "astId": 21454, + "astId": 21494, "contract": "contracts/factories/PairFactory.sol:PairFactory", "label": "allPairs", "offset": 0, @@ -490,7 +490,7 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 21458, + "astId": 21498, "contract": "contracts/factories/PairFactory.sol:PairFactory", "label": "isPair", "offset": 0, @@ -498,7 +498,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 21460, + "astId": 21500, "contract": "contracts/factories/PairFactory.sol:PairFactory", "label": "_temp0", "offset": 0, @@ -506,7 +506,7 @@ "type": "t_address" }, { - "astId": 21462, + "astId": 21502, "contract": "contracts/factories/PairFactory.sol:PairFactory", "label": "_temp1", "offset": 0, @@ -514,7 +514,7 @@ "type": "t_address" }, { - "astId": 21464, + "astId": 21504, "contract": "contracts/factories/PairFactory.sol:PairFactory", "label": "_temp", "offset": 20, diff --git a/deployments/arbitrumOne/RewardsDistributor.json b/deployments/arbitrumOne/RewardsDistributor.json index 2536ab7d..deff378b 100644 --- a/deployments/arbitrumOne/RewardsDistributor.json +++ b/deployments/arbitrumOne/RewardsDistributor.json @@ -1,5 +1,5 @@ { - "address": "0xd9891738458A5b1F1EfB5f82183b77c666d9064E", + "address": "0xffCC209120a8fb388140689ea1235e4eD78620d5", "abi": [ { "inputs": [ @@ -351,45 +351,45 @@ "type": "function" } ], - "transactionHash": "0xe554178d001c647246f9fa171b880e693ee215d6d4368948f9b6ceaab032ad0e", + "transactionHash": "0x85ea47b88d45de5a7f710b4cd864e46dea3cc99afefa103fa54aafee1b7d2a28", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xd9891738458A5b1F1EfB5f82183b77c666d9064E", + "contractAddress": "0xffCC209120a8fb388140689ea1235e4eD78620d5", "transactionIndex": 1, - "gasUsed": "11169043", - "logsBloom": "0x00000000000000000000000008000000000000000000000000000000000000000000000000000000000000002000000000000008000000000000000000240000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000408000000001000000000000000000000000000000000000", - "blockHash": "0xa69e0e8d19a1dbf3e8917d55c7d42c64e52fd279b93d02d2c7eda3a98a2ed9b6", - "transactionHash": "0xe554178d001c647246f9fa171b880e693ee215d6d4368948f9b6ceaab032ad0e", + "gasUsed": "11095108", + "logsBloom": "0x00000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000000000000000000200000001000000000000000000000000000000000000000000000000000004000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000080000000000000000000000010000000000000000008000000000000000000000000000000000000000000", + "blockHash": "0xf085e2ae966db473e170c44b22f33fa05b9bd636e4cdcdc9851084d9bffb44da", + "transactionHash": "0x85ea47b88d45de5a7f710b4cd864e46dea3cc99afefa103fa54aafee1b7d2a28", "logs": [ { "transactionIndex": 1, - "blockNumber": 53774100, - "transactionHash": "0xe554178d001c647246f9fa171b880e693ee215d6d4368948f9b6ceaab032ad0e", - "address": "0xC33f7f83CbB021846Cb9c58f2d8E3df428dbC8C1", + "blockNumber": 58032088, + "transactionHash": "0x85ea47b88d45de5a7f710b4cd864e46dea3cc99afefa103fa54aafee1b7d2a28", + "address": "0x944AF7785d57bcfC00e95388453B93DAD373216e", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000d9891738458a5b1f1efb5f82183b77c666d9064e", - "0x00000000000000000000000010df81252069c1095f541faca61646cb9ae76703" + "0x000000000000000000000000ffcc209120a8fb388140689ea1235e4ed78620d5", + "0x000000000000000000000000fa01adbaa40f0eeecea76b7b18ac8be064536787" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "logIndex": 0, - "blockHash": "0xa69e0e8d19a1dbf3e8917d55c7d42c64e52fd279b93d02d2c7eda3a98a2ed9b6" + "blockHash": "0xf085e2ae966db473e170c44b22f33fa05b9bd636e4cdcdc9851084d9bffb44da" } ], - "blockNumber": 53774100, - "cumulativeGasUsed": "11169043", + "blockNumber": 58032088, + "cumulativeGasUsed": "11095108", "status": 1, "byzantium": true }, "args": [ - "0x10Df81252069C1095F541FAca61646cb9Ae76703" + "0xfa01adbAA40f0EEeCEA76b7B18AC8bE064536787" ], "numDeployments": 1, - "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voting_escrow\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"time\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"CheckpointToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"claim_epoch\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"max_epoch\",\"type\":\"uint256\"}],\"name\":\"Claimed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"checkpoint_token\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint_total_supply\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"_tokenIds\",\"type\":\"uint256[]\"}],\"name\":\"claim_many\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_token_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"}],\"name\":\"setDepositor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"start_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"time_cursor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"time_cursor_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token_last_balance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"tokens_per_week\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_epoch_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"ve_for_at\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ve_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voting_escrow\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RewardsDistributor.sol\":\"RewardsDistributor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/*\\n\\n@title Curve Fee Distribution modified for ve(3,3) emissions\\n@author Curve Finance, andrecronje\\n@license MIT\\n\\n*/\\n\\ncontract RewardsDistributor is IRewardsDistributor {\\n event CheckpointToken(uint256 time, uint256 tokens);\\n\\n event Claimed(\\n uint256 tokenId,\\n uint256 amount,\\n uint256 claim_epoch,\\n uint256 max_epoch\\n );\\n\\n uint256 constant WEEK = 7 * 86400;\\n\\n uint256 public start_time;\\n uint256 public time_cursor;\\n mapping(uint256 => uint256) public time_cursor_of;\\n mapping(uint256 => uint256) public user_epoch_of;\\n\\n uint256 public last_token_time;\\n uint256[1000000000000000] public tokens_per_week;\\n\\n address public voting_escrow;\\n address public token;\\n uint256 public token_last_balance;\\n\\n uint256[1000000000000000] public ve_supply;\\n\\n address public depositor;\\n\\n constructor(address _voting_escrow) {\\n uint256 _t = (block.timestamp / WEEK) * WEEK;\\n start_time = _t;\\n last_token_time = _t;\\n time_cursor = _t;\\n address _token = IVotingEscrow(_voting_escrow).token();\\n token = _token;\\n voting_escrow = _voting_escrow;\\n depositor = msg.sender;\\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\\n }\\n\\n function timestamp() external view returns (uint256) {\\n return (block.timestamp / WEEK) * WEEK;\\n }\\n\\n function _checkpoint_token() internal {\\n uint256 token_balance = IERC20(token).balanceOf(address(this));\\n uint256 to_distribute = token_balance - token_last_balance;\\n token_last_balance = token_balance;\\n\\n uint256 t = last_token_time;\\n uint256 since_last = block.timestamp - t;\\n last_token_time = block.timestamp;\\n uint256 this_week = (t / WEEK) * WEEK;\\n uint256 next_week = 0;\\n\\n for (uint256 i = 0; i < 20; i++) {\\n next_week = this_week + WEEK;\\n if (block.timestamp < next_week) {\\n if (since_last == 0 && block.timestamp == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (block.timestamp - t)) /\\n since_last;\\n }\\n break;\\n } else {\\n if (since_last == 0 && next_week == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (next_week - t)) /\\n since_last;\\n }\\n }\\n t = next_week;\\n this_week = next_week;\\n }\\n emit CheckpointToken(block.timestamp, to_distribute);\\n }\\n\\n function checkpoint_token() external {\\n assert(msg.sender == depositor);\\n _checkpoint_token();\\n }\\n\\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\\n internal\\n view\\n returns (uint256)\\n {\\n uint256 _min = 0;\\n uint256 _max = IVotingEscrow(ve).epoch();\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n _mid\\n );\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function _find_timestamp_user_epoch(\\n address ve,\\n uint256 tokenId,\\n uint256 _timestamp,\\n uint256 max_user_epoch\\n ) internal view returns (uint256) {\\n uint256 _min = 0;\\n uint256 _max = max_user_epoch;\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\\n .user_point_history(tokenId, _mid);\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\\n external\\n view\\n returns (uint256)\\n {\\n address ve = voting_escrow;\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _timestamp,\\n max_user_epoch\\n );\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n epoch\\n );\\n return\\n MathDunks.max(\\n uint256(\\n int256(\\n pt.bias -\\n pt.slope *\\n (int128(int256(_timestamp - pt.ts)))\\n )\\n ),\\n 0\\n );\\n }\\n\\n function _checkpoint_total_supply() internal {\\n address ve = voting_escrow;\\n uint256 t = time_cursor;\\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\\n IVotingEscrow(ve).checkpoint();\\n\\n for (uint256 i = 0; i < 20; i++) {\\n if (t > rounded_timestamp) {\\n break;\\n } else {\\n uint256 epoch = _find_timestamp_epoch(ve, t);\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n epoch\\n );\\n int128 dt = 0;\\n if (t > pt.ts) {\\n dt = int128(int256(t - pt.ts));\\n }\\n ve_supply[t] = MathDunks.max(\\n uint256(int256(pt.bias - pt.slope * dt)),\\n 0\\n );\\n }\\n t += WEEK;\\n }\\n time_cursor = t;\\n }\\n\\n function checkpoint_total_supply() external {\\n _checkpoint_total_supply();\\n }\\n\\n function _claim(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\\n user_epoch_of[_tokenId] = user_epoch;\\n time_cursor_of[_tokenId] = week_cursor;\\n\\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\\n\\n return to_distribute;\\n }\\n\\n function _claimable(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal view returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n return to_distribute;\\n }\\n\\n function claimable(uint256 _tokenId) external view returns (uint256) {\\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\\n return _claimable(_tokenId, voting_escrow, _last_token_time);\\n }\\n\\n function claim(uint256 _tokenId) external returns (uint256) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\\n token_last_balance -= amount;\\n }\\n return amount;\\n }\\n\\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n address _voting_escrow = voting_escrow;\\n uint256 total = 0;\\n\\n for (uint256 i = 0; i < _tokenIds.length; i++) {\\n uint256 _tokenId = _tokenIds[i];\\n if (_tokenId == 0) break;\\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\\n total += amount;\\n }\\n }\\n if (total != 0) {\\n token_last_balance -= total;\\n }\\n\\n return true;\\n }\\n\\n // Once off event on contract initialize\\n function setDepositor(address _depositor) external {\\n require(msg.sender == depositor);\\n depositor = _depositor;\\n }\\n}\\n\",\"keccak256\":\"0xdbcfb11d65c6ca7d63baba42fb2f1222478c6ca78d8e81970032eff5e034e09b\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b5060405162001b9f38038062001b9f83398101604081905262000034916200019f565b600062093a80620000468142620001d1565b620000529190620001f4565b90508060008190555080600481905550806001819055506000826001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000aa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d091906200019f565b66038d7ea4c6800680546001600160a01b038381166001600160a01b0319928316811790935566038d7ea4c6800580549188169183168217905566071afd498d00088054909216331790915560405163095ea7b360e01b8152600481019190915260001960248201529192509063095ea7b3906044016020604051808303816000875af115801562000166573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200018c919062000222565b6200019657600080fd5b50505062000246565b600060208284031215620001b257600080fd5b81516001600160a01b0381168114620001ca57600080fd5b9392505050565b600082620001ef57634e487b7160e01b600052601260045260246000fd5b500490565b60008160001904831182151516156200021d57634e487b7160e01b600052601160045260246000fd5b500290565b6000602082840312156200023557600080fd5b81518015158114620001ca57600080fd5b61194980620002566000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea26469706673582212201bd70ac15ed6cd0b251036f174a839aeb92aa432fe7d09fa6cb45a0a25d2cda964736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea26469706673582212201bd70ac15ed6cd0b251036f174a839aeb92aa432fe7d09fa6cb45a0a25d2cda964736f6c634300080d0033", + "solcInputHash": "816572db58a4a8203fcf6f77728173df", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voting_escrow\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"time\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"CheckpointToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"claim_epoch\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"max_epoch\",\"type\":\"uint256\"}],\"name\":\"Claimed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"checkpoint_token\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint_total_supply\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"_tokenIds\",\"type\":\"uint256[]\"}],\"name\":\"claim_many\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_token_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"}],\"name\":\"setDepositor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"start_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"time_cursor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"time_cursor_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token_last_balance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"tokens_per_week\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_epoch_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"ve_for_at\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ve_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voting_escrow\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RewardsDistributor.sol\":\"RewardsDistributor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735353339323034313033\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/*\\n\\n@title Curve Fee Distribution modified for ve(3,3) emissions\\n@author Curve Finance, andrecronje\\n@license MIT\\n\\n*/\\n\\ncontract RewardsDistributor is IRewardsDistributor {\\n event CheckpointToken(uint256 time, uint256 tokens);\\n\\n event Claimed(\\n uint256 tokenId,\\n uint256 amount,\\n uint256 claim_epoch,\\n uint256 max_epoch\\n );\\n\\n uint256 constant WEEK = 7 * 86400;\\n\\n uint256 public start_time;\\n uint256 public time_cursor;\\n mapping(uint256 => uint256) public time_cursor_of;\\n mapping(uint256 => uint256) public user_epoch_of;\\n\\n uint256 public last_token_time;\\n uint256[1000000000000000] public tokens_per_week;\\n\\n address public voting_escrow;\\n address public token;\\n uint256 public token_last_balance;\\n\\n uint256[1000000000000000] public ve_supply;\\n\\n address public depositor;\\n\\n constructor(address _voting_escrow) {\\n uint256 _t = (block.timestamp / WEEK) * WEEK;\\n start_time = _t;\\n last_token_time = _t;\\n time_cursor = _t;\\n address _token = IVotingEscrow(_voting_escrow).token();\\n token = _token;\\n voting_escrow = _voting_escrow;\\n depositor = msg.sender;\\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\\n }\\n\\n function timestamp() external view returns (uint256) {\\n return (block.timestamp / WEEK) * WEEK;\\n }\\n\\n function _checkpoint_token() internal {\\n uint256 token_balance = IERC20(token).balanceOf(address(this));\\n uint256 to_distribute = token_balance - token_last_balance;\\n token_last_balance = token_balance;\\n\\n uint256 t = last_token_time;\\n uint256 since_last = block.timestamp - t;\\n last_token_time = block.timestamp;\\n uint256 this_week = (t / WEEK) * WEEK;\\n uint256 next_week = 0;\\n\\n for (uint256 i = 0; i < 20; i++) {\\n next_week = this_week + WEEK;\\n if (block.timestamp < next_week) {\\n if (since_last == 0 && block.timestamp == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (block.timestamp - t)) /\\n since_last;\\n }\\n break;\\n } else {\\n if (since_last == 0 && next_week == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (next_week - t)) /\\n since_last;\\n }\\n }\\n t = next_week;\\n this_week = next_week;\\n }\\n emit CheckpointToken(block.timestamp, to_distribute);\\n }\\n\\n function checkpoint_token() external {\\n assert(msg.sender == depositor);\\n _checkpoint_token();\\n }\\n\\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\\n internal\\n view\\n returns (uint256)\\n {\\n uint256 _min = 0;\\n uint256 _max = IVotingEscrow(ve).epoch();\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n _mid\\n );\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function _find_timestamp_user_epoch(\\n address ve,\\n uint256 tokenId,\\n uint256 _timestamp,\\n uint256 max_user_epoch\\n ) internal view returns (uint256) {\\n uint256 _min = 0;\\n uint256 _max = max_user_epoch;\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\\n .user_point_history(tokenId, _mid);\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\\n external\\n view\\n returns (uint256)\\n {\\n address ve = voting_escrow;\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _timestamp,\\n max_user_epoch\\n );\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n epoch\\n );\\n return\\n Math.max(\\n uint256(\\n int256(\\n pt.bias -\\n pt.slope *\\n (int128(int256(_timestamp - pt.ts)))\\n )\\n ),\\n 0\\n );\\n }\\n\\n function _checkpoint_total_supply() internal {\\n address ve = voting_escrow;\\n uint256 t = time_cursor;\\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\\n IVotingEscrow(ve).checkpoint();\\n\\n for (uint256 i = 0; i < 20; i++) {\\n if (t > rounded_timestamp) {\\n break;\\n } else {\\n uint256 epoch = _find_timestamp_epoch(ve, t);\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n epoch\\n );\\n int128 dt = 0;\\n if (t > pt.ts) {\\n dt = int128(int256(t - pt.ts));\\n }\\n ve_supply[t] = Math.max(\\n uint256(int256(pt.bias - pt.slope * dt)),\\n 0\\n );\\n }\\n t += WEEK;\\n }\\n time_cursor = t;\\n }\\n\\n function checkpoint_total_supply() external {\\n _checkpoint_total_supply();\\n }\\n\\n function _claim(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = Math.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n user_epoch = Math.min(max_user_epoch, user_epoch - 1);\\n user_epoch_of[_tokenId] = user_epoch;\\n time_cursor_of[_tokenId] = week_cursor;\\n\\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\\n\\n return to_distribute;\\n }\\n\\n function _claimable(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal view returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = Math.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n return to_distribute;\\n }\\n\\n function claimable(uint256 _tokenId) external view returns (uint256) {\\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\\n return _claimable(_tokenId, voting_escrow, _last_token_time);\\n }\\n\\n function claim(uint256 _tokenId) external returns (uint256) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\\n token_last_balance -= amount;\\n }\\n return amount;\\n }\\n\\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n address _voting_escrow = voting_escrow;\\n uint256 total = 0;\\n\\n for (uint256 i = 0; i < _tokenIds.length; i++) {\\n uint256 _tokenId = _tokenIds[i];\\n if (_tokenId == 0) break;\\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\\n total += amount;\\n }\\n }\\n if (total != 0) {\\n token_last_balance -= total;\\n }\\n\\n return true;\\n }\\n\\n // Once off event on contract initialize\\n function setDepositor(address _depositor) external {\\n require(msg.sender == depositor);\\n depositor = _depositor;\\n }\\n}\\n\",\"keccak256\":\"0xf1383d3056681a680d90f08bbb30c1b6b839f37a712aaa59ae5856a9846b012d\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3546b156d97633f7f8cad536d5454c81d1d604687c02b2eb105fdc33cb962b41\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b5060405162001b9e38038062001b9e83398101604081905262000034916200019f565b600062093a80620000468142620001d1565b620000529190620001f4565b90508060008190555080600481905550806001819055506000826001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000aa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d091906200019f565b66038d7ea4c6800680546001600160a01b038381166001600160a01b0319928316811790935566038d7ea4c6800580549188169183168217905566071afd498d00088054909216331790915560405163095ea7b360e01b8152600481019190915260001960248201529192509063095ea7b3906044016020604051808303816000875af115801562000166573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200018c919062000222565b6200019657600080fd5b50505062000246565b600060208284031215620001b257600080fd5b81516001600160a01b0381168114620001ca57600080fd5b9392505050565b600082620001ef57634e487b7160e01b600052601260045260246000fd5b500490565b60008160001904831182151516156200021d57634e487b7160e01b600052601160045260246000fd5b500290565b6000602082840312156200023557600080fd5b81518015158114620001ca57600080fd5b61194880620002566000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611566565b60036020526000908152604090205481565b6101756101703660046115c6565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611566565b6103fb565b61012f6101b5366004611566565b60026020526000908152604090205481565b61012f6101d536600461166c565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611566565b610679565b61012f610258366004611566565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611566565b6106dc565b6101eb61029736600461168e565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116cd565b6102e391906116ef565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170e565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611724565b93505b505080806103c39061173c565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611755565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116cd565b61042991906116ef565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611755565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176c565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179c565b905061061d8160400151876105f89190611755565b8260200151610607919061180e565b825161061391906118ac565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fc565b610650610e08565b565b610650610737565b600062093a8061066a81426116cd565b61067491906116ef565b905090565b60008062093a808060045461068e91906116cd565b61069891906116ef565b66038d7ea4c68005549091506104de9084906001600160a01b031683611065565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116cd565b61076991906116ef565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611402565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179c565b90506000816040015186111561086e57604082015161086b9087611755565b90505b61088d818360200151610881919061180e565b835161061391906118ac565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170e565b01555050506108be62093a8084611724565b9250806108ca8161173c565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176c565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179c565b905081600003610a685762093a8080600162093a808460400151610a479190611724565b610a519190611755565b610a5b91906116cd565b610a6591906116ef565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611724565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179c565b9250610c61565b6000826040015185610bae9190611755565b90506000610bd1846020015183610bc5919061180e565b855161061391906118ac565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170e565b015460058766038d7ea4c680008110610c2c57610c2c61170e565b0154610c3890836116ef565b610c4291906116cd565b610c4c908a611724565b98505b610c5c62093a8087611724565b955050505b80610c6b8161173c565b915050610ab1565b50610c8885610c8360018a611755565b611557565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611724565b610d2e906002611724565b610d3891906116cd565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179c565b905087816040015111610dc357819450610dd1565b610dce600183611755565b93505b50508080610dde9061173c565b915050610d04565b50909695505050505050565b6000818311610e0157816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7b919061176c565b9050600066038d7ea4c680075482610e939190611755565b66038d7ea4c680078390556004549091506000610eb08242611755565b426004559050600062093a80610ec681856116cd565b610ed091906116ef565b90506000805b601481101561102357610eec62093a8084611724565b915081421015610f755783158015610f0357508442145b15610f3d578560058466038d7ea4c680008110610f2257610f2261170e565b016000828254610f329190611724565b909155506110239050565b83610f488642611755565b610f5290886116ef565b610f5c91906116cd565b60058466038d7ea4c680008110610f2257610f2261170e565b83158015610f8257508482145b15610fbc578560058466038d7ea4c680008110610fa157610fa161170e565b016000828254610fb19190611724565b9091555061100a9050565b83610fc78684611755565b610fd190886116ef565b610fdb91906116cd565b60058466038d7ea4c680008110610ff457610ff461170e565b0160008282546110049190611724565b90915550505b819450819250808061101b9061173c565b915050610ed6565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d7919061176c565b600080549192508290036110f25760009450505050506104de565b6000888152600260205260408120549081900361111c57611115888a8486610cfe565b945061112e565b60008981526003602052604090205494505b8460000361113b57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ae919061179c565b9050816000036111f35762093a8080600162093a8084604001516111d29190611724565b6111dc9190611755565b6111e691906116cd565b6111f091906116ef565b91505b600454821061120b57600096505050505050506104de565b82821015611217578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f257898410156113f257826040015184101580156112615750858811155b1561132757611271600189611724565b9750829150858811156112b05760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e0565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611320919061179c565b92506113e0565b60008260400151856113399190611755565b90506000611350846020015183610bc5919061180e565b90508015801561135f5750878a115b1561136b5750506113f2565b80156113ce5766038d7ea4c680088666038d7ea4c6800081106113905761139061170e565b015460058766038d7ea4c6800081106113ab576113ab61170e565b01546113b790836116ef565b6113c191906116cd565b6113cb908a611724565b98505b6113db62093a8087611724565b955050505b806113ea8161173c565b91505061123c565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611449573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146d919061176c565b905060005b608081101561154d578183101561154d57600060026114918486611724565b61149c906002611724565b6114a691906116cd565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611515919061179c565b90508681604001511161152a57819450611538565b611535600183611755565b93505b505080806115459061173c565b915050611472565b5090949350505050565b6000818310610e0157816104de565b60006020828403121561157857600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115be576115be61157f565b604052919050565b600060208083850312156115d957600080fd5b823567ffffffffffffffff808211156115f157600080fd5b818501915085601f83011261160557600080fd5b8135818111156116175761161761157f565b8060051b9150611628848301611595565b818152918301840191848101908884111561164257600080fd5b938501935b8385101561166057843582529385019390850190611647565b98975050505050505050565b6000806040838503121561167f57600080fd5b50508035926020909101359150565b6000602082840312156116a057600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116ea57634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615611709576117096116b7565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611737576117376116b7565b500190565b60006001820161174e5761174e6116b7565b5060010190565b600082821015611767576117676116b7565b500390565b60006020828403121561177e57600080fd5b5051919050565b8051600f81900b811461179757600080fd5b919050565b6000608082840312156117ae57600080fd5b6040516080810181811067ffffffffffffffff821117156117d1576117d161157f565b6040526117dd83611785565b81526117eb60208401611785565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183e5761183e6116b7565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186a5761186a6116b7565b60008712925085820587128484161615611886576118866116b7565b8585058712818416161561189c5761189c6116b7565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d7576118d76116b7565b8160016001607f1b030183138116156118f2576118f26116b7565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea264697066735822122092fe21b106295456976ed857987ae3043c8b0559cd5b192decc29be4ee16ded364736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611566565b60036020526000908152604090205481565b6101756101703660046115c6565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611566565b6103fb565b61012f6101b5366004611566565b60026020526000908152604090205481565b61012f6101d536600461166c565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611566565b610679565b61012f610258366004611566565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611566565b6106dc565b6101eb61029736600461168e565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116cd565b6102e391906116ef565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170e565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611724565b93505b505080806103c39061173c565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611755565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116cd565b61042991906116ef565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611755565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176c565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179c565b905061061d8160400151876105f89190611755565b8260200151610607919061180e565b825161061391906118ac565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fc565b610650610e08565b565b610650610737565b600062093a8061066a81426116cd565b61067491906116ef565b905090565b60008062093a808060045461068e91906116cd565b61069891906116ef565b66038d7ea4c68005549091506104de9084906001600160a01b031683611065565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116cd565b61076991906116ef565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611402565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179c565b90506000816040015186111561086e57604082015161086b9087611755565b90505b61088d818360200151610881919061180e565b835161061391906118ac565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170e565b01555050506108be62093a8084611724565b9250806108ca8161173c565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176c565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179c565b905081600003610a685762093a8080600162093a808460400151610a479190611724565b610a519190611755565b610a5b91906116cd565b610a6591906116ef565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611724565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179c565b9250610c61565b6000826040015185610bae9190611755565b90506000610bd1846020015183610bc5919061180e565b855161061391906118ac565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170e565b015460058766038d7ea4c680008110610c2c57610c2c61170e565b0154610c3890836116ef565b610c4291906116cd565b610c4c908a611724565b98505b610c5c62093a8087611724565b955050505b80610c6b8161173c565b915050610ab1565b50610c8885610c8360018a611755565b611557565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611724565b610d2e906002611724565b610d3891906116cd565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179c565b905087816040015111610dc357819450610dd1565b610dce600183611755565b93505b50508080610dde9061173c565b915050610d04565b50909695505050505050565b6000818311610e0157816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7b919061176c565b9050600066038d7ea4c680075482610e939190611755565b66038d7ea4c680078390556004549091506000610eb08242611755565b426004559050600062093a80610ec681856116cd565b610ed091906116ef565b90506000805b601481101561102357610eec62093a8084611724565b915081421015610f755783158015610f0357508442145b15610f3d578560058466038d7ea4c680008110610f2257610f2261170e565b016000828254610f329190611724565b909155506110239050565b83610f488642611755565b610f5290886116ef565b610f5c91906116cd565b60058466038d7ea4c680008110610f2257610f2261170e565b83158015610f8257508482145b15610fbc578560058466038d7ea4c680008110610fa157610fa161170e565b016000828254610fb19190611724565b9091555061100a9050565b83610fc78684611755565b610fd190886116ef565b610fdb91906116cd565b60058466038d7ea4c680008110610ff457610ff461170e565b0160008282546110049190611724565b90915550505b819450819250808061101b9061173c565b915050610ed6565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d7919061176c565b600080549192508290036110f25760009450505050506104de565b6000888152600260205260408120549081900361111c57611115888a8486610cfe565b945061112e565b60008981526003602052604090205494505b8460000361113b57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ae919061179c565b9050816000036111f35762093a8080600162093a8084604001516111d29190611724565b6111dc9190611755565b6111e691906116cd565b6111f091906116ef565b91505b600454821061120b57600096505050505050506104de565b82821015611217578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f257898410156113f257826040015184101580156112615750858811155b1561132757611271600189611724565b9750829150858811156112b05760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e0565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611320919061179c565b92506113e0565b60008260400151856113399190611755565b90506000611350846020015183610bc5919061180e565b90508015801561135f5750878a115b1561136b5750506113f2565b80156113ce5766038d7ea4c680088666038d7ea4c6800081106113905761139061170e565b015460058766038d7ea4c6800081106113ab576113ab61170e565b01546113b790836116ef565b6113c191906116cd565b6113cb908a611724565b98505b6113db62093a8087611724565b955050505b806113ea8161173c565b91505061123c565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611449573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146d919061176c565b905060005b608081101561154d578183101561154d57600060026114918486611724565b61149c906002611724565b6114a691906116cd565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611515919061179c565b90508681604001511161152a57819450611538565b611535600183611755565b93505b505080806115459061173c565b915050611472565b5090949350505050565b6000818310610e0157816104de565b60006020828403121561157857600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115be576115be61157f565b604052919050565b600060208083850312156115d957600080fd5b823567ffffffffffffffff808211156115f157600080fd5b818501915085601f83011261160557600080fd5b8135818111156116175761161761157f565b8060051b9150611628848301611595565b818152918301840191848101908884111561164257600080fd5b938501935b8385101561166057843582529385019390850190611647565b98975050505050505050565b6000806040838503121561167f57600080fd5b50508035926020909101359150565b6000602082840312156116a057600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116ea57634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615611709576117096116b7565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611737576117376116b7565b500190565b60006001820161174e5761174e6116b7565b5060010190565b600082821015611767576117676116b7565b500390565b60006020828403121561177e57600080fd5b5051919050565b8051600f81900b811461179757600080fd5b919050565b6000608082840312156117ae57600080fd5b6040516080810181811067ffffffffffffffff821117156117d1576117d161157f565b6040526117dd83611785565b81526117eb60208401611785565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183e5761183e6116b7565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186a5761186a6116b7565b60008712925085820587128484161615611886576118866116b7565b8585058712818416161561189c5761189c6116b7565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d7576118d76116b7565b8160016001607f1b030183138116156118f2576118f26116b7565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea264697066735822122092fe21b106295456976ed857987ae3043c8b0559cd5b192decc29be4ee16ded364736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, @@ -403,7 +403,7 @@ "storageLayout": { "storage": [ { - "astId": 9410, + "astId": 9922, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "start_time", "offset": 0, @@ -411,7 +411,7 @@ "type": "t_uint256" }, { - "astId": 9412, + "astId": 9924, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "time_cursor", "offset": 0, @@ -419,7 +419,7 @@ "type": "t_uint256" }, { - "astId": 9416, + "astId": 9928, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "time_cursor_of", "offset": 0, @@ -427,7 +427,7 @@ "type": "t_mapping(t_uint256,t_uint256)" }, { - "astId": 9420, + "astId": 9932, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "user_epoch_of", "offset": 0, @@ -435,7 +435,7 @@ "type": "t_mapping(t_uint256,t_uint256)" }, { - "astId": 9422, + "astId": 9934, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "last_token_time", "offset": 0, @@ -443,7 +443,7 @@ "type": "t_uint256" }, { - "astId": 9426, + "astId": 9938, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "tokens_per_week", "offset": 0, @@ -451,7 +451,7 @@ "type": "t_array(t_uint256)1000000000000000_storage" }, { - "astId": 9428, + "astId": 9940, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "voting_escrow", "offset": 0, @@ -459,7 +459,7 @@ "type": "t_address" }, { - "astId": 9430, + "astId": 9942, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "token", "offset": 0, @@ -467,7 +467,7 @@ "type": "t_address" }, { - "astId": 9432, + "astId": 9944, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "token_last_balance", "offset": 0, @@ -475,7 +475,7 @@ "type": "t_uint256" }, { - "astId": 9436, + "astId": 9948, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "ve_supply", "offset": 0, @@ -483,7 +483,7 @@ "type": "t_array(t_uint256)1000000000000000_storage" }, { - "astId": 9438, + "astId": 9950, "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", "label": "depositor", "offset": 0, diff --git a/deployments/arbitrumOne/Router.json b/deployments/arbitrumOne/Router.json index b4febac4..228cb071 100644 --- a/deployments/arbitrumOne/Router.json +++ b/deployments/arbitrumOne/Router.json @@ -1,5 +1,5 @@ { - "address": "0x07d2FCFa095d52652cBC664F105F2d9Fb3799a47", + "address": "0x52A18b2386D6221Cf9DbcD4790456a23249e5279", "abi": [ { "inputs": [ @@ -979,31 +979,31 @@ "type": "receive" } ], - "transactionHash": "0x58eee942780ca824821a4aef9f4304d94dd16c37a1ac23c577ba412ac0d70d02", + "transactionHash": "0x72fccd23138adb616617ec4533ef557da429f67f176c253b006ab42fbece6e31", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x07d2FCFa095d52652cBC664F105F2d9Fb3799a47", + "contractAddress": "0x52A18b2386D6221Cf9DbcD4790456a23249e5279", "transactionIndex": 1, - "gasUsed": "21117639", + "gasUsed": "21295455", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xdaf429b1b8dd495aa7f78158cec510bd2d72bd844f7958bcd0e873c420a9f54e", - "transactionHash": "0x58eee942780ca824821a4aef9f4304d94dd16c37a1ac23c577ba412ac0d70d02", + "blockHash": "0x9da58c9904a2b1d24f1ad4708e16cc5162f74d5dd93eab180840de7505d469aa", + "transactionHash": "0x72fccd23138adb616617ec4533ef557da429f67f176c253b006ab42fbece6e31", "logs": [], - "blockNumber": 53774061, - "cumulativeGasUsed": "21117639", + "blockNumber": 58032037, + "cumulativeGasUsed": "21295455", "status": 1, "byzantium": true }, "args": [ - "0xA2db791281CdeeBb1EEDc78a34989df2Bfd479bE", - "0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83" + "0x9f7fdaB9317f1442808B90B819Ed0a4eF4f74994", + "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1" ], "numDeployments": 1, - "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_weth\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"UNSAFE_swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"}],\"name\":\"getAmountsOut\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reserveA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"pairFor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"}],\"name\":\"quoteAddLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"name\":\"quoteRemoveLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityETHWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"}],\"name\":\"sortTokens\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactETHForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForETH\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenFrom\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenTo\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokensSimple\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weth\",\"outputs\":[{\"internalType\":\"contract IWETH\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Router.sol\":\"Router\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Router.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairFactory.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\nimport \\\"contracts/interfaces/IWETH.sol\\\";\\n\\ncontract Router is IRouter {\\n struct route {\\n address from;\\n address to;\\n bool stable;\\n }\\n\\n address public immutable factory;\\n IWETH public immutable weth;\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n bytes32 immutable pairCodeHash;\\n\\n modifier ensure(uint256 deadline) {\\n require(deadline >= block.timestamp, \\\"Router: EXPIRED\\\");\\n _;\\n }\\n\\n constructor(address _factory, address _weth) {\\n factory = _factory;\\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\\n weth = IWETH(_weth);\\n }\\n\\n receive() external payable {\\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\\n }\\n\\n function sortTokens(address tokenA, address tokenB)\\n public\\n pure\\n returns (address token0, address token1)\\n {\\n require(tokenA != tokenB, \\\"Router: IDENTICAL_ADDRESSES\\\");\\n (token0, token1) = tokenA < tokenB\\n ? (tokenA, tokenB)\\n : (tokenB, tokenA);\\n require(token0 != address(0), \\\"Router: ZERO_ADDRESS\\\");\\n }\\n\\n // calculates the CREATE2 address for a pair without making any external calls\\n function pairFor(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (address pair) {\\n (address token0, address token1) = sortTokens(tokenA, tokenB);\\n pair = address(\\n uint160(\\n uint256(\\n keccak256(\\n abi.encodePacked(\\n hex\\\"ff\\\",\\n factory,\\n keccak256(abi.encodePacked(token0, token1, stable)),\\n pairCodeHash // init code hash\\n )\\n )\\n )\\n )\\n );\\n }\\n\\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\\n function quoteLiquidity(\\n uint256 amountA,\\n uint256 reserveA,\\n uint256 reserveB\\n ) internal pure returns (uint256 amountB) {\\n require(amountA > 0, \\\"Router: INSUFFICIENT_AMOUNT\\\");\\n require(reserveA > 0 && reserveB > 0, \\\"Router: INSUFFICIENT_LIQUIDITY\\\");\\n amountB = (amountA * reserveB) / reserveA;\\n }\\n\\n // fetches and sorts the reserves for a pair\\n function getReserves(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (uint256 reserveA, uint256 reserveB) {\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (uint256 reserve0, uint256 reserve1, ) = IPair(\\n pairFor(tokenA, tokenB, stable)\\n ).getReserves();\\n (reserveA, reserveB) = tokenA == token0\\n ? (reserve0, reserve1)\\n : (reserve1, reserve0);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n address tokenOut\\n ) external view returns (uint256 amount, bool stable) {\\n address pair = pairFor(tokenIn, tokenOut, true);\\n uint256 amountStable;\\n uint256 amountVolatile;\\n if (IPairFactory(factory).isPair(pair)) {\\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n pair = pairFor(tokenIn, tokenOut, false);\\n if (IPairFactory(factory).isPair(pair)) {\\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n return\\n amountStable > amountVolatile\\n ? (amountStable, true)\\n : (amountVolatile, false);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountsOut(uint256 amountIn, route[] memory routes)\\n public\\n view\\n returns (uint256[] memory amounts)\\n {\\n require(routes.length >= 1, \\\"Router: INVALID_PATH\\\");\\n amounts = new uint256[](routes.length + 1);\\n amounts[0] = amountIn;\\n for (uint256 i = 0; i < routes.length; i++) {\\n address pair = pairFor(\\n routes[i].from,\\n routes[i].to,\\n routes[i].stable\\n );\\n if (IPairFactory(factory).isPair(pair)) {\\n amounts[i + 1] = IPair(pair).getAmountOut(\\n amounts[i],\\n routes[i].from\\n );\\n }\\n }\\n }\\n\\n function isPair(address pair) external view returns (bool) {\\n return IPairFactory(factory).isPair(pair);\\n }\\n\\n function quoteAddLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired\\n )\\n external\\n view\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n (uint256 reserveA, uint256 reserveB) = (0, 0);\\n uint256 _totalSupply = 0;\\n if (_pair != address(0)) {\\n _totalSupply = IERC20(_pair).totalSupply();\\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\\n }\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n }\\n }\\n }\\n\\n function quoteRemoveLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity\\n ) external view returns (uint256 amountA, uint256 amountB) {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n\\n if (_pair == address(0)) {\\n return (0, 0);\\n }\\n\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n uint256 _totalSupply = IERC20(_pair).totalSupply();\\n\\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\\n }\\n\\n function _addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin\\n ) internal returns (uint256 amountA, uint256 amountB) {\\n require(amountADesired >= amountAMin);\\n require(amountBDesired >= amountBMin);\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n if (_pair == address(0)) {\\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\\n }\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n require(\\n amountBOptimal >= amountBMin,\\n \\\"Router: INSUFFICIENT_B_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n assert(amountAOptimal <= amountADesired);\\n require(\\n amountAOptimal >= amountAMin,\\n \\\"Router: INSUFFICIENT_A_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n }\\n }\\n }\\n\\n function addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n ensure(deadline)\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n (amountA, amountB) = _addLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n amountADesired,\\n amountBDesired,\\n amountAMin,\\n amountBMin\\n );\\n address pair = pairFor(tokenA, tokenB, stable);\\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\\n liquidity = IPair(pair).mint(to);\\n }\\n\\n function addLiquidityETH(\\n address token,\\n bool stable,\\n uint256 amountTokenDesired,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n payable\\n ensure(deadline)\\n returns (\\n uint256 amountToken,\\n uint256 amountETH,\\n uint256 liquidity\\n )\\n {\\n (amountToken, amountETH) = _addLiquidity(\\n token,\\n address(weth),\\n stable,\\n amountTokenDesired,\\n msg.value,\\n amountTokenMin,\\n amountETHMin\\n );\\n address pair = pairFor(token, address(weth), stable);\\n _safeTransferFrom(token, msg.sender, pair, amountToken);\\n weth.deposit{value: amountETH}();\\n assert(weth.transfer(pair, amountETH));\\n liquidity = IPair(pair).mint(to);\\n // refund dust eth, if any\\n if (msg.value > amountETH)\\n _safeTransferETH(msg.sender, msg.value - amountETH);\\n }\\n\\n // **** REMOVE LIQUIDITY ****\\n function removeLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (amountA, amountB) = tokenA == token0\\n ? (amount0, amount1)\\n : (amount1, amount0);\\n require(amountA >= amountAMin, \\\"Router: INSUFFICIENT_A_AMOUNT\\\");\\n require(amountB >= amountBMin, \\\"Router: INSUFFICIENT_B_AMOUNT\\\");\\n }\\n\\n function removeLiquidityETH(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\\n (amountToken, amountETH) = removeLiquidity(\\n token,\\n address(weth),\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n address(this),\\n deadline\\n );\\n _safeTransfer(token, to, amountToken);\\n weth.withdraw(amountETH);\\n _safeTransferETH(to, amountETH);\\n }\\n\\n function removeLiquidityWithPermit(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n {\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(\\n msg.sender,\\n address(this),\\n value,\\n deadline,\\n v,\\n r,\\n s\\n );\\n }\\n\\n (amountA, amountB) = removeLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n liquidity,\\n amountAMin,\\n amountBMin,\\n to,\\n deadline\\n );\\n }\\n\\n function removeLiquidityETHWithPermit(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountToken, uint256 amountETH) {\\n address pair = pairFor(token, address(weth), stable);\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\\n (amountToken, amountETH) = removeLiquidityETH(\\n token,\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n to,\\n deadline\\n );\\n }\\n\\n // **** SWAP ****\\n // requires the initial amount to have already been sent to the first pair\\n function _swap(\\n uint256[] memory amounts,\\n route[] memory routes,\\n address _to\\n ) internal virtual {\\n for (uint256 i = 0; i < routes.length; i++) {\\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\\n uint256 amountOut = amounts[i + 1];\\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\\n ? (uint256(0), amountOut)\\n : (amountOut, uint256(0));\\n address to = i < routes.length - 1\\n ? pairFor(\\n routes[i + 1].from,\\n routes[i + 1].to,\\n routes[i + 1].stable\\n )\\n : _to;\\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\\n amount0Out,\\n amount1Out,\\n to,\\n new bytes(0)\\n );\\n }\\n }\\n\\n function swapExactTokensForTokensSimple(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n address tokenFrom,\\n address tokenTo,\\n bool stable,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n route[] memory routes = new route[](1);\\n routes[0].from = tokenFrom;\\n routes[0].to = tokenTo;\\n routes[0].stable = stable;\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForTokens(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactETHForTokens(\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\\n require(routes[0].from == address(weth), \\\"Router: INVALID_PATH\\\");\\n amounts = getAmountsOut(msg.value, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n weth.deposit{value: amounts[0]}();\\n assert(\\n weth.transfer(\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n )\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForETH(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n require(\\n routes[routes.length - 1].to == address(weth),\\n \\\"Router: INVALID_PATH\\\"\\n );\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, address(this));\\n weth.withdraw(amounts[amounts.length - 1]);\\n _safeTransferETH(to, amounts[amounts.length - 1]);\\n }\\n\\n function UNSAFE_swapExactTokensForTokens(\\n uint256[] memory amounts,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory) {\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n return amounts;\\n }\\n\\n function _safeTransferETH(address to, uint256 value) internal {\\n (bool success, ) = to.call{value: value}(new bytes(0));\\n require(success, \\\"TransferHelper: ETH_TRANSFER_FAILED\\\");\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x3d84c846129d645eec66c37a493bb7fb401a2524497f450eaced155088305ead\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"},\"contracts/interfaces/IWETH.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n function transfer(address to, uint256 value) external returns (bool);\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0x20ad0b3a319a36e3430f0d8512ee3755de8f85a80effe78d06f333f5326ee3d7\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x60e06040523480156200001157600080fd5b50604051620039bc380380620039bc8339810160408190526200003491620000d8565b6001600160a01b038216608081905260408051631355724960e31b81529051639aab9248916004808201926020929091908290030181865afa1580156200007f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000a5919062000110565b60c0526001600160a01b031660a052506200012a565b80516001600160a01b0381168114620000d357600080fd5b919050565b60008060408385031215620000ec57600080fd5b620000f783620000bb565b91506200010760208401620000bb565b90509250929050565b6000602082840312156200012357600080fd5b5051919050565b60805160a05160c0516137c8620001f46000396000610ef901526000818161013e0152818161020b0152818161091901528181610b5801528181610da901528181611470015281816115830152818161161101528181611de901528181611e1f01528181611e5401528181611ee901528181612028015261207801526000818161042d01528181610c3e01528181610ebe015281816111770152818161128b0152818161199601528181611b0a01528181612115015281816126ff01526127a001526137c86000f3fe60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea2646970667358221220a5fbebccdd681576dc540b9cee199053b5ccdd41b782b05a7748e7178173beea64736f6c634300080d0033", - "deployedBytecode": "0x60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea2646970667358221220a5fbebccdd681576dc540b9cee199053b5ccdd41b782b05a7748e7178173beea64736f6c634300080d0033", + "solcInputHash": "816572db58a4a8203fcf6f77728173df", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_weth\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"UNSAFE_swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"}],\"name\":\"getAmountsOut\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reserveA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"pairFor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"}],\"name\":\"quoteAddLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"name\":\"quoteRemoveLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityETHWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"}],\"name\":\"sortTokens\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactETHForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForETH\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenFrom\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenTo\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokensSimple\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weth\",\"outputs\":[{\"internalType\":\"contract IWETH\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Router.sol\":\"Router\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735353339323034313033\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Router.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairFactory.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\nimport \\\"contracts/interfaces/IWETH.sol\\\";\\n\\ncontract Router is IRouter {\\n struct route {\\n address from;\\n address to;\\n bool stable;\\n }\\n\\n address public immutable factory;\\n IWETH public immutable weth;\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n bytes32 immutable pairCodeHash;\\n\\n modifier ensure(uint256 deadline) {\\n require(deadline >= block.timestamp, \\\"Router: EXPIRED\\\");\\n _;\\n }\\n\\n constructor(address _factory, address _weth) {\\n factory = _factory;\\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\\n weth = IWETH(_weth);\\n }\\n\\n receive() external payable {\\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\\n }\\n\\n function sortTokens(address tokenA, address tokenB)\\n public\\n pure\\n returns (address token0, address token1)\\n {\\n require(tokenA != tokenB, \\\"Router: IDENTICAL_ADDRESSES\\\");\\n (token0, token1) = tokenA < tokenB\\n ? (tokenA, tokenB)\\n : (tokenB, tokenA);\\n require(token0 != address(0), \\\"Router: ZERO_ADDRESS\\\");\\n }\\n\\n // calculates the CREATE2 address for a pair without making any external calls\\n function pairFor(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (address pair) {\\n (address token0, address token1) = sortTokens(tokenA, tokenB);\\n pair = address(\\n uint160(\\n uint256(\\n keccak256(\\n abi.encodePacked(\\n hex\\\"ff\\\",\\n factory,\\n keccak256(abi.encodePacked(token0, token1, stable)),\\n pairCodeHash // init code hash\\n )\\n )\\n )\\n )\\n );\\n }\\n\\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\\n function quoteLiquidity(\\n uint256 amountA,\\n uint256 reserveA,\\n uint256 reserveB\\n ) internal pure returns (uint256 amountB) {\\n require(amountA > 0, \\\"Router: INSUFFICIENT_AMOUNT\\\");\\n require(reserveA > 0 && reserveB > 0, \\\"Router: INSUFFICIENT_LIQUIDITY\\\");\\n amountB = (amountA * reserveB) / reserveA;\\n }\\n\\n // fetches and sorts the reserves for a pair\\n function getReserves(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (uint256 reserveA, uint256 reserveB) {\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (uint256 reserve0, uint256 reserve1, ) = IPair(\\n pairFor(tokenA, tokenB, stable)\\n ).getReserves();\\n (reserveA, reserveB) = tokenA == token0\\n ? (reserve0, reserve1)\\n : (reserve1, reserve0);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n address tokenOut\\n ) external view returns (uint256 amount, bool stable) {\\n address pair = pairFor(tokenIn, tokenOut, true);\\n uint256 amountStable;\\n uint256 amountVolatile;\\n if (IPairFactory(factory).isPair(pair)) {\\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n pair = pairFor(tokenIn, tokenOut, false);\\n if (IPairFactory(factory).isPair(pair)) {\\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n return\\n amountStable > amountVolatile\\n ? (amountStable, true)\\n : (amountVolatile, false);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountsOut(uint256 amountIn, route[] memory routes)\\n public\\n view\\n returns (uint256[] memory amounts)\\n {\\n require(routes.length >= 1, \\\"Router: INVALID_PATH\\\");\\n amounts = new uint256[](routes.length + 1);\\n amounts[0] = amountIn;\\n for (uint256 i = 0; i < routes.length; i++) {\\n address pair = pairFor(\\n routes[i].from,\\n routes[i].to,\\n routes[i].stable\\n );\\n if (IPairFactory(factory).isPair(pair)) {\\n amounts[i + 1] = IPair(pair).getAmountOut(\\n amounts[i],\\n routes[i].from\\n );\\n }\\n }\\n }\\n\\n function isPair(address pair) external view returns (bool) {\\n return IPairFactory(factory).isPair(pair);\\n }\\n\\n function quoteAddLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired\\n )\\n external\\n view\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n (uint256 reserveA, uint256 reserveB) = (0, 0);\\n uint256 _totalSupply = 0;\\n if (_pair != address(0)) {\\n _totalSupply = IERC20(_pair).totalSupply();\\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\\n }\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n liquidity = Math.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n liquidity = Math.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n liquidity = Math.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n }\\n }\\n }\\n\\n function quoteRemoveLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity\\n ) external view returns (uint256 amountA, uint256 amountB) {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n\\n if (_pair == address(0)) {\\n return (0, 0);\\n }\\n\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n uint256 _totalSupply = IERC20(_pair).totalSupply();\\n\\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\\n }\\n\\n function _addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin\\n ) internal returns (uint256 amountA, uint256 amountB) {\\n require(amountADesired >= amountAMin);\\n require(amountBDesired >= amountBMin);\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n if (_pair == address(0)) {\\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\\n }\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n require(\\n amountBOptimal >= amountBMin,\\n \\\"Router: INSUFFICIENT_B_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n assert(amountAOptimal <= amountADesired);\\n require(\\n amountAOptimal >= amountAMin,\\n \\\"Router: INSUFFICIENT_A_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n }\\n }\\n }\\n\\n function addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n ensure(deadline)\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n (amountA, amountB) = _addLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n amountADesired,\\n amountBDesired,\\n amountAMin,\\n amountBMin\\n );\\n address pair = pairFor(tokenA, tokenB, stable);\\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\\n liquidity = IPair(pair).mint(to);\\n }\\n\\n function addLiquidityETH(\\n address token,\\n bool stable,\\n uint256 amountTokenDesired,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n payable\\n ensure(deadline)\\n returns (\\n uint256 amountToken,\\n uint256 amountETH,\\n uint256 liquidity\\n )\\n {\\n (amountToken, amountETH) = _addLiquidity(\\n token,\\n address(weth),\\n stable,\\n amountTokenDesired,\\n msg.value,\\n amountTokenMin,\\n amountETHMin\\n );\\n address pair = pairFor(token, address(weth), stable);\\n _safeTransferFrom(token, msg.sender, pair, amountToken);\\n weth.deposit{value: amountETH}();\\n assert(weth.transfer(pair, amountETH));\\n liquidity = IPair(pair).mint(to);\\n // refund dust eth, if any\\n if (msg.value > amountETH)\\n _safeTransferETH(msg.sender, msg.value - amountETH);\\n }\\n\\n // **** REMOVE LIQUIDITY ****\\n function removeLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (amountA, amountB) = tokenA == token0\\n ? (amount0, amount1)\\n : (amount1, amount0);\\n require(amountA >= amountAMin, \\\"Router: INSUFFICIENT_A_AMOUNT\\\");\\n require(amountB >= amountBMin, \\\"Router: INSUFFICIENT_B_AMOUNT\\\");\\n }\\n\\n function removeLiquidityETH(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\\n (amountToken, amountETH) = removeLiquidity(\\n token,\\n address(weth),\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n address(this),\\n deadline\\n );\\n _safeTransfer(token, to, amountToken);\\n weth.withdraw(amountETH);\\n _safeTransferETH(to, amountETH);\\n }\\n\\n function removeLiquidityWithPermit(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n {\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(\\n msg.sender,\\n address(this),\\n value,\\n deadline,\\n v,\\n r,\\n s\\n );\\n }\\n\\n (amountA, amountB) = removeLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n liquidity,\\n amountAMin,\\n amountBMin,\\n to,\\n deadline\\n );\\n }\\n\\n function removeLiquidityETHWithPermit(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountToken, uint256 amountETH) {\\n address pair = pairFor(token, address(weth), stable);\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\\n (amountToken, amountETH) = removeLiquidityETH(\\n token,\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n to,\\n deadline\\n );\\n }\\n\\n // **** SWAP ****\\n // requires the initial amount to have already been sent to the first pair\\n function _swap(\\n uint256[] memory amounts,\\n route[] memory routes,\\n address _to\\n ) internal virtual {\\n for (uint256 i = 0; i < routes.length; i++) {\\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\\n uint256 amountOut = amounts[i + 1];\\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\\n ? (uint256(0), amountOut)\\n : (amountOut, uint256(0));\\n address to = i < routes.length - 1\\n ? pairFor(\\n routes[i + 1].from,\\n routes[i + 1].to,\\n routes[i + 1].stable\\n )\\n : _to;\\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\\n amount0Out,\\n amount1Out,\\n to,\\n new bytes(0)\\n );\\n }\\n }\\n\\n function swapExactTokensForTokensSimple(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n address tokenFrom,\\n address tokenTo,\\n bool stable,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n route[] memory routes = new route[](1);\\n routes[0].from = tokenFrom;\\n routes[0].to = tokenTo;\\n routes[0].stable = stable;\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForTokens(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactETHForTokens(\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\\n require(routes[0].from == address(weth), \\\"Router: INVALID_PATH\\\");\\n amounts = getAmountsOut(msg.value, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n weth.deposit{value: amounts[0]}();\\n assert(\\n weth.transfer(\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n )\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForETH(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n require(\\n routes[routes.length - 1].to == address(weth),\\n \\\"Router: INVALID_PATH\\\"\\n );\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, address(this));\\n weth.withdraw(amounts[amounts.length - 1]);\\n _safeTransferETH(to, amounts[amounts.length - 1]);\\n }\\n\\n function UNSAFE_swapExactTokensForTokens(\\n uint256[] memory amounts,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory) {\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n return amounts;\\n }\\n\\n function _safeTransferETH(address to, uint256 value) internal {\\n (bool success, ) = to.call{value: value}(new bytes(0));\\n require(success, \\\"TransferHelper: ETH_TRANSFER_FAILED\\\");\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x1a974004355612c10b2fc8211e7cbef3eed159a457b410446410754c8c40bc4b\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"},\"contracts/interfaces/IWETH.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n function transfer(address to, uint256 value) external returns (bool);\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0x20ad0b3a319a36e3430f0d8512ee3755de8f85a80effe78d06f333f5326ee3d7\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3546b156d97633f7f8cad536d5454c81d1d604687c02b2eb105fdc33cb962b41\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60e06040523480156200001157600080fd5b5060405162003ae838038062003ae88339810160408190526200003491620000d8565b6001600160a01b038216608081905260408051631355724960e31b81529051639aab9248916004808201926020929091908290030181865afa1580156200007f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000a5919062000110565b60c0526001600160a01b031660a052506200012a565b80516001600160a01b0381168114620000d357600080fd5b919050565b60008060408385031215620000ec57600080fd5b620000f783620000bb565b91506200010760208401620000bb565b90509250929050565b6000602082840312156200012357600080fd5b5051919050565b60805160a05160c0516138f4620001f46000396000610ef901526000818161013e0152818161020b0152818161091901528181610b5801528181610da901528181611470015281816115830152818161161101528181611de901528181611e1f01528181611e5401528181611ee901528181612028015261207801526000818161042d01528181610c3e01528181610ebe015281816111770152818161128b0152818161199601528181611b0a01528181612115015281816126ff01526127a001526138f46000f3fe60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612c98565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612ce4565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612d69565b6106d9565b6040516101a39190612de4565b3480156101e557600080fd5b506101cc6101f4366004612e6d565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612ee0565b610c37565b34801561027157600080fd5b50610192610280366004612f42565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612fec565b610e77565b3480156102b157600080fd5b506102c56102c0366004613037565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004613070565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b3660046130ff565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612fec565b611393565b6101cc610383366004613136565b61144b565b34801561039457600080fd5b506101cc6103a3366004613208565b6117aa565b3480156103b457600080fd5b506101cc6103c336600461334a565b611880565b3480156103d457600080fd5b506103056103e33660046133f0565b611b02565b3480156103f457600080fd5b5061019261040336600461344b565b611d02565b610305610416366004613507565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a366004613507565b611ffe565b34801561047b57600080fd5b5061048f61048a366004613562565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612e6d565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e39061357f565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061057391906135a8565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906135c5565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e39061357f565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566135e9565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6135e9565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66135e9565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f69190613615565b81518110610806576108066135e9565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e39061362c565b6108d481600081518110610842576108426135e9565b602002602001015160000151336108b484600081518110610865576108656135e9565b60200260200101516000015185600081518110610884576108846135e9565b602002602001015160200151866000815181106108a3576108a36135e9565b602002602001015160400151610e77565b866000815181106108c7576108c76135e9565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e39061357f565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168686610946600182613615565b818110610955576109556135e9565b905060600201602001602081019061096d9190613562565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e39061366e565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d66060830286013681900381019061369c565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a019190613615565b81518110610a1157610a116135e9565b60200260200101511015610a375760405162461bcd60e51b81526004016104e39061362c565b610af986866000818110610a4d57610a4d6135e9565b610a639260206060909202019081019150613562565b33610ae689896000818110610a7a57610a7a6135e9565b610a909260206060909202019081019150613562565b8a8a6000818110610aa357610aa36135e9565b9050606002016020016020810190610abb9190613562565b8b8b6000818110610ace57610ace6135e9565b90506060020160400160208101906102a091906136b8565b856000815181106108c7576108c76135e9565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c6060830286013681900381019061369c565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b949190613615565b81518110610ba457610ba46135e9565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f9190613615565b81518110610c1f57610c1f6135e9565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906136d5565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906136f9565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613716565b905080610d6d848961372f565b610d779190613764565b955080610d84838961372f565b610d8e9190613764565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e90600401613786565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e39061357f565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613716565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e491906135a8565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613716565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f891906135a8565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613716565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061141491906137c7565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e39061357f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6135e9565b6114c19260206060909202019081019150613562565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e39061366e565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a6060830286013681900381019061369c565b8152602001906001019061150d565b915086826001845161154b9190613615565b8151811061155b5761155b6135e9565b602002602001015110156115815760405162461bcd60e51b81526004016104e39061362c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36135e9565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546135e9565b61166a9260206060909202019081019150613562565b8989600081811061167d5761167d6135e9565b90506060020160200160208101906116959190613562565b8a8a6000818110610ace57610ace6135e9565b846000815181106116bb576116bb6135e9565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173791906135a8565b61174357611743612c98565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b82821015611795576117866060830286013681900381019061369c565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e39061357f565b611823868660008181106117e3576117e36135e9565b6117f99260206060909202019081019150613562565b3361181089896000818110610a7a57610a7a6135e9565b8a6000815181106108c7576108c76135e9565b611875878787808060200260200160405190810160405280939291908181526020016000905b82821015611795576118666060830286013681900381019061369c565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e39061366e565b81516118b19060016137f5565b67ffffffffffffffff8111156118c9576118c961319d565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096135e9565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386135e9565b602002602001015160000151858481518110611956576119566135e9565b6020026020010151602001518685815181106108a3576108a36135e9565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a0391906135a8565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296135e9565b6020026020010151868581518110611a4357611a436135e9565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613716565b83611acb8460016137f5565b81518110611adb57611adb6135e9565b6020026020010181815250505b5080611af38161380d565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906136d5565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906136f9565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613716565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a61372f565b612946565b611c599190613615565b9450611cf3565b6000611c6d8a8585612a35565b9050888111611cb557899750955085611cae84611c8a848b61372f565b611c949190613764565b84611c9f858b61372f565b611ca99190613764565b612aff565b9550611cf1565b6000611cc28a8587612a35565b9850899750889050611ced85611cd8858461372f565b611ce29190613764565b85611c9f868c61372f565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e90600401613786565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e39061357f565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a91906135a8565b611f6657611f66612c98565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613716565b925083341115611fef57611fef33611fea8634613615565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e39061357f565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612b15565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218291906135a8565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e39061357f565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee6060830286013681900381019061369c565b815260200190600101906121d1565b915086826001845161220f9190613615565b8151811061221f5761221f6135e9565b602002602001015110156122455760405162461bcd60e51b81526004016104e39061362c565b61225b86866000818110610a4d57610a4d6135e9565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e6060830286013681900381019061369c565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613852565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b509150915081801561239457508051158061239457508080602001905181019061239491906135a8565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86135e9565b6020026020010151600001518584815181106123e6576123e66135e9565b602002602001015160200151610f7f565b5090506000856124088460016137f5565b81518110612418576124186135e9565b60200260200101519050600080836001600160a01b0316878681518110612441576124416135e9565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b9190613615565b861061248757866124fa565b6124fa886124968860016137f5565b815181106124a6576124a66135e9565b602002602001015160000151898860016124c091906137f5565b815181106124d0576124d06135e9565b6020026020010151602001518a8960016124ea91906137f5565b815181106108a3576108a36135e9565b905061254d888781518110612511576125116135e9565b60200260200101516000015189888151811061252f5761252f6135e9565b6020026020010151602001518a89815181106108a3576108a36135e9565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa949392919061386e565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec9061380d565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613852565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016136d5565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906136f9565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016136d5565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906136f9565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a8484612a35565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a8486612a35565b90508a8111156128df576128df612c98565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b60008160000361295857506000919050565b6000600161296584612c04565b901c6001901b9050600181848161297e5761297e61374e565b048201901c905060018184816129965761299661374e565b048201901c905060018184816129ae576129ae61374e565b048201901c905060018184816129c6576129c661374e565b048201901c905060018184816129de576129de61374e565b048201901c905060018184816129f6576129f661374e565b048201901c90506001818481612a0e57612a0e61374e565b048201901c9050612a2e81828581612a2857612a2861374e565b04612aff565b9392505050565b6000808411612a865760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a965750600082115b612ae25760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612aed838661372f565b612af79190613764565b949350505050565b6000818310612b0e5781612a2e565b5090919050565b6000836001600160a01b03163b11612b2c57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b889190613852565b6000604051808303816000865af19150503d8060008114612bc5576040519150601f19603f3d011682016040523d82523d6000602084013e612bca565b606091505b5091509150818015612bf4575080511580612bf4575080806020019051810190612bf491906135a8565b612bfd57600080fd5b5050505050565b600080608083901c15612c1957608092831c92015b604083901c15612c2b57604092831c92015b602083901c15612c3d57602092831c92015b601083901c15612c4f57601092831c92015b600883901c15612c6157600892831c92015b600483901c15612c7357600492831c92015b600283901c15612c8557600292831c92015b600183901c156121825760010192915050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612cc357600080fd5b50565b8035612cd181612cae565b919050565b8015158114612cc357600080fd5b600080600080600080600080610100898b031215612d0157600080fd5b8835612d0c81612cae565b97506020890135612d1c81612cae565b96506040890135612d2c81612cd6565b9550606089013594506080890135935060a0890135925060c0890135612d5181612cae565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612d8457600080fd5b87359650602088013595506040880135612d9d81612cae565b94506060880135612dad81612cae565b93506080880135612dbd81612cd6565b925060a0880135612dcd81612cae565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612e1c57835183529284019291840191600101612e00565b50909695505050505050565b60008083601f840112612e3a57600080fd5b50813567ffffffffffffffff811115612e5257600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612e8657600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612eab57600080fd5b612eb789828a01612e28565b9095509350506060870135612ecb81612cae565b80925050608087013590509295509295509295565b60008060008060808587031215612ef657600080fd5b8435612f0181612cae565b93506020850135612f1181612cae565b92506040850135612f2181612cd6565b9396929550929360600135925050565b803560ff81168114612cd157600080fd5b60008060008060008060008060008060006101608c8e031215612f6457600080fd5b8b35612f6f81612cae565b9a5060208c0135612f7f81612cd6565b995060408c0135985060608c0135975060808c0135965060a08c0135612fa481612cae565b955060c08c0135945060e08c0135612fbb81612cd6565b9350612fca6101008d01612f31565b92506101208c013591506101408c013590509295989b509295989b9093969950565b60008060006060848603121561300157600080fd5b833561300c81612cae565b9250602084013561301c81612cae565b9150604084013561302c81612cd6565b809150509250925092565b6000806040838503121561304a57600080fd5b823561305581612cae565b9150602083013561306581612cae565b809150509250929050565b60008060008060008060008060006101208a8c03121561308f57600080fd5b893561309a81612cae565b985060208a01356130aa81612cae565b975060408a01356130ba81612cd6565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a01356130e681612cae565b809250506101008a013590509295985092959850929598565b60008060006060848603121561311457600080fd5b83359250602084013561312681612cae565b9150604084013561302c81612cae565b60008060008060006080868803121561314e57600080fd5b85359450602086013567ffffffffffffffff81111561316c57600080fd5b61317888828901612e28565b909550935050604086013561318c81612cae565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156131dc576131dc61319d565b604052919050565b600067ffffffffffffffff8211156131fe576131fe61319d565b5060051b60200190565b60008060008060006080868803121561322057600080fd5b853567ffffffffffffffff8082111561323857600080fd5b818801915088601f83011261324c57600080fd5b8135602061326161325c836131e4565b6131b3565b82815260059290921b8401810191818101908c84111561328057600080fd5b948201945b8386101561329e57853582529482019490820190613285565b995050890135925050808211156132b457600080fd5b506132c188828901612e28565b909550935061318c905060408701612cc6565b6000606082840312156132e657600080fd5b6040516060810181811067ffffffffffffffff821117156133095761330961319d565b604052905080823561331a81612cae565b8152602083013561332a81612cae565b6020820152604083013561333d81612cd6565b6040919091015292915050565b6000806040838503121561335d57600080fd5b8235915060208084013567ffffffffffffffff81111561337c57600080fd5b8401601f8101861361338d57600080fd5b803561339b61325c826131e4565b818152606091820283018401918482019190898411156133ba57600080fd5b938501935b838510156133e0576133d18a866132d4565b835293840193918501916133bf565b5080955050505050509250929050565b600080600080600060a0868803121561340857600080fd5b853561341381612cae565b9450602086013561342381612cae565b9350604086013561343381612cd6565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561346e57600080fd5b8c3561347981612cae565b9b5060208d013561348981612cae565b9a5060408d013561349981612cd6565b995060608d0135985060808d0135975060a08d0135965060c08d01356134be81612cae565b955060e08d013594506101008d01356134d681612cd6565b93506134e56101208e01612f31565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561352257600080fd5b873561352d81612cae565b9650602088013561353d81612cd6565b955060408801359450606088013593506080880135925060a0880135612dcd81612cae565b60006020828403121561357457600080fd5b8135612a2e81612cae565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156135ba57600080fd5b8151612a2e81612cd6565b600080604083850312156135d857600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613627576136276135ff565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b6000606082840312156136ae57600080fd5b612a2e83836132d4565b6000602082840312156136ca57600080fd5b8135612a2e81612cd6565b6001600160a01b039384168152919092166020820152901515604082015260600190565b60006020828403121561370b57600080fd5b8151612a2e81612cae565b60006020828403121561372857600080fd5b5051919050565b6000816000190483118215151615613749576137496135ff565b500290565b634e487b7160e01b600052601260045260246000fd5b60008261378157634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156137dc57600080fd5b8351925060208401519150604084015190509250925092565b60008219821115613808576138086135ff565b500190565b60006001820161381f5761381f6135ff565b5060010190565b60005b83811015613841578181015183820152602001613829565b838111156125f45750506000910152565b60008251613864818460208701613826565b9190910192915050565b84815283602082015260018060a01b038316604082015260806060820152600082518060808401526138a78160a0850160208701613826565b601f01601f19169190910160a0019594505050505056fea2646970667358221220f4972b3841f5721a1010ec70fa10b1529427c5fd2e8bb2e7053a697cb000efb864736f6c634300080d0033", + "deployedBytecode": "0x60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612c98565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612ce4565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612d69565b6106d9565b6040516101a39190612de4565b3480156101e557600080fd5b506101cc6101f4366004612e6d565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612ee0565b610c37565b34801561027157600080fd5b50610192610280366004612f42565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612fec565b610e77565b3480156102b157600080fd5b506102c56102c0366004613037565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004613070565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b3660046130ff565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612fec565b611393565b6101cc610383366004613136565b61144b565b34801561039457600080fd5b506101cc6103a3366004613208565b6117aa565b3480156103b457600080fd5b506101cc6103c336600461334a565b611880565b3480156103d457600080fd5b506103056103e33660046133f0565b611b02565b3480156103f457600080fd5b5061019261040336600461344b565b611d02565b610305610416366004613507565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a366004613507565b611ffe565b34801561047b57600080fd5b5061048f61048a366004613562565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612e6d565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e39061357f565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061057391906135a8565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906135c5565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e39061357f565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566135e9565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6135e9565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66135e9565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f69190613615565b81518110610806576108066135e9565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e39061362c565b6108d481600081518110610842576108426135e9565b602002602001015160000151336108b484600081518110610865576108656135e9565b60200260200101516000015185600081518110610884576108846135e9565b602002602001015160200151866000815181106108a3576108a36135e9565b602002602001015160400151610e77565b866000815181106108c7576108c76135e9565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e39061357f565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168686610946600182613615565b818110610955576109556135e9565b905060600201602001602081019061096d9190613562565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e39061366e565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d66060830286013681900381019061369c565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a019190613615565b81518110610a1157610a116135e9565b60200260200101511015610a375760405162461bcd60e51b81526004016104e39061362c565b610af986866000818110610a4d57610a4d6135e9565b610a639260206060909202019081019150613562565b33610ae689896000818110610a7a57610a7a6135e9565b610a909260206060909202019081019150613562565b8a8a6000818110610aa357610aa36135e9565b9050606002016020016020810190610abb9190613562565b8b8b6000818110610ace57610ace6135e9565b90506060020160400160208101906102a091906136b8565b856000815181106108c7576108c76135e9565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c6060830286013681900381019061369c565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b949190613615565b81518110610ba457610ba46135e9565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f9190613615565b81518110610c1f57610c1f6135e9565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906136d5565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906136f9565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613716565b905080610d6d848961372f565b610d779190613764565b955080610d84838961372f565b610d8e9190613764565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e90600401613786565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e39061357f565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613716565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e491906135a8565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613716565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f891906135a8565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613716565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061141491906137c7565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e39061357f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6135e9565b6114c19260206060909202019081019150613562565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e39061366e565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a6060830286013681900381019061369c565b8152602001906001019061150d565b915086826001845161154b9190613615565b8151811061155b5761155b6135e9565b602002602001015110156115815760405162461bcd60e51b81526004016104e39061362c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36135e9565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546135e9565b61166a9260206060909202019081019150613562565b8989600081811061167d5761167d6135e9565b90506060020160200160208101906116959190613562565b8a8a6000818110610ace57610ace6135e9565b846000815181106116bb576116bb6135e9565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173791906135a8565b61174357611743612c98565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b82821015611795576117866060830286013681900381019061369c565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e39061357f565b611823868660008181106117e3576117e36135e9565b6117f99260206060909202019081019150613562565b3361181089896000818110610a7a57610a7a6135e9565b8a6000815181106108c7576108c76135e9565b611875878787808060200260200160405190810160405280939291908181526020016000905b82821015611795576118666060830286013681900381019061369c565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e39061366e565b81516118b19060016137f5565b67ffffffffffffffff8111156118c9576118c961319d565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096135e9565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386135e9565b602002602001015160000151858481518110611956576119566135e9565b6020026020010151602001518685815181106108a3576108a36135e9565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a0391906135a8565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296135e9565b6020026020010151868581518110611a4357611a436135e9565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613716565b83611acb8460016137f5565b81518110611adb57611adb6135e9565b6020026020010181815250505b5080611af38161380d565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906136d5565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906136f9565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613716565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a61372f565b612946565b611c599190613615565b9450611cf3565b6000611c6d8a8585612a35565b9050888111611cb557899750955085611cae84611c8a848b61372f565b611c949190613764565b84611c9f858b61372f565b611ca99190613764565b612aff565b9550611cf1565b6000611cc28a8587612a35565b9850899750889050611ced85611cd8858461372f565b611ce29190613764565b85611c9f868c61372f565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e90600401613786565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e39061357f565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a91906135a8565b611f6657611f66612c98565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613716565b925083341115611fef57611fef33611fea8634613615565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e39061357f565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612b15565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218291906135a8565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e39061357f565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee6060830286013681900381019061369c565b815260200190600101906121d1565b915086826001845161220f9190613615565b8151811061221f5761221f6135e9565b602002602001015110156122455760405162461bcd60e51b81526004016104e39061362c565b61225b86866000818110610a4d57610a4d6135e9565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e6060830286013681900381019061369c565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613852565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b509150915081801561239457508051158061239457508080602001905181019061239491906135a8565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86135e9565b6020026020010151600001518584815181106123e6576123e66135e9565b602002602001015160200151610f7f565b5090506000856124088460016137f5565b81518110612418576124186135e9565b60200260200101519050600080836001600160a01b0316878681518110612441576124416135e9565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b9190613615565b861061248757866124fa565b6124fa886124968860016137f5565b815181106124a6576124a66135e9565b602002602001015160000151898860016124c091906137f5565b815181106124d0576124d06135e9565b6020026020010151602001518a8960016124ea91906137f5565b815181106108a3576108a36135e9565b905061254d888781518110612511576125116135e9565b60200260200101516000015189888151811061252f5761252f6135e9565b6020026020010151602001518a89815181106108a3576108a36135e9565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa949392919061386e565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec9061380d565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613852565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016136d5565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906136f9565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016136d5565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906136f9565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a8484612a35565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a8486612a35565b90508a8111156128df576128df612c98565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b60008160000361295857506000919050565b6000600161296584612c04565b901c6001901b9050600181848161297e5761297e61374e565b048201901c905060018184816129965761299661374e565b048201901c905060018184816129ae576129ae61374e565b048201901c905060018184816129c6576129c661374e565b048201901c905060018184816129de576129de61374e565b048201901c905060018184816129f6576129f661374e565b048201901c90506001818481612a0e57612a0e61374e565b048201901c9050612a2e81828581612a2857612a2861374e565b04612aff565b9392505050565b6000808411612a865760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a965750600082115b612ae25760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612aed838661372f565b612af79190613764565b949350505050565b6000818310612b0e5781612a2e565b5090919050565b6000836001600160a01b03163b11612b2c57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b889190613852565b6000604051808303816000865af19150503d8060008114612bc5576040519150601f19603f3d011682016040523d82523d6000602084013e612bca565b606091505b5091509150818015612bf4575080511580612bf4575080806020019051810190612bf491906135a8565b612bfd57600080fd5b5050505050565b600080608083901c15612c1957608092831c92015b604083901c15612c2b57604092831c92015b602083901c15612c3d57602092831c92015b601083901c15612c4f57601092831c92015b600883901c15612c6157600892831c92015b600483901c15612c7357600492831c92015b600283901c15612c8557600292831c92015b600183901c156121825760010192915050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612cc357600080fd5b50565b8035612cd181612cae565b919050565b8015158114612cc357600080fd5b600080600080600080600080610100898b031215612d0157600080fd5b8835612d0c81612cae565b97506020890135612d1c81612cae565b96506040890135612d2c81612cd6565b9550606089013594506080890135935060a0890135925060c0890135612d5181612cae565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612d8457600080fd5b87359650602088013595506040880135612d9d81612cae565b94506060880135612dad81612cae565b93506080880135612dbd81612cd6565b925060a0880135612dcd81612cae565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612e1c57835183529284019291840191600101612e00565b50909695505050505050565b60008083601f840112612e3a57600080fd5b50813567ffffffffffffffff811115612e5257600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612e8657600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612eab57600080fd5b612eb789828a01612e28565b9095509350506060870135612ecb81612cae565b80925050608087013590509295509295509295565b60008060008060808587031215612ef657600080fd5b8435612f0181612cae565b93506020850135612f1181612cae565b92506040850135612f2181612cd6565b9396929550929360600135925050565b803560ff81168114612cd157600080fd5b60008060008060008060008060008060006101608c8e031215612f6457600080fd5b8b35612f6f81612cae565b9a5060208c0135612f7f81612cd6565b995060408c0135985060608c0135975060808c0135965060a08c0135612fa481612cae565b955060c08c0135945060e08c0135612fbb81612cd6565b9350612fca6101008d01612f31565b92506101208c013591506101408c013590509295989b509295989b9093969950565b60008060006060848603121561300157600080fd5b833561300c81612cae565b9250602084013561301c81612cae565b9150604084013561302c81612cd6565b809150509250925092565b6000806040838503121561304a57600080fd5b823561305581612cae565b9150602083013561306581612cae565b809150509250929050565b60008060008060008060008060006101208a8c03121561308f57600080fd5b893561309a81612cae565b985060208a01356130aa81612cae565b975060408a01356130ba81612cd6565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a01356130e681612cae565b809250506101008a013590509295985092959850929598565b60008060006060848603121561311457600080fd5b83359250602084013561312681612cae565b9150604084013561302c81612cae565b60008060008060006080868803121561314e57600080fd5b85359450602086013567ffffffffffffffff81111561316c57600080fd5b61317888828901612e28565b909550935050604086013561318c81612cae565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156131dc576131dc61319d565b604052919050565b600067ffffffffffffffff8211156131fe576131fe61319d565b5060051b60200190565b60008060008060006080868803121561322057600080fd5b853567ffffffffffffffff8082111561323857600080fd5b818801915088601f83011261324c57600080fd5b8135602061326161325c836131e4565b6131b3565b82815260059290921b8401810191818101908c84111561328057600080fd5b948201945b8386101561329e57853582529482019490820190613285565b995050890135925050808211156132b457600080fd5b506132c188828901612e28565b909550935061318c905060408701612cc6565b6000606082840312156132e657600080fd5b6040516060810181811067ffffffffffffffff821117156133095761330961319d565b604052905080823561331a81612cae565b8152602083013561332a81612cae565b6020820152604083013561333d81612cd6565b6040919091015292915050565b6000806040838503121561335d57600080fd5b8235915060208084013567ffffffffffffffff81111561337c57600080fd5b8401601f8101861361338d57600080fd5b803561339b61325c826131e4565b818152606091820283018401918482019190898411156133ba57600080fd5b938501935b838510156133e0576133d18a866132d4565b835293840193918501916133bf565b5080955050505050509250929050565b600080600080600060a0868803121561340857600080fd5b853561341381612cae565b9450602086013561342381612cae565b9350604086013561343381612cd6565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561346e57600080fd5b8c3561347981612cae565b9b5060208d013561348981612cae565b9a5060408d013561349981612cd6565b995060608d0135985060808d0135975060a08d0135965060c08d01356134be81612cae565b955060e08d013594506101008d01356134d681612cd6565b93506134e56101208e01612f31565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561352257600080fd5b873561352d81612cae565b9650602088013561353d81612cd6565b955060408801359450606088013593506080880135925060a0880135612dcd81612cae565b60006020828403121561357457600080fd5b8135612a2e81612cae565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156135ba57600080fd5b8151612a2e81612cd6565b600080604083850312156135d857600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613627576136276135ff565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b6000606082840312156136ae57600080fd5b612a2e83836132d4565b6000602082840312156136ca57600080fd5b8135612a2e81612cd6565b6001600160a01b039384168152919092166020820152901515604082015260600190565b60006020828403121561370b57600080fd5b8151612a2e81612cae565b60006020828403121561372857600080fd5b5051919050565b6000816000190483118215151615613749576137496135ff565b500290565b634e487b7160e01b600052601260045260246000fd5b60008261378157634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156137dc57600080fd5b8351925060208401519150604084015190509250925092565b60008219821115613808576138086135ff565b500190565b60006001820161381f5761381f6135ff565b5060010190565b60005b83811015613841578181015183820152602001613829565b838111156125f45750506000910152565b60008251613864818460208701613826565b9190910192915050565b84815283602082015260018060a01b038316604082015260806060820152600082518060808401526138a78160a0850160208701613826565b601f01601f19169190910160a0019594505050505056fea2646970667358221220f4972b3841f5721a1010ec70fa10b1529427c5fd2e8bb2e7053a697cb000efb864736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumOne/VeArtProxy.json b/deployments/arbitrumOne/VeArtProxy.json index d8ad686b..51e5cbe9 100644 --- a/deployments/arbitrumOne/VeArtProxy.json +++ b/deployments/arbitrumOne/VeArtProxy.json @@ -1,5 +1,5 @@ { - "address": "0x4b40D5E4401EC24673cc9d4799457a3B5827c581", + "address": "0x0bd9d21b40428a650DbFC0F7bd3F7B6FA321F915", "abi": [ { "inputs": [ @@ -36,28 +36,28 @@ "type": "function" } ], - "transactionHash": "0xaea6c881d8fbd586965699a9451e8f32ed3536b204ecb1e490df8cf5677141a9", + "transactionHash": "0x05ebd073334884df4f081143a654a086464a4d49c43b0dad58fcb7700384d68a", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x4b40D5E4401EC24673cc9d4799457a3B5827c581", + "contractAddress": "0x0bd9d21b40428a650DbFC0F7bd3F7B6FA321F915", "transactionIndex": 1, - "gasUsed": "5573204", + "gasUsed": "5528609", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x34ad78b9a516d065f84e2b2c7125282551cc3907f1f97aaacb94abb885b05833", - "transactionHash": "0xaea6c881d8fbd586965699a9451e8f32ed3536b204ecb1e490df8cf5677141a9", + "blockHash": "0x94b1baa3d151e633a8a54630bf168cef2ccec575c61567ee62a6a36b1a8db72d", + "transactionHash": "0x05ebd073334884df4f081143a654a086464a4d49c43b0dad58fcb7700384d68a", "logs": [], - "blockNumber": 53774078, - "cumulativeGasUsed": "5573204", + "blockNumber": 58032060, + "cumulativeGasUsed": "5528609", "status": 1, "byzantium": true }, "args": [], "numDeployments": 1, - "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_locked_end\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"_tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"output\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VeArtProxy.sol\":\"VeArtProxy\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\nimport {Base64} from \\\"contracts/libraries/Base64.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\n\\ncontract VeArtProxy is IVeArtProxy {\\n function toString(uint value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT license\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint temp = value;\\n uint digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\\n output = '';\\n output = string(abi.encodePacked(output, \\\"token \\\", toString(_tokenId), ''));\\n output = string(abi.encodePacked(output, \\\"balanceOf \\\", toString(_balanceOf), ''));\\n output = string(abi.encodePacked(output, \\\"locked_end \\\", toString(_locked_end), ''));\\n output = string(abi.encodePacked(output, \\\"value \\\", toString(_value), ''));\\n\\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\\\"name\\\": \\\"lock #', toString(_tokenId), '\\\", \\\"description\\\": \\\"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\\\", \\\"image\\\": \\\"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\\\"}'))));\\n output = string(abi.encodePacked('data:application/json;base64,', json));\\n }\\n}\\n\",\"keccak256\":\"0x8757d8095922dcad7af8c6820415049fd7d5af61a5580719210e5e91a31d80b1\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/libraries/Base64.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n/// [MIT License]\\n/// @title Base64\\n/// @notice Provides a function for encoding some bytes in base64\\n/// @author Brecht Devos \\nlibrary Base64 {\\n bytes internal constant TABLE = \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\";\\n\\n /// @notice Encodes some bytes to the base64 representation\\n function encode(bytes memory data) internal pure returns (string memory) {\\n uint len = data.length;\\n if (len == 0) return \\\"\\\";\\n\\n // multiply by 4/3 rounded up\\n uint encodedLen = 4 * ((len + 2) / 3);\\n\\n // Add some extra buffer at the end\\n bytes memory result = new bytes(encodedLen + 32);\\n\\n bytes memory table = TABLE;\\n\\n assembly {\\n let tablePtr := add(table, 1)\\n let resultPtr := add(result, 32)\\n\\n for {\\n let i := 0\\n } lt(i, len) {\\n\\n } {\\n i := add(i, 3)\\n let input := and(mload(add(data, i)), 0xffffff)\\n\\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\\n out := shl(224, out)\\n\\n mstore(resultPtr, out)\\n\\n resultPtr := add(resultPtr, 4)\\n }\\n\\n switch mod(len, 3)\\n case 1 {\\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\\n }\\n case 2 {\\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\\n }\\n\\n mstore(result, encodedLen)\\n }\\n\\n return string(result);\\n }\\n}\\n\",\"keccak256\":\"0x55535e1e0a14bbac370fe5f25df23aa88c678b915af53517672130f9a54f7e3e\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50610a2b806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f64726f6d65206c6f636010918401918201527f6b732c2063616e206265207573656420746f20626f6f7374206761756765207960308201527f69656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c206160508201527f6e64207265636569766520627269626573222c2022696d616765223a2022646160708201527f74613a696d6167652f7376672b786d6c3b6261736536342c0000000000000000609082015283516107718160a8840160208801610435565b61227d60f01b60a8929091019182015260aa01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212205e17183bb106171fcd25152691eea4fe7c51c6576ba7661fd1601ee5ea93b74a64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f64726f6d65206c6f636010918401918201527f6b732c2063616e206265207573656420746f20626f6f7374206761756765207960308201527f69656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c206160508201527f6e64207265636569766520627269626573222c2022696d616765223a2022646160708201527f74613a696d6167652f7376672b786d6c3b6261736536342c0000000000000000609082015283516107718160a8840160208801610435565b61227d60f01b60a8929091019182015260aa01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212205e17183bb106171fcd25152691eea4fe7c51c6576ba7661fd1601ee5ea93b74a64736f6c634300080d0033", + "solcInputHash": "816572db58a4a8203fcf6f77728173df", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_locked_end\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"_tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"output\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VeArtProxy.sol\":\"VeArtProxy\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735353339323034313033\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\nimport {Base64} from \\\"contracts/libraries/Base64.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\n\\ncontract VeArtProxy is IVeArtProxy {\\n function toString(uint value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT license\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint temp = value;\\n uint digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\\n output = '';\\n output = string(abi.encodePacked(output, \\\"token \\\", toString(_tokenId), ''));\\n output = string(abi.encodePacked(output, \\\"balanceOf \\\", toString(_balanceOf), ''));\\n output = string(abi.encodePacked(output, \\\"locked_end \\\", toString(_locked_end), ''));\\n output = string(abi.encodePacked(output, \\\"value \\\", toString(_value), ''));\\n\\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\\\"name\\\": \\\"lock #', toString(_tokenId), '\\\", \\\"description\\\": \\\"Velocimeter locks, can be used to boost gauge yields, vote on token emission, and receive bribes\\\", \\\"image\\\": \\\"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\\\"}'))));\\n output = string(abi.encodePacked('data:application/json;base64,', json));\\n }\\n}\\n\",\"keccak256\":\"0xc526ae7232c93412d664837d1171f1bf5d231a4ea33bcc7a8d0b4e3fa6a9e227\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/libraries/Base64.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n/// [MIT License]\\n/// @title Base64\\n/// @notice Provides a function for encoding some bytes in base64\\n/// @author Brecht Devos \\nlibrary Base64 {\\n bytes internal constant TABLE = \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\";\\n\\n /// @notice Encodes some bytes to the base64 representation\\n function encode(bytes memory data) internal pure returns (string memory) {\\n uint len = data.length;\\n if (len == 0) return \\\"\\\";\\n\\n // multiply by 4/3 rounded up\\n uint encodedLen = 4 * ((len + 2) / 3);\\n\\n // Add some extra buffer at the end\\n bytes memory result = new bytes(encodedLen + 32);\\n\\n bytes memory table = TABLE;\\n\\n assembly {\\n let tablePtr := add(table, 1)\\n let resultPtr := add(result, 32)\\n\\n for {\\n let i := 0\\n } lt(i, len) {\\n\\n } {\\n i := add(i, 3)\\n let input := and(mload(add(data, i)), 0xffffff)\\n\\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\\n out := shl(224, out)\\n\\n mstore(resultPtr, out)\\n\\n resultPtr := add(resultPtr, 4)\\n }\\n\\n switch mod(len, 3)\\n case 1 {\\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\\n }\\n case 2 {\\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\\n }\\n\\n mstore(result, encodedLen)\\n }\\n\\n return string(result);\\n }\\n}\\n\",\"keccak256\":\"0x55535e1e0a14bbac370fe5f25df23aa88c678b915af53517672130f9a54f7e3e\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610a2b806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f63696d65746572206c6010918401918201527f6f636b732c2063616e206265207573656420746f20626f6f737420676175676560308201527f207969656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c60508201527f20616e64207265636569766520627269626573222c2022696d616765223a202260708201527f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000609082015283516107718160aa840160208801610435565b61227d60f01b60aa929091019182015260ac01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212206beba50bd59595a890518a9080b7c214bc15efb61d69e2e84a9dde18a0ce8b0664736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f63696d65746572206c6010918401918201527f6f636b732c2063616e206265207573656420746f20626f6f737420676175676560308201527f207969656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c60508201527f20616e64207265636569766520627269626573222c2022696d616765223a202260708201527f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000609082015283516107718160aa840160208801610435565b61227d60f01b60aa929091019182015260ac01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212206beba50bd59595a890518a9080b7c214bc15efb61d69e2e84a9dde18a0ce8b0664736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/arbitrumOne/VelocimeterLibrary.json b/deployments/arbitrumOne/VelocimeterLibrary.json new file mode 100644 index 00000000..2b346abb --- /dev/null +++ b/deployments/arbitrumOne/VelocimeterLibrary.json @@ -0,0 +1,229 @@ +{ + "address": "0xfe873D4923b343F0D6BD98045a9C82D8dDEC511E", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_router", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getAmountOut", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getMinimumValue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getSample", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getTradeDiff", + "outputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "pair", + "type": "address" + } + ], + "name": "getTradeDiff", + "outputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xc919c4b01eba0c3723bcd8d8270941d15e976df506c6089fbad1db856248e17e", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0xfe873D4923b343F0D6BD98045a9C82D8dDEC511E", + "transactionIndex": 2, + "gasUsed": "6199193", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xd583e75c029e17593f34c157da62910008d69f3c40f7fec1f19defb2acbcd44d", + "transactionHash": "0xc919c4b01eba0c3723bcd8d8270941d15e976df506c6089fbad1db856248e17e", + "logs": [], + "blockNumber": 58032049, + "cumulativeGasUsed": "7479073", + "status": 1, + "byzantium": true + }, + "args": [ + "0x52A18b2386D6221Cf9DbcD4790456a23249e5279" + ], + "numDeployments": 1, + "solcInputHash": "816572db58a4a8203fcf6f77728173df", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getMinimumValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getSample\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"getTradeDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VelocimeterLibrary.sol\":\"VelocimeterLibrary\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735353339323034313033\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VelocimeterLibrary.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\n\\ncontract VelocimeterLibrary {\\n IRouter internal immutable router;\\n\\n constructor(address _router) {\\n router = IRouter(_router);\\n }\\n\\n function _f(uint x0, uint y) internal pure returns (uint) {\\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\\n }\\n\\n function _d(uint x0, uint y) internal pure returns (uint) {\\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\\n }\\n\\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\\n for (uint i = 0; i < 255; i++) {\\n uint y_prev = y;\\n uint k = _f(x0, y);\\n if (k < xy) {\\n uint dy = (xy - k)*1e18/_d(x0, y);\\n y = y + dy;\\n } else {\\n uint dy = (k - xy)*1e18/_d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\\n }\\n\\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\\n return (sample, r0, r1);\\n }\\n\\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\\n }\\n\\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\\n if (stable) {\\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\\n _reserve0 = _reserve0 * 1e18 / decimals0;\\n _reserve1 = _reserve1 * 1e18 / decimals1;\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\\n } else {\\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\\n return amountIn * reserveB / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\\n if (stable) {\\n uint _x = x * 1e18 / decimals0;\\n uint _y = y * 1e18 / decimals1;\\n uint _a = (_x * _y) / 1e18;\\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return _a * _b / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n \\n}\\n\",\"keccak256\":\"0x8fa888fd7bda7d3d44a2cc0fd62aeb594c767907f24e7cd390a5fe998d60f388\",\"license\":\"MIT\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"}},\"version\":1}", + "bytecode": "0x60a060405234801561001057600080fd5b5060405161100238038061100283398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051610f626100a06000396000818161010c015281816102730152818161043701526105cb0152610f626000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea2646970667358221220792878ccaa1ffb9f37b02a29e85a06e7a64a3ab2fabca685c4b98b1d383b18e064736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c8063525007331461005c578063865db5e21461008f578063be3b428e146100b7578063da214231146100d8578063ec323c00146100eb575b600080fd5b61006f61006a366004610d03565b6100fe565b604080519384526020840192909252908201526060015b60405180910390f35b6100a261009d366004610d4e565b610265565b60408051928352602083019190915201610086565b6100ca6100c5366004610d03565b61042a565b604051908152602001610086565b6100ca6100e6366004610d4e565b6105be565b6100a26100f9366004610da1565b610704565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b815260040161015a93929190610dd8565b602060405180830381865afa158015610177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019b9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610e19565b5095505094509450945094506000816001600160a01b03168c6001600160a01b03161461023d578361022e8785610ea3565b6102389190610ec2565b610252565b826102488686610ea3565b6102529190610ec2565b9c939b5091995091975050505050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8c8c8c6040518463ffffffff1660e01b81526004016102c193929190610dd8565b602060405180830381865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190610e19565b509550955095509550955095506000816001600160a01b03168c6001600160a01b0316146103a557846103968886610ea3565b6103a09190610ec2565b6103ba565b836103b08787610ea3565b6103ba9190610ec2565b9050806103cd828e8888878d8d8b610838565b6103df90670de0b6b3a7640000610ea3565b6103e99190610ec2565b98508c6103fc8e8e8888878d8d8b610838565b61040e90670de0b6b3a7640000610ea3565b6104189190610ec2565b97505050505050505094509492505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161048593929190610dd8565b602060405180830381865afa1580156104a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c69190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b031614610569578461055a8886610ea3565b6105649190610ec2565b61057e565b836105748787610ea3565b61057e9190610ec2565b905080610591828d8888878d8d8b610838565b6105a390670de0b6b3a7640000610ea3565b6105ad9190610ec2565b9750505050505050505b9392505050565b60008060008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634c1ee03e8b8b8b6040518463ffffffff1660e01b815260040161061993929190610dd8565b602060405180830381865afa158015610636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065a9190610dfc565b6001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610e19565b509550955095509550955095508a6106d98c8c8787868c8c8a610838565b6106eb90670de0b6b3a7640000610ea3565b6106f59190610ec2565b9b9a5050505050505050505050565b600080600080600080600080886001600160a01b031663392f37e96040518163ffffffff1660e01b815260040160e060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190610e19565b509550955095509550955095506000816001600160a01b03168b6001600160a01b0316146107b457846107a58886610ea3565b6107af9190610ec2565b6107c9565b836107bf8787610ea3565b6107c99190610ec2565b9050806107dc828d8888878d8d8b610838565b6107ee90670de0b6b3a7640000610ea3565b6107f89190610ec2565b98508b61080b8d8d8888878d8d8b610838565b61081d90670de0b6b3a7640000610ea3565b6108279190610ec2565b975050505050505050935093915050565b6000811561097e57600061084f88888588886109d8565b90508461086489670de0b6b3a7640000610ea3565b61086e9190610ec2565b97508361088388670de0b6b3a7640000610ea3565b61088d9190610ec2565b9650600080876001600160a01b03168b6001600160a01b0316146108b257888a6108b5565b89895b91509150876001600160a01b03168b6001600160a01b0316146108f457856108e58d670de0b6b3a7640000610ea3565b6108ef9190610ec2565b610911565b866109078d670de0b6b3a7640000610ea3565b6109119190610ec2565b9b506000610929610922848f610ee4565b8584610ac9565b6109339083610efc565b9050670de0b6b3a7640000896001600160a01b03168d6001600160a01b03161461095d578861095f565b875b6109699083610ea3565b6109739190610ec2565b9450505050506109cc565b600080866001600160a01b03168a6001600160a01b0316146109a15787896109a4565b88885b90925090506109b38b83610ee4565b6109bd828d610ea3565b6109c79190610ec2565b925050505b98975050505050505050565b60008315610ab3576000836109f588670de0b6b3a7640000610ea3565b6109ff9190610ec2565b9050600083610a1688670de0b6b3a7640000610ea3565b610a209190610ec2565b90506000670de0b6b3a7640000610a378385610ea3565b610a419190610ec2565b90506000670de0b6b3a7640000610a588480610ea3565b610a629190610ec2565b670de0b6b3a7640000610a758680610ea3565b610a7f9190610ec2565b610a899190610ee4565b9050670de0b6b3a7640000610a9e8284610ea3565b610aa89190610ec2565b945050505050610ac0565b610abd8587610ea3565b90505b95945050505050565b6000805b60ff811015610bcf57826000610ae38783610bd8565b905085811015610b33576000610af98887610c75565b610b038389610efc565b610b1590670de0b6b3a7640000610ea3565b610b1f9190610ec2565b9050610b2b8187610ee4565b955050610b75565b6000610b3f8887610c75565b610b498884610efc565b610b5b90670de0b6b3a7640000610ea3565b610b659190610ec2565b9050610b718187610efc565b9550505b81851115610b9e576001610b898387610efc565b11610b99578493505050506105b7565b610bba565b6001610baa8684610efc565b11610bba578493505050506105b7565b50508080610bc790610f13565b915050610acd565b50909392505050565b6000670de0b6b3a764000082818581610bf18280610ea3565b610bfb9190610ec2565b610c059190610ea3565b610c0f9190610ec2565b610c199190610ea3565b610c239190610ec2565b670de0b6b3a7640000808481610c398280610ea3565b610c439190610ec2565b610c4d9190610ea3565b610c579190610ec2565b610c619086610ea3565b610c6b9190610ec2565b6105b79190610ee4565b6000670de0b6b3a76400008381610c8c8280610ea3565b610c969190610ec2565b610ca09190610ea3565b610caa9190610ec2565b670de0b6b3a764000080610cbe8580610ea3565b610cc89190610ec2565b610cd3866003610ea3565b610c619190610ea3565b6001600160a01b0381168114610cf257600080fd5b50565b8015158114610cf257600080fd5b600080600060608486031215610d1857600080fd5b8335610d2381610cdd565b92506020840135610d3381610cdd565b91506040840135610d4381610cf5565b809150509250925092565b60008060008060808587031215610d6457600080fd5b843593506020850135610d7681610cdd565b92506040850135610d8681610cdd565b91506060850135610d9681610cf5565b939692955090935050565b600080600060608486031215610db657600080fd5b833592506020840135610dc881610cdd565b91506040840135610d4381610cdd565b6001600160a01b039384168152919092166020820152901515604082015260600190565b600060208284031215610e0e57600080fd5b81516105b781610cdd565b600080600080600080600060e0888a031215610e3457600080fd5b875196506020880151955060408801519450606088015193506080880151610e5b81610cf5565b60a0890151909350610e6c81610cdd565b60c0890151909250610e7d81610cdd565b8091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610ebd57610ebd610e8d565b500290565b600082610edf57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610ef757610ef7610e8d565b500190565b600082821015610f0e57610f0e610e8d565b500390565b600060018201610f2557610f25610e8d565b506001019056fea2646970667358221220792878ccaa1ffb9f37b02a29e85a06e7a64a3ab2fabca685c4b98b1d383b18e064736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/arbitrumOne/Voter.json b/deployments/arbitrumOne/Voter.json index 10fa498b..717da6d6 100644 --- a/deployments/arbitrumOne/Voter.json +++ b/deployments/arbitrumOne/Voter.json @@ -1,5 +1,5 @@ { - "address": "0x29C487a354D11315059204Df4F7d8AB1aa008ebb", + "address": "0x2862Bf1ADC96d485B6E85C062b170903DE9A2Bd5", "abi": [ { "inputs": [ @@ -1141,33 +1141,33 @@ "type": "function" } ], - "transactionHash": "0x6525dd63638ff4ed2b7e6556e27d3903e730609c0503ea6facd921de9c091e43", + "transactionHash": "0x6ce83e7ad5d102309efb3a54d6b379a5bcce7218756a507aad0c0fe1228f6ac8", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x29C487a354D11315059204Df4F7d8AB1aa008ebb", + "contractAddress": "0x2862Bf1ADC96d485B6E85C062b170903DE9A2Bd5", "transactionIndex": 1, - "gasUsed": "21064022", + "gasUsed": "21090155", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x52e0ff5d75dfe71eff1e0a08b81f63681b1af7d28d6d0b1d0a83bdf04a49458c", - "transactionHash": "0x6525dd63638ff4ed2b7e6556e27d3903e730609c0503ea6facd921de9c091e43", + "blockHash": "0x9eef43e5bae2e6ddc3ce3985dac30acd1664cdbfa05d5325050adaf477343f4e", + "transactionHash": "0x6ce83e7ad5d102309efb3a54d6b379a5bcce7218756a507aad0c0fe1228f6ac8", "logs": [], - "blockNumber": 53774108, - "cumulativeGasUsed": "21064022", + "blockNumber": 58032097, + "cumulativeGasUsed": "21090155", "status": 1, "byzantium": true }, "args": [ - "0x10Df81252069C1095F541FAca61646cb9Ae76703", - "0xA2db791281CdeeBb1EEDc78a34989df2Bfd479bE", - "0x2CCb061AD1b50211cF79f33e690452497941a2fe", - "0xBcC3c06e1D22E44Ac807D76A887fFB40765e0D16" + "0xfa01adbAA40f0EEeCEA76b7B18AC8bE064536787", + "0x9f7fdaB9317f1442808B90B819Ed0a4eF4f74994", + "0x2B0BB6962e89bD5FE9510Ff09Af8D709be21AAD7", + "0xf4F344Cfa1A82eDD37C96E879f01D9CA03f385b9" ], "numDeployments": 1, - "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_gauges\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_bribes\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Abstained\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Attach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Detach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributeReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"internal_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"external_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"name\":\"GaugeCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeKilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeRevived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"reward\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NotifyReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Voted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"whitelister\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"Whitelisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"attachTokenToGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bribefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_bribes\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimBribes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_fees\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"}],\"name\":\"claimRewards\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"detachTokenFromGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"finish\",\"type\":\"uint256\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distributeFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distro\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"emergencyCouncil\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"external_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gaugefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"gauges\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_tokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"internal_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isAlive\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isGauge\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isWhitelisted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"killGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"lastVoted\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"length\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"notifyRewardAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"poke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolForGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"poolVote\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"reset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"reviveGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_council\",\"type\":\"address\"}],\"name\":\"setEmergencyCouncil\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"setGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalWeight\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"updateFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"name\":\"updateForRange\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"updateGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedWeights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"_poolVote\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_weights\",\"type\":\"uint256[]\"}],\"name\":\"vote\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"votes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"weights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"whitelist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Voter.sol\":\"Voter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Voter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/libraries/Math.sol';\\nimport 'contracts/interfaces/IBribe.sol';\\nimport 'contracts/interfaces/IBribeFactory.sol';\\nimport 'contracts/interfaces/IGauge.sol';\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/interfaces/IERC20.sol';\\nimport 'contracts/interfaces/IMinter.sol';\\nimport 'contracts/interfaces/IPair.sol';\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/interfaces/IVoter.sol';\\nimport 'contracts/interfaces/IVotingEscrow.sol';\\n\\ncontract Voter is IVoter {\\n\\n address public immutable _ve; // the ve token that governs these contracts\\n address public immutable factory; // the PairFactory\\n address internal immutable base;\\n address public immutable gaugefactory;\\n address public immutable bribefactory;\\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\\n address public minter;\\n address public governor; // should be set to an IGovernor\\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\\n\\n uint public totalWeight; // total voting weight\\n\\n address[] public pools; // all pools viable for incentives\\n mapping(address => address) public gauges; // pool => gauge\\n mapping(address => address) public poolForGauge; // gauge => pool\\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\\n mapping(address => uint256) public weights; // pool => weight\\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\\n mapping(uint => address[]) public poolVote; // nft => pools\\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\\n mapping(address => bool) public isGauge;\\n mapping(address => bool) public isWhitelisted;\\n mapping(address => bool) public isAlive;\\n\\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\\n event GaugeKilled(address indexed gauge);\\n event GaugeRevived(address indexed gauge);\\n event Voted(address indexed voter, uint tokenId, uint256 weight);\\n event Abstained(uint tokenId, uint256 weight);\\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\\n event Whitelisted(address indexed whitelister, address indexed token);\\n\\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\\n _ve = __ve;\\n factory = _factory;\\n base = IVotingEscrow(__ve).token();\\n gaugefactory = _gauges;\\n bribefactory = _bribes;\\n minter = msg.sender;\\n governor = msg.sender;\\n emergencyCouncil = msg.sender;\\n }\\n\\n // simple re-entrancy check\\n uint internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n modifier onlyNewEpoch(uint _tokenId) {\\n // ensure new epoch since last vote \\n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \\\"TOKEN_ALREADY_VOTED_THIS_EPOCH\\\");\\n _;\\n }\\n\\n function initialize(address[] memory _tokens, address _minter) external {\\n require(msg.sender == minter);\\n for (uint i = 0; i < _tokens.length; i++) {\\n _whitelist(_tokens[i]);\\n }\\n minter = _minter;\\n }\\n\\n function setGovernor(address _governor) public {\\n require(msg.sender == governor);\\n governor = _governor;\\n }\\n\\n function setEmergencyCouncil(address _council) public {\\n require(msg.sender == emergencyCouncil);\\n emergencyCouncil = _council;\\n }\\n\\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n lastVoted[_tokenId] = block.timestamp;\\n _reset(_tokenId);\\n IVotingEscrow(_ve).abstain(_tokenId);\\n }\\n\\n function _reset(uint _tokenId) internal {\\n address[] storage _poolVote = poolVote[_tokenId];\\n uint _poolVoteCnt = _poolVote.length;\\n uint256 _totalWeight = 0;\\n\\n for (uint i = 0; i < _poolVoteCnt; i ++) {\\n address _pool = _poolVote[i];\\n uint256 _votes = votes[_tokenId][_pool];\\n\\n if (_votes != 0) {\\n _updateFor(gauges[_pool]);\\n weights[_pool] -= _votes;\\n votes[_tokenId][_pool] -= _votes;\\n if (_votes > 0) {\\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n _totalWeight += _votes;\\n } else {\\n _totalWeight -= _votes;\\n }\\n emit Abstained(_tokenId, _votes);\\n }\\n }\\n totalWeight -= uint256(_totalWeight);\\n usedWeights[_tokenId] = 0;\\n delete poolVote[_tokenId];\\n }\\n\\n function poke(uint _tokenId) external {\\n address[] memory _poolVote = poolVote[_tokenId];\\n uint _poolCnt = _poolVote.length;\\n uint256[] memory _weights = new uint256[](_poolCnt);\\n\\n for (uint i = 0; i < _poolCnt; i ++) {\\n _weights[i] = votes[_tokenId][_poolVote[i]];\\n }\\n\\n _vote(_tokenId, _poolVote, _weights);\\n }\\n\\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\\n _reset(_tokenId);\\n uint _poolCnt = _poolVote.length;\\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\\n uint256 _totalVoteWeight = 0;\\n uint256 _totalWeight = 0;\\n uint256 _usedWeight = 0;\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n _totalVoteWeight += _weights[i];\\n }\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n address _pool = _poolVote[i];\\n address _gauge = gauges[_pool];\\n\\n if (isGauge[_gauge]) {\\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\\n require(votes[_tokenId][_pool] == 0);\\n require(_poolWeight != 0);\\n _updateFor(_gauge);\\n\\n poolVote[_tokenId].push(_pool);\\n\\n weights[_pool] += _poolWeight;\\n votes[_tokenId][_pool] += _poolWeight;\\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n _usedWeight += _poolWeight;\\n _totalWeight += _poolWeight;\\n emit Voted(msg.sender, _tokenId, _poolWeight);\\n }\\n }\\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\\n totalWeight += uint256(_totalWeight);\\n usedWeights[_tokenId] = uint256(_usedWeight);\\n }\\n\\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n require(_poolVote.length == _weights.length);\\n lastVoted[tokenId] = block.timestamp;\\n _vote(tokenId, _poolVote, _weights);\\n }\\n\\n function whitelist(address _token) public {\\n require(msg.sender == governor);\\n _whitelist(_token);\\n }\\n\\n function _whitelist(address _token) internal {\\n require(!isWhitelisted[_token]);\\n isWhitelisted[_token] = true;\\n emit Whitelisted(msg.sender, _token);\\n }\\n\\n function createGauge(address _pool) external returns (address) {\\n require(gauges[_pool] == address(0x0), \\\"exists\\\");\\n address[] memory allowedRewards = new address[](3);\\n address[] memory internalRewards = new address[](2);\\n bool isPair = IPairFactory(factory).isPair(_pool);\\n address tokenA;\\n address tokenB;\\n\\n if (isPair) {\\n (tokenA, tokenB) = IPair(_pool).tokens();\\n allowedRewards[0] = tokenA;\\n allowedRewards[1] = tokenB;\\n internalRewards[0] = tokenA;\\n internalRewards[1] = tokenB;\\n\\n if (base != tokenA && base != tokenB) {\\n allowedRewards[2] = base;\\n }\\n }\\n\\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\\n require(isPair, \\\"!_pool\\\");\\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \\\"!whitelisted\\\");\\n }\\n\\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\\n\\n IERC20(base).approve(_gauge, type(uint).max);\\n internal_bribes[_gauge] = _internal_bribe;\\n external_bribes[_gauge] = _external_bribe;\\n gauges[_pool] = _gauge;\\n poolForGauge[_gauge] = _pool;\\n isGauge[_gauge] = true;\\n isAlive[_gauge] = true;\\n _updateFor(_gauge);\\n pools.push(_pool);\\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\\n return _gauge;\\n }\\n\\n function killGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(isAlive[_gauge], \\\"gauge already dead\\\");\\n isAlive[_gauge] = false;\\n claimable[_gauge] = 0;\\n emit GaugeKilled(_gauge);\\n }\\n\\n function reviveGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(!isAlive[_gauge], \\\"gauge already alive\\\");\\n isAlive[_gauge] = true;\\n emit GaugeRevived(_gauge);\\n }\\n\\n function attachTokenToGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\\n emit Attach(account, msg.sender, tokenId);\\n }\\n\\n function emitDeposit(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]);\\n emit Deposit(account, msg.sender, tokenId, amount);\\n }\\n\\n function detachTokenFromGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\\n emit Detach(account, msg.sender, tokenId);\\n }\\n\\n function emitWithdraw(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n emit Withdraw(account, msg.sender, tokenId, amount);\\n }\\n\\n function length() external view returns (uint) {\\n return pools.length;\\n }\\n\\n uint internal index;\\n mapping(address => uint) internal supplyIndex;\\n mapping(address => uint) public claimable;\\n\\n function notifyRewardAmount(uint amount) external {\\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index += _ratio;\\n }\\n emit NotifyReward(msg.sender, base, amount);\\n }\\n\\n function updateFor(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n _updateFor(_gauges[i]);\\n }\\n }\\n\\n function updateForRange(uint start, uint end) public {\\n for (uint i = start; i < end; i++) {\\n _updateFor(gauges[pools[i]]);\\n }\\n }\\n\\n function updateAll() external {\\n updateForRange(0, pools.length);\\n }\\n\\n function updateGauge(address _gauge) external {\\n _updateFor(_gauge);\\n }\\n\\n function _updateFor(address _gauge) internal {\\n address _pool = poolForGauge[_gauge];\\n uint256 _supplied = weights[_pool];\\n if (_supplied > 0) {\\n uint _supplyIndex = supplyIndex[_gauge];\\n uint _index = index; // get global index0 for accumulated distro\\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\\n if (_delta > 0) {\\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\\n if (isAlive[_gauge]) {\\n claimable[_gauge] += _share;\\n }\\n }\\n } else {\\n supplyIndex[_gauge] = index; // new users are set to the default global state\\n }\\n }\\n\\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\\n }\\n }\\n\\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _bribes.length; i++) {\\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _fees.length; i++) {\\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function distributeFees(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n if (IGauge(_gauges[i]).isForPair()){\\n IGauge(_gauges[i]).claimFees();\\n }\\n }\\n }\\n\\n function distribute(address _gauge) public lock {\\n IMinter(minter).update_period();\\n _updateFor(_gauge); // should set claimable to 0 if killed\\n uint _claimable = claimable[_gauge];\\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\\n claimable[_gauge] = 0;\\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\\n emit DistributeReward(msg.sender, _gauge, _claimable);\\n }\\n }\\n\\n function distro() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute(uint start, uint finish) public {\\n for (uint x = start; x < finish; x++) {\\n distribute(gauges[pools[x]]);\\n }\\n }\\n\\n function distribute(address[] memory _gauges) external {\\n for (uint x = 0; x < _gauges.length; x++) {\\n distribute(_gauges[x]);\\n }\\n }\\n\\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2ff3fc2765dfa0c54870e428d3a2c625f413fb6e10ed7742e786ab4404aae6dc\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x61012060405260016011553480156200001757600080fd5b5060405162003656380380620036568339810160408190526200003a916200011c565b6001600160a01b03808516608081905290841660a05260408051637e062a3560e11b8152905163fc0c546a916004808201926020929091908290030181865afa1580156200008c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b2919062000179565b6001600160a01b0390811660c05291821660e0521661010052505060008054336001600160a01b03199182168117909255600180548216831790556002805490911690911790556200019e565b80516001600160a01b03811681146200011757600080fd5b919050565b600080600080608085870312156200013357600080fd5b6200013e85620000ff565b93506200014e60208601620000ff565b92506200015e60408601620000ff565b91506200016e60608601620000ff565b905092959194509250565b6000602082840312156200018c57600080fd5b6200019782620000ff565b9392505050565b60805160a05160c05160e051610100516133e062000276600039600081816103e701528181611c680152611ce60152600081816104d30152611d79015260008181610b9401528181610c0d01528181610edd01528181610f9901528181611acd01528181611b0601528181611b380152611e5a0152600081816106fc015261192401526000818161058c0152818161092b015281816109d701528181610c9a01528181611069015281816111ea0152818161131a015281816114d901528181611dab015281816125e501526129a801526133e06000f3fe608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea26469706673582212202ba017d0b62c0f1d47ae8bb31cfdd049608b388bc02e3c268f1b267d8dd357d564736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea26469706673582212202ba017d0b62c0f1d47ae8bb31cfdd049608b388bc02e3c268f1b267d8dd357d564736f6c634300080d0033", + "solcInputHash": "816572db58a4a8203fcf6f77728173df", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_gauges\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_bribes\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Abstained\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Attach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Detach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributeReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"internal_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"external_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"name\":\"GaugeCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeKilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeRevived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"reward\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NotifyReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Voted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"whitelister\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"Whitelisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"attachTokenToGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bribefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_bribes\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimBribes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_fees\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"}],\"name\":\"claimRewards\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"detachTokenFromGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"finish\",\"type\":\"uint256\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distributeFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distro\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"emergencyCouncil\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"external_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gaugefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"gauges\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_tokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"internal_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isAlive\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isGauge\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isWhitelisted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"killGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"lastVoted\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"length\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"notifyRewardAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"poke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolForGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"poolVote\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"reset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"reviveGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_council\",\"type\":\"address\"}],\"name\":\"setEmergencyCouncil\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"setGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalWeight\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"updateFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"name\":\"updateForRange\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"updateGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedWeights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"_poolVote\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_weights\",\"type\":\"uint256[]\"}],\"name\":\"vote\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"votes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"weights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"whitelist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Voter.sol\":\"Voter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735353339323034313033\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Voter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IBribeFactory.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IGaugeFactory.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IMinter.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairFactory.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\ncontract Voter is IVoter {\\n address public immutable _ve; // the ve token that governs these contracts\\n address public immutable factory; // the PairFactory\\n address internal immutable base;\\n address public immutable gaugefactory;\\n address public immutable bribefactory;\\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\\n address public minter;\\n address public governor; // should be set to an IGovernor\\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\\n\\n uint256 public totalWeight; // total voting weight\\n\\n address[] public pools; // all pools viable for incentives\\n mapping(address => address) public gauges; // pool => gauge\\n mapping(address => address) public poolForGauge; // gauge => pool\\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\\n mapping(address => uint256) public weights; // pool => weight\\n mapping(uint256 => mapping(address => uint256)) public votes; // nft => pool => votes\\n mapping(uint256 => address[]) public poolVote; // nft => pools\\n mapping(uint256 => uint256) public usedWeights; // nft => total voting weight of user\\n mapping(uint256 => uint256) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\\n mapping(address => bool) public isGauge;\\n mapping(address => bool) public isWhitelisted;\\n mapping(address => bool) public isAlive;\\n\\n event GaugeCreated(\\n address indexed gauge,\\n address creator,\\n address internal_bribe,\\n address indexed external_bribe,\\n address indexed pool\\n );\\n event GaugeKilled(address indexed gauge);\\n event GaugeRevived(address indexed gauge);\\n event Voted(address indexed voter, uint256 tokenId, uint256 weight);\\n event Abstained(uint256 tokenId, uint256 weight);\\n event Deposit(\\n address indexed lp,\\n address indexed gauge,\\n uint256 tokenId,\\n uint256 amount\\n );\\n event Withdraw(\\n address indexed lp,\\n address indexed gauge,\\n uint256 tokenId,\\n uint256 amount\\n );\\n event NotifyReward(\\n address indexed sender,\\n address indexed reward,\\n uint256 amount\\n );\\n event DistributeReward(\\n address indexed sender,\\n address indexed gauge,\\n uint256 amount\\n );\\n event Attach(address indexed owner, address indexed gauge, uint256 tokenId);\\n event Detach(address indexed owner, address indexed gauge, uint256 tokenId);\\n event Whitelisted(address indexed whitelister, address indexed token);\\n\\n constructor(\\n address __ve,\\n address _factory,\\n address _gauges,\\n address _bribes\\n ) {\\n _ve = __ve;\\n factory = _factory;\\n base = IVotingEscrow(__ve).token();\\n gaugefactory = _gauges;\\n bribefactory = _bribes;\\n minter = msg.sender;\\n governor = msg.sender;\\n emergencyCouncil = msg.sender;\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n modifier onlyNewEpoch(uint256 _tokenId) {\\n // ensure new epoch since last vote\\n require(\\n (block.timestamp / DURATION) * DURATION > lastVoted[_tokenId],\\n \\\"TOKEN_ALREADY_VOTED_THIS_EPOCH\\\"\\n );\\n _;\\n }\\n\\n function initialize(address[] memory _tokens, address _minter) external {\\n require(msg.sender == minter);\\n for (uint256 i = 0; i < _tokens.length; i++) {\\n _whitelist(_tokens[i]);\\n }\\n minter = _minter;\\n }\\n\\n function setGovernor(address _governor) public {\\n require(msg.sender == governor);\\n governor = _governor;\\n }\\n\\n function setEmergencyCouncil(address _council) public {\\n require(msg.sender == emergencyCouncil);\\n emergencyCouncil = _council;\\n }\\n\\n function reset(uint256 _tokenId) external onlyNewEpoch(_tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n lastVoted[_tokenId] = block.timestamp;\\n _reset(_tokenId);\\n IVotingEscrow(_ve).abstain(_tokenId);\\n }\\n\\n function _reset(uint256 _tokenId) internal {\\n address[] storage _poolVote = poolVote[_tokenId];\\n uint256 _poolVoteCnt = _poolVote.length;\\n uint256 _totalWeight = 0;\\n\\n for (uint256 i = 0; i < _poolVoteCnt; i++) {\\n address _pool = _poolVote[i];\\n uint256 _votes = votes[_tokenId][_pool];\\n\\n if (_votes != 0) {\\n _updateFor(gauges[_pool]);\\n weights[_pool] -= _votes;\\n votes[_tokenId][_pool] -= _votes;\\n if (_votes > 0) {\\n IBribe(internal_bribes[gauges[_pool]])._withdraw(\\n uint256(_votes),\\n _tokenId\\n );\\n IBribe(external_bribes[gauges[_pool]])._withdraw(\\n uint256(_votes),\\n _tokenId\\n );\\n _totalWeight += _votes;\\n } else {\\n _totalWeight -= _votes;\\n }\\n emit Abstained(_tokenId, _votes);\\n }\\n }\\n totalWeight -= uint256(_totalWeight);\\n usedWeights[_tokenId] = 0;\\n delete poolVote[_tokenId];\\n }\\n\\n // remove poke function\\n\\n function poke(uint256 _tokenId) external {\\n require(\\n IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId) ||\\n msg.sender == governor\\n );\\n address[] memory _poolVote = poolVote[_tokenId];\\n uint256 _poolCnt = _poolVote.length;\\n uint256[] memory _weights = new uint256[](_poolCnt);\\n\\n for (uint256 i = 0; i < _poolCnt; i++) {\\n _weights[i] = votes[_tokenId][_poolVote[i]];\\n }\\n\\n _vote(_tokenId, _poolVote, _weights);\\n }\\n\\n function _vote(\\n uint256 _tokenId,\\n address[] memory _poolVote,\\n uint256[] memory _weights\\n ) internal {\\n _reset(_tokenId);\\n uint256 _poolCnt = _poolVote.length;\\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\\n uint256 _totalVoteWeight = 0;\\n uint256 _totalWeight = 0;\\n uint256 _usedWeight = 0;\\n\\n for (uint256 i = 0; i < _poolCnt; i++) {\\n _totalVoteWeight += _weights[i];\\n }\\n\\n for (uint256 i = 0; i < _poolCnt; i++) {\\n address _pool = _poolVote[i];\\n address _gauge = gauges[_pool];\\n\\n if (isGauge[_gauge]) {\\n uint256 _poolWeight = (_weights[i] * _weight) /\\n _totalVoteWeight;\\n require(votes[_tokenId][_pool] == 0);\\n require(_poolWeight != 0);\\n _updateFor(_gauge);\\n\\n poolVote[_tokenId].push(_pool);\\n\\n weights[_pool] += _poolWeight;\\n votes[_tokenId][_pool] += _poolWeight;\\n IBribe(internal_bribes[_gauge])._deposit(\\n uint256(_poolWeight),\\n _tokenId\\n );\\n IBribe(external_bribes[_gauge])._deposit(\\n uint256(_poolWeight),\\n _tokenId\\n );\\n _usedWeight += _poolWeight;\\n _totalWeight += _poolWeight;\\n emit Voted(msg.sender, _tokenId, _poolWeight);\\n }\\n }\\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\\n totalWeight += uint256(_totalWeight);\\n usedWeights[_tokenId] = uint256(_usedWeight);\\n }\\n\\n function vote(\\n uint256 tokenId,\\n address[] calldata _poolVote,\\n uint256[] calldata _weights\\n ) external onlyNewEpoch(tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n require(_poolVote.length == _weights.length);\\n lastVoted[tokenId] = block.timestamp;\\n _vote(tokenId, _poolVote, _weights);\\n }\\n\\n function whitelist(address _token) public {\\n require(msg.sender == governor);\\n _whitelist(_token);\\n }\\n\\n function _whitelist(address _token) internal {\\n require(!isWhitelisted[_token]);\\n isWhitelisted[_token] = true;\\n emit Whitelisted(msg.sender, _token);\\n }\\n\\n function createGauge(address _pool) external returns (address) {\\n require(gauges[_pool] == address(0x0), \\\"exists\\\");\\n address[] memory allowedRewards = new address[](3);\\n address[] memory internalRewards = new address[](2);\\n bool isPair = IPairFactory(factory).isPair(_pool);\\n address tokenA;\\n address tokenB;\\n\\n if (isPair) {\\n (tokenA, tokenB) = IPair(_pool).tokens();\\n allowedRewards[0] = tokenA;\\n allowedRewards[1] = tokenB;\\n internalRewards[0] = tokenA;\\n internalRewards[1] = tokenB;\\n\\n if (base != tokenA && base != tokenB) {\\n allowedRewards[2] = base;\\n }\\n }\\n\\n if (msg.sender != governor) {\\n // gov can create for any pool, even non-Velocimeter pairs\\n require(isPair, \\\"!_pool\\\");\\n require(\\n isWhitelisted[tokenA] && isWhitelisted[tokenB],\\n \\\"!whitelisted\\\"\\n );\\n }\\n\\n address _internal_bribe = IBribeFactory(bribefactory)\\n .createInternalBribe(internalRewards);\\n address _external_bribe = IBribeFactory(bribefactory)\\n .createExternalBribe(allowedRewards);\\n address _gauge = IGaugeFactory(gaugefactory).createGauge(\\n _pool,\\n _internal_bribe,\\n _external_bribe,\\n _ve,\\n isPair,\\n allowedRewards\\n );\\n\\n IERC20(base).approve(_gauge, type(uint256).max);\\n internal_bribes[_gauge] = _internal_bribe;\\n external_bribes[_gauge] = _external_bribe;\\n gauges[_pool] = _gauge;\\n poolForGauge[_gauge] = _pool;\\n isGauge[_gauge] = true;\\n isAlive[_gauge] = true;\\n _updateFor(_gauge);\\n pools.push(_pool);\\n emit GaugeCreated(\\n _gauge,\\n msg.sender,\\n _internal_bribe,\\n _external_bribe,\\n _pool\\n );\\n return _gauge;\\n }\\n\\n function killGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(isAlive[_gauge], \\\"gauge already dead\\\");\\n isAlive[_gauge] = false;\\n claimable[_gauge] = 0;\\n emit GaugeKilled(_gauge);\\n }\\n\\n function reviveGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(!isAlive[_gauge], \\\"gauge already alive\\\");\\n isAlive[_gauge] = true;\\n emit GaugeRevived(_gauge);\\n }\\n\\n function attachTokenToGauge(uint256 tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\\n emit Attach(account, msg.sender, tokenId);\\n }\\n\\n function emitDeposit(\\n uint256 tokenId,\\n address account,\\n uint256 amount\\n ) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]);\\n emit Deposit(account, msg.sender, tokenId, amount);\\n }\\n\\n function detachTokenFromGauge(uint256 tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\\n emit Detach(account, msg.sender, tokenId);\\n }\\n\\n function emitWithdraw(\\n uint256 tokenId,\\n address account,\\n uint256 amount\\n ) external {\\n require(isGauge[msg.sender]);\\n emit Withdraw(account, msg.sender, tokenId, amount);\\n }\\n\\n function length() external view returns (uint256) {\\n return pools.length;\\n }\\n\\n uint256 internal index;\\n mapping(address => uint256) internal supplyIndex;\\n mapping(address => uint256) public claimable;\\n\\n function notifyRewardAmount(uint256 amount) external {\\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\\n uint256 _ratio = (amount * 1e18) / totalWeight; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index += _ratio;\\n }\\n emit NotifyReward(msg.sender, base, amount);\\n }\\n\\n function updateFor(address[] memory _gauges) external {\\n for (uint256 i = 0; i < _gauges.length; i++) {\\n _updateFor(_gauges[i]);\\n }\\n }\\n\\n function updateForRange(uint256 start, uint256 end) public {\\n for (uint256 i = start; i < end; i++) {\\n _updateFor(gauges[pools[i]]);\\n }\\n }\\n\\n function updateAll() external {\\n updateForRange(0, pools.length);\\n }\\n\\n function updateGauge(address _gauge) external {\\n _updateFor(_gauge);\\n }\\n\\n function _updateFor(address _gauge) internal {\\n address _pool = poolForGauge[_gauge];\\n uint256 _supplied = weights[_pool];\\n if (_supplied > 0) {\\n uint256 _supplyIndex = supplyIndex[_gauge];\\n uint256 _index = index; // get global index0 for accumulated distro\\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\\n uint256 _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\\n if (_delta > 0) {\\n uint256 _share = (uint256(_supplied) * _delta) / 1e18; // add accrued difference for each supplied token\\n if (isAlive[_gauge]) {\\n claimable[_gauge] += _share;\\n }\\n }\\n } else {\\n supplyIndex[_gauge] = index; // new users are set to the default global state\\n }\\n }\\n\\n function claimRewards(address[] memory _gauges, address[][] memory _tokens)\\n external\\n {\\n for (uint256 i = 0; i < _gauges.length; i++) {\\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\\n }\\n }\\n\\n function claimBribes(\\n address[] memory _bribes,\\n address[][] memory _tokens,\\n uint256 _tokenId\\n ) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint256 i = 0; i < _bribes.length; i++) {\\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function claimFees(\\n address[] memory _fees,\\n address[][] memory _tokens,\\n uint256 _tokenId\\n ) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint256 i = 0; i < _fees.length; i++) {\\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function distributeFees(address[] memory _gauges) external {\\n for (uint256 i = 0; i < _gauges.length; i++) {\\n if (IGauge(_gauges[i]).isForPair()) {\\n IGauge(_gauges[i]).claimFees();\\n }\\n }\\n }\\n\\n function distribute(address _gauge) public lock {\\n IMinter(minter).update_period();\\n _updateFor(_gauge); // should set claimable to 0 if killed\\n uint256 _claimable = claimable[_gauge];\\n if (\\n _claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0\\n ) {\\n claimable[_gauge] = 0;\\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\\n emit DistributeReward(msg.sender, _gauge, _claimable);\\n }\\n }\\n\\n function distro() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute(uint256 start, uint256 finish) public {\\n for (uint256 x = start; x < finish; x++) {\\n distribute(gauges[pools[x]]);\\n }\\n }\\n\\n function distribute(address[] memory _gauges) external {\\n for (uint256 x = 0; x < _gauges.length; x++) {\\n distribute(_gauges[x]);\\n }\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0xe4fe11e5be64cff367b06b35f2496e33c3ee4a33cae4243f9076fc1fd35014b9\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3546b156d97633f7f8cad536d5454c81d1d604687c02b2eb105fdc33cb962b41\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x61012060405260016011553480156200001757600080fd5b506040516200370a3803806200370a8339810160408190526200003a916200011c565b6001600160a01b03808516608081905290841660a05260408051637e062a3560e11b8152905163fc0c546a916004808201926020929091908290030181865afa1580156200008c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b2919062000179565b6001600160a01b0390811660c05291821660e0521661010052505060008054336001600160a01b03199182168117909255600180548216831790556002805490911690911790556200019e565b80516001600160a01b03811681146200011757600080fd5b919050565b600080600080608085870312156200013357600080fd5b6200013e85620000ff565b93506200014e60208601620000ff565b92506200015e60408601620000ff565b91506200016e60608601620000ff565b905092959194509250565b6000602082840312156200018c57600080fd5b6200019782620000ff565b9392505050565b60805160a05160c05160e0516101005161348d6200027d600039600081816103e701528181611d150152611d930152600081816104d30152611e26015260008181610c4101528181610cba01528181610f8a0152818161104601528181611b7a01528181611bb301528181611be50152611f070152600081816106fc01526119d101526000818161058c0152818161092b015281816109d701528181610a5b01528181610d470152818161111601528181611297015281816113c70152818161158601528181611e58015281816126920152612a55015261348d6000f3fe608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612d97565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612d97565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612f1a565b6107de565b005b6103ba6103ca366004612f7e565b610894565b6103ba6103dd366004612f7e565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612d97565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612f7e565b610c3c565b61039961044d366004612d97565b60146020526000908152604090205481565b6103ba61046d366004612f97565b610d0f565b6103ba610480366004612fc7565b610de9565b6103ba610e64565b6103ba610e75565b6103ba6104a336600461300e565b610e84565b6103ba6104b6366004612d97565b610ec8565b6103ba6104c936600461304b565b6110fa565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612f97565b611243565b6103ba610516366004612d97565b611339565b6103ba6105293660046130b8565b611345565b6103ba61053c36600461304b565b6113ab565b60025461031f906001600160a01b031681565b610399610562366004612f7e565b600c6020526000908152604090205481565b6103ba610582366004613126565b6114f4565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612d97565b61168c565b6103ba6105d8366004612d97565b611791565b6103ba6105eb3660046130b8565b6117b1565b6103ba6105fe366004612d97565b611817565b61031f610611366004612d97565b611914565b6103ba6106243660046131a0565b6120b3565b610399610637366004612d97565b60096020526000908152604090205481565b61031f6106573660046130b8565b612137565b61038561066a366004612d97565b600e6020526000908152604090205460ff1681565b61031f61068d366004612f7e565b61216f565b61031f6106a0366004612d97565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612d97565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612d97565b612199565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c36600461300e565b6121d2565b61039961073f366004612f97565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a36600461300e565b6122ef565b6103ba61077d366004612d97565b61232f565b6103ba6107903660046131a0565b612368565b61031f6107a3366004612d97565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612f7e565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc6131d8565b60200260200101516001600160a01b03166331279d3d33848481518110610825576108256131d8565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613232565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b5050505080806108879061326c565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b38142613285565b6108bd91906132a7565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e91906132c6565b6109a757600080fd5b6000828152600d602052604090204290556109c1826123c7565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015610aaa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ace91906132c6565b80610ae357506001546001600160a01b031633145b610aec57600080fd5b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610b4c57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610b2e575b5050505050905060008151905060008167ffffffffffffffff811115610b7457610b74612dbb565b604051908082528060200260200182016040528015610b9d578160200160208202803683370190505b50905060005b82811015610c2a57600a60008681526020019081526020016000206000858381518110610bd257610bd26131d8565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610c0d57610c0d6131d8565b602090810291909101015280610c228161326c565b915050610ba3565b50610c3684848361266e565b50505050565b610c687f0000000000000000000000000000000000000000000000000000000000000000333084612aec565b600354600090610c8083670de0b6b3a76400006132a7565b610c8a9190613285565b90508015610caa578060126000828254610ca491906132e8565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610d2b57600080fd5b8115610dac57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610d9357600080fd5b505af1158015610da7573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610d03565b6000546001600160a01b03163314610e0057600080fd5b60005b8251811015610e4057610e2e838281518110610e2157610e216131d8565b6020026020010151612bdc565b80610e388161326c565b915050610e03565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610e7390600090611345565b565b600454610e73906000906117b1565b60005b8151811015610ec457610eb2828281518110610ea557610ea56131d8565b6020026020010151610ec8565b80610ebc8161326c565b915050610e87565b5050565b601154600114610ed757600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610f32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f569190613300565b50610f6081612c4f565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610fd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ffc9190613300565b811180156110165750600061101462093a8083613285565b115b156110f1576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b15801561109857600080fd5b505af11580156110ac573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611165573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061118991906132c6565b61119257600080fd5b60005b8351811015610c36578381815181106111b0576111b06131d8565b60200260200101516001600160a01b031663a7852afa838584815181106111d9576111d96131d8565b60200260200101516040518363ffffffff1660e01b81526004016111fe929190613319565b600060405180830381600087803b15801561121857600080fd5b505af115801561122c573d6000803e3d6000fd5b50505050808061123b9061326c565b915050611195565b336000908152600e602052604090205460ff1661125f57600080fd5b3360009081526010602052604090205460ff1661127b57600080fd5b81156112fc5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b1580156112e357600080fd5b505af11580156112f7573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610d03565b61134281612c4f565b50565b815b8181101561088f576113996005600060048481548110611369576113696131d8565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610ec8565b806113a38161326c565b915050611347565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611416573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061143a91906132c6565b61144357600080fd5b60005b8351811015610c3657838181518110611461576114616131d8565b60200260200101516001600160a01b031663a7852afa8385848151811061148a5761148a6131d8565b60200260200101516040518363ffffffff1660e01b81526004016114af929190613319565b600060405180830381600087803b1580156114c957600080fd5b505af11580156114dd573d6000803e3d6000fd5b5050505080806114ec9061326c565b915050611446565b6000858152600d6020526040902054859062093a806115138142613285565b61151d91906132a7565b1161156a5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156115d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115f991906132c6565b61160257600080fd5b83821461160e57600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a0282810182019093528982529093508992508891829185019084908082843760009201919091525061266e92505050565b6002546001600160a01b031633146116de5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661173b5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146117a857600080fd5b61134281612bdc565b815b8181101561088f5761180560056000600484815481106117d5576117d56131d8565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612c4f565b8061180f8161326c565b9150506117b3565b6002546001600160a01b031633146118695760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff16156118c85760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156119675760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa158015611a18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3c91906132c6565b90506000808215611c3857866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015611a86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aaa9190613332565b80925081935050508185600081518110611ac657611ac66131d8565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611afa57611afa6131d8565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611b2e57611b2e6131d8565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611b6257611b626131d8565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611bde5750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611c38577f000000000000000000000000000000000000000000000000000000000000000085600281518110611c1757611c176131d8565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611cfb5782611c805760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611cc057506001600160a01b0381166000908152600f602052604090205460ff165b611cfb5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611d4a908890600401613361565b6020604051808303816000875af1158015611d69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d8d9190613374565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611ddd9190613361565b6020604051808303816000875af1158015611dfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e209190613374565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611e9a96959493929190613391565b6020604051808303816000875af1158015611eb9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611edd9190613374565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611f52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f7691906132c6565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff1990811660019081179092556010909452919020805490921617905561201381612c4f565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff166120cf57600080fd5b3360009081526010602052604090205460ff166120eb57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b602052816000526040600020818154811061215357600080fd5b6000918252602090912001546001600160a01b03169150829050565b6004818154811061217f57600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b031633146121b057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610ec4578181815181106121f0576121f06131d8565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612235573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061225991906132c6565b156122dd57818181518110612270576122706131d8565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af11580156122b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122da91906133e1565b50505b806122e78161326c565b9150506121d5565b60005b8151811015610ec45761231d828281518110612310576123106131d8565b6020026020010151612c4f565b806123278161326c565b9150506122f2565b6002546001600160a01b0316331461234657600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff1661238457600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161212a565b6000818152600b6020526040812080549091805b828110156126325760008482815481106123f7576123f76131d8565b6000918252602080832090910154888352600a825260408084206001600160a01b0390921680855291909252912054909150801561261d576001600160a01b038083166000908152600560205260409020546124539116612c4f565b6001600160a01b0382166000908152600960205260408120805483929061247b908490613405565b90915550506000878152600a602090815260408083206001600160a01b0386168452909152812080548392906124b2908490613405565b909155505080156125d6576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561252857600080fd5b505af115801561253c573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156125ab57600080fd5b505af11580156125bf573d6000803e3d6000fd5b5050505080846125cf91906132e8565b93506125e3565b6125e08185613405565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061262a9061326c565b9150506123db565b5080600360008282546126459190613405565b90915550506000848152600c60209081526040808320839055600b9091528120610c3691612d50565b612677836123c7565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa1580156126e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127059190613300565b90506000806000805b8581101561274f57868181518110612728576127286131d8565b60200260200101518461273b91906132e8565b9350806127478161326c565b91505061270e565b5060005b85811015612a3857600088828151811061276f5761276f6131d8565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff1615612a2357600086888b86815181106127c3576127c36131d8565b60200260200101516127d591906132a7565b6127df9190613285565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561280f57600080fd5b8060000361281c57600080fd5b61282582612c4f565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b038816908117909155835260099091528120805483929061287a9084906132e8565b909155505060008c8152600a602090815260408083206001600160a01b0387168452909152812080548392906128b19084906132e8565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561291257600080fd5b505af1158015612926573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b8152600401612999929190918252602082015260400190565b600060405180830381600087803b1580156129b357600080fd5b505af11580156129c7573d6000803e3d6000fd5b5050505080856129d791906132e8565b94506129e381876132e8565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612a309061326c565b915050612753565b508015612aba5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b158015612aa157600080fd5b505af1158015612ab5573d6000803e3d6000fd5b505050505b8160036000828254612acc91906132e8565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612b0357600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612b67919061341c565b6000604051808303816000865af19150503d8060008114612ba4576040519150601f19603f3d011682016040523d82523d6000602084013e612ba9565b606091505b5091509150818015612bd3575080511580612bd3575080806020019051810190612bd391906132c6565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612c0257600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612d2f576001600160a01b038316600090815260136020526040812080546012549182905591612cad8383613405565b90508015610a37576000670de0b6b3a7640000612cca83876132a7565b612cd49190613285565b6001600160a01b03881660009081526010602052604090205490915060ff1615612d26576001600160a01b03871660009081526014602052604081208054839290612d209084906132e8565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061134291905b80821115612d7e5760008155600101612d6a565b5090565b6001600160a01b038116811461134257600080fd5b600060208284031215612da957600080fd5b8135612db481612d82565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612dfa57612dfa612dbb565b604052919050565b600067ffffffffffffffff821115612e1c57612e1c612dbb565b5060051b60200190565b600082601f830112612e3757600080fd5b81356020612e4c612e4783612e02565b612dd1565b82815260059290921b84018101918181019086841115612e6b57600080fd5b8286015b84811015612e8f578035612e8281612d82565b8352918301918301612e6f565b509695505050505050565b600082601f830112612eab57600080fd5b81356020612ebb612e4783612e02565b82815260059290921b84018101918181019086841115612eda57600080fd5b8286015b84811015612e8f57803567ffffffffffffffff811115612efe5760008081fd5b612f0c8986838b0101612e26565b845250918301918301612ede565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff80821115612f4557600080fd5b612f5186838701612e26565b93506020850135915080821115612f6757600080fd5b50612f7485828601612e9a565b9150509250929050565b600060208284031215612f9057600080fd5b5035919050565b60008060408385031215612faa57600080fd5b823591506020830135612fbc81612d82565b809150509250929050565b60008060408385031215612fda57600080fd5b823567ffffffffffffffff811115612ff157600080fd5b612ffd85828601612e26565b9250506020830135612fbc81612d82565b60006020828403121561302057600080fd5b813567ffffffffffffffff81111561303757600080fd5b61304384828501612e26565b949350505050565b60008060006060848603121561306057600080fd5b833567ffffffffffffffff8082111561307857600080fd5b61308487838801612e26565b9450602086013591508082111561309a57600080fd5b506130a786828701612e9a565b925050604084013590509250925092565b600080604083850312156130cb57600080fd5b50508035926020909101359150565b60008083601f8401126130ec57600080fd5b50813567ffffffffffffffff81111561310457600080fd5b6020830191508360208260051b850101111561311f57600080fd5b9250929050565b60008060008060006060868803121561313e57600080fd5b85359450602086013567ffffffffffffffff8082111561315d57600080fd5b61316989838a016130da565b9096509450604088013591508082111561318257600080fd5b5061318f888289016130da565b969995985093965092949392505050565b6000806000606084860312156131b557600080fd5b8335925060208401356131c781612d82565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b838110156132275781516001600160a01b031687529582019590820190600101613202565b509495945050505050565b6001600160a01b0383168152604060208201819052600090613043908301846131ee565b634e487b7160e01b600052601160045260246000fd5b60006001820161327e5761327e613256565b5060010190565b6000826132a257634e487b7160e01b600052601260045260246000fd5b500490565b60008160001904831182151516156132c1576132c1613256565b500290565b6000602082840312156132d857600080fd5b81518015158114612db457600080fd5b600082198211156132fb576132fb613256565b500190565b60006020828403121561331257600080fd5b5051919050565b82815260406020820152600061304360408301846131ee565b6000806040838503121561334557600080fd5b825161335081612d82565b6020840151909250612fbc81612d82565b602081526000612db460208301846131ee565b60006020828403121561338657600080fd5b8151612db481612d82565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a082018190526000906133d5908301846131ee565b98975050505050505050565b600080604083850312156133f457600080fd5b505080516020909101519092909150565b60008282101561341757613417613256565b500390565b6000825160005b8181101561343d5760208186018101518583015201613423565b8181111561344c576000828501525b50919091019291505056fea2646970667358221220a59b8fe29c5f6234f643747f5ca9318f804bfc0468e2248ff69509730b9bbff164736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612d97565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612d97565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612f1a565b6107de565b005b6103ba6103ca366004612f7e565b610894565b6103ba6103dd366004612f7e565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612d97565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612f7e565b610c3c565b61039961044d366004612d97565b60146020526000908152604090205481565b6103ba61046d366004612f97565b610d0f565b6103ba610480366004612fc7565b610de9565b6103ba610e64565b6103ba610e75565b6103ba6104a336600461300e565b610e84565b6103ba6104b6366004612d97565b610ec8565b6103ba6104c936600461304b565b6110fa565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612f97565b611243565b6103ba610516366004612d97565b611339565b6103ba6105293660046130b8565b611345565b6103ba61053c36600461304b565b6113ab565b60025461031f906001600160a01b031681565b610399610562366004612f7e565b600c6020526000908152604090205481565b6103ba610582366004613126565b6114f4565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612d97565b61168c565b6103ba6105d8366004612d97565b611791565b6103ba6105eb3660046130b8565b6117b1565b6103ba6105fe366004612d97565b611817565b61031f610611366004612d97565b611914565b6103ba6106243660046131a0565b6120b3565b610399610637366004612d97565b60096020526000908152604090205481565b61031f6106573660046130b8565b612137565b61038561066a366004612d97565b600e6020526000908152604090205460ff1681565b61031f61068d366004612f7e565b61216f565b61031f6106a0366004612d97565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612d97565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612d97565b612199565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c36600461300e565b6121d2565b61039961073f366004612f97565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a36600461300e565b6122ef565b6103ba61077d366004612d97565b61232f565b6103ba6107903660046131a0565b612368565b61031f6107a3366004612d97565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612f7e565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc6131d8565b60200260200101516001600160a01b03166331279d3d33848481518110610825576108256131d8565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613232565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b5050505080806108879061326c565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b38142613285565b6108bd91906132a7565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e91906132c6565b6109a757600080fd5b6000828152600d602052604090204290556109c1826123c7565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015610aaa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ace91906132c6565b80610ae357506001546001600160a01b031633145b610aec57600080fd5b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610b4c57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610b2e575b5050505050905060008151905060008167ffffffffffffffff811115610b7457610b74612dbb565b604051908082528060200260200182016040528015610b9d578160200160208202803683370190505b50905060005b82811015610c2a57600a60008681526020019081526020016000206000858381518110610bd257610bd26131d8565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610c0d57610c0d6131d8565b602090810291909101015280610c228161326c565b915050610ba3565b50610c3684848361266e565b50505050565b610c687f0000000000000000000000000000000000000000000000000000000000000000333084612aec565b600354600090610c8083670de0b6b3a76400006132a7565b610c8a9190613285565b90508015610caa578060126000828254610ca491906132e8565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610d2b57600080fd5b8115610dac57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610d9357600080fd5b505af1158015610da7573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610d03565b6000546001600160a01b03163314610e0057600080fd5b60005b8251811015610e4057610e2e838281518110610e2157610e216131d8565b6020026020010151612bdc565b80610e388161326c565b915050610e03565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610e7390600090611345565b565b600454610e73906000906117b1565b60005b8151811015610ec457610eb2828281518110610ea557610ea56131d8565b6020026020010151610ec8565b80610ebc8161326c565b915050610e87565b5050565b601154600114610ed757600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610f32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f569190613300565b50610f6081612c4f565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610fd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ffc9190613300565b811180156110165750600061101462093a8083613285565b115b156110f1576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b15801561109857600080fd5b505af11580156110ac573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611165573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061118991906132c6565b61119257600080fd5b60005b8351811015610c36578381815181106111b0576111b06131d8565b60200260200101516001600160a01b031663a7852afa838584815181106111d9576111d96131d8565b60200260200101516040518363ffffffff1660e01b81526004016111fe929190613319565b600060405180830381600087803b15801561121857600080fd5b505af115801561122c573d6000803e3d6000fd5b50505050808061123b9061326c565b915050611195565b336000908152600e602052604090205460ff1661125f57600080fd5b3360009081526010602052604090205460ff1661127b57600080fd5b81156112fc5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b1580156112e357600080fd5b505af11580156112f7573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610d03565b61134281612c4f565b50565b815b8181101561088f576113996005600060048481548110611369576113696131d8565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610ec8565b806113a38161326c565b915050611347565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611416573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061143a91906132c6565b61144357600080fd5b60005b8351811015610c3657838181518110611461576114616131d8565b60200260200101516001600160a01b031663a7852afa8385848151811061148a5761148a6131d8565b60200260200101516040518363ffffffff1660e01b81526004016114af929190613319565b600060405180830381600087803b1580156114c957600080fd5b505af11580156114dd573d6000803e3d6000fd5b5050505080806114ec9061326c565b915050611446565b6000858152600d6020526040902054859062093a806115138142613285565b61151d91906132a7565b1161156a5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156115d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115f991906132c6565b61160257600080fd5b83821461160e57600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a0282810182019093528982529093508992508891829185019084908082843760009201919091525061266e92505050565b6002546001600160a01b031633146116de5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661173b5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146117a857600080fd5b61134281612bdc565b815b8181101561088f5761180560056000600484815481106117d5576117d56131d8565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612c4f565b8061180f8161326c565b9150506117b3565b6002546001600160a01b031633146118695760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff16156118c85760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156119675760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa158015611a18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3c91906132c6565b90506000808215611c3857866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015611a86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aaa9190613332565b80925081935050508185600081518110611ac657611ac66131d8565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611afa57611afa6131d8565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611b2e57611b2e6131d8565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611b6257611b626131d8565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611bde5750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611c38577f000000000000000000000000000000000000000000000000000000000000000085600281518110611c1757611c176131d8565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611cfb5782611c805760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611cc057506001600160a01b0381166000908152600f602052604090205460ff165b611cfb5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611d4a908890600401613361565b6020604051808303816000875af1158015611d69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d8d9190613374565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611ddd9190613361565b6020604051808303816000875af1158015611dfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e209190613374565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611e9a96959493929190613391565b6020604051808303816000875af1158015611eb9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611edd9190613374565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611f52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f7691906132c6565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff1990811660019081179092556010909452919020805490921617905561201381612c4f565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff166120cf57600080fd5b3360009081526010602052604090205460ff166120eb57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b602052816000526040600020818154811061215357600080fd5b6000918252602090912001546001600160a01b03169150829050565b6004818154811061217f57600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b031633146121b057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610ec4578181815181106121f0576121f06131d8565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612235573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061225991906132c6565b156122dd57818181518110612270576122706131d8565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af11580156122b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122da91906133e1565b50505b806122e78161326c565b9150506121d5565b60005b8151811015610ec45761231d828281518110612310576123106131d8565b6020026020010151612c4f565b806123278161326c565b9150506122f2565b6002546001600160a01b0316331461234657600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff1661238457600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161212a565b6000818152600b6020526040812080549091805b828110156126325760008482815481106123f7576123f76131d8565b6000918252602080832090910154888352600a825260408084206001600160a01b0390921680855291909252912054909150801561261d576001600160a01b038083166000908152600560205260409020546124539116612c4f565b6001600160a01b0382166000908152600960205260408120805483929061247b908490613405565b90915550506000878152600a602090815260408083206001600160a01b0386168452909152812080548392906124b2908490613405565b909155505080156125d6576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561252857600080fd5b505af115801561253c573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156125ab57600080fd5b505af11580156125bf573d6000803e3d6000fd5b5050505080846125cf91906132e8565b93506125e3565b6125e08185613405565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061262a9061326c565b9150506123db565b5080600360008282546126459190613405565b90915550506000848152600c60209081526040808320839055600b9091528120610c3691612d50565b612677836123c7565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa1580156126e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127059190613300565b90506000806000805b8581101561274f57868181518110612728576127286131d8565b60200260200101518461273b91906132e8565b9350806127478161326c565b91505061270e565b5060005b85811015612a3857600088828151811061276f5761276f6131d8565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff1615612a2357600086888b86815181106127c3576127c36131d8565b60200260200101516127d591906132a7565b6127df9190613285565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561280f57600080fd5b8060000361281c57600080fd5b61282582612c4f565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b038816908117909155835260099091528120805483929061287a9084906132e8565b909155505060008c8152600a602090815260408083206001600160a01b0387168452909152812080548392906128b19084906132e8565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561291257600080fd5b505af1158015612926573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b8152600401612999929190918252602082015260400190565b600060405180830381600087803b1580156129b357600080fd5b505af11580156129c7573d6000803e3d6000fd5b5050505080856129d791906132e8565b94506129e381876132e8565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612a309061326c565b915050612753565b508015612aba5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b158015612aa157600080fd5b505af1158015612ab5573d6000803e3d6000fd5b505050505b8160036000828254612acc91906132e8565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612b0357600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612b67919061341c565b6000604051808303816000865af19150503d8060008114612ba4576040519150601f19603f3d011682016040523d82523d6000602084013e612ba9565b606091505b5091509150818015612bd3575080511580612bd3575080806020019051810190612bd391906132c6565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612c0257600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612d2f576001600160a01b038316600090815260136020526040812080546012549182905591612cad8383613405565b90508015610a37576000670de0b6b3a7640000612cca83876132a7565b612cd49190613285565b6001600160a01b03881660009081526010602052604090205490915060ff1615612d26576001600160a01b03871660009081526014602052604081208054839290612d209084906132e8565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061134291905b80821115612d7e5760008155600101612d6a565b5090565b6001600160a01b038116811461134257600080fd5b600060208284031215612da957600080fd5b8135612db481612d82565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612dfa57612dfa612dbb565b604052919050565b600067ffffffffffffffff821115612e1c57612e1c612dbb565b5060051b60200190565b600082601f830112612e3757600080fd5b81356020612e4c612e4783612e02565b612dd1565b82815260059290921b84018101918181019086841115612e6b57600080fd5b8286015b84811015612e8f578035612e8281612d82565b8352918301918301612e6f565b509695505050505050565b600082601f830112612eab57600080fd5b81356020612ebb612e4783612e02565b82815260059290921b84018101918181019086841115612eda57600080fd5b8286015b84811015612e8f57803567ffffffffffffffff811115612efe5760008081fd5b612f0c8986838b0101612e26565b845250918301918301612ede565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff80821115612f4557600080fd5b612f5186838701612e26565b93506020850135915080821115612f6757600080fd5b50612f7485828601612e9a565b9150509250929050565b600060208284031215612f9057600080fd5b5035919050565b60008060408385031215612faa57600080fd5b823591506020830135612fbc81612d82565b809150509250929050565b60008060408385031215612fda57600080fd5b823567ffffffffffffffff811115612ff157600080fd5b612ffd85828601612e26565b9250506020830135612fbc81612d82565b60006020828403121561302057600080fd5b813567ffffffffffffffff81111561303757600080fd5b61304384828501612e26565b949350505050565b60008060006060848603121561306057600080fd5b833567ffffffffffffffff8082111561307857600080fd5b61308487838801612e26565b9450602086013591508082111561309a57600080fd5b506130a786828701612e9a565b925050604084013590509250925092565b600080604083850312156130cb57600080fd5b50508035926020909101359150565b60008083601f8401126130ec57600080fd5b50813567ffffffffffffffff81111561310457600080fd5b6020830191508360208260051b850101111561311f57600080fd5b9250929050565b60008060008060006060868803121561313e57600080fd5b85359450602086013567ffffffffffffffff8082111561315d57600080fd5b61316989838a016130da565b9096509450604088013591508082111561318257600080fd5b5061318f888289016130da565b969995985093965092949392505050565b6000806000606084860312156131b557600080fd5b8335925060208401356131c781612d82565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b838110156132275781516001600160a01b031687529582019590820190600101613202565b509495945050505050565b6001600160a01b0383168152604060208201819052600090613043908301846131ee565b634e487b7160e01b600052601160045260246000fd5b60006001820161327e5761327e613256565b5060010190565b6000826132a257634e487b7160e01b600052601260045260246000fd5b500490565b60008160001904831182151516156132c1576132c1613256565b500290565b6000602082840312156132d857600080fd5b81518015158114612db457600080fd5b600082198211156132fb576132fb613256565b500190565b60006020828403121561331257600080fd5b5051919050565b82815260406020820152600061304360408301846131ee565b6000806040838503121561334557600080fd5b825161335081612d82565b6020840151909250612fbc81612d82565b602081526000612db460208301846131ee565b60006020828403121561338657600080fd5b8151612db481612d82565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a082018190526000906133d5908301846131ee565b98975050505050505050565b600080604083850312156133f457600080fd5b505080516020909101519092909150565b60008282101561341757613417613256565b500390565b6000825160005b8181101561343d5760208186018101518583015201613423565b8181111561344c576000828501525b50919091019291505056fea2646970667358221220a59b8fe29c5f6234f643747f5ca9318f804bfc0468e2248ff69509730b9bbff164736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, @@ -1181,7 +1181,7 @@ "storageLayout": { "storage": [ { - "astId": 14322, + "astId": 14342, "contract": "contracts/Voter.sol:Voter", "label": "minter", "offset": 0, @@ -1189,7 +1189,7 @@ "type": "t_address" }, { - "astId": 14324, + "astId": 14344, "contract": "contracts/Voter.sol:Voter", "label": "governor", "offset": 0, @@ -1197,7 +1197,7 @@ "type": "t_address" }, { - "astId": 14326, + "astId": 14346, "contract": "contracts/Voter.sol:Voter", "label": "emergencyCouncil", "offset": 0, @@ -1205,7 +1205,7 @@ "type": "t_address" }, { - "astId": 14328, + "astId": 14348, "contract": "contracts/Voter.sol:Voter", "label": "totalWeight", "offset": 0, @@ -1213,7 +1213,7 @@ "type": "t_uint256" }, { - "astId": 14331, + "astId": 14351, "contract": "contracts/Voter.sol:Voter", "label": "pools", "offset": 0, @@ -1221,7 +1221,7 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 14335, + "astId": 14355, "contract": "contracts/Voter.sol:Voter", "label": "gauges", "offset": 0, @@ -1229,7 +1229,7 @@ "type": "t_mapping(t_address,t_address)" }, { - "astId": 14339, + "astId": 14359, "contract": "contracts/Voter.sol:Voter", "label": "poolForGauge", "offset": 0, @@ -1237,7 +1237,7 @@ "type": "t_mapping(t_address,t_address)" }, { - "astId": 14343, + "astId": 14363, "contract": "contracts/Voter.sol:Voter", "label": "internal_bribes", "offset": 0, @@ -1245,7 +1245,7 @@ "type": "t_mapping(t_address,t_address)" }, { - "astId": 14347, + "astId": 14367, "contract": "contracts/Voter.sol:Voter", "label": "external_bribes", "offset": 0, @@ -1253,7 +1253,7 @@ "type": "t_mapping(t_address,t_address)" }, { - "astId": 14351, + "astId": 14371, "contract": "contracts/Voter.sol:Voter", "label": "weights", "offset": 0, @@ -1261,7 +1261,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 14357, + "astId": 14377, "contract": "contracts/Voter.sol:Voter", "label": "votes", "offset": 0, @@ -1269,7 +1269,7 @@ "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))" }, { - "astId": 14362, + "astId": 14382, "contract": "contracts/Voter.sol:Voter", "label": "poolVote", "offset": 0, @@ -1277,7 +1277,7 @@ "type": "t_mapping(t_uint256,t_array(t_address)dyn_storage)" }, { - "astId": 14366, + "astId": 14386, "contract": "contracts/Voter.sol:Voter", "label": "usedWeights", "offset": 0, @@ -1285,7 +1285,7 @@ "type": "t_mapping(t_uint256,t_uint256)" }, { - "astId": 14370, + "astId": 14390, "contract": "contracts/Voter.sol:Voter", "label": "lastVoted", "offset": 0, @@ -1293,7 +1293,7 @@ "type": "t_mapping(t_uint256,t_uint256)" }, { - "astId": 14374, + "astId": 14394, "contract": "contracts/Voter.sol:Voter", "label": "isGauge", "offset": 0, @@ -1301,7 +1301,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 14378, + "astId": 14398, "contract": "contracts/Voter.sol:Voter", "label": "isWhitelisted", "offset": 0, @@ -1309,7 +1309,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 14382, + "astId": 14402, "contract": "contracts/Voter.sol:Voter", "label": "isAlive", "offset": 0, @@ -1317,7 +1317,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 14528, + "astId": 14548, "contract": "contracts/Voter.sol:Voter", "label": "_unlocked", "offset": 0, @@ -1325,7 +1325,7 @@ "type": "t_uint256" }, { - "astId": 15620, + "astId": 15657, "contract": "contracts/Voter.sol:Voter", "label": "index", "offset": 0, @@ -1333,7 +1333,7 @@ "type": "t_uint256" }, { - "astId": 15624, + "astId": 15661, "contract": "contracts/Voter.sol:Voter", "label": "supplyIndex", "offset": 0, @@ -1341,7 +1341,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 15628, + "astId": 15665, "contract": "contracts/Voter.sol:Voter", "label": "claimable", "offset": 0, diff --git a/deployments/arbitrumOne/VotingEscrow.json b/deployments/arbitrumOne/VotingEscrow.json index b308be02..4fbd69f7 100644 --- a/deployments/arbitrumOne/VotingEscrow.json +++ b/deployments/arbitrumOne/VotingEscrow.json @@ -1,5 +1,5 @@ { - "address": "0x10Df81252069C1095F541FAca61646cb9Ae76703", + "address": "0xfa01adbAA40f0EEeCEA76b7B18AC8bE064536787", "abi": [ { "inputs": [ @@ -1521,62 +1521,62 @@ "type": "function" } ], - "transactionHash": "0x0d188c6284ab3f8819012287ed29c698d71269b7a82470a6dc166a8d66485061", + "transactionHash": "0xd3b7df5588e008b92a1b951bfba42d6598a0d14a3f6d66b17ce66ef8c9efa053", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0x10Df81252069C1095F541FAca61646cb9Ae76703", + "contractAddress": "0xfa01adbAA40f0EEeCEA76b7B18AC8bE064536787", "transactionIndex": 1, - "gasUsed": "30673850", - "logsBloom": "0x00000000000000000000000008000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000040000000000000000000000000008000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000010000102000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x0300bc4c5219d7cde2f65e67a4050d0df88e8cf53a3168d85b5211d4eb901d1a", - "transactionHash": "0x0d188c6284ab3f8819012287ed29c698d71269b7a82470a6dc166a8d66485061", + "gasUsed": "30470284", + "logsBloom": "0x00000000000000000000000000000000000000000000400000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000100000000008000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000010000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000020000000000000000000000008000000000000000000000000000000002000000000", + "blockHash": "0xa8c0d8777601b5c5671d1684e9c34fe7272b0cd70b1058add4b25afc46969f52", + "transactionHash": "0xd3b7df5588e008b92a1b951bfba42d6598a0d14a3f6d66b17ce66ef8c9efa053", "logs": [ { "transactionIndex": 1, - "blockNumber": 53774090, - "transactionHash": "0x0d188c6284ab3f8819012287ed29c698d71269b7a82470a6dc166a8d66485061", - "address": "0x10Df81252069C1095F541FAca61646cb9Ae76703", + "blockNumber": 58032078, + "transactionHash": "0xd3b7df5588e008b92a1b951bfba42d6598a0d14a3f6d66b17ce66ef8c9efa053", + "address": "0xfa01adbAA40f0EEeCEA76b7B18AC8bE064536787", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000010df81252069c1095f541faca61646cb9ae76703", + "0x000000000000000000000000fa01adbaa40f0eeecea76b7b18ac8be064536787", "0x0000000000000000000000000000000000000000000000000000000000000000" ], "data": "0x", "logIndex": 0, - "blockHash": "0x0300bc4c5219d7cde2f65e67a4050d0df88e8cf53a3168d85b5211d4eb901d1a" + "blockHash": "0xa8c0d8777601b5c5671d1684e9c34fe7272b0cd70b1058add4b25afc46969f52" }, { "transactionIndex": 1, - "blockNumber": 53774090, - "transactionHash": "0x0d188c6284ab3f8819012287ed29c698d71269b7a82470a6dc166a8d66485061", - "address": "0x10Df81252069C1095F541FAca61646cb9Ae76703", + "blockNumber": 58032078, + "transactionHash": "0xd3b7df5588e008b92a1b951bfba42d6598a0d14a3f6d66b17ce66ef8c9efa053", + "address": "0xfa01adbAA40f0EEeCEA76b7B18AC8bE064536787", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x00000000000000000000000010df81252069c1095f541faca61646cb9ae76703", + "0x000000000000000000000000fa01adbaa40f0eeecea76b7b18ac8be064536787", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000" ], "data": "0x", "logIndex": 1, - "blockHash": "0x0300bc4c5219d7cde2f65e67a4050d0df88e8cf53a3168d85b5211d4eb901d1a" + "blockHash": "0xa8c0d8777601b5c5671d1684e9c34fe7272b0cd70b1058add4b25afc46969f52" } ], - "blockNumber": 53774090, - "cumulativeGasUsed": "30673850", + "blockNumber": 58032078, + "cumulativeGasUsed": "30470284", "status": 1, "byzantium": true }, "args": [ - "0xC33f7f83CbB021846Cb9c58f2d8E3df428dbC8C1", - "0x4b40D5E4401EC24673cc9d4799457a3B5827c581" + "0x944AF7785d57bcfC00e95388453B93DAD373216e", + "0x0bd9d21b40428a650DbFC0F7bd3F7B6FA321F915" ], "numDeployments": 1, - "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token_addr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"art_proxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromDelegate\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toDelegate\",\"type\":\"address\"}],\"name\":\"DelegateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"DelegateVotesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"locktime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum VotingEscrow.DepositType\",\"name\":\"deposit_type\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"prevSupply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"supply\",\"type\":\"uint256\"}],\"name\":\"Supply\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DELEGATION_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_DELEGATES\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"abstain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_approved\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"artProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"attach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"attachments\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"balanceOfAtNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_t\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFTAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"block_number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"checkpoints\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"create_lock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"create_lock_for\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"}],\"name\":\"delegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"delegateBySig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"}],\"name\":\"delegates\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"deposit_for\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"detach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastTotalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotesIndex\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"get_last_user_slope\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"increase_amount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"increase_unlock_time\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"isApprovedOrOwner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"locked\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"amount\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"locked__end\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_from\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_to\",\"type\":\"uint256\"}],\"name\":\"merge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"numCheckpoints\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ownership_change\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_proxy\",\"type\":\"address\"}],\"name\":\"setArtProxy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voter\",\"type\":\"address\"}],\"name\":\"setVoter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"slope_changes\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenIndex\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"t\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAtT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_idx\",\"type\":\"uint256\"}],\"name\":\"user_point_history__ts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"voted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"voting\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\",\"details\":\"Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\",\"kind\":\"dev\",\"methods\":{\"approve(address,uint256)\":{\"details\":\"Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address. Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner. Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP) Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"Address to be approved for the given NFT ID.\",\"_tokenId\":\"ID of the token to be approved.\"}},\"balanceOf(address)\":{\"details\":\"Returns the number of NFTs owned by `_owner`. Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\",\"params\":{\"_owner\":\"Address for whom to query the balance.\"}},\"constructor\":{\"params\":{\"token_addr\":\"`VELO` token address\"}},\"create_lock(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_value\":\"Amount to deposit\"}},\"create_lock_for(uint256,uint256,address)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_to\":\"Address to deposit\",\"_value\":\"Amount to deposit\"}},\"delegate(address)\":{\"params\":{\"delegatee\":\"The address to delegate votes to\"}},\"delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Delegates votes from signer to `delegatee`.\"},\"deposit_for(uint256,uint256)\":{\"details\":\"Anyone (even a smart contract) can deposit for someone else, but cannot extend their locktime and deposit for a brand new user\",\"params\":{\"_tokenId\":\"lock NFT\",\"_value\":\"Amount to add to user's lock\"}},\"getApproved(uint256)\":{\"details\":\"Get the approved address for a single NFT.\",\"params\":{\"_tokenId\":\"ID of the NFT to query the approval of.\"}},\"getVotes(address)\":{\"params\":{\"account\":\"The address to get votes balance\"},\"returns\":{\"_0\":\"The number of current votes for `account`\"}},\"get_last_user_slope(uint256)\":{\"params\":{\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Value of the slope\"}},\"increase_amount(uint256,uint256)\":{\"params\":{\"_value\":\"Amount of tokens to deposit and add to the lock\"}},\"increase_unlock_time(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"New number of seconds until tokens unlock\"}},\"isApprovedForAll(address,address)\":{\"details\":\"Checks if `_operator` is an approved operator for `_owner`.\",\"params\":{\"_operator\":\"The address that acts on behalf of the owner.\",\"_owner\":\"The address that owns the NFTs.\"}},\"locked__end(uint256)\":{\"params\":{\"_tokenId\":\"User NFT\"},\"returns\":{\"_0\":\"Epoch time of the lock end\"}},\"ownerOf(uint256)\":{\"details\":\"Returns the address of the owner of the NFT.\",\"params\":{\"_tokenId\":\"The identifier for an NFT.\"}},\"safeTransferFrom(address,address,uint256)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"safeTransferFrom(address,address,uint256,bytes)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_data\":\"Additional data with no specified format, sent in call to `_to`.\",\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"details\":\"Enables or disables approval for a third party (\\\"operator\\\") to manage all of `msg.sender`'s assets. It also emits the ApprovalForAll event. Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"True if the operators is approved, false to revoke approval.\",\"_operator\":\"Address to add to the set of authorized operators.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Interface identification is specified in ERC-165.\",\"params\":{\"_interfaceID\":\"Id of the interface\"}},\"tokenOfOwnerByIndex(address,uint256)\":{\"details\":\"Get token by index\"},\"tokenURI(uint256)\":{\"details\":\"Returns current token URI metadata\",\"params\":{\"_tokenId\":\"Token ID to fetch URI for.\"}},\"totalSupplyAt(uint256)\":{\"params\":{\"_block\":\"Block to calculate the total voting power at\"},\"returns\":{\"_0\":\"Total voting power at `_block`\"}},\"totalSupplyAtT(uint256)\":{\"details\":\"Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\",\"returns\":{\"_0\":\"Total voting power\"}},\"transferFrom(address,address,uint256)\":{\"details\":\"Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"user_point_history__ts(uint256,uint256)\":{\"params\":{\"_idx\":\"User epoch number\",\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Epoch time of the checkpoint\"}},\"withdraw(uint256)\":{\"details\":\"Only possible if the lock has expired\"}},\"stateVariables\":{\"ERC165_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC165\"},\"ERC721_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721\"},\"ERC721_METADATA_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721Metadata\"},\"_not_entered\":{\"details\":\"reentrancy guard\"},\"idToApprovals\":{\"details\":\"Mapping from NFT ID to approved address.\"},\"idToOwner\":{\"details\":\"Mapping from NFT ID to the address that owns it.\"},\"name\":{\"details\":\"Returns the token collection name.\"},\"ownerToNFTokenCount\":{\"details\":\"Mapping from owner address to count of his tokens.\"},\"ownerToNFTokenIdList\":{\"details\":\"Mapping from owner address to mapping of index to tokenIds\"},\"ownerToOperators\":{\"details\":\"Mapping from owner address to mapping of operator addresses.\"},\"supportedInterfaces\":{\"details\":\"Mapping of interface id to bool about whether or not it's supported\"},\"symbol\":{\"details\":\"Returns the token collection symbol.\"},\"tokenId\":{\"details\":\"Current count of token\"},\"tokenToOwnerIndex\":{\"details\":\"Mapping from NFT ID to index of owner\"}},\"title\":\"Voting Escrow\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DELEGATION_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the delegation struct used by the contract\"},\"DOMAIN_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the contract's domain\"},\"checkpoint()\":{\"notice\":\"Record global data to checkpoint\"},\"checkpoints(address,uint32)\":{\"notice\":\"A record of delegated token checkpoints for each account, by index\"},\"constructor\":{\"notice\":\"Contract constructor\"},\"create_lock(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\"},\"create_lock_for(uint256,uint256,address)\":{\"notice\":\"Deposit `_value` tokens for `_to` and lock for `_lock_duration`\"},\"delegate(address)\":{\"notice\":\"Delegate votes from `msg.sender` to `delegatee`\"},\"delegates(address)\":{\"notice\":\"Overrides the standard `Comp.sol` delegates mapping to return the delegator's own address if they haven't delegated. This avoids having to delegate to oneself.\"},\"deposit_for(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `_tokenId` and add to the lock\"},\"getVotes(address)\":{\"notice\":\"Gets the current votes balance for `account`\"},\"get_last_user_slope(uint256)\":{\"notice\":\"Get the most recently recorded rate of voting power decrease for `_tokenId`\"},\"increase_amount(uint256,uint256)\":{\"notice\":\"Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\"},\"increase_unlock_time(uint256,uint256)\":{\"notice\":\"Extend the unlock time for `_tokenId`\"},\"locked__end(uint256)\":{\"notice\":\"Get timestamp when `_tokenId`'s lock finishes\"},\"nonces(address)\":{\"notice\":\"A record of states for signing / validating signatures\"},\"numCheckpoints(address)\":{\"notice\":\"The number of checkpoints for each account\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"This works even if sender doesn't own any tokens at the time.\"},\"totalSupplyAt(uint256)\":{\"notice\":\"Calculate total voting power at some point in the past\"},\"totalSupplyAtT(uint256)\":{\"notice\":\"Calculate total voting power\"},\"transferFrom(address,address,uint256)\":{\"notice\":\"The caller is responsible to confirm that `_to` is capable of receiving NFTs or else they maybe be permanently lost.\"},\"user_point_history__ts(uint256,uint256)\":{\"notice\":\"Get the timestamp for checkpoint `_idx` for `_tokenId`\"},\"withdraw(uint256)\":{\"notice\":\"Withdraw all tokens for `_tokenId`\"}},\"notice\":\"veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFTVotes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VotingEscrow.sol\":\"VotingEscrow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VotingEscrow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IERC721, IERC721Metadata} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {IERC721Receiver} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {IERC20} from \\\"contracts/interfaces/IERC20.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\nimport {IVotingEscrow} from \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/// @title Voting Escrow\\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\\n enum DepositType {\\n DEPOSIT_FOR_TYPE,\\n CREATE_LOCK_TYPE,\\n INCREASE_LOCK_AMOUNT,\\n INCREASE_UNLOCK_TIME,\\n MERGE_TYPE\\n }\\n\\n struct LockedBalance {\\n int128 amount;\\n uint end;\\n }\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint ts;\\n uint blk; // block\\n }\\n /* We cannot really do block numbers per se b/c slope is per time, not per block\\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\\n * What we can do is to extrapolate ***At functions */\\n\\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\\n struct Checkpoint {\\n uint timestamp;\\n uint[] tokenIds;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Deposit(\\n address indexed provider,\\n uint tokenId,\\n uint value,\\n uint indexed locktime,\\n DepositType deposit_type,\\n uint ts\\n );\\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\\n event Supply(uint prevSupply, uint supply);\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n address public immutable token;\\n address public voter;\\n address public team;\\n address public artProxy;\\n\\n mapping(uint => Point) public point_history; // epoch -> unsigned point\\n\\n /// @dev Mapping of interface id to bool about whether or not it's supported\\n mapping(bytes4 => bool) internal supportedInterfaces;\\n\\n /// @dev ERC165 interface ID of ERC165\\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\\n\\n /// @dev ERC165 interface ID of ERC721\\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\\n\\n /// @dev ERC165 interface ID of ERC721Metadata\\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\\n\\n /// @dev Current count of token\\n uint internal tokenId;\\n\\n /// @notice Contract constructor\\n /// @param token_addr `VELO` token address\\n constructor(address token_addr, address art_proxy) {\\n token = token_addr;\\n voter = msg.sender;\\n team = msg.sender;\\n artProxy = art_proxy;\\n\\n point_history[0].blk = block.number;\\n point_history[0].ts = block.timestamp;\\n\\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\\n\\n // mint-ish\\n emit Transfer(address(0), address(this), tokenId);\\n // burn-ish\\n emit Transfer(address(this), address(0), tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n MODIFIERS\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev reentrancy guard\\n uint8 internal constant _not_entered = 1;\\n uint8 internal constant _entered = 2;\\n uint8 internal _entered_state = 1;\\n modifier nonreentrant() {\\n require(_entered_state == _not_entered);\\n _entered_state = _entered;\\n _;\\n _entered_state = _not_entered;\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string constant public name = \\\"veNFT\\\";\\n string constant public symbol = \\\"veNFT\\\";\\n string constant public version = \\\"1.0.0\\\";\\n uint8 constant public decimals = 18;\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team);\\n team = _team;\\n }\\n\\n function setArtProxy(address _proxy) external {\\n require(msg.sender == team);\\n artProxy = _proxy;\\n }\\n\\n /// @dev Returns current token URI metadata\\n /// @param _tokenId Token ID to fetch URI for.\\n function tokenURI(uint _tokenId) external view returns (string memory) {\\n require(idToOwner[_tokenId] != address(0), \\\"Query for nonexistent token\\\");\\n LockedBalance memory _locked = locked[_tokenId];\\n return IVeArtProxy(artProxy)._tokenURI(\\n _tokenId,\\n _balanceOfNFT(_tokenId, block.timestamp),\\n _locked.end,\\n uint(int256(_locked.amount))\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 BALANCE/OWNER STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to the address that owns it.\\n mapping(uint => address) internal idToOwner;\\n\\n /// @dev Mapping from owner address to count of his tokens.\\n mapping(address => uint) internal ownerToNFTokenCount;\\n\\n /// @dev Returns the address of the owner of the NFT.\\n /// @param _tokenId The identifier for an NFT.\\n function ownerOf(uint _tokenId) public view returns (address) {\\n return idToOwner[_tokenId];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function _balance(address _owner) internal view returns (uint) {\\n return ownerToNFTokenCount[_owner];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function balanceOf(address _owner) external view returns (uint) {\\n return _balance(_owner);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 APPROVAL STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to approved address.\\n mapping(uint => address) internal idToApprovals;\\n\\n /// @dev Mapping from owner address to mapping of operator addresses.\\n mapping(address => mapping(address => bool)) internal ownerToOperators;\\n\\n mapping(uint => uint) public ownership_change;\\n\\n /// @dev Get the approved address for a single NFT.\\n /// @param _tokenId ID of the NFT to query the approval of.\\n function getApproved(uint _tokenId) external view returns (address) {\\n return idToApprovals[_tokenId];\\n }\\n\\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\\n /// @param _owner The address that owns the NFTs.\\n /// @param _operator The address that acts on behalf of the owner.\\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\\n return (ownerToOperators[_owner])[_operator];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\\n /// @param _approved Address to be approved for the given NFT ID.\\n /// @param _tokenId ID of the token to be approved.\\n function approve(address _approved, uint _tokenId) public {\\n address owner = idToOwner[_tokenId];\\n // Throws if `_tokenId` is not a valid NFT\\n require(owner != address(0));\\n // Throws if `_approved` is the current owner\\n require(_approved != owner);\\n // Check requirements\\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\\n require(senderIsOwner || senderIsApprovedForAll);\\n // Set the approval\\n idToApprovals[_tokenId] = _approved;\\n emit Approval(owner, _approved, _tokenId);\\n }\\n\\n /// @dev Enables or disables approval for a third party (\\\"operator\\\") to manage all of\\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\\n /// @notice This works even if sender doesn't own any tokens at the time.\\n /// @param _operator Address to add to the set of authorized operators.\\n /// @param _approved True if the operators is approved, false to revoke approval.\\n function setApprovalForAll(address _operator, bool _approved) external {\\n // Throws if `_operator` is the `msg.sender`\\n assert(_operator != msg.sender);\\n ownerToOperators[msg.sender][_operator] = _approved;\\n emit ApprovalForAll(msg.sender, _operator, _approved);\\n }\\n\\n /* TRANSFER FUNCTIONS */\\n /// @dev Clear an approval of a given address\\n /// Throws if `_owner` is not the current owner.\\n function _clearApproval(address _owner, uint _tokenId) internal {\\n // Throws if `_owner` is not the current owner\\n assert(idToOwner[_tokenId] == _owner);\\n if (idToApprovals[_tokenId] != address(0)) {\\n // Reset approvals\\n idToApprovals[_tokenId] = address(0);\\n }\\n }\\n\\n /// @dev Returns whether the given spender can transfer a given token ID\\n /// @param _spender address of the spender to query\\n /// @param _tokenId uint ID of the token to be transferred\\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\\n address owner = idToOwner[_tokenId];\\n bool spenderIsOwner = owner == _spender;\\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\\n }\\n\\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\\n return _isApprovedOrOwner(_spender, _tokenId);\\n }\\n\\n /// @dev Exeute transfer of a NFT.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_tokenId` is not a valid NFT.\\n function _transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n address _sender\\n ) internal {\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n // Check requirements\\n require(_isApprovedOrOwner(_sender, _tokenId));\\n // Clear approval. Throws if `_from` is not the current owner\\n _clearApproval(_from, _tokenId);\\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\\n _removeTokenFrom(_from, _tokenId);\\n // auto re-delegate\\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\\n // Add NFT\\n _addTokenTo(_to, _tokenId);\\n // Set the block of ownership transfer (for Flash NFT protection)\\n ownership_change[_tokenId] = block.number;\\n // Log the transfer\\n emit Transfer(_from, _to, _tokenId);\\n }\\n\\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\\n /// they maybe be permanently lost.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n safeTransferFrom(_from, _to, _tokenId, \\\"\\\");\\n }\\n\\n function _isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n uint size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n /// @param _data Additional data with no specified format, sent in call to `_to`.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n bytes memory _data\\n ) public {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n\\n if (_isContract(_to)) {\\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\\n revert(\\\"ERC721: ERC721Receiver rejected tokens\\\");\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert('ERC721: transfer to non ERC721Receiver implementer');\\n } else {\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC165 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Interface identification is specified in ERC-165.\\n /// @param _interfaceID Id of the interface\\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\\n return supportedInterfaces[_interfaceID];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from owner address to mapping of index to tokenIds\\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\\n\\n /// @dev Mapping from NFT ID to index of owner\\n mapping(uint => uint) internal tokenToOwnerIndex;\\n\\n /// @dev Get token by index\\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\\n return ownerToNFTokenIdList[_owner][_tokenIndex];\\n }\\n\\n /// @dev Add a NFT to an index mapping to a given address\\n /// @param _to address of the receiver\\n /// @param _tokenId uint ID Of the token to be added\\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\\n uint current_count = _balance(_to);\\n\\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\\n tokenToOwnerIndex[_tokenId] = current_count;\\n }\\n\\n /// @dev Add a NFT to a given address\\n /// Throws if `_tokenId` is owned by someone.\\n function _addTokenTo(address _to, uint _tokenId) internal {\\n // Throws if `_tokenId` is owned by someone\\n assert(idToOwner[_tokenId] == address(0));\\n // Change the owner\\n idToOwner[_tokenId] = _to;\\n // Update owner token index tracking\\n _addTokenToOwnerList(_to, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_to] += 1;\\n }\\n\\n /// @dev Function to mint tokens\\n /// Throws if `_to` is zero address.\\n /// Throws if `_tokenId` is owned by someone.\\n /// @param _to The address that will receive the minted tokens.\\n /// @param _tokenId The token id to mint.\\n /// @return A boolean that indicates if the operation was successful.\\n function _mint(address _to, uint _tokenId) internal returns (bool) {\\n // Throws if `_to` is zero address\\n assert(_to != address(0));\\n // checkpoint for gov\\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\\n // Add NFT. Throws if `_tokenId` is owned by someone\\n _addTokenTo(_to, _tokenId);\\n emit Transfer(address(0), _to, _tokenId);\\n return true;\\n }\\n\\n /// @dev Remove a NFT from an index mapping to a given address\\n /// @param _from address of the sender\\n /// @param _tokenId uint ID Of the token to be removed\\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\\n // Delete\\n uint current_count = _balance(_from) - 1;\\n uint current_index = tokenToOwnerIndex[_tokenId];\\n\\n if (current_count == current_index) {\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n } else {\\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\\n\\n // Add\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[lastTokenId] = current_index;\\n\\n // Delete\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n }\\n }\\n\\n /// @dev Remove a NFT from a given address\\n /// Throws if `_from` is not the current owner.\\n function _removeTokenFrom(address _from, uint _tokenId) internal {\\n // Throws if `_from` is not the current owner\\n assert(idToOwner[_tokenId] == _from);\\n // Change the owner\\n idToOwner[_tokenId] = address(0);\\n // Update owner token index tracking\\n _removeTokenFromOwnerList(_from, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_from] -= 1;\\n }\\n\\n function _burn(uint _tokenId) internal {\\n require(_isApprovedOrOwner(msg.sender, _tokenId), \\\"caller is not owner nor approved\\\");\\n\\n address owner = ownerOf(_tokenId);\\n\\n // Clear approval\\n approve(address(0), _tokenId);\\n // checkpoint for gov\\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\\n // Remove token\\n _removeTokenFrom(msg.sender, _tokenId);\\n emit Transfer(owner, address(0), _tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public user_point_epoch;\\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\\n mapping(uint => LockedBalance) public locked;\\n uint public epoch;\\n mapping(uint => int128) public slope_changes; // time -> signed slope change\\n uint public supply;\\n\\n uint internal constant WEEK = 1 weeks;\\n uint internal constant MAXTIME = 4 * 365 * 86400;\\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\\n uint internal constant MULTIPLIER = 1 ether;\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @return Value of the slope\\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\\n uint uepoch = user_point_epoch[_tokenId];\\n return user_point_history[_tokenId][uepoch].slope;\\n }\\n\\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @param _idx User epoch number\\n /// @return Epoch time of the checkpoint\\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\\n return user_point_history[_tokenId][_idx].ts;\\n }\\n\\n /// @notice Get timestamp when `_tokenId`'s lock finishes\\n /// @param _tokenId User NFT\\n /// @return Epoch time of the lock end\\n function locked__end(uint _tokenId) external view returns (uint) {\\n return locked[_tokenId].end;\\n }\\n\\n /// @notice Record global and per-user data to checkpoint\\n /// @param _tokenId NFT token ID. No user checkpoint if 0\\n /// @param old_locked Pevious locked amount / end lock time for the user\\n /// @param new_locked New locked amount / end lock time for the user\\n function _checkpoint(\\n uint _tokenId,\\n LockedBalance memory old_locked,\\n LockedBalance memory new_locked\\n ) internal {\\n Point memory u_old;\\n Point memory u_new;\\n int128 old_dslope = 0;\\n int128 new_dslope = 0;\\n uint _epoch = epoch;\\n\\n if (_tokenId != 0) {\\n // Calculate slopes and biases\\n // Kept at zero when they have to\\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\\n u_old.slope = old_locked.amount / iMAXTIME;\\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\\n }\\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\\n u_new.slope = new_locked.amount / iMAXTIME;\\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\\n }\\n\\n // Read values of scheduled changes in the slope\\n // old_locked.end can be in the past and in the future\\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\\n old_dslope = slope_changes[old_locked.end];\\n if (new_locked.end != 0) {\\n if (new_locked.end == old_locked.end) {\\n new_dslope = old_dslope;\\n } else {\\n new_dslope = slope_changes[new_locked.end];\\n }\\n }\\n }\\n\\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\\n if (_epoch > 0) {\\n last_point = point_history[_epoch];\\n }\\n uint last_checkpoint = last_point.ts;\\n // initial_last_point is used for extrapolation to calculate block number\\n // (approximately, for *At methods) and save them\\n // as we cannot figure that out exactly from inside the contract\\n Point memory initial_last_point = last_point;\\n uint block_slope = 0; // dblock/dt\\n if (block.timestamp > last_point.ts) {\\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\\n }\\n // If last point is already recorded in this block, slope=0\\n // But that's ok b/c we know the block in such case\\n\\n // Go over weeks to fill history and calculate what the current point is\\n {\\n uint t_i = (last_checkpoint / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n // Hopefully it won't happen that this won't get used in 5 years!\\n // If it does, users will be able to withdraw but vote weight will be broken\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > block.timestamp) {\\n t_i = block.timestamp;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\\n last_point.slope += d_slope;\\n if (last_point.bias < 0) {\\n // This can happen\\n last_point.bias = 0;\\n }\\n if (last_point.slope < 0) {\\n // This cannot happen - just in case\\n last_point.slope = 0;\\n }\\n last_checkpoint = t_i;\\n last_point.ts = t_i;\\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\\n _epoch += 1;\\n if (t_i == block.timestamp) {\\n last_point.blk = block.number;\\n break;\\n } else {\\n point_history[_epoch] = last_point;\\n }\\n }\\n }\\n\\n epoch = _epoch;\\n // Now point_history is filled until t=now\\n\\n if (_tokenId != 0) {\\n // If last point was in this block, the slope change has been applied already\\n // But in such case we have 0 slope(s)\\n last_point.slope += (u_new.slope - u_old.slope);\\n last_point.bias += (u_new.bias - u_old.bias);\\n if (last_point.slope < 0) {\\n last_point.slope = 0;\\n }\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n }\\n\\n // Record the changed point into history\\n point_history[_epoch] = last_point;\\n\\n if (_tokenId != 0) {\\n // Schedule the slope changes (slope is going down)\\n // We subtract new_user_slope from [new_locked.end]\\n // and add old_user_slope to [old_locked.end]\\n if (old_locked.end > block.timestamp) {\\n // old_dslope was - u_old.slope, so we cancel that\\n old_dslope += u_old.slope;\\n if (new_locked.end == old_locked.end) {\\n old_dslope -= u_new.slope; // It was a new deposit, not extension\\n }\\n slope_changes[old_locked.end] = old_dslope;\\n }\\n\\n if (new_locked.end > block.timestamp) {\\n if (new_locked.end > old_locked.end) {\\n new_dslope -= u_new.slope; // old slope disappeared at this point\\n slope_changes[new_locked.end] = new_dslope;\\n }\\n // else: we recorded it already in old_dslope\\n }\\n // Now handle user history\\n uint user_epoch = user_point_epoch[_tokenId] + 1;\\n\\n user_point_epoch[_tokenId] = user_epoch;\\n u_new.ts = block.timestamp;\\n u_new.blk = block.number;\\n user_point_history[_tokenId][user_epoch] = u_new;\\n }\\n }\\n\\n /// @notice Deposit and lock tokens for a user\\n /// @param _tokenId NFT that holds lock\\n /// @param _value Amount to deposit\\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\\n /// @param locked_balance Previous locked amount / timestamp\\n /// @param deposit_type The type of deposit\\n function _deposit_for(\\n uint _tokenId,\\n uint _value,\\n uint unlock_time,\\n LockedBalance memory locked_balance,\\n DepositType deposit_type\\n ) internal {\\n LockedBalance memory _locked = locked_balance;\\n uint supply_before = supply;\\n\\n supply = supply_before + _value;\\n LockedBalance memory old_locked;\\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\\n // Adding to existing lock, or if a lock is expired - creating a new one\\n _locked.amount += int128(int256(_value));\\n if (unlock_time != 0) {\\n _locked.end = unlock_time;\\n }\\n locked[_tokenId] = _locked;\\n\\n // Possibilities:\\n // Both old_locked.end could be current or expired (>/< block.timestamp)\\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\\n // _locked.end > block.timestamp (always)\\n _checkpoint(_tokenId, old_locked, _locked);\\n\\n address from = msg.sender;\\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\\n assert(IERC20(token).transferFrom(from, address(this), _value));\\n }\\n\\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\\n emit Supply(supply_before, supply_before + _value);\\n }\\n\\n function block_number() external view returns (uint) {\\n return block.number;\\n }\\n\\n /// @notice Record global data to checkpoint\\n function checkpoint() external {\\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\\n }\\n\\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\\n /// cannot extend their locktime and deposit for a brand new user\\n /// @param _tokenId lock NFT\\n /// @param _value Amount to add to user's lock\\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n require(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_value > 0); // dev: need non-zero value\\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n ++tokenId;\\n uint _tokenId = tokenId;\\n _mint(_to, _tokenId);\\n\\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\\n return _tokenId;\\n }\\n\\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, msg.sender);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, _to);\\n }\\n\\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\\n /// @param _value Amount of tokens to deposit and add to the lock\\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n assert(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\\n }\\n\\n /// @notice Extend the unlock time for `_tokenId`\\n /// @param _lock_duration New number of seconds until tokens unlock\\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_locked.end > block.timestamp, 'Lock expired');\\n require(_locked.amount > 0, 'Nothing is locked');\\n require(unlock_time > _locked.end, 'Can only increase lock duration');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\\n }\\n\\n /// @notice Withdraw all tokens for `_tokenId`\\n /// @dev Only possible if the lock has expired\\n function withdraw(uint _tokenId) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n require(block.timestamp >= _locked.end, \\\"The lock didn't expire\\\");\\n uint value = uint(int256(_locked.amount));\\n\\n locked[_tokenId] = LockedBalance(0,0);\\n uint supply_before = supply;\\n supply = supply_before - value;\\n\\n // old_locked can have either expired <= timestamp or zero end\\n // _locked has only 0 end\\n // Both can have >= 0 amount\\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\\n\\n assert(IERC20(token).transfer(msg.sender, value));\\n\\n // Burn the NFT\\n _burn(_tokenId);\\n\\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\\n emit Supply(supply_before, supply_before - value);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\\n // They measure the weights for the purpose of voting, so they don't represent\\n // real coins.\\n\\n /// @notice Binary search to estimate timestamp for block number\\n /// @param _block Block to find\\n /// @param max_epoch Don't go beyond this epoch\\n /// @return Approximate timestamp for block\\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\\n // Binary search\\n uint _min = 0;\\n uint _max = max_epoch;\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (point_history[_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n /// @notice Get the current voting power for `_tokenId`\\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\\n /// @param _tokenId NFT for lock\\n /// @param _t Epoch time to return voting power at\\n /// @return User voting power\\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\\n uint _epoch = user_point_epoch[_tokenId];\\n if (_epoch == 0) {\\n return 0;\\n } else {\\n Point memory last_point = user_point_history[_tokenId][_epoch];\\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(int256(last_point.bias));\\n }\\n }\\n\\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\\n if (ownership_change[_tokenId] == block.number) return 0;\\n return _balanceOfNFT(_tokenId, block.timestamp);\\n }\\n\\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\\n return _balanceOfNFT(_tokenId, _t);\\n }\\n\\n /// @notice Measure voting power of `_tokenId` at block height `_block`\\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\\n /// @param _tokenId User's wallet NFT\\n /// @param _block Block to calculate the voting power at\\n /// @return Voting power\\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\\n // Copying and pasting totalSupply code because Vyper cannot pass by\\n // reference yet\\n assert(_block <= block.number);\\n\\n // Binary search\\n uint _min = 0;\\n uint _max = user_point_epoch[_tokenId];\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (user_point_history[_tokenId][_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n\\n Point memory upoint = user_point_history[_tokenId][_min];\\n\\n uint max_epoch = epoch;\\n uint _epoch = _find_block_epoch(_block, max_epoch);\\n Point memory point_0 = point_history[_epoch];\\n uint d_block = 0;\\n uint d_t = 0;\\n if (_epoch < max_epoch) {\\n Point memory point_1 = point_history[_epoch + 1];\\n d_block = point_1.blk - point_0.blk;\\n d_t = point_1.ts - point_0.ts;\\n } else {\\n d_block = block.number - point_0.blk;\\n d_t = block.timestamp - point_0.ts;\\n }\\n uint block_time = point_0.ts;\\n if (d_block != 0) {\\n block_time += (d_t * (_block - point_0.blk)) / d_block;\\n }\\n\\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\\n if (upoint.bias >= 0) {\\n return uint(uint128(upoint.bias));\\n } else {\\n return 0;\\n }\\n }\\n\\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\\n return _balanceOfAtNFT(_tokenId, _block);\\n }\\n\\n /// @notice Calculate total voting power at some point in the past\\n /// @param _block Block to calculate the total voting power at\\n /// @return Total voting power at `_block`\\n function totalSupplyAt(uint _block) external view returns (uint) {\\n assert(_block <= block.number);\\n uint _epoch = epoch;\\n uint target_epoch = _find_block_epoch(_block, _epoch);\\n\\n Point memory point = point_history[target_epoch];\\n uint dt = 0;\\n if (target_epoch < _epoch) {\\n Point memory point_next = point_history[target_epoch + 1];\\n if (point.blk != point_next.blk) {\\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\\n }\\n } else {\\n if (point.blk != block.number) {\\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\\n }\\n }\\n // Now dt contains info on how far are we beyond point\\n return _supply_at(point, point.ts + dt);\\n }\\n /// @notice Calculate total voting power at some point in the past\\n /// @param point The point (bias/slope) to start search from\\n /// @param t Time to calculate the total voting power at\\n /// @return Total voting power at that time\\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\\n Point memory last_point = point;\\n uint t_i = (last_point.ts / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > t) {\\n t_i = t;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\\n if (t_i == t) {\\n break;\\n }\\n last_point.slope += d_slope;\\n last_point.ts = t_i;\\n }\\n\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(uint128(last_point.bias));\\n }\\n\\n function totalSupply() external view returns (uint) {\\n return totalSupplyAtT(block.timestamp);\\n }\\n\\n /// @notice Calculate total voting power\\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\\n /// @return Total voting power\\n function totalSupplyAtT(uint t) public view returns (uint) {\\n uint _epoch = epoch;\\n Point memory last_point = point_history[_epoch];\\n return _supply_at(last_point, t);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public attachments;\\n mapping(uint => bool) public voted;\\n\\n function setVoter(address _voter) external {\\n require(msg.sender == voter);\\n voter = _voter;\\n }\\n\\n function voting(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = true;\\n }\\n\\n function abstain(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = false;\\n }\\n\\n function attach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] + 1;\\n }\\n\\n function detach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] - 1;\\n }\\n\\n function merge(uint _from, uint _to) external {\\n require(attachments[_from] == 0 && !voted[_from], \\\"attached\\\");\\n require(_from != _to);\\n require(_isApprovedOrOwner(msg.sender, _from));\\n require(_isApprovedOrOwner(msg.sender, _to));\\n\\n LockedBalance memory _locked0 = locked[_from];\\n LockedBalance memory _locked1 = locked[_to];\\n uint value0 = uint(int256(_locked0.amount));\\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\\n\\n locked[_from] = LockedBalance(0, 0);\\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\\n _burn(_from);\\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of each accounts delegate\\n mapping(address => address) private _delegates;\\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\\n\\n /// @notice A record of delegated token checkpoints for each account, by index\\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint32) public numCheckpoints;\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping(address => uint) public nonces;\\n\\n /**\\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\\n * the delegator's own address if they haven't delegated.\\n * This avoids having to delegate to oneself.\\n */\\n function delegates(address delegator) public view returns (address) {\\n address current = _delegates[delegator];\\n return current == address(0) ? delegator : current;\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getVotes(address account) external view returns (uint) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n votes = votes + _balanceOfNFT(tId, block.timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint storage cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPastVotes(address account, uint timestamp)\\n public\\n view\\n returns (uint)\\n {\\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\\n // Sum votes\\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n // Use the provided input timestamp here to get the right decay\\n votes = votes + _balanceOfNFT(tId, timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\\n return totalSupplyAtT(timestamp);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _moveTokenDelegates(\\n address srcRep,\\n address dstRep,\\n uint _tokenId\\n ) internal {\\n if (srcRep != dstRep && _tokenId > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except _tokenId\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (tId != _tokenId) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n // All the same plus _tokenId\\n require(\\n dstRepOld.length + 1 <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n dstRepNew.push(_tokenId);\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _findWhatCheckpointToWrite(address account)\\n internal\\n view\\n returns (uint32)\\n {\\n uint _timestamp = block.timestamp;\\n uint32 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n return _nCheckPoints - 1;\\n } else {\\n return _nCheckPoints;\\n }\\n }\\n\\n function _moveAllDelegates(\\n address owner,\\n address srcRep,\\n address dstRep\\n ) internal {\\n // You can only redelegate what you own\\n if (srcRep != dstRep) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except what owner owns\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (idToOwner[tId] != owner) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n uint ownerTokenCount = ownerToNFTokenCount[owner];\\n require(\\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n // All the same\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n // Plus all that's owned\\n for (uint i = 0; i < ownerTokenCount; i++) {\\n uint tId = ownerToNFTokenIdList[owner][i];\\n dstRepNew.push(tId);\\n }\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\\n address currentDelegate = delegates(delegator);\\n\\n _delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n _moveAllDelegates(delegator, currentDelegate, delegatee);\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n if (delegatee == address(0)) delegatee = msg.sender;\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n function delegateBySig(\\n address delegatee,\\n uint nonce,\\n uint expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public {\\n bytes32 domainSeparator = keccak256(\\n abi.encode(\\n DOMAIN_TYPEHASH,\\n keccak256(bytes(name)),\\n keccak256(bytes(version)),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 structHash = keccak256(\\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash)\\n );\\n address signatory = ecrecover(digest, v, r, s);\\n require(\\n signatory != address(0),\\n \\\"VotingEscrow::delegateBySig: invalid signature\\\"\\n );\\n require(\\n nonce == nonces[signatory]++,\\n \\\"VotingEscrow::delegateBySig: invalid nonce\\\"\\n );\\n require(\\n block.timestamp <= expiry,\\n \\\"VotingEscrow::delegateBySig: signature expired\\\"\\n );\\n return _delegate(signatory, delegatee);\\n }\\n}\\n\",\"keccak256\":\"0x37e5ee306472a946a665be22bc1d370d566a575a1fac84f72f97b0575571d40d\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x41bbb2c41036ca64b2f6c9e973e8cfaa113ebc42af86702cd0d267f915a7e886\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60a06040526006805460ff191660011790553480156200001e57600080fd5b5060405162004a1c38038062004a1c8339810160408190526200004191620001b8565b6001600160a01b0382811660805260008054336001600160a01b031991821681178355600180548316909117815560028054909216938516939093179055437f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f0155427f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f005560046020527f9fe05126d2d9ecf60592e254dead906a4b2e492f36cca727682c38e9008c6ac1805460ff1990811684179091557f4267c0a6fd96b7a87f183ee8744f24d011423cd0e0142b3f563f183d8d9a456b8054821684179055635b5e139f60e01b82527e24030bcf4927897dffe721c2d8dda4bfd8910861687c42b03a463b43b04147805490911690921790915560055460405190913091600080516020620049fc833981519152908290a46005546040516000903090600080516020620049fc833981519152908390a45050620001f0565b80516001600160a01b0381168114620001b357600080fd5b919050565b60008060408385031215620001cc57600080fd5b620001d7836200019b565b9150620001e7602084016200019b565b90509250929050565b6080516147e26200021a60003960008181610b220152818161101801526133b501526147e26000f3fe608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea2646970667358221220245dd4da7f4eb9a32bfed7d913c4bc4316ce8585e535cd4e280eb72cdc5dab1c64736f6c634300080d0033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea2646970667358221220245dd4da7f4eb9a32bfed7d913c4bc4316ce8585e535cd4e280eb72cdc5dab1c64736f6c634300080d0033", + "solcInputHash": "816572db58a4a8203fcf6f77728173df", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token_addr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"art_proxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromDelegate\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toDelegate\",\"type\":\"address\"}],\"name\":\"DelegateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"DelegateVotesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"locktime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum VotingEscrow.DepositType\",\"name\":\"deposit_type\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"prevSupply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"supply\",\"type\":\"uint256\"}],\"name\":\"Supply\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DELEGATION_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_DELEGATES\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"abstain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_approved\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"artProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"attach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"attachments\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"balanceOfAtNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_t\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFTAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"block_number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"checkpoints\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"create_lock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"create_lock_for\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"}],\"name\":\"delegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"delegateBySig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"}],\"name\":\"delegates\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"deposit_for\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"detach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastTotalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotesIndex\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"get_last_user_slope\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"increase_amount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"increase_unlock_time\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"isApprovedOrOwner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"locked\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"amount\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"locked__end\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_from\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_to\",\"type\":\"uint256\"}],\"name\":\"merge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"numCheckpoints\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ownership_change\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_proxy\",\"type\":\"address\"}],\"name\":\"setArtProxy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voter\",\"type\":\"address\"}],\"name\":\"setVoter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"slope_changes\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenIndex\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"t\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAtT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_idx\",\"type\":\"uint256\"}],\"name\":\"user_point_history__ts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"voted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"voting\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\",\"details\":\"Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\",\"kind\":\"dev\",\"methods\":{\"approve(address,uint256)\":{\"details\":\"Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address. Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner. Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP) Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"Address to be approved for the given NFT ID.\",\"_tokenId\":\"ID of the token to be approved.\"}},\"balanceOf(address)\":{\"details\":\"Returns the number of NFTs owned by `_owner`. Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\",\"params\":{\"_owner\":\"Address for whom to query the balance.\"}},\"constructor\":{\"params\":{\"token_addr\":\"`FLOW` token address\"}},\"create_lock(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_value\":\"Amount to deposit\"}},\"create_lock_for(uint256,uint256,address)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_to\":\"Address to deposit\",\"_value\":\"Amount to deposit\"}},\"delegate(address)\":{\"params\":{\"delegatee\":\"The address to delegate votes to\"}},\"delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Delegates votes from signer to `delegatee`.\"},\"deposit_for(uint256,uint256)\":{\"details\":\"Anyone (even a smart contract) can deposit for someone else, but cannot extend their locktime and deposit for a brand new user\",\"params\":{\"_tokenId\":\"lock NFT\",\"_value\":\"Amount to add to user's lock\"}},\"getApproved(uint256)\":{\"details\":\"Get the approved address for a single NFT.\",\"params\":{\"_tokenId\":\"ID of the NFT to query the approval of.\"}},\"getVotes(address)\":{\"params\":{\"account\":\"The address to get votes balance\"},\"returns\":{\"_0\":\"The number of current votes for `account`\"}},\"get_last_user_slope(uint256)\":{\"params\":{\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Value of the slope\"}},\"increase_amount(uint256,uint256)\":{\"params\":{\"_value\":\"Amount of tokens to deposit and add to the lock\"}},\"increase_unlock_time(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"New number of seconds until tokens unlock\"}},\"isApprovedForAll(address,address)\":{\"details\":\"Checks if `_operator` is an approved operator for `_owner`.\",\"params\":{\"_operator\":\"The address that acts on behalf of the owner.\",\"_owner\":\"The address that owns the NFTs.\"}},\"locked__end(uint256)\":{\"params\":{\"_tokenId\":\"User NFT\"},\"returns\":{\"_0\":\"Epoch time of the lock end\"}},\"ownerOf(uint256)\":{\"details\":\"Returns the address of the owner of the NFT.\",\"params\":{\"_tokenId\":\"The identifier for an NFT.\"}},\"safeTransferFrom(address,address,uint256)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"safeTransferFrom(address,address,uint256,bytes)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_data\":\"Additional data with no specified format, sent in call to `_to`.\",\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"details\":\"Enables or disables approval for a third party (\\\"operator\\\") to manage all of `msg.sender`'s assets. It also emits the ApprovalForAll event. Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"True if the operators is approved, false to revoke approval.\",\"_operator\":\"Address to add to the set of authorized operators.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Interface identification is specified in ERC-165.\",\"params\":{\"_interfaceID\":\"Id of the interface\"}},\"tokenOfOwnerByIndex(address,uint256)\":{\"details\":\"Get token by index\"},\"tokenURI(uint256)\":{\"details\":\"Returns current token URI metadata\",\"params\":{\"_tokenId\":\"Token ID to fetch URI for.\"}},\"totalSupplyAt(uint256)\":{\"params\":{\"_block\":\"Block to calculate the total voting power at\"},\"returns\":{\"_0\":\"Total voting power at `_block`\"}},\"totalSupplyAtT(uint256)\":{\"details\":\"Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\",\"returns\":{\"_0\":\"Total voting power\"}},\"transferFrom(address,address,uint256)\":{\"details\":\"Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"user_point_history__ts(uint256,uint256)\":{\"params\":{\"_idx\":\"User epoch number\",\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Epoch time of the checkpoint\"}},\"withdraw(uint256)\":{\"details\":\"Only possible if the lock has expired\"}},\"stateVariables\":{\"ERC165_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC165\"},\"ERC721_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721\"},\"ERC721_METADATA_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721Metadata\"},\"_not_entered\":{\"details\":\"reentrancy guard\"},\"idToApprovals\":{\"details\":\"Mapping from NFT ID to approved address.\"},\"idToOwner\":{\"details\":\"Mapping from NFT ID to the address that owns it.\"},\"name\":{\"details\":\"Returns the token collection name.\"},\"ownerToNFTokenCount\":{\"details\":\"Mapping from owner address to count of his tokens.\"},\"ownerToNFTokenIdList\":{\"details\":\"Mapping from owner address to mapping of index to tokenIds\"},\"ownerToOperators\":{\"details\":\"Mapping from owner address to mapping of operator addresses.\"},\"supportedInterfaces\":{\"details\":\"Mapping of interface id to bool about whether or not it's supported\"},\"symbol\":{\"details\":\"Returns the token collection symbol.\"},\"tokenId\":{\"details\":\"Current count of token\"},\"tokenToOwnerIndex\":{\"details\":\"Mapping from NFT ID to index of owner\"}},\"title\":\"Voting Escrow\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DELEGATION_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the delegation struct used by the contract\"},\"DOMAIN_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the contract's domain\"},\"checkpoint()\":{\"notice\":\"Record global data to checkpoint\"},\"checkpoints(address,uint32)\":{\"notice\":\"A record of delegated token checkpoints for each account, by index\"},\"constructor\":{\"notice\":\"Contract constructor\"},\"create_lock(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\"},\"create_lock_for(uint256,uint256,address)\":{\"notice\":\"Deposit `_value` tokens for `_to` and lock for `_lock_duration`\"},\"delegate(address)\":{\"notice\":\"Delegate votes from `msg.sender` to `delegatee`\"},\"delegates(address)\":{\"notice\":\"Overrides the standard `Comp.sol` delegates mapping to return the delegator's own address if they haven't delegated. This avoids having to delegate to oneself.\"},\"deposit_for(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `_tokenId` and add to the lock\"},\"getVotes(address)\":{\"notice\":\"Gets the current votes balance for `account`\"},\"get_last_user_slope(uint256)\":{\"notice\":\"Get the most recently recorded rate of voting power decrease for `_tokenId`\"},\"increase_amount(uint256,uint256)\":{\"notice\":\"Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\"},\"increase_unlock_time(uint256,uint256)\":{\"notice\":\"Extend the unlock time for `_tokenId`\"},\"locked__end(uint256)\":{\"notice\":\"Get timestamp when `_tokenId`'s lock finishes\"},\"nonces(address)\":{\"notice\":\"A record of states for signing / validating signatures\"},\"numCheckpoints(address)\":{\"notice\":\"The number of checkpoints for each account\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"This works even if sender doesn't own any tokens at the time.\"},\"totalSupplyAt(uint256)\":{\"notice\":\"Calculate total voting power at some point in the past\"},\"totalSupplyAtT(uint256)\":{\"notice\":\"Calculate total voting power\"},\"transferFrom(address,address,uint256)\":{\"notice\":\"The caller is responsible to confirm that `_to` is capable of receiving NFTs or else they maybe be permanently lost.\"},\"user_point_history__ts(uint256,uint256)\":{\"notice\":\"Get the timestamp for checkpoint `_idx` for `_tokenId`\"},\"withdraw(uint256)\":{\"notice\":\"Withdraw all tokens for `_tokenId`\"}},\"notice\":\"veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFTVotes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VotingEscrow.sol\":\"VotingEscrow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735353339323034313033\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VotingEscrow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IERC721, IERC721Metadata} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {IERC721Receiver} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {IERC20} from \\\"contracts/interfaces/IERC20.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\nimport {IVotingEscrow} from \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/// @title Voting Escrow\\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\\n enum DepositType {\\n DEPOSIT_FOR_TYPE,\\n CREATE_LOCK_TYPE,\\n INCREASE_LOCK_AMOUNT,\\n INCREASE_UNLOCK_TIME,\\n MERGE_TYPE\\n }\\n\\n struct LockedBalance {\\n int128 amount;\\n uint end;\\n }\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint ts;\\n uint blk; // block\\n }\\n /* We cannot really do block numbers per se b/c slope is per time, not per block\\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\\n * What we can do is to extrapolate ***At functions */\\n\\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\\n struct Checkpoint {\\n uint timestamp;\\n uint[] tokenIds;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Deposit(\\n address indexed provider,\\n uint tokenId,\\n uint value,\\n uint indexed locktime,\\n DepositType deposit_type,\\n uint ts\\n );\\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\\n event Supply(uint prevSupply, uint supply);\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n address public immutable token;\\n address public voter;\\n address public team;\\n address public artProxy;\\n\\n mapping(uint => Point) public point_history; // epoch -> unsigned point\\n\\n /// @dev Mapping of interface id to bool about whether or not it's supported\\n mapping(bytes4 => bool) internal supportedInterfaces;\\n\\n /// @dev ERC165 interface ID of ERC165\\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\\n\\n /// @dev ERC165 interface ID of ERC721\\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\\n\\n /// @dev ERC165 interface ID of ERC721Metadata\\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\\n\\n /// @dev Current count of token\\n uint internal tokenId;\\n\\n /// @notice Contract constructor\\n /// @param token_addr `FLOW` token address\\n constructor(address token_addr, address art_proxy) {\\n token = token_addr;\\n voter = msg.sender;\\n team = msg.sender;\\n artProxy = art_proxy;\\n\\n point_history[0].blk = block.number;\\n point_history[0].ts = block.timestamp;\\n\\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\\n\\n // mint-ish\\n emit Transfer(address(0), address(this), tokenId);\\n // burn-ish\\n emit Transfer(address(this), address(0), tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n MODIFIERS\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev reentrancy guard\\n uint8 internal constant _not_entered = 1;\\n uint8 internal constant _entered = 2;\\n uint8 internal _entered_state = 1;\\n modifier nonreentrant() {\\n require(_entered_state == _not_entered);\\n _entered_state = _entered;\\n _;\\n _entered_state = _not_entered;\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string constant public name = \\\"veNFT\\\";\\n string constant public symbol = \\\"veNFT\\\";\\n string constant public version = \\\"1.0.0\\\";\\n uint8 constant public decimals = 18;\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team);\\n team = _team;\\n }\\n\\n function setArtProxy(address _proxy) external {\\n require(msg.sender == team);\\n artProxy = _proxy;\\n }\\n\\n /// @dev Returns current token URI metadata\\n /// @param _tokenId Token ID to fetch URI for.\\n function tokenURI(uint _tokenId) external view returns (string memory) {\\n require(idToOwner[_tokenId] != address(0), \\\"Query for nonexistent token\\\");\\n LockedBalance memory _locked = locked[_tokenId];\\n return IVeArtProxy(artProxy)._tokenURI(\\n _tokenId,\\n _balanceOfNFT(_tokenId, block.timestamp),\\n _locked.end,\\n uint(int256(_locked.amount))\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 BALANCE/OWNER STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to the address that owns it.\\n mapping(uint => address) internal idToOwner;\\n\\n /// @dev Mapping from owner address to count of his tokens.\\n mapping(address => uint) internal ownerToNFTokenCount;\\n\\n /// @dev Returns the address of the owner of the NFT.\\n /// @param _tokenId The identifier for an NFT.\\n function ownerOf(uint _tokenId) public view returns (address) {\\n return idToOwner[_tokenId];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function _balance(address _owner) internal view returns (uint) {\\n return ownerToNFTokenCount[_owner];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function balanceOf(address _owner) external view returns (uint) {\\n return _balance(_owner);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 APPROVAL STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to approved address.\\n mapping(uint => address) internal idToApprovals;\\n\\n /// @dev Mapping from owner address to mapping of operator addresses.\\n mapping(address => mapping(address => bool)) internal ownerToOperators;\\n\\n mapping(uint => uint) public ownership_change;\\n\\n /// @dev Get the approved address for a single NFT.\\n /// @param _tokenId ID of the NFT to query the approval of.\\n function getApproved(uint _tokenId) external view returns (address) {\\n return idToApprovals[_tokenId];\\n }\\n\\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\\n /// @param _owner The address that owns the NFTs.\\n /// @param _operator The address that acts on behalf of the owner.\\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\\n return (ownerToOperators[_owner])[_operator];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\\n /// @param _approved Address to be approved for the given NFT ID.\\n /// @param _tokenId ID of the token to be approved.\\n function approve(address _approved, uint _tokenId) public {\\n address owner = idToOwner[_tokenId];\\n // Throws if `_tokenId` is not a valid NFT\\n require(owner != address(0));\\n // Throws if `_approved` is the current owner\\n require(_approved != owner);\\n // Check requirements\\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\\n require(senderIsOwner || senderIsApprovedForAll);\\n // Set the approval\\n idToApprovals[_tokenId] = _approved;\\n emit Approval(owner, _approved, _tokenId);\\n }\\n\\n /// @dev Enables or disables approval for a third party (\\\"operator\\\") to manage all of\\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\\n /// @notice This works even if sender doesn't own any tokens at the time.\\n /// @param _operator Address to add to the set of authorized operators.\\n /// @param _approved True if the operators is approved, false to revoke approval.\\n function setApprovalForAll(address _operator, bool _approved) external {\\n // Throws if `_operator` is the `msg.sender`\\n assert(_operator != msg.sender);\\n ownerToOperators[msg.sender][_operator] = _approved;\\n emit ApprovalForAll(msg.sender, _operator, _approved);\\n }\\n\\n /* TRANSFER FUNCTIONS */\\n /// @dev Clear an approval of a given address\\n /// Throws if `_owner` is not the current owner.\\n function _clearApproval(address _owner, uint _tokenId) internal {\\n // Throws if `_owner` is not the current owner\\n assert(idToOwner[_tokenId] == _owner);\\n if (idToApprovals[_tokenId] != address(0)) {\\n // Reset approvals\\n idToApprovals[_tokenId] = address(0);\\n }\\n }\\n\\n /// @dev Returns whether the given spender can transfer a given token ID\\n /// @param _spender address of the spender to query\\n /// @param _tokenId uint ID of the token to be transferred\\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\\n address owner = idToOwner[_tokenId];\\n bool spenderIsOwner = owner == _spender;\\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\\n }\\n\\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\\n return _isApprovedOrOwner(_spender, _tokenId);\\n }\\n\\n /// @dev Exeute transfer of a NFT.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_tokenId` is not a valid NFT.\\n function _transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n address _sender\\n ) internal {\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n // Check requirements\\n require(_isApprovedOrOwner(_sender, _tokenId));\\n // Clear approval. Throws if `_from` is not the current owner\\n _clearApproval(_from, _tokenId);\\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\\n _removeTokenFrom(_from, _tokenId);\\n // auto re-delegate\\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\\n // Add NFT\\n _addTokenTo(_to, _tokenId);\\n // Set the block of ownership transfer (for Flash NFT protection)\\n ownership_change[_tokenId] = block.number;\\n // Log the transfer\\n emit Transfer(_from, _to, _tokenId);\\n }\\n\\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\\n /// they maybe be permanently lost.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n safeTransferFrom(_from, _to, _tokenId, \\\"\\\");\\n }\\n\\n function _isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n uint size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n /// @param _data Additional data with no specified format, sent in call to `_to`.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n bytes memory _data\\n ) public {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n\\n if (_isContract(_to)) {\\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\\n revert(\\\"ERC721: ERC721Receiver rejected tokens\\\");\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert('ERC721: transfer to non ERC721Receiver implementer');\\n } else {\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC165 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Interface identification is specified in ERC-165.\\n /// @param _interfaceID Id of the interface\\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\\n return supportedInterfaces[_interfaceID];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from owner address to mapping of index to tokenIds\\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\\n\\n /// @dev Mapping from NFT ID to index of owner\\n mapping(uint => uint) internal tokenToOwnerIndex;\\n\\n /// @dev Get token by index\\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\\n return ownerToNFTokenIdList[_owner][_tokenIndex];\\n }\\n\\n /// @dev Add a NFT to an index mapping to a given address\\n /// @param _to address of the receiver\\n /// @param _tokenId uint ID Of the token to be added\\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\\n uint current_count = _balance(_to);\\n\\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\\n tokenToOwnerIndex[_tokenId] = current_count;\\n }\\n\\n /// @dev Add a NFT to a given address\\n /// Throws if `_tokenId` is owned by someone.\\n function _addTokenTo(address _to, uint _tokenId) internal {\\n // Throws if `_tokenId` is owned by someone\\n assert(idToOwner[_tokenId] == address(0));\\n // Change the owner\\n idToOwner[_tokenId] = _to;\\n // Update owner token index tracking\\n _addTokenToOwnerList(_to, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_to] += 1;\\n }\\n\\n /// @dev Function to mint tokens\\n /// Throws if `_to` is zero address.\\n /// Throws if `_tokenId` is owned by someone.\\n /// @param _to The address that will receive the minted tokens.\\n /// @param _tokenId The token id to mint.\\n /// @return A boolean that indicates if the operation was successful.\\n function _mint(address _to, uint _tokenId) internal returns (bool) {\\n // Throws if `_to` is zero address\\n assert(_to != address(0));\\n // checkpoint for gov\\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\\n // Add NFT. Throws if `_tokenId` is owned by someone\\n _addTokenTo(_to, _tokenId);\\n emit Transfer(address(0), _to, _tokenId);\\n return true;\\n }\\n\\n /// @dev Remove a NFT from an index mapping to a given address\\n /// @param _from address of the sender\\n /// @param _tokenId uint ID Of the token to be removed\\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\\n // Delete\\n uint current_count = _balance(_from) - 1;\\n uint current_index = tokenToOwnerIndex[_tokenId];\\n\\n if (current_count == current_index) {\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n } else {\\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\\n\\n // Add\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[lastTokenId] = current_index;\\n\\n // Delete\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n }\\n }\\n\\n /// @dev Remove a NFT from a given address\\n /// Throws if `_from` is not the current owner.\\n function _removeTokenFrom(address _from, uint _tokenId) internal {\\n // Throws if `_from` is not the current owner\\n assert(idToOwner[_tokenId] == _from);\\n // Change the owner\\n idToOwner[_tokenId] = address(0);\\n // Update owner token index tracking\\n _removeTokenFromOwnerList(_from, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_from] -= 1;\\n }\\n\\n function _burn(uint _tokenId) internal {\\n require(_isApprovedOrOwner(msg.sender, _tokenId), \\\"caller is not owner nor approved\\\");\\n\\n address owner = ownerOf(_tokenId);\\n\\n // Clear approval\\n approve(address(0), _tokenId);\\n // checkpoint for gov\\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\\n // Remove token\\n _removeTokenFrom(msg.sender, _tokenId);\\n emit Transfer(owner, address(0), _tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public user_point_epoch;\\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\\n mapping(uint => LockedBalance) public locked;\\n uint public epoch;\\n mapping(uint => int128) public slope_changes; // time -> signed slope change\\n uint public supply;\\n\\n uint internal constant WEEK = 1 weeks;\\n uint internal constant MAXTIME = 4 * 365 * 86400;\\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\\n uint internal constant MULTIPLIER = 1 ether;\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @return Value of the slope\\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\\n uint uepoch = user_point_epoch[_tokenId];\\n return user_point_history[_tokenId][uepoch].slope;\\n }\\n\\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @param _idx User epoch number\\n /// @return Epoch time of the checkpoint\\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\\n return user_point_history[_tokenId][_idx].ts;\\n }\\n\\n /// @notice Get timestamp when `_tokenId`'s lock finishes\\n /// @param _tokenId User NFT\\n /// @return Epoch time of the lock end\\n function locked__end(uint _tokenId) external view returns (uint) {\\n return locked[_tokenId].end;\\n }\\n\\n /// @notice Record global and per-user data to checkpoint\\n /// @param _tokenId NFT token ID. No user checkpoint if 0\\n /// @param old_locked Pevious locked amount / end lock time for the user\\n /// @param new_locked New locked amount / end lock time for the user\\n function _checkpoint(\\n uint _tokenId,\\n LockedBalance memory old_locked,\\n LockedBalance memory new_locked\\n ) internal {\\n Point memory u_old;\\n Point memory u_new;\\n int128 old_dslope = 0;\\n int128 new_dslope = 0;\\n uint _epoch = epoch;\\n\\n if (_tokenId != 0) {\\n // Calculate slopes and biases\\n // Kept at zero when they have to\\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\\n u_old.slope = old_locked.amount / iMAXTIME;\\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\\n }\\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\\n u_new.slope = new_locked.amount / iMAXTIME;\\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\\n }\\n\\n // Read values of scheduled changes in the slope\\n // old_locked.end can be in the past and in the future\\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\\n old_dslope = slope_changes[old_locked.end];\\n if (new_locked.end != 0) {\\n if (new_locked.end == old_locked.end) {\\n new_dslope = old_dslope;\\n } else {\\n new_dslope = slope_changes[new_locked.end];\\n }\\n }\\n }\\n\\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\\n if (_epoch > 0) {\\n last_point = point_history[_epoch];\\n }\\n uint last_checkpoint = last_point.ts;\\n // initial_last_point is used for extrapolation to calculate block number\\n // (approximately, for *At methods) and save them\\n // as we cannot figure that out exactly from inside the contract\\n Point memory initial_last_point = last_point;\\n uint block_slope = 0; // dblock/dt\\n if (block.timestamp > last_point.ts) {\\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\\n }\\n // If last point is already recorded in this block, slope=0\\n // But that's ok b/c we know the block in such case\\n\\n // Go over weeks to fill history and calculate what the current point is\\n {\\n uint t_i = (last_checkpoint / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n // Hopefully it won't happen that this won't get used in 5 years!\\n // If it does, users will be able to withdraw but vote weight will be broken\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > block.timestamp) {\\n t_i = block.timestamp;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\\n last_point.slope += d_slope;\\n if (last_point.bias < 0) {\\n // This can happen\\n last_point.bias = 0;\\n }\\n if (last_point.slope < 0) {\\n // This cannot happen - just in case\\n last_point.slope = 0;\\n }\\n last_checkpoint = t_i;\\n last_point.ts = t_i;\\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\\n _epoch += 1;\\n if (t_i == block.timestamp) {\\n last_point.blk = block.number;\\n break;\\n } else {\\n point_history[_epoch] = last_point;\\n }\\n }\\n }\\n\\n epoch = _epoch;\\n // Now point_history is filled until t=now\\n\\n if (_tokenId != 0) {\\n // If last point was in this block, the slope change has been applied already\\n // But in such case we have 0 slope(s)\\n last_point.slope += (u_new.slope - u_old.slope);\\n last_point.bias += (u_new.bias - u_old.bias);\\n if (last_point.slope < 0) {\\n last_point.slope = 0;\\n }\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n }\\n\\n // Record the changed point into history\\n point_history[_epoch] = last_point;\\n\\n if (_tokenId != 0) {\\n // Schedule the slope changes (slope is going down)\\n // We subtract new_user_slope from [new_locked.end]\\n // and add old_user_slope to [old_locked.end]\\n if (old_locked.end > block.timestamp) {\\n // old_dslope was - u_old.slope, so we cancel that\\n old_dslope += u_old.slope;\\n if (new_locked.end == old_locked.end) {\\n old_dslope -= u_new.slope; // It was a new deposit, not extension\\n }\\n slope_changes[old_locked.end] = old_dslope;\\n }\\n\\n if (new_locked.end > block.timestamp) {\\n if (new_locked.end > old_locked.end) {\\n new_dslope -= u_new.slope; // old slope disappeared at this point\\n slope_changes[new_locked.end] = new_dslope;\\n }\\n // else: we recorded it already in old_dslope\\n }\\n // Now handle user history\\n uint user_epoch = user_point_epoch[_tokenId] + 1;\\n\\n user_point_epoch[_tokenId] = user_epoch;\\n u_new.ts = block.timestamp;\\n u_new.blk = block.number;\\n user_point_history[_tokenId][user_epoch] = u_new;\\n }\\n }\\n\\n /// @notice Deposit and lock tokens for a user\\n /// @param _tokenId NFT that holds lock\\n /// @param _value Amount to deposit\\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\\n /// @param locked_balance Previous locked amount / timestamp\\n /// @param deposit_type The type of deposit\\n function _deposit_for(\\n uint _tokenId,\\n uint _value,\\n uint unlock_time,\\n LockedBalance memory locked_balance,\\n DepositType deposit_type\\n ) internal {\\n LockedBalance memory _locked = locked_balance;\\n uint supply_before = supply;\\n\\n supply = supply_before + _value;\\n LockedBalance memory old_locked;\\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\\n // Adding to existing lock, or if a lock is expired - creating a new one\\n _locked.amount += int128(int256(_value));\\n if (unlock_time != 0) {\\n _locked.end = unlock_time;\\n }\\n locked[_tokenId] = _locked;\\n\\n // Possibilities:\\n // Both old_locked.end could be current or expired (>/< block.timestamp)\\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\\n // _locked.end > block.timestamp (always)\\n _checkpoint(_tokenId, old_locked, _locked);\\n\\n address from = msg.sender;\\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\\n assert(IERC20(token).transferFrom(from, address(this), _value));\\n }\\n\\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\\n emit Supply(supply_before, supply_before + _value);\\n }\\n\\n function block_number() external view returns (uint) {\\n return block.number;\\n }\\n\\n /// @notice Record global data to checkpoint\\n function checkpoint() external {\\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\\n }\\n\\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\\n /// cannot extend their locktime and deposit for a brand new user\\n /// @param _tokenId lock NFT\\n /// @param _value Amount to add to user's lock\\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n require(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_value > 0); // dev: need non-zero value\\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n ++tokenId;\\n uint _tokenId = tokenId;\\n _mint(_to, _tokenId);\\n\\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\\n return _tokenId;\\n }\\n\\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, msg.sender);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, _to);\\n }\\n\\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\\n /// @param _value Amount of tokens to deposit and add to the lock\\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n assert(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\\n }\\n\\n /// @notice Extend the unlock time for `_tokenId`\\n /// @param _lock_duration New number of seconds until tokens unlock\\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_locked.end > block.timestamp, 'Lock expired');\\n require(_locked.amount > 0, 'Nothing is locked');\\n require(unlock_time > _locked.end, 'Can only increase lock duration');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\\n }\\n\\n /// @notice Withdraw all tokens for `_tokenId`\\n /// @dev Only possible if the lock has expired\\n function withdraw(uint _tokenId) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n require(block.timestamp >= _locked.end, \\\"The lock didn't expire\\\");\\n uint value = uint(int256(_locked.amount));\\n\\n locked[_tokenId] = LockedBalance(0,0);\\n uint supply_before = supply;\\n supply = supply_before - value;\\n\\n // old_locked can have either expired <= timestamp or zero end\\n // _locked has only 0 end\\n // Both can have >= 0 amount\\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\\n\\n assert(IERC20(token).transfer(msg.sender, value));\\n\\n // Burn the NFT\\n _burn(_tokenId);\\n\\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\\n emit Supply(supply_before, supply_before - value);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\\n // They measure the weights for the purpose of voting, so they don't represent\\n // real coins.\\n\\n /// @notice Binary search to estimate timestamp for block number\\n /// @param _block Block to find\\n /// @param max_epoch Don't go beyond this epoch\\n /// @return Approximate timestamp for block\\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\\n // Binary search\\n uint _min = 0;\\n uint _max = max_epoch;\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (point_history[_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n /// @notice Get the current voting power for `_tokenId`\\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\\n /// @param _tokenId NFT for lock\\n /// @param _t Epoch time to return voting power at\\n /// @return User voting power\\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\\n uint _epoch = user_point_epoch[_tokenId];\\n if (_epoch == 0) {\\n return 0;\\n } else {\\n Point memory last_point = user_point_history[_tokenId][_epoch];\\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(int256(last_point.bias));\\n }\\n }\\n\\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\\n if (ownership_change[_tokenId] == block.number) return 0;\\n return _balanceOfNFT(_tokenId, block.timestamp);\\n }\\n\\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\\n return _balanceOfNFT(_tokenId, _t);\\n }\\n\\n /// @notice Measure voting power of `_tokenId` at block height `_block`\\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\\n /// @param _tokenId User's wallet NFT\\n /// @param _block Block to calculate the voting power at\\n /// @return Voting power\\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\\n // Copying and pasting totalSupply code because Vyper cannot pass by\\n // reference yet\\n assert(_block <= block.number);\\n\\n // Binary search\\n uint _min = 0;\\n uint _max = user_point_epoch[_tokenId];\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (user_point_history[_tokenId][_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n\\n Point memory upoint = user_point_history[_tokenId][_min];\\n\\n uint max_epoch = epoch;\\n uint _epoch = _find_block_epoch(_block, max_epoch);\\n Point memory point_0 = point_history[_epoch];\\n uint d_block = 0;\\n uint d_t = 0;\\n if (_epoch < max_epoch) {\\n Point memory point_1 = point_history[_epoch + 1];\\n d_block = point_1.blk - point_0.blk;\\n d_t = point_1.ts - point_0.ts;\\n } else {\\n d_block = block.number - point_0.blk;\\n d_t = block.timestamp - point_0.ts;\\n }\\n uint block_time = point_0.ts;\\n if (d_block != 0) {\\n block_time += (d_t * (_block - point_0.blk)) / d_block;\\n }\\n\\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\\n if (upoint.bias >= 0) {\\n return uint(uint128(upoint.bias));\\n } else {\\n return 0;\\n }\\n }\\n\\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\\n return _balanceOfAtNFT(_tokenId, _block);\\n }\\n\\n /// @notice Calculate total voting power at some point in the past\\n /// @param _block Block to calculate the total voting power at\\n /// @return Total voting power at `_block`\\n function totalSupplyAt(uint _block) external view returns (uint) {\\n assert(_block <= block.number);\\n uint _epoch = epoch;\\n uint target_epoch = _find_block_epoch(_block, _epoch);\\n\\n Point memory point = point_history[target_epoch];\\n uint dt = 0;\\n if (target_epoch < _epoch) {\\n Point memory point_next = point_history[target_epoch + 1];\\n if (point.blk != point_next.blk) {\\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\\n }\\n } else {\\n if (point.blk != block.number) {\\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\\n }\\n }\\n // Now dt contains info on how far are we beyond point\\n return _supply_at(point, point.ts + dt);\\n }\\n /// @notice Calculate total voting power at some point in the past\\n /// @param point The point (bias/slope) to start search from\\n /// @param t Time to calculate the total voting power at\\n /// @return Total voting power at that time\\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\\n Point memory last_point = point;\\n uint t_i = (last_point.ts / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > t) {\\n t_i = t;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\\n if (t_i == t) {\\n break;\\n }\\n last_point.slope += d_slope;\\n last_point.ts = t_i;\\n }\\n\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(uint128(last_point.bias));\\n }\\n\\n function totalSupply() external view returns (uint) {\\n return totalSupplyAtT(block.timestamp);\\n }\\n\\n /// @notice Calculate total voting power\\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\\n /// @return Total voting power\\n function totalSupplyAtT(uint t) public view returns (uint) {\\n uint _epoch = epoch;\\n Point memory last_point = point_history[_epoch];\\n return _supply_at(last_point, t);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public attachments;\\n mapping(uint => bool) public voted;\\n\\n function setVoter(address _voter) external {\\n require(msg.sender == voter);\\n voter = _voter;\\n }\\n\\n function voting(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = true;\\n }\\n\\n function abstain(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = false;\\n }\\n\\n function attach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] + 1;\\n }\\n\\n function detach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] - 1;\\n }\\n\\n function merge(uint _from, uint _to) external {\\n require(attachments[_from] == 0 && !voted[_from], \\\"attached\\\");\\n require(_from != _to);\\n require(_isApprovedOrOwner(msg.sender, _from));\\n require(_isApprovedOrOwner(msg.sender, _to));\\n\\n LockedBalance memory _locked0 = locked[_from];\\n LockedBalance memory _locked1 = locked[_to];\\n uint value0 = uint(int256(_locked0.amount));\\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\\n\\n locked[_from] = LockedBalance(0, 0);\\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\\n _burn(_from);\\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of each accounts delegate\\n mapping(address => address) private _delegates;\\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\\n\\n /// @notice A record of delegated token checkpoints for each account, by index\\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint32) public numCheckpoints;\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping(address => uint) public nonces;\\n\\n /**\\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\\n * the delegator's own address if they haven't delegated.\\n * This avoids having to delegate to oneself.\\n */\\n function delegates(address delegator) public view returns (address) {\\n address current = _delegates[delegator];\\n return current == address(0) ? delegator : current;\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getVotes(address account) external view returns (uint) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n votes = votes + _balanceOfNFT(tId, block.timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint storage cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPastVotes(address account, uint timestamp)\\n public\\n view\\n returns (uint)\\n {\\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\\n // Sum votes\\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n // Use the provided input timestamp here to get the right decay\\n votes = votes + _balanceOfNFT(tId, timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\\n return totalSupplyAtT(timestamp);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _moveTokenDelegates(\\n address srcRep,\\n address dstRep,\\n uint _tokenId\\n ) internal {\\n if (srcRep != dstRep && _tokenId > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except _tokenId\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (tId != _tokenId) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n // All the same plus _tokenId\\n require(\\n dstRepOld.length + 1 <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n dstRepNew.push(_tokenId);\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _findWhatCheckpointToWrite(address account)\\n internal\\n view\\n returns (uint32)\\n {\\n uint _timestamp = block.timestamp;\\n uint32 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n return _nCheckPoints - 1;\\n } else {\\n return _nCheckPoints;\\n }\\n }\\n\\n function _moveAllDelegates(\\n address owner,\\n address srcRep,\\n address dstRep\\n ) internal {\\n // You can only redelegate what you own\\n if (srcRep != dstRep) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except what owner owns\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (idToOwner[tId] != owner) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n uint ownerTokenCount = ownerToNFTokenCount[owner];\\n require(\\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n // All the same\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n // Plus all that's owned\\n for (uint i = 0; i < ownerTokenCount; i++) {\\n uint tId = ownerToNFTokenIdList[owner][i];\\n dstRepNew.push(tId);\\n }\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\\n address currentDelegate = delegates(delegator);\\n\\n _delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n _moveAllDelegates(delegator, currentDelegate, delegatee);\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n if (delegatee == address(0)) delegatee = msg.sender;\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n function delegateBySig(\\n address delegatee,\\n uint nonce,\\n uint expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public {\\n bytes32 domainSeparator = keccak256(\\n abi.encode(\\n DOMAIN_TYPEHASH,\\n keccak256(bytes(name)),\\n keccak256(bytes(version)),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 structHash = keccak256(\\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash)\\n );\\n address signatory = ecrecover(digest, v, r, s);\\n require(\\n signatory != address(0),\\n \\\"VotingEscrow::delegateBySig: invalid signature\\\"\\n );\\n require(\\n nonce == nonces[signatory]++,\\n \\\"VotingEscrow::delegateBySig: invalid nonce\\\"\\n );\\n require(\\n block.timestamp <= expiry,\\n \\\"VotingEscrow::delegateBySig: signature expired\\\"\\n );\\n return _delegate(signatory, delegatee);\\n }\\n}\\n\",\"keccak256\":\"0x7109ed9d84b5504fe5d4c73d5a10997a0b73f2f4d45813ce5e161997d405fd73\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x41bbb2c41036ca64b2f6c9e973e8cfaa113ebc42af86702cd0d267f915a7e886\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a06040526006805460ff191660011790553480156200001e57600080fd5b5060405162004a1c38038062004a1c8339810160408190526200004191620001b8565b6001600160a01b0382811660805260008054336001600160a01b031991821681178355600180548316909117815560028054909216938516939093179055437f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f0155427f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f005560046020527f9fe05126d2d9ecf60592e254dead906a4b2e492f36cca727682c38e9008c6ac1805460ff1990811684179091557f4267c0a6fd96b7a87f183ee8744f24d011423cd0e0142b3f563f183d8d9a456b8054821684179055635b5e139f60e01b82527e24030bcf4927897dffe721c2d8dda4bfd8910861687c42b03a463b43b04147805490911690921790915560055460405190913091600080516020620049fc833981519152908290a46005546040516000903090600080516020620049fc833981519152908390a45050620001f0565b80516001600160a01b0381168114620001b357600080fd5b919050565b60008060408385031215620001cc57600080fd5b620001d7836200019b565b9150620001e7602084016200019b565b90509250929050565b6080516147e26200021a60003960008181610b220152818161101801526133b501526147e26000f3fe608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea26469706673582212207414e763e50126846f1d35c7cbdb3471a7585ac7f76203fdbe0144acf7cebd6c64736f6c634300080d0033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea26469706673582212207414e763e50126846f1d35c7cbdb3471a7585ac7f76203fdbe0144acf7cebd6c64736f6c634300080d0033", "devdoc": { "author": "Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)", "details": "Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).", @@ -1597,7 +1597,7 @@ }, "constructor": { "params": { - "token_addr": "`VELO` token address" + "token_addr": "`FLOW` token address" } }, "create_lock(uint256,uint256)": { @@ -1881,7 +1881,7 @@ "storageLayout": { "storage": [ { - "astId": 16268, + "astId": 16307, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "voter", "offset": 0, @@ -1889,7 +1889,7 @@ "type": "t_address" }, { - "astId": 16270, + "astId": 16309, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "team", "offset": 0, @@ -1897,7 +1897,7 @@ "type": "t_address" }, { - "astId": 16272, + "astId": 16311, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "artProxy", "offset": 0, @@ -1905,15 +1905,15 @@ "type": "t_address" }, { - "astId": 16277, + "astId": 16316, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "point_history", "offset": 0, "slot": "3", - "type": "t_mapping(t_uint256,t_struct(Point)16227_storage)" + "type": "t_mapping(t_uint256,t_struct(Point)16266_storage)" }, { - "astId": 16282, + "astId": 16321, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "supportedInterfaces", "offset": 0, @@ -1921,7 +1921,7 @@ "type": "t_mapping(t_bytes4,t_bool)" }, { - "astId": 16297, + "astId": 16336, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "tokenId", "offset": 0, @@ -1929,7 +1929,7 @@ "type": "t_uint256" }, { - "astId": 16392, + "astId": 16431, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "_entered_state", "offset": 0, @@ -1937,7 +1937,7 @@ "type": "t_uint8" }, { - "astId": 16511, + "astId": 16550, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "idToOwner", "offset": 0, @@ -1945,7 +1945,7 @@ "type": "t_mapping(t_uint256,t_address)" }, { - "astId": 16516, + "astId": 16555, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "ownerToNFTokenCount", "offset": 0, @@ -1953,7 +1953,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 16560, + "astId": 16599, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "idToApprovals", "offset": 0, @@ -1961,7 +1961,7 @@ "type": "t_mapping(t_uint256,t_address)" }, { - "astId": 16567, + "astId": 16606, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "ownerToOperators", "offset": 0, @@ -1969,7 +1969,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 16571, + "astId": 16610, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "ownership_change", "offset": 0, @@ -1977,7 +1977,7 @@ "type": "t_mapping(t_uint256,t_uint256)" }, { - "astId": 17016, + "astId": 17055, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "ownerToNFTokenIdList", "offset": 0, @@ -1985,7 +1985,7 @@ "type": "t_mapping(t_address,t_mapping(t_uint256,t_uint256))" }, { - "astId": 17021, + "astId": 17060, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "tokenToOwnerIndex", "offset": 0, @@ -1993,7 +1993,7 @@ "type": "t_mapping(t_uint256,t_uint256)" }, { - "astId": 17326, + "astId": 17365, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "user_point_epoch", "offset": 0, @@ -2001,23 +2001,23 @@ "type": "t_mapping(t_uint256,t_uint256)" }, { - "astId": 17333, + "astId": 17372, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "user_point_history", "offset": 0, "slot": "15", - "type": "t_mapping(t_uint256,t_array(t_struct(Point)16227_storage)1000000000_storage)" + "type": "t_mapping(t_uint256,t_array(t_struct(Point)16266_storage)1000000000_storage)" }, { - "astId": 17338, + "astId": 17377, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "locked", "offset": 0, "slot": "16", - "type": "t_mapping(t_uint256,t_struct(LockedBalance)16218_storage)" + "type": "t_mapping(t_uint256,t_struct(LockedBalance)16257_storage)" }, { - "astId": 17340, + "astId": 17379, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "epoch", "offset": 0, @@ -2025,7 +2025,7 @@ "type": "t_uint256" }, { - "astId": 17344, + "astId": 17383, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "slope_changes", "offset": 0, @@ -2033,7 +2033,7 @@ "type": "t_mapping(t_uint256,t_int128)" }, { - "astId": 17346, + "astId": 17385, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "supply", "offset": 0, @@ -2041,7 +2041,7 @@ "type": "t_uint256" }, { - "astId": 19217, + "astId": 19256, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "attachments", "offset": 0, @@ -2049,7 +2049,7 @@ "type": "t_mapping(t_uint256,t_uint256)" }, { - "astId": 19221, + "astId": 19260, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "voted", "offset": 0, @@ -2057,7 +2057,7 @@ "type": "t_mapping(t_uint256,t_bool)" }, { - "astId": 19452, + "astId": 19491, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "_delegates", "offset": 0, @@ -2065,15 +2065,15 @@ "type": "t_mapping(t_address,t_address)" }, { - "astId": 19463, + "astId": 19502, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "checkpoints", "offset": 0, "slot": "23", - "type": "t_mapping(t_address,t_mapping(t_uint32,t_struct(Checkpoint)16233_storage))" + "type": "t_mapping(t_address,t_mapping(t_uint32,t_struct(Checkpoint)16272_storage))" }, { - "astId": 19468, + "astId": 19507, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "numCheckpoints", "offset": 0, @@ -2081,7 +2081,7 @@ "type": "t_mapping(t_address,t_uint32)" }, { - "astId": 19473, + "astId": 19512, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "nonces", "offset": 0, @@ -2095,8 +2095,8 @@ "label": "address", "numberOfBytes": "20" }, - "t_array(t_struct(Point)16227_storage)1000000000_storage": { - "base": "t_struct(Point)16227_storage", + "t_array(t_struct(Point)16266_storage)1000000000_storage": { + "base": "t_struct(Point)16266_storage", "encoding": "inplace", "label": "struct VotingEscrow.Point[1000000000]", "numberOfBytes": "96000000000" @@ -2150,12 +2150,12 @@ "numberOfBytes": "32", "value": "t_mapping(t_uint256,t_uint256)" }, - "t_mapping(t_address,t_mapping(t_uint32,t_struct(Checkpoint)16233_storage))": { + "t_mapping(t_address,t_mapping(t_uint32,t_struct(Checkpoint)16272_storage))": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => mapping(uint32 => struct VotingEscrow.Checkpoint))", "numberOfBytes": "32", - "value": "t_mapping(t_uint32,t_struct(Checkpoint)16233_storage)" + "value": "t_mapping(t_uint32,t_struct(Checkpoint)16272_storage)" }, "t_mapping(t_address,t_uint256)": { "encoding": "mapping", @@ -2185,12 +2185,12 @@ "numberOfBytes": "32", "value": "t_address" }, - "t_mapping(t_uint256,t_array(t_struct(Point)16227_storage)1000000000_storage)": { + "t_mapping(t_uint256,t_array(t_struct(Point)16266_storage)1000000000_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct VotingEscrow.Point[1000000000])", "numberOfBytes": "32", - "value": "t_array(t_struct(Point)16227_storage)1000000000_storage" + "value": "t_array(t_struct(Point)16266_storage)1000000000_storage" }, "t_mapping(t_uint256,t_bool)": { "encoding": "mapping", @@ -2206,19 +2206,19 @@ "numberOfBytes": "32", "value": "t_int128" }, - "t_mapping(t_uint256,t_struct(LockedBalance)16218_storage)": { + "t_mapping(t_uint256,t_struct(LockedBalance)16257_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct VotingEscrow.LockedBalance)", "numberOfBytes": "32", - "value": "t_struct(LockedBalance)16218_storage" + "value": "t_struct(LockedBalance)16257_storage" }, - "t_mapping(t_uint256,t_struct(Point)16227_storage)": { + "t_mapping(t_uint256,t_struct(Point)16266_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct VotingEscrow.Point)", "numberOfBytes": "32", - "value": "t_struct(Point)16227_storage" + "value": "t_struct(Point)16266_storage" }, "t_mapping(t_uint256,t_uint256)": { "encoding": "mapping", @@ -2227,19 +2227,19 @@ "numberOfBytes": "32", "value": "t_uint256" }, - "t_mapping(t_uint32,t_struct(Checkpoint)16233_storage)": { + "t_mapping(t_uint32,t_struct(Checkpoint)16272_storage)": { "encoding": "mapping", "key": "t_uint32", "label": "mapping(uint32 => struct VotingEscrow.Checkpoint)", "numberOfBytes": "32", - "value": "t_struct(Checkpoint)16233_storage" + "value": "t_struct(Checkpoint)16272_storage" }, - "t_struct(Checkpoint)16233_storage": { + "t_struct(Checkpoint)16272_storage": { "encoding": "inplace", "label": "struct VotingEscrow.Checkpoint", "members": [ { - "astId": 16229, + "astId": 16268, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "timestamp", "offset": 0, @@ -2247,7 +2247,7 @@ "type": "t_uint256" }, { - "astId": 16232, + "astId": 16271, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "tokenIds", "offset": 0, @@ -2257,12 +2257,12 @@ ], "numberOfBytes": "64" }, - "t_struct(LockedBalance)16218_storage": { + "t_struct(LockedBalance)16257_storage": { "encoding": "inplace", "label": "struct VotingEscrow.LockedBalance", "members": [ { - "astId": 16215, + "astId": 16254, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "amount", "offset": 0, @@ -2270,7 +2270,7 @@ "type": "t_int128" }, { - "astId": 16217, + "astId": 16256, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "end", "offset": 0, @@ -2280,12 +2280,12 @@ ], "numberOfBytes": "64" }, - "t_struct(Point)16227_storage": { + "t_struct(Point)16266_storage": { "encoding": "inplace", "label": "struct VotingEscrow.Point", "members": [ { - "astId": 16220, + "astId": 16259, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "bias", "offset": 0, @@ -2293,7 +2293,7 @@ "type": "t_int128" }, { - "astId": 16222, + "astId": 16261, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "slope", "offset": 16, @@ -2301,7 +2301,7 @@ "type": "t_int128" }, { - "astId": 16224, + "astId": 16263, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "ts", "offset": 0, @@ -2309,7 +2309,7 @@ "type": "t_uint256" }, { - "astId": 16226, + "astId": 16265, "contract": "contracts/VotingEscrow.sol:VotingEscrow", "label": "blk", "offset": 0, diff --git a/deployments/arbitrumOne/WrappedExternalBribeFactory.json b/deployments/arbitrumOne/WrappedExternalBribeFactory.json index 020f594f..3978894a 100644 --- a/deployments/arbitrumOne/WrappedExternalBribeFactory.json +++ b/deployments/arbitrumOne/WrappedExternalBribeFactory.json @@ -1,5 +1,5 @@ { - "address": "0xbb88E349257e4355946C2604fEd168165989285c", + "address": "0x76C9347739842E72509106e6aef616552bD0C9a7", "abi": [ { "inputs": [ @@ -77,30 +77,30 @@ "type": "function" } ], - "transactionHash": "0xe910624a59ad0487fff48182a26d189b2e6384c5389ce0ae2483da6dbc9bcf00", + "transactionHash": "0x1108f76fd230452fdc0732a9528c0f8257954178702f04a5dc763d34aee5cf16", "receipt": { "to": null, "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", - "contractAddress": "0xbb88E349257e4355946C2604fEd168165989285c", - "transactionIndex": 1, - "gasUsed": "10475233", + "contractAddress": "0x76C9347739842E72509106e6aef616552bD0C9a7", + "transactionIndex": 3, + "gasUsed": "11333646", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x502c654130fc432a20ef80e86336a8d5e1aed325c26ae2a13d4eb3b2a8779b33", - "transactionHash": "0xe910624a59ad0487fff48182a26d189b2e6384c5389ce0ae2483da6dbc9bcf00", + "blockHash": "0x1c406f984b385a93f37729f64bc8a2b4ae40913808c4cee065716f60de1acab1", + "transactionHash": "0x1108f76fd230452fdc0732a9528c0f8257954178702f04a5dc763d34aee5cf16", "logs": [], - "blockNumber": 56592743, - "cumulativeGasUsed": "10475233", + "blockNumber": 58032225, + "cumulativeGasUsed": "13108501", "status": 1, "byzantium": true }, "args": [ - "0x29C487a354D11315059204Df4F7d8AB1aa008ebb" + "0x2862Bf1ADC96d485B6E85C062b170903DE9A2Bd5" ], "numDeployments": 1, - "solcInputHash": "4e21824d68c90a2d8601cfb8f8d80414", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voter\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"existing_bribe\",\"type\":\"address\"}],\"name\":\"createBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"oldBribeToNew\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/WrappedExternalBribeFactory.sol\":\"WrappedExternalBribeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735303731393533363138\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/ExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract ExternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve; // \\u5929\\u4f7f\\u306e\\u305f\\u307e\\u3054\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balanceOf;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n _prevSupply = supplyCheckpoints[\\n getPriorSupplyIndex(_nextEpochStart + DURATION)\\n ].supply;\\n prevRewards.balanceOf =\\n (cp0.balanceOf *\\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (block.timestamp > _lastEpochEnd) {\\n reward +=\\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\\n }\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0xfe1e53dea8a63ce448c5856a740ed73038ad29a9dcd0f2a2752049b146bb4eb0\",\"license\":\"MIT\"},\"contracts/WrappedExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/ExternalBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract WrappedExternalBribe {\\n address public immutable voter;\\n address public immutable _ve;\\n ExternalBribe public underlying_bribe;\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct RewardCheckpoint {\\n uint256 timestamp;\\n uint256 balance;\\n }\\n\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address _old_bribe) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n underlying_bribe = ExternalBribe(_old_bribe);\\n\\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\\n address underlying_reward = underlying_bribe.rewards(i);\\n if (underlying_reward != address(0)) {\\n isReward[underlying_reward] = true;\\n rewards.push(underlying_reward);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\\n tokenId,\\n _startTimestamp\\n );\\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n RewardCheckpoint memory prevRewards;\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevTs = 0;\\n uint256 _prevBal = 0;\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\\n uint256 _nextEpochStart = _bribeStart(_prevTs);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balance;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\\n underlying_bribe.getPriorSupplyIndex(\\n _nextEpochStart + DURATION\\n )\\n );\\n prevRewards.balance =\\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\\n uint256 _lastEpochStart = _bribeStart(_prevTs);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (\\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\\n ) {\\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\\n );\\n reward +=\\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n _prevSupply;\\n }\\n\\n return reward;\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x855fa341d3139522255811d9a9df463636e27fd6e21bd07c38adacad734af6ed\",\"license\":\"MIT\"},\"contracts/factories/WrappedExternalBribeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\\n\\ncontract WrappedExternalBribeFactory {\\n address public immutable voter;\\n mapping(address => address) public oldBribeToNew;\\n address public last_bribe;\\n\\n constructor(address _voter) {\\n voter = _voter;\\n }\\n\\n function createBribe(address existing_bribe) external returns (address) {\\n require(\\n oldBribeToNew[existing_bribe] == address(0),\\n \\\"Wrapped bribe already created\\\"\\n );\\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\\n oldBribeToNew[existing_bribe] = last_bribe;\\n return last_bribe;\\n }\\n}\\n\",\"keccak256\":\"0x4e88b50000e3cf490ae8602b55555bbc02f95fda5926b1a532debfe54ac06bb2\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", - "bytecode": "0x60a060405234801561001057600080fd5b50604051611d5d380380611d5d83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051611ccc61009160003960008181609b01526101530152611ccc6000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632fcd8f271461005157806346c96aac146100965780636bd1a72c146100bd578063b1d0fc82146100d0575b600080fd5b61007a61005f366004610205565b6000602081905290815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b61007a7f000000000000000000000000000000000000000000000000000000000000000081565b61007a6100cb366004610205565b6100e3565b60015461007a906001600160a01b031681565b6001600160a01b03818116600090815260208190526040812054909116156101515760405162461bcd60e51b815260206004820152601d60248201527f5772617070656420627269626520616c72656164792063726561746564000000604482015260640160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000008260405161017f906101f8565b6001600160a01b03928316815291166020820152604001604051809103906000f0801580156101b2573d6000803e3d6000fd5b50600180546001600160a01b039283166001600160a01b031991821681178355948316600090815260208190526040902080549091169094179093559154909116919050565b611a618061023683390190565b60006020828403121561021757600080fd5b81356001600160a01b038116811461022e57600080fd5b939250505056fe60c060405260016006553480156200001657600080fd5b5060405162001a6138038062001a61833981016040819052620000399162000275565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002ad565b6001600160a01b0390811660a052600080546001600160a01b0319169183169190911781555b60008054906101000a90046001600160a01b03166001600160a01b031663e68863966040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000122573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001489190620002d2565b8110156200024f5760008054604051637980d7a160e11b8152600481018490526001600160a01b039091169063f301af4290602401602060405180830381865afa1580156200019b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001c19190620002ad565b90506001600160a01b0381161562000239576001600160a01b0381166000818152600560205260408120805460ff191660019081179091556004805491820181559091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b03191690911790555b50806200024681620002ec565b915050620000d0565b50505062000314565b80516001600160a01b03811681146200027057600080fd5b919050565b600080604083850312156200028957600080fd5b620002948362000258565b9150620002a46020840162000258565b90509250929050565b600060208284031215620002c057600080fd5b620002cb8262000258565b9392505050565b600060208284031215620002e557600080fd5b5051919050565b6000600182016200030d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a0516117046200035d600039600081816101e6015281816108f301528181610b1d0152610fd701526000818161014e01528181610ada0152610d1801526117046000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80639418f939116100a2578063da09d19d11610071578063da09d19d14610281578063e6886396146102a1578063f25e55a5146102a9578063f301af42146102d4578063f5f8d365146102e757600080fd5b80639418f9391461023357806399bcc05214610248578063a7852afa1461025b578063b66503cf1461026e57600080fd5b8063638634ee116100de578063638634ee146101bb5780636c4f5398146101ce5780638dd598fb146101e157806392777b291461020857600080fd5b80630175e23b146101105780633e491d471461013657806346c96aac146101495780634d5ce03814610188575b600080fd5b61012361011e366004611393565b6102fa565b6040519081526020015b60405180910390f35b6101236101443660046113d4565b61033c565b6101707f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161012d565b6101ab610196366004611400565b60056020526000908152604090205460ff1681565b604051901515815260200161012d565b6101236101c9366004611400565b6108cd565b600054610170906001600160a01b031681565b6101707f000000000000000000000000000000000000000000000000000000000000000081565b6101236102163660046113d4565b600160209081526000928352604080842090915290825290205481565b61024661024136600461141d565b6108f1565b005b610123610256366004611400565b610a82565b610246610269366004611475565b610abb565b61024661027c3660046113d4565b610cbb565b61012361028f366004611400565b60026020526000908152604090205481565b600454610123565b6101236102b73660046113d4565b600360209081526000928352604080842090915290825290205481565b6101706102e2366004611393565b610f7d565b6102466102f5366004611475565b610fa7565b6000806103068361117b565b9050600061031762093a808361155c565b90508084106103325761032d8262093a8061155c565b610334565b815b949350505050565b6001600160a01b0382811660009081526003602090815260408083208584529091528082205482549151635058979360e01b81526004810186905292939092911690635058979390602401602060405180830381865afa1580156103a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103c89190611574565b6000036103d95760009150506108c7565b600080546040516328a3532760e21b815260048101869052602481018490526001600160a01b039091169063a28d4c9c90604401602060405180830381865afa15801561042a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044e9190611574565b60008054604051635058979360e01b81526004810188905292935090916001916001600160a01b031690635058979390602401602060405180830381865afa15801561049e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c29190611574565b6104cc919061158d565b905060006104ed604051806040016040528060008152602001600081525090565b6104f68561117b565b8152600080600185156106f357865b61051060018861158d565b81116106f157600054604051631277308160e21b8152600481018d9052602481018390526001600160a01b03909116906349dcc204906044016040805180830381865afa158015610565573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058991906115a4565b909450925060006105998561117b565b86519091508111156105b75760208601516105b4908861155c565b96505b8086526000546001600160a01b031663f7412baf816376f4be366105de62093a808661155c565b6040518263ffffffff1660e01b81526004016105fc91815260200190565b602060405180830381865afa158015610619573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063d9190611574565b6040518263ffffffff1660e01b815260040161065b91815260200190565b6040805180830381865afa158015610677573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061069b91906115a4565b6001600160a01b038f1660009081526001602090815260408083208684529091529020549094508491506106cf90866115c8565b6106d991906115fd565b602087015250806106e981611611565b915050610505565b505b600054604051631277308160e21b8152600481018c9052602481018890526001600160a01b03909116906349dcc204906044016040805180830381865afa158015610742573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076691906115a4565b909350915060006107768461117b565b9050600061078762093a808361155c565b905080421180156107975750808a105b156108ba57600054604051633b7a5f1b60e11b8152600481018390526001600160a01b039091169063f7412baf9082906376f4be3690602401602060405180830381865afa1580156107ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108119190611574565b6040518263ffffffff1660e01b815260040161082f91815260200190565b6040805180830381865afa15801561084b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086f91906115a4565b6001600160a01b038f1660009081526001602090815260408083208784529091529020549094508491506108a390866115c8565b6108ad91906115fd565b6108b7908861155c565b96505b5094985050505050505050505b92915050565b6001600160a01b0381166000908152600260205260408120546108c7904290611194565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610951573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610975919061162a565b6001600160a01b0316336001600160a01b0316146109c65760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600484815481106109e3576109e3611647565b6000918252602090912001546001600160a01b031614610a0257600080fd5b6001600160a01b03808316600090815260056020526040808220805460ff1990811690915592841682529020805490911660011790556004805482919085908110610a4f57610a4f611647565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a8e426102fa565b6001600160a01b039093166000908152600160209081526040808320958352949052929092205492915050565b600654600114610aca57600080fd5b6002600655336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b0457600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610b6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b90919061162a565b905060005b8251811015610cb0576000610bc3848381518110610bb557610bb5611647565b60200260200101518661033c565b90504260036000868581518110610bdc57610bdc611647565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610c3757610c37848381518110610c2857610c28611647565b602002602001015184836111ac565b838281518110610c4957610c49611647565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610c9591815260200190565b60405180910390a35080610ca881611611565b915050610b95565b505060016006555050565b600654600114610cca57600080fd5b600260065580610cd957600080fd5b6001600160a01b03821660009081526005602052604090205460ff16610e2157604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610d5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d83919061165d565b610dcf5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c697374656460448201526064016109bd565b600454601011610e215760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e7300000000000000000060448201526064016109bd565b6000610e2c426102fa565b6001600160a01b0384166000908152600160209081526040808320848452909152902054909150610e5f8433308661129b565b610e69838261155c565b6001600160a01b0385166000908152600160209081526040808320868452909152902055610e9a62093a808361155c565b6001600160a01b03851660009081526002602090815260408083209390935560059052205460ff16610f2c576001600160a01b0384166000818152600560205260408120805460ff191660019081179091556004805491820181559091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a3505060016006555050565b60048181548110610f8d57600080fd5b6000918252602090912001546001600160a01b0316905081565b600654600114610fb657600080fd5b600260065560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611026573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104a919061165d565b61105357600080fd5b60005b815181101561117157600061108483838151811061107657611076611647565b60200260200101518561033c565b9050426003600085858151811061109d5761109d611647565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812088825290925290205580156110f8576110f88383815181106110e9576110e9611647565b602002602001015133836111ac565b82828151811061110a5761110a611647565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161115691815260200190565b60405180910390a3508061116981611611565b915050611056565b5050600160065550565b600061118a62093a808361167f565b6108c7908361158d565b60008183106111a357816111a5565b825b9392505050565b6000836001600160a01b03163b116111c357600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161121f9190611693565b6000604051808303816000865af19150503d806000811461125c576040519150601f19603f3d011682016040523d82523d6000602084013e611261565b606091505b509150915081801561128b57508051158061128b57508080602001905181019061128b919061165d565b61129457600080fd5b5050505050565b6000846001600160a01b03163b116112b257600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916113169190611693565b6000604051808303816000865af19150503d8060008114611353576040519150601f19603f3d011682016040523d82523d6000602084013e611358565b606091505b5091509150818015611382575080511580611382575080806020019051810190611382919061165d565b61138b57600080fd5b505050505050565b6000602082840312156113a557600080fd5b5035919050565b6001600160a01b03811681146113c157600080fd5b50565b80356113cf816113ac565b919050565b600080604083850312156113e757600080fd5b82356113f2816113ac565b946020939093013593505050565b60006020828403121561141257600080fd5b81356111a5816113ac565b60008060006060848603121561143257600080fd5b833592506020840135611444816113ac565b91506040840135611454816113ac565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561148857600080fd5b8235915060208084013567ffffffffffffffff808211156114a857600080fd5b818601915086601f8301126114bc57600080fd5b8135818111156114ce576114ce61145f565b8060051b604051601f19603f830116810181811085821117156114f3576114f361145f565b60405291825284820192508381018501918983111561151157600080fd5b938501935b8285101561153657611527856113c4565b84529385019392850192611516565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561156f5761156f611546565b500190565b60006020828403121561158657600080fd5b5051919050565b60008282101561159f5761159f611546565b500390565b600080604083850312156115b757600080fd5b505080516020909101519092909150565b60008160001904831182151516156115e2576115e2611546565b500290565b634e487b7160e01b600052601260045260246000fd5b60008261160c5761160c6115e7565b500490565b60006001820161162357611623611546565b5060010190565b60006020828403121561163c57600080fd5b81516111a5816113ac565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561166f57600080fd5b815180151581146111a557600080fd5b60008261168e5761168e6115e7565b500690565b6000825160005b818110156116b4576020818601810151858301520161169a565b818111156116c3576000828501525b50919091019291505056fea26469706673582212200cd58109058435150b86689c579157aac22bb1bf34bcba8fe86630ae677bab0f64736f6c634300080d0033a26469706673582212204aa3dda9eda9f8a5fdd9bf2ced3a5d88c86e34ca5a36bacbb53589f8e2fccc7164736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632fcd8f271461005157806346c96aac146100965780636bd1a72c146100bd578063b1d0fc82146100d0575b600080fd5b61007a61005f366004610205565b6000602081905290815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b61007a7f000000000000000000000000000000000000000000000000000000000000000081565b61007a6100cb366004610205565b6100e3565b60015461007a906001600160a01b031681565b6001600160a01b03818116600090815260208190526040812054909116156101515760405162461bcd60e51b815260206004820152601d60248201527f5772617070656420627269626520616c72656164792063726561746564000000604482015260640160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000008260405161017f906101f8565b6001600160a01b03928316815291166020820152604001604051809103906000f0801580156101b2573d6000803e3d6000fd5b50600180546001600160a01b039283166001600160a01b031991821681178355948316600090815260208190526040902080549091169094179093559154909116919050565b611a618061023683390190565b60006020828403121561021757600080fd5b81356001600160a01b038116811461022e57600080fd5b939250505056fe60c060405260016006553480156200001657600080fd5b5060405162001a6138038062001a61833981016040819052620000399162000275565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002ad565b6001600160a01b0390811660a052600080546001600160a01b0319169183169190911781555b60008054906101000a90046001600160a01b03166001600160a01b031663e68863966040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000122573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001489190620002d2565b8110156200024f5760008054604051637980d7a160e11b8152600481018490526001600160a01b039091169063f301af4290602401602060405180830381865afa1580156200019b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001c19190620002ad565b90506001600160a01b0381161562000239576001600160a01b0381166000818152600560205260408120805460ff191660019081179091556004805491820181559091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b03191690911790555b50806200024681620002ec565b915050620000d0565b50505062000314565b80516001600160a01b03811681146200027057600080fd5b919050565b600080604083850312156200028957600080fd5b620002948362000258565b9150620002a46020840162000258565b90509250929050565b600060208284031215620002c057600080fd5b620002cb8262000258565b9392505050565b600060208284031215620002e557600080fd5b5051919050565b6000600182016200030d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a0516117046200035d600039600081816101e6015281816108f301528181610b1d0152610fd701526000818161014e01528181610ada0152610d1801526117046000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80639418f939116100a2578063da09d19d11610071578063da09d19d14610281578063e6886396146102a1578063f25e55a5146102a9578063f301af42146102d4578063f5f8d365146102e757600080fd5b80639418f9391461023357806399bcc05214610248578063a7852afa1461025b578063b66503cf1461026e57600080fd5b8063638634ee116100de578063638634ee146101bb5780636c4f5398146101ce5780638dd598fb146101e157806392777b291461020857600080fd5b80630175e23b146101105780633e491d471461013657806346c96aac146101495780634d5ce03814610188575b600080fd5b61012361011e366004611393565b6102fa565b6040519081526020015b60405180910390f35b6101236101443660046113d4565b61033c565b6101707f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161012d565b6101ab610196366004611400565b60056020526000908152604090205460ff1681565b604051901515815260200161012d565b6101236101c9366004611400565b6108cd565b600054610170906001600160a01b031681565b6101707f000000000000000000000000000000000000000000000000000000000000000081565b6101236102163660046113d4565b600160209081526000928352604080842090915290825290205481565b61024661024136600461141d565b6108f1565b005b610123610256366004611400565b610a82565b610246610269366004611475565b610abb565b61024661027c3660046113d4565b610cbb565b61012361028f366004611400565b60026020526000908152604090205481565b600454610123565b6101236102b73660046113d4565b600360209081526000928352604080842090915290825290205481565b6101706102e2366004611393565b610f7d565b6102466102f5366004611475565b610fa7565b6000806103068361117b565b9050600061031762093a808361155c565b90508084106103325761032d8262093a8061155c565b610334565b815b949350505050565b6001600160a01b0382811660009081526003602090815260408083208584529091528082205482549151635058979360e01b81526004810186905292939092911690635058979390602401602060405180830381865afa1580156103a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103c89190611574565b6000036103d95760009150506108c7565b600080546040516328a3532760e21b815260048101869052602481018490526001600160a01b039091169063a28d4c9c90604401602060405180830381865afa15801561042a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044e9190611574565b60008054604051635058979360e01b81526004810188905292935090916001916001600160a01b031690635058979390602401602060405180830381865afa15801561049e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c29190611574565b6104cc919061158d565b905060006104ed604051806040016040528060008152602001600081525090565b6104f68561117b565b8152600080600185156106f357865b61051060018861158d565b81116106f157600054604051631277308160e21b8152600481018d9052602481018390526001600160a01b03909116906349dcc204906044016040805180830381865afa158015610565573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058991906115a4565b909450925060006105998561117b565b86519091508111156105b75760208601516105b4908861155c565b96505b8086526000546001600160a01b031663f7412baf816376f4be366105de62093a808661155c565b6040518263ffffffff1660e01b81526004016105fc91815260200190565b602060405180830381865afa158015610619573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063d9190611574565b6040518263ffffffff1660e01b815260040161065b91815260200190565b6040805180830381865afa158015610677573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061069b91906115a4565b6001600160a01b038f1660009081526001602090815260408083208684529091529020549094508491506106cf90866115c8565b6106d991906115fd565b602087015250806106e981611611565b915050610505565b505b600054604051631277308160e21b8152600481018c9052602481018890526001600160a01b03909116906349dcc204906044016040805180830381865afa158015610742573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076691906115a4565b909350915060006107768461117b565b9050600061078762093a808361155c565b905080421180156107975750808a105b156108ba57600054604051633b7a5f1b60e11b8152600481018390526001600160a01b039091169063f7412baf9082906376f4be3690602401602060405180830381865afa1580156107ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108119190611574565b6040518263ffffffff1660e01b815260040161082f91815260200190565b6040805180830381865afa15801561084b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086f91906115a4565b6001600160a01b038f1660009081526001602090815260408083208784529091529020549094508491506108a390866115c8565b6108ad91906115fd565b6108b7908861155c565b96505b5094985050505050505050505b92915050565b6001600160a01b0381166000908152600260205260408120546108c7904290611194565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610951573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610975919061162a565b6001600160a01b0316336001600160a01b0316146109c65760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600484815481106109e3576109e3611647565b6000918252602090912001546001600160a01b031614610a0257600080fd5b6001600160a01b03808316600090815260056020526040808220805460ff1990811690915592841682529020805490911660011790556004805482919085908110610a4f57610a4f611647565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a8e426102fa565b6001600160a01b039093166000908152600160209081526040808320958352949052929092205492915050565b600654600114610aca57600080fd5b6002600655336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b0457600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610b6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b90919061162a565b905060005b8251811015610cb0576000610bc3848381518110610bb557610bb5611647565b60200260200101518661033c565b90504260036000868581518110610bdc57610bdc611647565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610c3757610c37848381518110610c2857610c28611647565b602002602001015184836111ac565b838281518110610c4957610c49611647565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610c9591815260200190565b60405180910390a35080610ca881611611565b915050610b95565b505060016006555050565b600654600114610cca57600080fd5b600260065580610cd957600080fd5b6001600160a01b03821660009081526005602052604090205460ff16610e2157604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610d5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d83919061165d565b610dcf5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c697374656460448201526064016109bd565b600454601011610e215760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e7300000000000000000060448201526064016109bd565b6000610e2c426102fa565b6001600160a01b0384166000908152600160209081526040808320848452909152902054909150610e5f8433308661129b565b610e69838261155c565b6001600160a01b0385166000908152600160209081526040808320868452909152902055610e9a62093a808361155c565b6001600160a01b03851660009081526002602090815260408083209390935560059052205460ff16610f2c576001600160a01b0384166000818152600560205260408120805460ff191660019081179091556004805491820181559091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a3505060016006555050565b60048181548110610f8d57600080fd5b6000918252602090912001546001600160a01b0316905081565b600654600114610fb657600080fd5b600260065560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611026573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104a919061165d565b61105357600080fd5b60005b815181101561117157600061108483838151811061107657611076611647565b60200260200101518561033c565b9050426003600085858151811061109d5761109d611647565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812088825290925290205580156110f8576110f88383815181106110e9576110e9611647565b602002602001015133836111ac565b82828151811061110a5761110a611647565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161115691815260200190565b60405180910390a3508061116981611611565b915050611056565b5050600160065550565b600061118a62093a808361167f565b6108c7908361158d565b60008183106111a357816111a5565b825b9392505050565b6000836001600160a01b03163b116111c357600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161121f9190611693565b6000604051808303816000865af19150503d806000811461125c576040519150601f19603f3d011682016040523d82523d6000602084013e611261565b606091505b509150915081801561128b57508051158061128b57508080602001905181019061128b919061165d565b61129457600080fd5b5050505050565b6000846001600160a01b03163b116112b257600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916113169190611693565b6000604051808303816000865af19150503d8060008114611353576040519150601f19603f3d011682016040523d82523d6000602084013e611358565b606091505b5091509150818015611382575080511580611382575080806020019051810190611382919061165d565b61138b57600080fd5b505050505050565b6000602082840312156113a557600080fd5b5035919050565b6001600160a01b03811681146113c157600080fd5b50565b80356113cf816113ac565b919050565b600080604083850312156113e757600080fd5b82356113f2816113ac565b946020939093013593505050565b60006020828403121561141257600080fd5b81356111a5816113ac565b60008060006060848603121561143257600080fd5b833592506020840135611444816113ac565b91506040840135611454816113ac565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561148857600080fd5b8235915060208084013567ffffffffffffffff808211156114a857600080fd5b818601915086601f8301126114bc57600080fd5b8135818111156114ce576114ce61145f565b8060051b604051601f19603f830116810181811085821117156114f3576114f361145f565b60405291825284820192508381018501918983111561151157600080fd5b938501935b8285101561153657611527856113c4565b84529385019392850192611516565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561156f5761156f611546565b500190565b60006020828403121561158657600080fd5b5051919050565b60008282101561159f5761159f611546565b500390565b600080604083850312156115b757600080fd5b505080516020909101519092909150565b60008160001904831182151516156115e2576115e2611546565b500290565b634e487b7160e01b600052601260045260246000fd5b60008261160c5761160c6115e7565b500490565b60006001820161162357611623611546565b5060010190565b60006020828403121561163c57600080fd5b81516111a5816113ac565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561166f57600080fd5b815180151581146111a557600080fd5b60008261168e5761168e6115e7565b500690565b6000825160005b818110156116b4576020818601810151858301520161169a565b818111156116c3576000828501525b50919091019291505056fea26469706673582212200cd58109058435150b86689c579157aac22bb1bf34bcba8fe86630ae677bab0f64736f6c634300080d0033a26469706673582212204aa3dda9eda9f8a5fdd9bf2ced3a5d88c86e34ca5a36bacbb53589f8e2fccc7164736f6c634300080d0033", + "solcInputHash": "816572db58a4a8203fcf6f77728173df", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voter\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"existing_bribe\",\"type\":\"address\"}],\"name\":\"createBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"oldBribeToNew\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/WrappedExternalBribeFactory.sol\":\"WrappedExternalBribeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735353339323034313033\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/ExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\\\";\\n\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract ExternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve; // \\u5929\\u4f7f\\u306e\\u305f\\u307e\\u3054\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return Math.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balanceOf;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n _prevSupply = supplyCheckpoints[\\n getPriorSupplyIndex(_nextEpochStart + DURATION)\\n ].supply;\\n prevRewards.balanceOf =\\n (cp0.balanceOf *\\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (block.timestamp > _lastEpochEnd) {\\n reward +=\\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\\n }\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x0026916e62de3e8d8c183fb2baea5512ef16c50760bf8e0f98a69de1e763a03f\",\"license\":\"MIT\"},\"contracts/WrappedExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\\\";\\nimport \\\"contracts/ExternalBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract WrappedExternalBribe {\\n address public immutable voter;\\n address public immutable _ve;\\n ExternalBribe public underlying_bribe;\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct RewardCheckpoint {\\n uint256 timestamp;\\n uint256 balance;\\n }\\n\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address _old_bribe) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n underlying_bribe = ExternalBribe(_old_bribe);\\n\\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\\n address underlying_reward = underlying_bribe.rewards(i);\\n if (underlying_reward != address(0)) {\\n isReward[underlying_reward] = true;\\n rewards.push(underlying_reward);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return Math.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\\n tokenId,\\n _startTimestamp\\n );\\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n RewardCheckpoint memory prevRewards;\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevTs = 0;\\n uint256 _prevBal = 0;\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\\n uint256 _nextEpochStart = _bribeStart(_prevTs);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balance;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\\n underlying_bribe.getPriorSupplyIndex(\\n _nextEpochStart + DURATION\\n )\\n );\\n prevRewards.balance =\\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\\n uint256 _lastEpochStart = _bribeStart(_prevTs);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (\\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\\n ) {\\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\\n );\\n reward +=\\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n _prevSupply;\\n }\\n\\n return reward;\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0xd1bad333f3070b57462289a924c60cc20161cc4c349b7d3d99561e0b371cc200\",\"license\":\"MIT\"},\"contracts/factories/WrappedExternalBribeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\\n\\ncontract WrappedExternalBribeFactory {\\n address public immutable voter;\\n mapping(address => address) public oldBribeToNew;\\n address public last_bribe;\\n\\n constructor(address _voter) {\\n voter = _voter;\\n }\\n\\n function createBribe(address existing_bribe) external returns (address) {\\n require(\\n oldBribeToNew[existing_bribe] == address(0),\\n \\\"Wrapped bribe already created\\\"\\n );\\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\\n oldBribeToNew[existing_bribe] = last_bribe;\\n return last_bribe;\\n }\\n}\\n\",\"keccak256\":\"0x4e88b50000e3cf490ae8602b55555bbc02f95fda5926b1a532debfe54ac06bb2\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3546b156d97633f7f8cad536d5454c81d1d604687c02b2eb105fdc33cb962b41\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a060405234801561001057600080fd5b50604051611d5d380380611d5d83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051611ccc61009160003960008181609b01526101530152611ccc6000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632fcd8f271461005157806346c96aac146100965780636bd1a72c146100bd578063b1d0fc82146100d0575b600080fd5b61007a61005f366004610205565b6000602081905290815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b61007a7f000000000000000000000000000000000000000000000000000000000000000081565b61007a6100cb366004610205565b6100e3565b60015461007a906001600160a01b031681565b6001600160a01b03818116600090815260208190526040812054909116156101515760405162461bcd60e51b815260206004820152601d60248201527f5772617070656420627269626520616c72656164792063726561746564000000604482015260640160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000008260405161017f906101f8565b6001600160a01b03928316815291166020820152604001604051809103906000f0801580156101b2573d6000803e3d6000fd5b50600180546001600160a01b039283166001600160a01b031991821681178355948316600090815260208190526040902080549091169094179093559154909116919050565b611a618061023683390190565b60006020828403121561021757600080fd5b81356001600160a01b038116811461022e57600080fd5b939250505056fe60c060405260016006553480156200001657600080fd5b5060405162001a6138038062001a61833981016040819052620000399162000275565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002ad565b6001600160a01b0390811660a052600080546001600160a01b0319169183169190911781555b60008054906101000a90046001600160a01b03166001600160a01b031663e68863966040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000122573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001489190620002d2565b8110156200024f5760008054604051637980d7a160e11b8152600481018490526001600160a01b039091169063f301af4290602401602060405180830381865afa1580156200019b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001c19190620002ad565b90506001600160a01b0381161562000239576001600160a01b0381166000818152600560205260408120805460ff191660019081179091556004805491820181559091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b03191690911790555b50806200024681620002ec565b915050620000d0565b50505062000314565b80516001600160a01b03811681146200027057600080fd5b919050565b600080604083850312156200028957600080fd5b620002948362000258565b9150620002a46020840162000258565b90509250929050565b600060208284031215620002c057600080fd5b620002cb8262000258565b9392505050565b600060208284031215620002e557600080fd5b5051919050565b6000600182016200030d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a0516117046200035d600039600081816101e6015281816108f301528181610b1d0152610fd701526000818161014e01528181610ada0152610d1801526117046000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80639418f939116100a2578063da09d19d11610071578063da09d19d14610281578063e6886396146102a1578063f25e55a5146102a9578063f301af42146102d4578063f5f8d365146102e757600080fd5b80639418f9391461023357806399bcc05214610248578063a7852afa1461025b578063b66503cf1461026e57600080fd5b8063638634ee116100de578063638634ee146101bb5780636c4f5398146101ce5780638dd598fb146101e157806392777b291461020857600080fd5b80630175e23b146101105780633e491d471461013657806346c96aac146101495780634d5ce03814610188575b600080fd5b61012361011e366004611393565b6102fa565b6040519081526020015b60405180910390f35b6101236101443660046113d4565b61033c565b6101707f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161012d565b6101ab610196366004611400565b60056020526000908152604090205460ff1681565b604051901515815260200161012d565b6101236101c9366004611400565b6108cd565b600054610170906001600160a01b031681565b6101707f000000000000000000000000000000000000000000000000000000000000000081565b6101236102163660046113d4565b600160209081526000928352604080842090915290825290205481565b61024661024136600461141d565b6108f1565b005b610123610256366004611400565b610a82565b610246610269366004611475565b610abb565b61024661027c3660046113d4565b610cbb565b61012361028f366004611400565b60026020526000908152604090205481565b600454610123565b6101236102b73660046113d4565b600360209081526000928352604080842090915290825290205481565b6101706102e2366004611393565b610f7d565b6102466102f5366004611475565b610fa7565b6000806103068361117b565b9050600061031762093a808361155c565b90508084106103325761032d8262093a8061155c565b610334565b815b949350505050565b6001600160a01b0382811660009081526003602090815260408083208584529091528082205482549151635058979360e01b81526004810186905292939092911690635058979390602401602060405180830381865afa1580156103a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103c89190611574565b6000036103d95760009150506108c7565b600080546040516328a3532760e21b815260048101869052602481018490526001600160a01b039091169063a28d4c9c90604401602060405180830381865afa15801561042a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044e9190611574565b60008054604051635058979360e01b81526004810188905292935090916001916001600160a01b031690635058979390602401602060405180830381865afa15801561049e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c29190611574565b6104cc919061158d565b905060006104ed604051806040016040528060008152602001600081525090565b6104f68561117b565b8152600080600185156106f357865b61051060018861158d565b81116106f157600054604051631277308160e21b8152600481018d9052602481018390526001600160a01b03909116906349dcc204906044016040805180830381865afa158015610565573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058991906115a4565b909450925060006105998561117b565b86519091508111156105b75760208601516105b4908861155c565b96505b8086526000546001600160a01b031663f7412baf816376f4be366105de62093a808661155c565b6040518263ffffffff1660e01b81526004016105fc91815260200190565b602060405180830381865afa158015610619573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063d9190611574565b6040518263ffffffff1660e01b815260040161065b91815260200190565b6040805180830381865afa158015610677573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061069b91906115a4565b6001600160a01b038f1660009081526001602090815260408083208684529091529020549094508491506106cf90866115c8565b6106d991906115fd565b602087015250806106e981611611565b915050610505565b505b600054604051631277308160e21b8152600481018c9052602481018890526001600160a01b03909116906349dcc204906044016040805180830381865afa158015610742573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076691906115a4565b909350915060006107768461117b565b9050600061078762093a808361155c565b905080421180156107975750808a105b156108ba57600054604051633b7a5f1b60e11b8152600481018390526001600160a01b039091169063f7412baf9082906376f4be3690602401602060405180830381865afa1580156107ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108119190611574565b6040518263ffffffff1660e01b815260040161082f91815260200190565b6040805180830381865afa15801561084b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086f91906115a4565b6001600160a01b038f1660009081526001602090815260408083208784529091529020549094508491506108a390866115c8565b6108ad91906115fd565b6108b7908861155c565b96505b5094985050505050505050505b92915050565b6001600160a01b0381166000908152600260205260408120546108c7904290611194565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610951573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610975919061162a565b6001600160a01b0316336001600160a01b0316146109c65760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600484815481106109e3576109e3611647565b6000918252602090912001546001600160a01b031614610a0257600080fd5b6001600160a01b03808316600090815260056020526040808220805460ff1990811690915592841682529020805490911660011790556004805482919085908110610a4f57610a4f611647565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a8e426102fa565b6001600160a01b039093166000908152600160209081526040808320958352949052929092205492915050565b600654600114610aca57600080fd5b6002600655336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b0457600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610b6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b90919061162a565b905060005b8251811015610cb0576000610bc3848381518110610bb557610bb5611647565b60200260200101518661033c565b90504260036000868581518110610bdc57610bdc611647565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610c3757610c37848381518110610c2857610c28611647565b602002602001015184836111ac565b838281518110610c4957610c49611647565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610c9591815260200190565b60405180910390a35080610ca881611611565b915050610b95565b505060016006555050565b600654600114610cca57600080fd5b600260065580610cd957600080fd5b6001600160a01b03821660009081526005602052604090205460ff16610e2157604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610d5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d83919061165d565b610dcf5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c697374656460448201526064016109bd565b600454601011610e215760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e7300000000000000000060448201526064016109bd565b6000610e2c426102fa565b6001600160a01b0384166000908152600160209081526040808320848452909152902054909150610e5f8433308661129b565b610e69838261155c565b6001600160a01b0385166000908152600160209081526040808320868452909152902055610e9a62093a808361155c565b6001600160a01b03851660009081526002602090815260408083209390935560059052205460ff16610f2c576001600160a01b0384166000818152600560205260408120805460ff191660019081179091556004805491820181559091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a3505060016006555050565b60048181548110610f8d57600080fd5b6000918252602090912001546001600160a01b0316905081565b600654600114610fb657600080fd5b600260065560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611026573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104a919061165d565b61105357600080fd5b60005b815181101561117157600061108483838151811061107657611076611647565b60200260200101518561033c565b9050426003600085858151811061109d5761109d611647565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812088825290925290205580156110f8576110f88383815181106110e9576110e9611647565b602002602001015133836111ac565b82828151811061110a5761110a611647565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161115691815260200190565b60405180910390a3508061116981611611565b915050611056565b5050600160065550565b600061118a62093a808361167f565b6108c7908361158d565b60008183106111a357816111a5565b825b9392505050565b6000836001600160a01b03163b116111c357600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161121f9190611693565b6000604051808303816000865af19150503d806000811461125c576040519150601f19603f3d011682016040523d82523d6000602084013e611261565b606091505b509150915081801561128b57508051158061128b57508080602001905181019061128b919061165d565b61129457600080fd5b5050505050565b6000846001600160a01b03163b116112b257600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916113169190611693565b6000604051808303816000865af19150503d8060008114611353576040519150601f19603f3d011682016040523d82523d6000602084013e611358565b606091505b5091509150818015611382575080511580611382575080806020019051810190611382919061165d565b61138b57600080fd5b505050505050565b6000602082840312156113a557600080fd5b5035919050565b6001600160a01b03811681146113c157600080fd5b50565b80356113cf816113ac565b919050565b600080604083850312156113e757600080fd5b82356113f2816113ac565b946020939093013593505050565b60006020828403121561141257600080fd5b81356111a5816113ac565b60008060006060848603121561143257600080fd5b833592506020840135611444816113ac565b91506040840135611454816113ac565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561148857600080fd5b8235915060208084013567ffffffffffffffff808211156114a857600080fd5b818601915086601f8301126114bc57600080fd5b8135818111156114ce576114ce61145f565b8060051b604051601f19603f830116810181811085821117156114f3576114f361145f565b60405291825284820192508381018501918983111561151157600080fd5b938501935b8285101561153657611527856113c4565b84529385019392850192611516565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561156f5761156f611546565b500190565b60006020828403121561158657600080fd5b5051919050565b60008282101561159f5761159f611546565b500390565b600080604083850312156115b757600080fd5b505080516020909101519092909150565b60008160001904831182151516156115e2576115e2611546565b500290565b634e487b7160e01b600052601260045260246000fd5b60008261160c5761160c6115e7565b500490565b60006001820161162357611623611546565b5060010190565b60006020828403121561163c57600080fd5b81516111a5816113ac565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561166f57600080fd5b815180151581146111a557600080fd5b60008261168e5761168e6115e7565b500690565b6000825160005b818110156116b4576020818601810151858301520161169a565b818111156116c3576000828501525b50919091019291505056fea26469706673582212204c68f24fbe87b92598fd129edadb7398ee5c00fbd53ee158cc73b9c2995c90eb64736f6c634300080d0033a26469706673582212208e50c0572ca7dbe34ebb03c2d342129b354ed41e5b340393120a3678bfa0ff1464736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632fcd8f271461005157806346c96aac146100965780636bd1a72c146100bd578063b1d0fc82146100d0575b600080fd5b61007a61005f366004610205565b6000602081905290815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b61007a7f000000000000000000000000000000000000000000000000000000000000000081565b61007a6100cb366004610205565b6100e3565b60015461007a906001600160a01b031681565b6001600160a01b03818116600090815260208190526040812054909116156101515760405162461bcd60e51b815260206004820152601d60248201527f5772617070656420627269626520616c72656164792063726561746564000000604482015260640160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000008260405161017f906101f8565b6001600160a01b03928316815291166020820152604001604051809103906000f0801580156101b2573d6000803e3d6000fd5b50600180546001600160a01b039283166001600160a01b031991821681178355948316600090815260208190526040902080549091169094179093559154909116919050565b611a618061023683390190565b60006020828403121561021757600080fd5b81356001600160a01b038116811461022e57600080fd5b939250505056fe60c060405260016006553480156200001657600080fd5b5060405162001a6138038062001a61833981016040819052620000399162000275565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002ad565b6001600160a01b0390811660a052600080546001600160a01b0319169183169190911781555b60008054906101000a90046001600160a01b03166001600160a01b031663e68863966040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000122573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001489190620002d2565b8110156200024f5760008054604051637980d7a160e11b8152600481018490526001600160a01b039091169063f301af4290602401602060405180830381865afa1580156200019b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001c19190620002ad565b90506001600160a01b0381161562000239576001600160a01b0381166000818152600560205260408120805460ff191660019081179091556004805491820181559091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b03191690911790555b50806200024681620002ec565b915050620000d0565b50505062000314565b80516001600160a01b03811681146200027057600080fd5b919050565b600080604083850312156200028957600080fd5b620002948362000258565b9150620002a46020840162000258565b90509250929050565b600060208284031215620002c057600080fd5b620002cb8262000258565b9392505050565b600060208284031215620002e557600080fd5b5051919050565b6000600182016200030d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a0516117046200035d600039600081816101e6015281816108f301528181610b1d0152610fd701526000818161014e01528181610ada0152610d1801526117046000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80639418f939116100a2578063da09d19d11610071578063da09d19d14610281578063e6886396146102a1578063f25e55a5146102a9578063f301af42146102d4578063f5f8d365146102e757600080fd5b80639418f9391461023357806399bcc05214610248578063a7852afa1461025b578063b66503cf1461026e57600080fd5b8063638634ee116100de578063638634ee146101bb5780636c4f5398146101ce5780638dd598fb146101e157806392777b291461020857600080fd5b80630175e23b146101105780633e491d471461013657806346c96aac146101495780634d5ce03814610188575b600080fd5b61012361011e366004611393565b6102fa565b6040519081526020015b60405180910390f35b6101236101443660046113d4565b61033c565b6101707f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161012d565b6101ab610196366004611400565b60056020526000908152604090205460ff1681565b604051901515815260200161012d565b6101236101c9366004611400565b6108cd565b600054610170906001600160a01b031681565b6101707f000000000000000000000000000000000000000000000000000000000000000081565b6101236102163660046113d4565b600160209081526000928352604080842090915290825290205481565b61024661024136600461141d565b6108f1565b005b610123610256366004611400565b610a82565b610246610269366004611475565b610abb565b61024661027c3660046113d4565b610cbb565b61012361028f366004611400565b60026020526000908152604090205481565b600454610123565b6101236102b73660046113d4565b600360209081526000928352604080842090915290825290205481565b6101706102e2366004611393565b610f7d565b6102466102f5366004611475565b610fa7565b6000806103068361117b565b9050600061031762093a808361155c565b90508084106103325761032d8262093a8061155c565b610334565b815b949350505050565b6001600160a01b0382811660009081526003602090815260408083208584529091528082205482549151635058979360e01b81526004810186905292939092911690635058979390602401602060405180830381865afa1580156103a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103c89190611574565b6000036103d95760009150506108c7565b600080546040516328a3532760e21b815260048101869052602481018490526001600160a01b039091169063a28d4c9c90604401602060405180830381865afa15801561042a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044e9190611574565b60008054604051635058979360e01b81526004810188905292935090916001916001600160a01b031690635058979390602401602060405180830381865afa15801561049e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c29190611574565b6104cc919061158d565b905060006104ed604051806040016040528060008152602001600081525090565b6104f68561117b565b8152600080600185156106f357865b61051060018861158d565b81116106f157600054604051631277308160e21b8152600481018d9052602481018390526001600160a01b03909116906349dcc204906044016040805180830381865afa158015610565573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058991906115a4565b909450925060006105998561117b565b86519091508111156105b75760208601516105b4908861155c565b96505b8086526000546001600160a01b031663f7412baf816376f4be366105de62093a808661155c565b6040518263ffffffff1660e01b81526004016105fc91815260200190565b602060405180830381865afa158015610619573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063d9190611574565b6040518263ffffffff1660e01b815260040161065b91815260200190565b6040805180830381865afa158015610677573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061069b91906115a4565b6001600160a01b038f1660009081526001602090815260408083208684529091529020549094508491506106cf90866115c8565b6106d991906115fd565b602087015250806106e981611611565b915050610505565b505b600054604051631277308160e21b8152600481018c9052602481018890526001600160a01b03909116906349dcc204906044016040805180830381865afa158015610742573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076691906115a4565b909350915060006107768461117b565b9050600061078762093a808361155c565b905080421180156107975750808a105b156108ba57600054604051633b7a5f1b60e11b8152600481018390526001600160a01b039091169063f7412baf9082906376f4be3690602401602060405180830381865afa1580156107ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108119190611574565b6040518263ffffffff1660e01b815260040161082f91815260200190565b6040805180830381865afa15801561084b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086f91906115a4565b6001600160a01b038f1660009081526001602090815260408083208784529091529020549094508491506108a390866115c8565b6108ad91906115fd565b6108b7908861155c565b96505b5094985050505050505050505b92915050565b6001600160a01b0381166000908152600260205260408120546108c7904290611194565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610951573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610975919061162a565b6001600160a01b0316336001600160a01b0316146109c65760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600484815481106109e3576109e3611647565b6000918252602090912001546001600160a01b031614610a0257600080fd5b6001600160a01b03808316600090815260056020526040808220805460ff1990811690915592841682529020805490911660011790556004805482919085908110610a4f57610a4f611647565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a8e426102fa565b6001600160a01b039093166000908152600160209081526040808320958352949052929092205492915050565b600654600114610aca57600080fd5b6002600655336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b0457600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610b6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b90919061162a565b905060005b8251811015610cb0576000610bc3848381518110610bb557610bb5611647565b60200260200101518661033c565b90504260036000868581518110610bdc57610bdc611647565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610c3757610c37848381518110610c2857610c28611647565b602002602001015184836111ac565b838281518110610c4957610c49611647565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610c9591815260200190565b60405180910390a35080610ca881611611565b915050610b95565b505060016006555050565b600654600114610cca57600080fd5b600260065580610cd957600080fd5b6001600160a01b03821660009081526005602052604090205460ff16610e2157604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610d5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d83919061165d565b610dcf5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c697374656460448201526064016109bd565b600454601011610e215760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e7300000000000000000060448201526064016109bd565b6000610e2c426102fa565b6001600160a01b0384166000908152600160209081526040808320848452909152902054909150610e5f8433308661129b565b610e69838261155c565b6001600160a01b0385166000908152600160209081526040808320868452909152902055610e9a62093a808361155c565b6001600160a01b03851660009081526002602090815260408083209390935560059052205460ff16610f2c576001600160a01b0384166000818152600560205260408120805460ff191660019081179091556004805491820181559091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a3505060016006555050565b60048181548110610f8d57600080fd5b6000918252602090912001546001600160a01b0316905081565b600654600114610fb657600080fd5b600260065560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611026573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104a919061165d565b61105357600080fd5b60005b815181101561117157600061108483838151811061107657611076611647565b60200260200101518561033c565b9050426003600085858151811061109d5761109d611647565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812088825290925290205580156110f8576110f88383815181106110e9576110e9611647565b602002602001015133836111ac565b82828151811061110a5761110a611647565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161115691815260200190565b60405180910390a3508061116981611611565b915050611056565b5050600160065550565b600061118a62093a808361167f565b6108c7908361158d565b60008183106111a357816111a5565b825b9392505050565b6000836001600160a01b03163b116111c357600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161121f9190611693565b6000604051808303816000865af19150503d806000811461125c576040519150601f19603f3d011682016040523d82523d6000602084013e611261565b606091505b509150915081801561128b57508051158061128b57508080602001905181019061128b919061165d565b61129457600080fd5b5050505050565b6000846001600160a01b03163b116112b257600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916113169190611693565b6000604051808303816000865af19150503d8060008114611353576040519150601f19603f3d011682016040523d82523d6000602084013e611358565b606091505b5091509150818015611382575080511580611382575080806020019051810190611382919061165d565b61138b57600080fd5b505050505050565b6000602082840312156113a557600080fd5b5035919050565b6001600160a01b03811681146113c157600080fd5b50565b80356113cf816113ac565b919050565b600080604083850312156113e757600080fd5b82356113f2816113ac565b946020939093013593505050565b60006020828403121561141257600080fd5b81356111a5816113ac565b60008060006060848603121561143257600080fd5b833592506020840135611444816113ac565b91506040840135611454816113ac565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561148857600080fd5b8235915060208084013567ffffffffffffffff808211156114a857600080fd5b818601915086601f8301126114bc57600080fd5b8135818111156114ce576114ce61145f565b8060051b604051601f19603f830116810181811085821117156114f3576114f361145f565b60405291825284820192508381018501918983111561151157600080fd5b938501935b8285101561153657611527856113c4565b84529385019392850192611516565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561156f5761156f611546565b500190565b60006020828403121561158657600080fd5b5051919050565b60008282101561159f5761159f611546565b500390565b600080604083850312156115b757600080fd5b505080516020909101519092909150565b60008160001904831182151516156115e2576115e2611546565b500290565b634e487b7160e01b600052601260045260246000fd5b60008261160c5761160c6115e7565b500490565b60006001820161162357611623611546565b5060010190565b60006020828403121561163c57600080fd5b81516111a5816113ac565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561166f57600080fd5b815180151581146111a557600080fd5b60008261168e5761168e6115e7565b500690565b6000825160005b818110156116b4576020818601810151858301520161169a565b818111156116c3576000828501525b50919091019291505056fea26469706673582212204c68f24fbe87b92598fd129edadb7398ee5c00fbd53ee158cc73b9c2995c90eb64736f6c634300080d0033a26469706673582212208e50c0572ca7dbe34ebb03c2d342129b354ed41e5b340393120a3678bfa0ff1464736f6c634300080d0033", "devdoc": { "kind": "dev", "methods": {}, @@ -114,7 +114,7 @@ "storageLayout": { "storage": [ { - "astId": 21824, + "astId": 21862, "contract": "contracts/factories/WrappedExternalBribeFactory.sol:WrappedExternalBribeFactory", "label": "oldBribeToNew", "offset": 0, @@ -122,7 +122,7 @@ "type": "t_mapping(t_address,t_address)" }, { - "astId": 21826, + "astId": 21864, "contract": "contracts/factories/WrappedExternalBribeFactory.sol:WrappedExternalBribeFactory", "label": "last_bribe", "offset": 0, diff --git a/deployments/arbitrumOne/solcInputs/816572db58a4a8203fcf6f77728173df.json b/deployments/arbitrumOne/solcInputs/816572db58a4a8203fcf6f77728173df.json new file mode 100644 index 00000000..a5525e18 --- /dev/null +++ b/deployments/arbitrumOne/solcInputs/816572db58a4a8203fcf6f77728173df.json @@ -0,0 +1,247 @@ +{ + "language": "Solidity", + "sources": { + "contracts/ExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\";\n\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract ExternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve; // 天使のたまご\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return Math.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balanceOf;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n _prevSupply = supplyCheckpoints[\n getPriorSupplyIndex(_nextEpochStart + DURATION)\n ].supply;\n prevRewards.balanceOf =\n (cp0.balanceOf *\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (block.timestamp > _lastEpochEnd) {\n reward +=\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\n }\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/ExternalBribeV.sol": { + "content": "" + }, + "contracts/factories/BribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport \"contracts/InternalBribe.sol\";\nimport \"contracts/ExternalBribe.sol\";\n\ncontract BribeFactory is IBribeFactory {\n address public last_internal_bribe;\n address public last_external_bribe;\n\n function createInternalBribe(address[] memory allowedRewards)\n external\n returns (address)\n {\n last_internal_bribe = address(\n new InternalBribe(msg.sender, allowedRewards)\n );\n return last_internal_bribe;\n }\n\n function createExternalBribe(address[] memory allowedRewards)\n external\n returns (address)\n {\n last_external_bribe = address(\n new ExternalBribe(msg.sender, allowedRewards)\n );\n return last_external_bribe;\n }\n}\n" + }, + "contracts/factories/GaugeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IGaugeFactory.sol';\nimport 'contracts/Gauge.sol';\n\ncontract GaugeFactory is IGaugeFactory {\n address public last_gauge;\n\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\n return last_gauge;\n }\n}\n" + }, + "contracts/factories/PairFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/Pair.sol\";\n\ncontract PairFactory is IPairFactory {\n bool public isPaused;\n address public pauser;\n address public pendingPauser;\n\n uint256 public stableFee;\n uint256 public volatileFee;\n uint256 public constant MAX_FEE = 50; // 0.5%\n address public feeManager;\n address public pendingFeeManager;\n\n mapping(address => mapping(address => mapping(bool => address)))\n public getPair;\n address[] public allPairs;\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\n\n address internal _temp0;\n address internal _temp1;\n bool internal _temp;\n\n event PairCreated(\n address indexed token0,\n address indexed token1,\n bool stable,\n address pair,\n uint256\n );\n\n constructor() {\n pauser = msg.sender;\n isPaused = false;\n feeManager = msg.sender;\n // stableFee = 2; // 0.02%\n // volatileFee = 2;\n stableFee = 3; // 0.03%\n volatileFee = 25; // 0.25%\n }\n\n function allPairsLength() external view returns (uint256) {\n return allPairs.length;\n }\n\n function setPauser(address _pauser) external {\n require(msg.sender == pauser);\n pendingPauser = _pauser;\n }\n\n function acceptPauser() external {\n require(msg.sender == pendingPauser);\n pauser = pendingPauser;\n }\n\n function setPause(bool _state) external {\n require(msg.sender == pauser);\n isPaused = _state;\n }\n\n function setFeeManager(address _feeManager) external {\n require(msg.sender == feeManager, \"not fee manager\");\n pendingFeeManager = _feeManager;\n }\n\n function acceptFeeManager() external {\n require(msg.sender == pendingFeeManager, \"not pending fee manager\");\n feeManager = pendingFeeManager;\n }\n\n function setFee(bool _stable, uint256 _fee) external {\n require(msg.sender == feeManager, \"not fee manager\");\n require(_fee <= MAX_FEE, \"fee too high\");\n require(_fee != 0, \"fee must be nonzero\");\n if (_stable) {\n stableFee = _fee;\n } else {\n volatileFee = _fee;\n }\n }\n\n function getFee(bool _stable) public view returns (uint256) {\n return _stable ? stableFee : volatileFee;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(Pair).creationCode);\n }\n\n function getInitializable()\n external\n view\n returns (\n address,\n address,\n bool\n )\n {\n return (_temp0, _temp1, _temp);\n }\n\n function createPair(\n address tokenA,\n address tokenB,\n bool stable\n ) external returns (address pair) {\n require(tokenA != tokenB, \"IA\"); // Pair: IDENTICAL_ADDRESSES\n (address token0, address token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"ZA\"); // Pair: ZERO_ADDRESS\n require(getPair[token0][token1][stable] == address(0), \"PE\"); // Pair: PAIR_EXISTS - single check is sufficient\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\n (_temp0, _temp1, _temp) = (token0, token1, stable);\n pair = address(new Pair{salt: salt}());\n getPair[token0][token1][stable] = pair;\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n isPair[pair] = true;\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\n }\n}\n" + }, + "contracts/factories/WrappedExternalBribeFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\n\ncontract WrappedExternalBribeFactory {\n address public immutable voter;\n mapping(address => address) public oldBribeToNew;\n address public last_bribe;\n\n constructor(address _voter) {\n voter = _voter;\n }\n\n function createBribe(address existing_bribe) external returns (address) {\n require(\n oldBribeToNew[existing_bribe] == address(0),\n \"Wrapped bribe already created\"\n );\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\n oldBribeToNew[existing_bribe] = last_bribe;\n return last_bribe;\n }\n}\n" + }, + "contracts/Flow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IFlow.sol\";\n\ncontract Flow is IFlow {\n string public constant name = \"Velocimeter\";\n string public constant symbol = \"FLOW\";\n uint8 public constant decimals = 18;\n uint256 public totalSupply = 0;\n\n mapping(address => uint256) public balanceOf;\n mapping(address => mapping(address => uint256)) public allowance;\n\n bool public initialMinted;\n address public minter;\n address public redemptionReceiver;\n address public merkleClaim;\n\n event Transfer(address indexed from, address indexed to, uint256 value);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 value\n );\n\n constructor() {\n minter = msg.sender;\n _mint(msg.sender, 0);\n }\n\n // No checks as its meant to be once off to set minting rights to BaseV1 Minter\n function setMinter(address _minter) external {\n require(msg.sender == minter);\n minter = _minter;\n }\n\n function setRedemptionReceiver(address _receiver) external {\n require(msg.sender == minter);\n redemptionReceiver = _receiver;\n }\n\n function setMerkleClaim(address _merkleClaim) external {\n require(msg.sender == minter);\n merkleClaim = _merkleClaim;\n }\n\n // NFTs are minted from this amount as well now\n function initialMint(address _recipient) external {\n require(msg.sender == minter && !initialMinted);\n initialMinted = true;\n _mint(_recipient, 400 * 1e6 * 1e18); //#settings\n }\n\n function approve(address _spender, uint256 _value) external returns (bool) {\n allowance[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function _mint(address _to, uint256 _amount) internal returns (bool) {\n totalSupply += _amount;\n unchecked {\n balanceOf[_to] += _amount;\n }\n emit Transfer(address(0x0), _to, _amount);\n return true;\n }\n\n function _transfer(\n address _from,\n address _to,\n uint256 _value\n ) internal returns (bool) {\n balanceOf[_from] -= _value;\n unchecked {\n balanceOf[_to] += _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function transfer(address _to, uint256 _value) external returns (bool) {\n return _transfer(msg.sender, _to, _value);\n }\n\n function transferFrom(\n address _from,\n address _to,\n uint256 _value\n ) external returns (bool) {\n uint256 allowed_from = allowance[_from][msg.sender];\n if (allowed_from != type(uint256).max) {\n allowance[_from][msg.sender] -= _value;\n }\n return _transfer(_from, _to, _value);\n }\n\n function mint(address account, uint256 amount) external returns (bool) {\n require(msg.sender == minter);\n _mint(account, amount);\n return true;\n }\n\n function claim(address account, uint256 amount) external returns (bool) {\n require(msg.sender == redemptionReceiver || msg.sender == merkleClaim);\n _mint(account, amount);\n return true;\n }\n}\n" + }, + "contracts/FlowGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IGovernor} from \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\nimport {L2GovernorCountingSimple} from \"contracts/governance/L2GovernorCountingSimple.sol\";\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\nimport {L2GovernorVotesQuorumFraction} from \"contracts/governance/L2GovernorVotesQuorumFraction.sol\";\n\ncontract FlowGovernor is\n L2Governor,\n L2GovernorCountingSimple,\n L2GovernorVotes,\n L2GovernorVotesQuorumFraction\n{\n address public team;\n uint256 public constant MAX_PROPOSAL_NUMERATOR = 50; // max 5%\n uint256 public constant PROPOSAL_DENOMINATOR = 1000;\n uint256 public proposalNumerator = 2; // start at 0.02%\n\n constructor(IVotes _ve)\n L2Governor(\"Velocimeter Governor\")\n L2GovernorVotes(_ve)\n L2GovernorVotesQuorumFraction(4) // 4%\n {\n team = msg.sender;\n }\n\n function votingDelay() public pure override(IGovernor) returns (uint256) {\n return 15 minutes; // 1 block\n }\n\n function votingPeriod() public pure override(IGovernor) returns (uint256) {\n return 1 weeks;\n }\n\n function setTeam(address newTeam) external {\n require(msg.sender == team, \"not team\");\n team = newTeam;\n }\n\n function setProposalNumerator(uint256 numerator) external {\n require(msg.sender == team, \"not team\");\n require(numerator <= MAX_PROPOSAL_NUMERATOR, \"numerator too high\");\n proposalNumerator = numerator;\n }\n\n function proposalThreshold()\n public\n view\n override(L2Governor)\n returns (uint256)\n {\n return\n (token.getPastTotalSupply(block.timestamp) * proposalNumerator) /\n PROPOSAL_DENOMINATOR;\n }\n}\n" + }, + "contracts/Gauge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\ncontract Gauge is IGauge {\n address public immutable stake; // the LP token that needs to be staked for rewards\n address public immutable _ve; // the ve token used for gauges\n address public immutable internal_bribe;\n address public immutable external_bribe;\n address public immutable voter;\n\n uint256 public derivedSupply;\n mapping(address => uint256) public derivedBalances;\n\n bool public isForPair;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n uint256 internal constant PRECISION = 10**18;\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(address => uint256)) public lastEarn;\n mapping(address => mapping(address => uint256))\n public userRewardPerTokenStored;\n\n mapping(address => uint256) public tokenIds;\n\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(address => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n uint256 public fees0;\n uint256 public fees1;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(\n address _stake,\n address _internal_bribe,\n address _external_bribe,\n address __ve,\n address _voter,\n bool _forPair,\n address[] memory _allowedRewardTokens\n ) {\n stake = _stake;\n internal_bribe = _internal_bribe;\n external_bribe = _external_bribe;\n _ve = __ve;\n voter = _voter;\n isForPair = _forPair;\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function claimFees()\n external\n lock\n returns (uint256 claimed0, uint256 claimed1)\n {\n return _claimFees();\n }\n\n function _claimFees()\n internal\n returns (uint256 claimed0, uint256 claimed1)\n {\n if (!isForPair) {\n return (0, 0);\n }\n (claimed0, claimed1) = IPair(stake).claimFees();\n if (claimed0 > 0 || claimed1 > 0) {\n uint256 _fees0 = fees0 + claimed0;\n uint256 _fees1 = fees1 + claimed1;\n (address _token0, address _token1) = IPair(stake).tokens();\n if (\n _fees0 > IBribe(internal_bribe).left(_token0) &&\n _fees0 / DURATION > 0\n ) {\n fees0 = 0;\n _safeApprove(_token0, internal_bribe, _fees0);\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\n } else {\n fees0 = _fees0;\n }\n if (\n _fees1 > IBribe(internal_bribe).left(_token1) &&\n _fees1 / DURATION > 0\n ) {\n fees1 = 0;\n _safeApprove(_token1, internal_bribe, _fees1);\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\n } else {\n fees1 = _fees1;\n }\n\n emit ClaimFees(msg.sender, claimed0, claimed1);\n }\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(address account, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(address account, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[account][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[account] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n derivedSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return Math.min(block.timestamp, periodFinish[token]);\n }\n\n function getReward(address account, address[] memory tokens) external lock {\n require(msg.sender == account || msg.sender == voter);\n _unlocked = 1;\n IVoter(voter).distribute(address(this));\n _unlocked = 2;\n\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], account);\n lastEarn[tokens[i]][account] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n\n uint256 _derivedBalance = derivedBalances[account];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(account);\n derivedBalances[account] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(account, derivedBalances[account]);\n _writeSupplyCheckpoint();\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (derivedSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n Math.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n PRECISION) / derivedSupply);\n }\n\n function derivedBalance(address account) public view returns (uint256) {\n return balanceOf[account];\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = Math.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = Math.max(timestamp1, startTimestamp);\n return (\n (((Math.min(endTime, periodFinish[token]) -\n Math.min(\n Math.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n PRECISION) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = Math.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n Math.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\n function earned(address token, address account)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = Math.max(\n lastEarn[token][account],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[account] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\n uint256 _endIndex = numCheckpoints[account] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[account][i];\n Checkpoint memory cp1 = checkpoints[account][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n PRECISION;\n }\n }\n\n Checkpoint memory cp = checkpoints[account][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n Math.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][account]\n ))) /\n PRECISION;\n\n return reward;\n }\n\n function depositAll(uint256 tokenId) external {\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\n }\n\n function deposit(uint256 amount, uint256 tokenId) public lock {\n require(amount > 0);\n _updateRewardForAllTokens();\n\n _safeTransferFrom(stake, msg.sender, address(this), amount);\n totalSupply += amount;\n balanceOf[msg.sender] += amount;\n\n if (tokenId > 0) {\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\n if (tokenIds[msg.sender] == 0) {\n tokenIds[msg.sender] = tokenId;\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\n }\n require(tokenIds[msg.sender] == tokenId);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, _derivedBalance);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function withdrawAll() external {\n withdraw(balanceOf[msg.sender]);\n }\n\n function withdraw(uint256 amount) public {\n uint256 tokenId = 0;\n if (amount == balanceOf[msg.sender]) {\n tokenId = tokenIds[msg.sender];\n }\n withdrawToken(amount, tokenId);\n }\n\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[msg.sender] -= amount;\n _safeTransfer(stake, msg.sender, amount);\n\n if (tokenId > 0) {\n require(tokenId == tokenIds[msg.sender]);\n tokenIds[msg.sender] = 0;\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\n } else {\n tokenId = tokenIds[msg.sender];\n }\n\n uint256 _derivedBalance = derivedBalances[msg.sender];\n derivedSupply -= _derivedBalance;\n _derivedBalance = derivedBalance(msg.sender);\n derivedBalances[msg.sender] = _derivedBalance;\n derivedSupply += _derivedBalance;\n\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\n _writeSupplyCheckpoint();\n\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(token != stake);\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"rewards tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n _claimFees();\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeApprove(\n address token,\n address spender,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/governance/L2Governor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/Governor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Address.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Context.sol\";\nimport \"lib/openzeppelin-contracts/contracts/utils/Timers.sol\";\nimport \"lib/openzeppelin-contracts/contracts/governance/IGovernor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2Governor.sol)\n *\n * @dev Core of the governance system, designed to be extended though various modules.\n *\n * This contract is abstract and requires several function to be implemented in various modules:\n *\n * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}\n * - A voting module must implement {_getVotes}\n * - Additionanly, the {votingPeriod} must also be implemented\n *\n * _Available since v4.3._\n */\nabstract contract L2Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {\n using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;\n using SafeCast for uint256;\n using Timers for Timers.Timestamp;\n\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n bytes32 public constant EXTENDED_BALLOT_TYPEHASH =\n keccak256(\"ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)\");\n\n struct ProposalCore {\n Timers.Timestamp voteStart;\n Timers.Timestamp voteEnd;\n bool executed;\n bool canceled;\n }\n\n string private _name;\n\n mapping(uint256 => ProposalCore) private _proposals;\n\n // This queue keeps track of the governor operating on itself. Calls to functions protected by the\n // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},\n // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the\n // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.\n DoubleEndedQueue.Bytes32Deque private _governanceCall;\n\n /**\n * @dev Restricts a function so it can only be executed through governance proposals. For example, governance\n * parameter setters in {GovernorSettings} are protected using this modifier.\n *\n * The governance executing address may be different from the Governor's own address, for example it could be a\n * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these\n * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,\n * for example, additional timelock proposers are not able to change governance parameters without going through the\n * governance protocol (since v4.6).\n */\n modifier onlyGovernance() {\n require(_msgSender() == _executor(), \"Governor: onlyGovernance\");\n if (_executor() != address(this)) {\n bytes32 msgDataHash = keccak256(_msgData());\n // loop until popping the expected operation - throw if deque is empty (operation not authorized)\n while (_governanceCall.popFront() != msgDataHash) {}\n }\n _;\n }\n\n /**\n * @dev Sets the value for {name} and {version}\n */\n constructor(string memory name_) EIP712(name_, version()) {\n _name = name_;\n }\n\n /**\n * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)\n */\n receive() external payable virtual {\n require(_executor() == address(this));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n // In addition to the current interfaceId, also support previous version of the interfaceId that did not\n // include the castVoteWithReasonAndParams() function as standard\n return\n interfaceId ==\n (type(IGovernor).interfaceId ^\n this.castVoteWithReasonAndParams.selector ^\n this.castVoteWithReasonAndParamsBySig.selector ^\n this.getVotesWithParams.selector) ||\n interfaceId == type(IGovernor).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IGovernor-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IGovernor-version}.\n */\n function version() public view virtual override returns (string memory) {\n return \"1\";\n }\n\n /**\n * @dev See {IGovernor-hashProposal}.\n *\n * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array\n * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id\n * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in\n * advance, before the proposal is submitted.\n *\n * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the\n * same proposal (with same operation and same description) will have the same id if submitted on multiple governors\n * across multiple networks. This also means that in order to execute the same operation twice (on the same\n * governor) the proposer will have to change the description in order to avoid proposal id conflicts.\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual override returns (uint256) {\n return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));\n }\n\n /**\n * @dev See {IGovernor-state}.\n */\n function state(uint256 proposalId) public view virtual override returns (ProposalState) {\n ProposalCore storage proposal = _proposals[proposalId];\n\n if (proposal.executed) {\n return ProposalState.Executed;\n }\n\n if (proposal.canceled) {\n return ProposalState.Canceled;\n }\n\n uint256 start = proposalSnapshot(proposalId);\n\n if (start == 0) {\n revert(\"Governor: unknown proposal id\");\n }\n\n if (start >= block.timestamp) {\n return ProposalState.Pending;\n }\n\n uint256 deadline = proposalDeadline(proposalId);\n\n if (deadline >= block.timestamp) {\n return ProposalState.Active;\n }\n\n if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {\n return ProposalState.Succeeded;\n } else {\n return ProposalState.Defeated;\n }\n }\n\n /**\n * @dev See {IGovernor-proposalSnapshot}.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteStart.getDeadline();\n }\n\n /**\n * @dev See {IGovernor-proposalDeadline}.\n */\n function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {\n return _proposals[proposalId].voteEnd.getDeadline();\n }\n\n /**\n * @dev Part of the Governor Bravo's interface: _\"The number of votes required in order for a voter to become a proposer\"_.\n */\n function proposalThreshold() public view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Amount of votes already cast passes the threshold limit.\n */\n function _quorumReached(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Is the proposal successful or not.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);\n\n /**\n * @dev Get the voting weight of `account` at a specific `blockTimestamp`, for a vote as described by `params`.\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) internal view virtual returns (uint256);\n\n /**\n * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.\n *\n * Note: Support is generic and can represent various things depending on the voting system used.\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory params\n ) internal virtual;\n\n /**\n * @dev Default additional encoded parameters used by castVote methods that don't include them\n *\n * Note: Should be overridden by specific implementations to use an appropriate value, the\n * meaning of the additional params, in the context of that implementation\n */\n function _defaultParams() internal view virtual returns (bytes memory) {\n return \"\";\n }\n\n /**\n * @dev See {IGovernor-propose}.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual override returns (uint256) {\n require(\n getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),\n \"Governor: proposer votes below proposal threshold\"\n );\n\n uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));\n\n require(targets.length == values.length, \"Governor: invalid proposal length\");\n require(targets.length == calldatas.length, \"Governor: invalid proposal length\");\n require(targets.length > 0, \"Governor: empty proposal\");\n\n ProposalCore storage proposal = _proposals[proposalId];\n require(proposal.voteStart.isUnset(), \"Governor: proposal already exists\");\n\n uint64 start = block.timestamp.toUint64() + votingDelay().toUint64();\n uint64 deadline = start + votingPeriod().toUint64();\n\n proposal.voteStart.setDeadline(start);\n proposal.voteEnd.setDeadline(deadline);\n\n emit ProposalCreated(\n proposalId,\n _msgSender(),\n targets,\n values,\n new string[](targets.length),\n calldatas,\n start,\n deadline,\n description\n );\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-execute}.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual override returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n\n ProposalState status = state(proposalId);\n require(\n status == ProposalState.Succeeded || status == ProposalState.Queued,\n \"Governor: proposal not successful\"\n );\n _proposals[proposalId].executed = true;\n\n emit ProposalExecuted(proposalId);\n\n _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);\n _execute(proposalId, targets, values, calldatas, descriptionHash);\n _afterExecute(proposalId, targets, values, calldatas, descriptionHash);\n\n return proposalId;\n }\n\n /**\n * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism\n */\n function _execute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n string memory errorMessage = \"Governor: call reverted without message\";\n for (uint256 i = 0; i < targets.length; ++i) {\n (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);\n Address.verifyCallResult(success, returndata, errorMessage);\n }\n }\n\n /**\n * @dev Hook before execution is triggered.\n */\n function _beforeExecute(\n uint256, /* proposalId */\n address[] memory targets,\n uint256[] memory, /* values */\n bytes[] memory calldatas,\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n for (uint256 i = 0; i < targets.length; ++i) {\n if (targets[i] == address(this)) {\n _governanceCall.pushBack(keccak256(calldatas[i]));\n }\n }\n }\n }\n\n /**\n * @dev Hook after execution is triggered.\n */\n function _afterExecute(\n uint256, /* proposalId */\n address[] memory, /* targets */\n uint256[] memory, /* values */\n bytes[] memory, /* calldatas */\n bytes32 /*descriptionHash*/\n ) internal virtual {\n if (_executor() != address(this)) {\n if (!_governanceCall.empty()) {\n _governanceCall.clear();\n }\n }\n }\n\n /**\n * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as\n * canceled to allow distinguishing it from executed proposals.\n *\n * Emits a {IGovernor-ProposalCanceled} event.\n */\n function _cancel(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) internal virtual returns (uint256) {\n uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);\n ProposalState status = state(proposalId);\n\n require(\n status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,\n \"Governor: proposal not active\"\n );\n _proposals[proposalId].canceled = true;\n\n emit ProposalCanceled(proposalId);\n\n return proposalId;\n }\n\n /**\n * @dev See {IGovernor-getVotes}.\n */\n function getVotes(address account, uint256 blockTimestamp) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, _defaultParams());\n }\n\n /**\n * @dev See {IGovernor-getVotesWithParams}.\n */\n function getVotesWithParams(\n address account,\n uint256 blockTimestamp,\n bytes memory params\n ) public view virtual override returns (uint256) {\n return _getVotes(account, blockTimestamp, params);\n }\n\n /**\n * @dev See {IGovernor-castVote}.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReason}.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason);\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParams}.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual override returns (uint256) {\n address voter = _msgSender();\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev See {IGovernor-castVoteBySig}.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),\n v,\n r,\n s\n );\n return _castVote(proposalId, voter, support, \"\");\n }\n\n /**\n * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override returns (uint256) {\n address voter = ECDSA.recover(\n _hashTypedDataV4(\n keccak256(\n abi.encode(\n EXTENDED_BALLOT_TYPEHASH,\n proposalId,\n support,\n keccak256(bytes(reason)),\n keccak256(params)\n )\n )\n ),\n v,\n r,\n s\n );\n\n return _castVote(proposalId, voter, support, reason, params);\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason\n ) internal virtual returns (uint256) {\n return _castVote(proposalId, account, support, reason, _defaultParams());\n }\n\n /**\n * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve\n * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.\n *\n * Emits a {IGovernor-VoteCast} event.\n */\n function _castVote(\n uint256 proposalId,\n address account,\n uint8 support,\n string memory reason,\n bytes memory params\n ) internal virtual returns (uint256) {\n ProposalCore storage proposal = _proposals[proposalId];\n require(state(proposalId) == ProposalState.Active, \"Governor: vote not currently active\");\n\n uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);\n _countVote(proposalId, account, support, weight, params);\n\n if (params.length == 0) {\n emit VoteCast(account, proposalId, support, weight, reason);\n } else {\n emit VoteCastWithParams(account, proposalId, support, weight, reason, params);\n }\n\n return weight;\n }\n\n /**\n * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor\n * is some contract other than the governor itself, like when using a timelock, this function can be invoked\n * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.\n * Note that if the executor is simply the governor itself, use of `relay` is redundant.\n */\n function relay(\n address target,\n uint256 value,\n bytes calldata data\n ) external virtual onlyGovernance {\n Address.functionCallWithValue(target, data, value);\n }\n\n /**\n * @dev Address through which the governor executes action. Will be overloaded by module that execute actions\n * through another contract such as a timelock.\n */\n function _executor() internal view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(\n address,\n address,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" + }, + "contracts/governance/L2GovernorCountingSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorCountingSimple.sol)\n *\n * @dev Extension of {Governor} for simple, 3 options, vote counting.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorCountingSimple is L2Governor {\n /**\n * @dev Supported vote types. Matches Governor Bravo ordering.\n */\n enum VoteType {\n Against,\n For,\n Abstain\n }\n\n struct ProposalVote {\n uint256 againstVotes;\n uint256 forVotes;\n uint256 abstainVotes;\n mapping(address => bool) hasVoted;\n }\n\n mapping(uint256 => ProposalVote) private _proposalVotes;\n\n /**\n * @dev See {IGovernor-COUNTING_MODE}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual override returns (string memory) {\n return \"support=bravo&quorum=for,abstain\";\n }\n\n /**\n * @dev See {IGovernor-hasVoted}.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {\n return _proposalVotes[proposalId].hasVoted[account];\n }\n\n /**\n * @dev Accessor to the internal vote counts.\n */\n function proposalVotes(uint256 proposalId)\n public\n view\n virtual\n returns (\n uint256 againstVotes,\n uint256 forVotes,\n uint256 abstainVotes\n )\n {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);\n }\n\n /**\n * @dev See {Governor-_quorumReached}.\n */\n function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;\n }\n\n /**\n * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.\n */\n function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n return proposalvote.forVotes > proposalvote.againstVotes;\n }\n\n /**\n * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).\n */\n function _countVote(\n uint256 proposalId,\n address account,\n uint8 support,\n uint256 weight,\n bytes memory // params\n ) internal virtual override {\n ProposalVote storage proposalvote = _proposalVotes[proposalId];\n\n require(!proposalvote.hasVoted[account], \"GovernorVotingSimple: vote already cast\");\n proposalvote.hasVoted[account] = true;\n\n if (support == uint8(VoteType.Against)) {\n proposalvote.againstVotes += weight;\n } else if (support == uint8(VoteType.For)) {\n proposalvote.forVotes += weight;\n } else if (support == uint8(VoteType.Abstain)) {\n proposalvote.abstainVotes += weight;\n } else {\n revert(\"GovernorVotingSimple: invalid value for enum VoteType\");\n }\n }\n}\n" + }, + "contracts/governance/L2GovernorVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)\n\npragma solidity ^0.8.0;\n\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {L2Governor} from \"contracts/governance/L2Governor.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotes.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotes is L2Governor {\n IVotes public immutable token;\n\n constructor(IVotes tokenAddress) {\n token = tokenAddress;\n }\n\n /**\n * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).\n */\n function _getVotes(\n address account,\n uint256 blockTimestamp,\n bytes memory /*params*/\n ) internal view virtual override returns (uint256) {\n return token.getPastVotes(account, blockTimestamp);\n }\n}\n" + }, + "contracts/governance/L2GovernorVotesQuorumFraction.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)\n\npragma solidity ^0.8.0;\n\nimport {L2GovernorVotes} from \"contracts/governance/L2GovernorVotes.sol\";\n\n/**\n * @author Modified from RollCall (https://github.com/withtally/rollcall/blob/main/src/standards/L2GovernorVotesQuorumFraction.sol)\n *\n * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a\n * fraction of the total supply.\n *\n * _Available since v4.3._\n */\nabstract contract L2GovernorVotesQuorumFraction is L2GovernorVotes {\n uint256 private _quorumNumerator;\n\n event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n /**\n * @dev Initialize quorum as a fraction of the token's total supply.\n *\n * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is\n * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be\n * customized by overriding {quorumDenominator}.\n */\n constructor(uint256 quorumNumeratorValue) {\n _updateQuorumNumerator(quorumNumeratorValue);\n }\n\n /**\n * @dev Returns the current quorum numerator. See {quorumDenominator}.\n */\n function quorumNumerator() public view virtual returns (uint256) {\n return _quorumNumerator;\n }\n\n /**\n * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.\n */\n function quorumDenominator() public view virtual returns (uint256) {\n return 100;\n }\n\n /**\n * @dev Returns the quorum for a block timestamp, in terms of number of votes: `supply * numerator / denominator`.\n */\n function quorum(uint256 blockTimestamp) public view virtual override returns (uint256) {\n return (token.getPastTotalSupply(blockTimestamp) * quorumNumerator()) / quorumDenominator();\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - Must be called through a governance proposal.\n * - New numerator must be smaller or equal to the denominator.\n */\n function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {\n _updateQuorumNumerator(newQuorumNumerator);\n }\n\n /**\n * @dev Changes the quorum numerator.\n *\n * Emits a {QuorumNumeratorUpdated} event.\n *\n * Requirements:\n *\n * - New numerator must be smaller or equal to the denominator.\n */\n function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {\n require(\n newQuorumNumerator <= quorumDenominator(),\n \"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator\"\n );\n\n uint256 oldQuorumNumerator = _quorumNumerator;\n _quorumNumerator = newQuorumNumerator;\n\n emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);\n }\n}\n" + }, + "contracts/interfaces/IBribe.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribe {\n function _deposit(uint amount, uint tokenId) external;\n function _withdraw(uint amount, uint tokenId) external;\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\n function notifyRewardAmount(address token, uint amount) external;\n function left(address token) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IBribeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IBribeFactory {\n function createInternalBribe(address[] memory) external returns (address);\n function createExternalBribe(address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IERC20.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function transfer(address recipient, uint amount) external returns (bool);\n function decimals() external view returns (uint8);\n function symbol() external view returns (string memory);\n function balanceOf(address) external view returns (uint);\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\n function allowance(address owner, address spender) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint value);\n event Approval(address indexed owner, address indexed spender, uint value);\n}\n" + }, + "contracts/interfaces/IFlow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IFlow {\n function totalSupply() external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function approve(address spender, uint value) external returns (bool);\n function transfer(address, uint) external returns (bool);\n function transferFrom(address,address,uint) external returns (bool);\n function mint(address, uint) external returns (bool);\n function minter() external returns (address);\n function claim(address, uint) external returns (bool);\n}\n" + }, + "contracts/interfaces/IGauge.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGauge {\n function notifyRewardAmount(address token, uint amount) external;\n function getReward(address account, address[] memory tokens) external;\n function claimFees() external returns (uint claimed0, uint claimed1);\n function left(address token) external view returns (uint);\n function isForPair() external view returns (bool);\n}\n" + }, + "contracts/interfaces/IGaugeFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IGaugeFactory {\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\n}\n" + }, + "contracts/interfaces/IMinter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IMinter {\n function update_period() external returns (uint);\n}\n" + }, + "contracts/interfaces/IPair.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPair {\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\n function claimFees() external returns (uint, uint);\n function tokens() external returns (address, address);\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function burn(address to) external returns (uint amount0, uint amount1);\n function mint(address to) external returns (uint liquidity);\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\n function getAmountOut(uint, address) external view returns (uint);\n}\n" + }, + "contracts/interfaces/IPairCallee.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairCallee {\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" + }, + "contracts/interfaces/IPairFactory.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IPairFactory {\n function allPairsLength() external view returns (uint);\n function isPair(address pair) external view returns (bool);\n function pairCodeHash() external pure returns (bytes32);\n function getPair(address tokenA, address token, bool stable) external view returns (address);\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\n}\n" + }, + "contracts/interfaces/IRewardsDistributor.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRewardsDistributor {\n function checkpoint_token() external;\n function checkpoint_total_supply() external;\n}\n" + }, + "contracts/interfaces/IRouter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IRouter {\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\n}\n" + }, + "contracts/interfaces/IVeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVeArtProxy {\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\n}\n" + }, + "contracts/interfaces/IVoter.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVoter {\n function _ve() external view returns (address);\n function governor() external view returns (address);\n function emergencyCouncil() external view returns (address);\n function attachTokenToGauge(uint _tokenId, address account) external;\n function detachTokenFromGauge(uint _tokenId, address account) external;\n function emitDeposit(uint _tokenId, address account, uint amount) external;\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\n function isWhitelisted(address token) external view returns (bool);\n function notifyRewardAmount(uint amount) external;\n function distribute(address _gauge) external;\n}\n" + }, + "contracts/interfaces/IVotingEscrow.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IVotingEscrow {\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint256 ts;\n uint256 blk; // block\n }\n\n function token() external view returns (address);\n function team() external returns (address);\n function epoch() external view returns (uint);\n function point_history(uint loc) external view returns (Point memory);\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\n function user_point_epoch(uint tokenId) external view returns (uint);\n\n function ownerOf(uint) external view returns (address);\n function isApprovedOrOwner(address, uint) external view returns (bool);\n function transferFrom(address, address, uint) external;\n\n function voting(uint tokenId) external;\n function abstain(uint tokenId) external;\n function attach(uint tokenId) external;\n function detach(uint tokenId) external;\n\n function checkpoint() external;\n function deposit_for(uint tokenId, uint value) external;\n function create_lock_for(uint, uint, address) external returns (uint);\n\n function balanceOfNFT(uint) external view returns (uint);\n function totalSupply() external view returns (uint);\n}\n" + }, + "contracts/interfaces/IWETH.sol": { + "content": "pragma solidity 0.8.13;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint256 value) external returns (bool);\n function withdraw(uint256) external;\n}\n" + }, + "contracts/InternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract InternalBribe is IBribe {\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\n address public immutable _ve;\n\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\n\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n // default snx staking contract implementation\n mapping(address => uint256) public rewardRate;\n mapping(address => uint256) public periodFinish;\n mapping(address => uint256) public lastUpdateTime;\n mapping(address => uint256) public rewardPerTokenStored;\n\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n mapping(address => mapping(uint256 => uint256))\n public userRewardPerTokenStored;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n uint256 public totalSupply;\n mapping(uint256 => uint256) public balanceOf;\n\n /// @notice A checkpoint for marking balance\n struct Checkpoint {\n uint256 timestamp;\n uint256 balanceOf;\n }\n\n /// @notice A checkpoint for marking reward rate\n struct RewardPerTokenCheckpoint {\n uint256 timestamp;\n uint256 rewardPerToken;\n }\n\n /// @notice A checkpoint for marking supply\n struct SupplyCheckpoint {\n uint256 timestamp;\n uint256 supply;\n }\n\n /// @notice A record of balance checkpoints for each account, by index\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\n /// @notice The number of checkpoints for each account\n mapping(uint256 => uint256) public numCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\n /// @notice The number of checkpoints\n uint256 public supplyNumCheckpoints;\n /// @notice A record of balance checkpoints for each token, by index\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\n public rewardPerTokenCheckpoints;\n /// @notice The number of checkpoints for each token\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\n\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address[] memory _allowedRewardTokens) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\n if (_allowedRewardTokens[i] != address(0)) {\n isReward[_allowedRewardTokens[i]] = true;\n rewards.push(_allowedRewardTokens[i]);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n /**\n * @notice Determine the prior balance for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param tokenId The token of the NFT to check\n * @param timestamp The timestamp to get the balance at\n * @return The balance the account had as of the given block\n */\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = numCheckpoints[tokenId];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[tokenId][0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[tokenId][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorSupplyIndex(uint256 timestamp)\n public\n view\n returns (uint256)\n {\n uint256 nCheckpoints = supplyNumCheckpoints;\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (supplyCheckpoints[0].timestamp > timestamp) {\n return 0;\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPriorRewardPerToken(address token, uint256 timestamp)\n public\n view\n returns (uint256, uint256)\n {\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\n if (nCheckpoints == 0) {\n return (0, 0);\n }\n\n // First check most recent balance\n if (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\n timestamp\n ) {\n return (\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\n .rewardPerToken,\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\n );\n }\n\n // Next check implicit zero balance\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\n return (0, 0);\n }\n\n uint256 lower = 0;\n uint256 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\n token\n ][center];\n if (cp.timestamp == timestamp) {\n return (cp.rewardPerToken, cp.timestamp);\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return (\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\n rewardPerTokenCheckpoints[token][lower].timestamp\n );\n }\n\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\n uint256 _timestamp = block.timestamp;\n uint256 _nCheckPoints = numCheckpoints[tokenId];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\n } else {\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\n _timestamp,\n balance\n );\n numCheckpoints[tokenId] = _nCheckPoints + 1;\n }\n }\n\n function _writeRewardPerTokenCheckpoint(\n address token,\n uint256 reward,\n uint256 timestamp\n ) internal {\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\n\n if (\n _nCheckPoints > 0 &&\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\n timestamp\n ) {\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\n .rewardPerToken = reward;\n } else {\n rewardPerTokenCheckpoints[token][\n _nCheckPoints\n ] = RewardPerTokenCheckpoint(timestamp, reward);\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\n }\n }\n\n function _writeSupplyCheckpoint() internal {\n uint256 _nCheckPoints = supplyNumCheckpoints;\n uint256 _timestamp = block.timestamp;\n\n if (\n _nCheckPoints > 0 &&\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\n ) {\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\n } else {\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\n _timestamp,\n totalSupply\n );\n supplyNumCheckpoints = _nCheckPoints + 1;\n }\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return Math.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n (\n rewardPerTokenStored[tokens[i]],\n lastUpdateTime[tokens[i]]\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\n\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\n tokens[i]\n ];\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function rewardPerToken(address token) public view returns (uint256) {\n if (totalSupply == 0) {\n return rewardPerTokenStored[token];\n }\n return\n rewardPerTokenStored[token] +\n (((lastTimeRewardApplicable(token) -\n Math.min(lastUpdateTime[token], periodFinish[token])) *\n rewardRate[token] *\n 10**IERC20(token).decimals()) / totalSupply);\n }\n\n function batchRewardPerToken(address token, uint256 maxRuns) external {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _batchRewardPerToken(token, maxRuns);\n }\n\n function _batchRewardPerToken(address token, uint256 maxRuns)\n internal\n returns (uint256, uint256)\n {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = Math.min(supplyNumCheckpoints - 1, maxRuns);\n\n for (uint256 i = _startIndex; i < _endIndex; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\n _startTimestamp = endTime;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function _calcRewardPerToken(\n address token,\n uint256 timestamp1,\n uint256 timestamp0,\n uint256 supply,\n uint256 startTimestamp\n ) internal view returns (uint256, uint256) {\n uint256 endTime = Math.max(timestamp1, startTimestamp);\n return (\n (((Math.min(endTime, periodFinish[token]) -\n Math.min(\n Math.max(timestamp0, startTimestamp),\n periodFinish[token]\n )) *\n rewardRate[token] *\n 10**IERC20(token).decimals()) / supply),\n endTime\n );\n }\n\n /// @dev Update stored rewardPerToken values without the last one snapshot\n /// If the contract will get \"out of gas\" error on users actions this will be helpful\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\n external\n {\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, maxRuns, false);\n }\n\n function _updateRewardForAllTokens() internal {\n uint256 length = rewards.length;\n for (uint256 i; i < length; i++) {\n address token = rewards[i];\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n }\n }\n\n function _updateRewardPerToken(\n address token,\n uint256 maxRuns,\n bool actualLast\n ) internal returns (uint256, uint256) {\n uint256 _startTimestamp = lastUpdateTime[token];\n uint256 reward = rewardPerTokenStored[token];\n\n if (supplyNumCheckpoints == 0) {\n return (reward, _startTimestamp);\n }\n\n if (rewardRate[token] == 0) {\n return (reward, block.timestamp);\n }\n\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\n uint256 _endIndex = Math.min(supplyNumCheckpoints - 1, maxRuns);\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\n if (sp0.supply > 0) {\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\n token,\n sp1.timestamp,\n sp0.timestamp,\n sp0.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\n _startTimestamp = _endTime;\n }\n }\n }\n\n if (actualLast) {\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\n if (sp.supply > 0) {\n (uint256 _reward, ) = _calcRewardPerToken(\n token,\n lastTimeRewardApplicable(token),\n Math.max(sp.timestamp, _startTimestamp),\n sp.supply,\n _startTimestamp\n );\n reward += _reward;\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\n _startTimestamp = block.timestamp;\n }\n }\n\n return (reward, _startTimestamp);\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = Math.max(\n lastEarn[token][tokenId],\n rewardPerTokenCheckpoints[token][0].timestamp\n );\n if (numCheckpoints[tokenId] == 0) {\n return 0;\n }\n\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\n\n uint256 reward = 0;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n Checkpoint memory cp0 = checkpoints[tokenId][i];\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\n token,\n cp0.timestamp\n );\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\n token,\n cp1.timestamp\n );\n reward +=\n (cp0.balanceOf *\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\n 10**IERC20(token).decimals();\n }\n }\n\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\n token,\n cp.timestamp\n );\n reward +=\n (cp.balanceOf *\n (rewardPerToken(token) -\n Math.max(\n _rewardPerTokenStored,\n userRewardPerTokenStored[token][tokenId]\n ))) /\n 10**IERC20(token).decimals();\n\n return reward;\n }\n\n // This is an external function, but internal notation is used since it can only be called \"internally\" from Gauges\n function _deposit(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply += amount;\n balanceOf[tokenId] += amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Deposit(msg.sender, tokenId, amount);\n }\n\n function _withdraw(uint256 amount, uint256 tokenId) external {\n require(msg.sender == voter);\n _updateRewardForAllTokens();\n\n totalSupply -= amount;\n balanceOf[tokenId] -= amount;\n\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\n _writeSupplyCheckpoint();\n\n emit Withdraw(msg.sender, tokenId, amount);\n }\n\n function left(address token) external view returns (uint256) {\n if (block.timestamp >= periodFinish[token]) return 0;\n uint256 _remaining = periodFinish[token] - block.timestamp;\n return _remaining * rewardRate[token];\n }\n\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n require(isReward[token]);\n\n if (rewardRate[token] == 0)\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\n (\n rewardPerTokenStored[token],\n lastUpdateTime[token]\n ) = _updateRewardPerToken(token, type(uint256).max, true);\n\n if (block.timestamp >= periodFinish[token]) {\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = amount / DURATION;\n } else {\n uint256 _remaining = periodFinish[token] - block.timestamp;\n uint256 _left = _remaining * rewardRate[token];\n require(amount > _left);\n _safeTransferFrom(token, msg.sender, address(this), amount);\n rewardRate[token] = (amount + _left) / DURATION;\n }\n require(rewardRate[token] > 0);\n uint256 balance = IERC20(token).balanceOf(address(this));\n require(\n rewardRate[token] <= balance / DURATION,\n \"Provided reward too high\"\n );\n periodFinish[token] = block.timestamp + DURATION;\n\n emit NotifyReward(msg.sender, token, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/libraries/Base64.sol": { + "content": "pragma solidity 0.8.13;\n\n/// [MIT License]\n/// @title Base64\n/// @notice Provides a function for encoding some bytes in base64\n/// @author Brecht Devos \nlibrary Base64 {\n bytes internal constant TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /// @notice Encodes some bytes to the base64 representation\n function encode(bytes memory data) internal pure returns (string memory) {\n uint len = data.length;\n if (len == 0) return \"\";\n\n // multiply by 4/3 rounded up\n uint encodedLen = 4 * ((len + 2) / 3);\n\n // Add some extra buffer at the end\n bytes memory result = new bytes(encodedLen + 32);\n\n bytes memory table = TABLE;\n\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let i := 0\n } lt(i, len) {\n\n } {\n i := add(i, 3)\n let input := and(mload(add(data, i)), 0xffffff)\n\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n out := shl(8, out)\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n out := shl(224, out)\n\n mstore(resultPtr, out)\n\n resultPtr := add(resultPtr, 4)\n }\n\n switch mod(len, 3)\n case 1 {\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\n }\n case 2 {\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\n }\n\n mstore(result, encodedLen)\n }\n\n return string(result);\n }\n}\n" + }, + "contracts/libraries/Math.sol": { + "content": "pragma solidity 0.8.13;\n\n// this causes issue with forge test as there is already a Math.sol in the forge repo\nlibrary Math {\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n\n function cbrt(uint256 n) internal pure returns (uint256) {\n unchecked {\n uint256 x = 0;\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\n x <<= 1;\n uint256 z = 3 * x * (x + 1) + 1;\n if (n / y >= z) {\n n -= y * z;\n x += 1;\n }\n }\n return x;\n }\n }\n}\n" + }, + "contracts/Minter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\";\n\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IFlow.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\n\ncontract Minter is IMinter {\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\n uint256 internal constant EMISSION = 990;\n uint256 internal constant TAIL_EMISSION = 2;\n uint256 internal constant PRECISION = 1000;\n IFlow public immutable _flow;\n IVoter public immutable _voter;\n IVotingEscrow public immutable _ve;\n IRewardsDistributor public immutable _rewards_distributor;\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M FLOW (FLOW has 18 decimals)\n uint256 public active_period;\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\n\n address internal initializer;\n address public team;\n address public pendingTeam;\n uint256 public teamRate;\n uint256 public constant MAX_TEAM_RATE = 50; // 5% max\n\n event Mint(\n address indexed sender,\n uint256 weekly,\n uint256 circulating_supply,\n uint256 circulating_emission\n );\n\n constructor(\n address __voter, // the voting & distribution system\n address __ve, // the ve(3,3) system that will be locked into\n address __rewards_distributor // the distribution system that ensures users aren't diluted\n ) {\n initializer = msg.sender;\n team = msg.sender;\n teamRate = 30; // 30 bps = 3%\n _flow = IFlow(IVotingEscrow(__ve).token());\n _voter = IVoter(__voter);\n _ve = IVotingEscrow(__ve);\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\n }\n\n function initialize(\n address[] memory claimants, // partnerAddrs\n uint256[] memory amounts, // partnerAmounts\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\n ) external {\n require(initializer == msg.sender);\n _flow.mint(address(this), max);\n _flow.approve(address(_ve), type(uint256).max);\n for (uint256 i = 0; i < claimants.length; i++) {\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\n }\n initializer = address(0);\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\n }\n\n function setTeam(address _team) external {\n require(msg.sender == team, \"not team\");\n pendingTeam = _team;\n }\n\n function acceptTeam() external {\n require(msg.sender == pendingTeam, \"not pending team\");\n team = pendingTeam;\n }\n\n function setTeamRate(uint256 _teamRate) external {\n require(msg.sender == team, \"not team\");\n require(_teamRate <= MAX_TEAM_RATE, \"rate too high\");\n teamRate = _teamRate;\n }\n\n // calculate circulating supply as total token supply - locked supply\n function circulating_supply() public view returns (uint256) {\n return _flow.totalSupply() - _ve.totalSupply();\n }\n\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\n function calculate_emission() public view returns (uint256) {\n return (weekly * EMISSION) / PRECISION;\n }\n\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\n function weekly_emission() public view returns (uint256) {\n return Math.max(calculate_emission(), circulating_emission());\n }\n\n // calculates tail end (infinity) emissions as 0.2% of total supply\n function circulating_emission() public view returns (uint256) {\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\n }\n\n // calculate inflation and adjust ve balances accordingly\n function calculate_growth(uint256 _minted) public view returns (uint256) {\n uint256 _veTotal = _ve.totalSupply();\n uint256 _flowTotal = _flow.totalSupply();\n return\n (((((_minted * _veTotal) / _flowTotal) * _veTotal) / _flowTotal) *\n _veTotal) /\n _flowTotal /\n 2;\n }\n\n // update period can only be called once per cycle (1 week)\n function update_period() external returns (uint256) {\n uint256 _period = active_period;\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\n // only trigger if new week\n _period = (block.timestamp / WEEK) * WEEK;\n active_period = _period;\n weekly = weekly_emission();\n\n uint256 _growth = calculate_growth(weekly);\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\n (PRECISION - teamRate);\n uint256 _required = _growth + weekly + _teamEmissions;\n uint256 _balanceOf = _flow.balanceOf(address(this));\n if (_balanceOf < _required) {\n _flow.mint(address(this), _required - _balanceOf);\n }\n\n require(_flow.transfer(team, _teamEmissions));\n require(_flow.transfer(address(_rewards_distributor), _growth));\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\n\n _flow.approve(address(_voter), weekly);\n _voter.notifyRewardAmount(weekly);\n\n emit Mint(\n msg.sender,\n weekly,\n circulating_supply(),\n circulating_emission()\n );\n }\n return _period;\n }\n}\n" + }, + "contracts/Pair.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairCallee.sol\";\nimport \"contracts/factories/PairFactory.sol\";\nimport \"contracts/PairFees.sol\";\n\n// The base pair of pools, either stable or volatile\ncontract Pair is IPair {\n string public name;\n string public symbol;\n uint8 public constant decimals = 18;\n\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\n bool public immutable stable;\n\n uint256 public totalSupply = 0;\n\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n bytes32 internal DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 internal constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n\n address public immutable token0;\n address public immutable token1;\n address public immutable fees;\n address immutable factory;\n\n // Structure to capture time period obervations every 30 minutes, used for local oracles\n struct Observation {\n uint256 timestamp;\n uint256 reserve0Cumulative;\n uint256 reserve1Cumulative;\n }\n\n // Capture oracle reading every 30 minutes\n uint256 constant periodSize = 1800;\n\n Observation[] public observations;\n\n uint256 internal immutable decimals0;\n uint256 internal immutable decimals1;\n\n uint256 public reserve0;\n uint256 public reserve1;\n uint256 public blockTimestampLast;\n\n uint256 public reserve0CumulativeLast;\n uint256 public reserve1CumulativeLast;\n\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \"clean\"\n // this further allows LP holders to easily claim fees for tokens they have/staked\n uint256 public index0 = 0;\n uint256 public index1 = 0;\n\n // position assigned to each LP to track their current index0 & index1 vs the global position\n mapping(address => uint256) public supplyIndex0;\n mapping(address => uint256) public supplyIndex1;\n\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\n mapping(address => uint256) public claimable0;\n mapping(address => uint256) public claimable1;\n\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n event Burn(\n address indexed sender,\n uint256 amount0,\n uint256 amount1,\n address indexed to\n );\n event Swap(\n address indexed sender,\n uint256 amount0In,\n uint256 amount1In,\n uint256 amount0Out,\n uint256 amount1Out,\n address indexed to\n );\n event Sync(uint256 reserve0, uint256 reserve1);\n event Claim(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1\n );\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n constructor() {\n factory = msg.sender;\n (address _token0, address _token1, bool _stable) = PairFactory(\n msg.sender\n ).getInitializable();\n (token0, token1, stable) = (_token0, _token1, _stable);\n fees = address(new PairFees(_token0, _token1));\n if (_stable) {\n name = string(\n abi.encodePacked(\n \"StableV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"sAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n } else {\n name = string(\n abi.encodePacked(\n \"VolatileV1 AMM - \",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n symbol = string(\n abi.encodePacked(\n \"vAMM-\",\n IERC20(_token0).symbol(),\n \"/\",\n IERC20(_token1).symbol()\n )\n );\n }\n\n decimals0 = 10**IERC20(_token0).decimals();\n decimals1 = 10**IERC20(_token1).decimals();\n\n observations.push(Observation(block.timestamp, 0, 0));\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function observationLength() external view returns (uint256) {\n return observations.length;\n }\n\n function lastObservation() public view returns (Observation memory) {\n return observations[observations.length - 1];\n }\n\n function metadata()\n external\n view\n returns (\n uint256 dec0,\n uint256 dec1,\n uint256 r0,\n uint256 r1,\n bool st,\n address t0,\n address t1\n )\n {\n return (\n decimals0,\n decimals1,\n reserve0,\n reserve1,\n stable,\n token0,\n token1\n );\n }\n\n function tokens() external view returns (address, address) {\n return (token0, token1);\n }\n\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\n _updateFor(msg.sender);\n\n claimed0 = claimable0[msg.sender];\n claimed1 = claimable1[msg.sender];\n\n if (claimed0 > 0 || claimed1 > 0) {\n claimable0[msg.sender] = 0;\n claimable1[msg.sender] = 0;\n\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\n\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\n }\n }\n\n // Accrue fees on token0\n function _update0(uint256 amount) internal {\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index0 += _ratio;\n }\n emit Fees(msg.sender, amount, 0);\n }\n\n // Accrue fees on token1\n function _update1(uint256 amount) internal {\n _safeTransfer(token1, fees, amount);\n uint256 _ratio = (amount * 1e18) / totalSupply;\n if (_ratio > 0) {\n index1 += _ratio;\n }\n emit Fees(msg.sender, 0, amount);\n }\n\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\n // Fees are segregated from core funds, so fees can never put liquidity at risk\n function _updateFor(address recipient) internal {\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\n if (_supplied > 0) {\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\n uint256 _supplyIndex1 = supplyIndex1[recipient];\n uint256 _index0 = index0; // get global index0 for accumulated fees\n uint256 _index1 = index1;\n supplyIndex0[recipient] = _index0; // update user current position to global position\n supplyIndex1[recipient] = _index1;\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\n uint256 _delta1 = _index1 - _supplyIndex1;\n if (_delta0 > 0) {\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\n claimable0[recipient] += _share;\n }\n if (_delta1 > 0) {\n uint256 _share = (_supplied * _delta1) / 1e18;\n claimable1[recipient] += _share;\n }\n } else {\n supplyIndex0[recipient] = index0; // new users are set to the default global state\n supplyIndex1[recipient] = index1;\n }\n }\n\n function getReserves()\n public\n view\n returns (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n )\n {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(\n uint256 balance0,\n uint256 balance1,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal {\n uint256 blockTimestamp = block.timestamp;\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n reserve0CumulativeLast += _reserve0 * timeElapsed;\n reserve1CumulativeLast += _reserve1 * timeElapsed;\n }\n\n Observation memory _point = lastObservation();\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\n if (timeElapsed > periodSize) {\n observations.push(\n Observation(\n blockTimestamp,\n reserve0CumulativeLast,\n reserve1CumulativeLast\n )\n );\n }\n reserve0 = balance0;\n reserve1 = balance1;\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\n function currentCumulativePrices()\n public\n view\n returns (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n uint256 blockTimestamp\n )\n {\n blockTimestamp = block.timestamp;\n reserve0Cumulative = reserve0CumulativeLast;\n reserve1Cumulative = reserve1CumulativeLast;\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (\n uint256 _reserve0,\n uint256 _reserve1,\n uint256 _blockTimestampLast\n ) = getReserves();\n if (_blockTimestampLast != blockTimestamp) {\n // subtraction overflow is desired\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\n reserve0Cumulative += _reserve0 * timeElapsed;\n reserve1Cumulative += _reserve1 * timeElapsed;\n }\n }\n\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\n function current(address tokenIn, uint256 amountIn)\n external\n view\n returns (uint256 amountOut)\n {\n Observation memory _observation = lastObservation();\n (\n uint256 reserve0Cumulative,\n uint256 reserve1Cumulative,\n\n ) = currentCumulativePrices();\n if (block.timestamp == _observation.timestamp) {\n _observation = observations[observations.length - 2];\n }\n\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\n uint256 _reserve0 = (reserve0Cumulative -\n _observation.reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (reserve1Cumulative -\n _observation.reserve1Cumulative) / timeElapsed;\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n // as per `current`, however allows user configured granularity, up to the full window size\n function quote(\n address tokenIn,\n uint256 amountIn,\n uint256 granularity\n ) external view returns (uint256 amountOut) {\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\n uint256 priceAverageCumulative;\n for (uint256 i = 0; i < _prices.length; i++) {\n priceAverageCumulative += _prices[i];\n }\n return priceAverageCumulative / granularity;\n }\n\n // returns a memory set of twap prices\n function prices(\n address tokenIn,\n uint256 amountIn,\n uint256 points\n ) external view returns (uint256[] memory) {\n return sample(tokenIn, amountIn, points, 1);\n }\n\n function sample(\n address tokenIn,\n uint256 amountIn,\n uint256 points,\n uint256 window\n ) public view returns (uint256[] memory) {\n uint256[] memory _prices = new uint256[](points);\n\n uint256 length = observations.length - 1;\n uint256 i = length - (points * window);\n uint256 nextIndex = 0;\n uint256 index = 0;\n\n for (; i < length; i += window) {\n nextIndex = i + window;\n uint256 timeElapsed = observations[nextIndex].timestamp -\n observations[i].timestamp;\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\n observations[i].reserve0Cumulative) / timeElapsed;\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\n observations[i].reserve1Cumulative) / timeElapsed;\n _prices[index] = _getAmountOut(\n amountIn,\n tokenIn,\n _reserve0,\n _reserve1\n );\n // index < length; length cannot overflow\n unchecked {\n index = index + 1;\n }\n }\n return _prices;\n }\n\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\n // standard uniswap v2 implementation\n function mint(address to) external lock returns (uint256 liquidity) {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\n uint256 _amount0 = _balance0 - _reserve0;\n uint256 _amount1 = _balance1 - _reserve1;\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n liquidity = Math.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n } else {\n liquidity = Math.min(\n (_amount0 * _totalSupply) / _reserve0,\n (_amount1 * _totalSupply) / _reserve1\n );\n }\n require(liquidity > 0, \"ILM\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\n _mint(to, liquidity);\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Mint(msg.sender, _amount0, _amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n // standard uniswap v2 implementation\n function burn(address to)\n external\n lock\n returns (uint256 amount0, uint256 amount1)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n (address _token0, address _token1) = (token0, token1);\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\n uint256 _liquidity = balanceOf[address(this)];\n\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, \"ILB\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\n _burn(address(this), _liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(\n uint256 amount0Out,\n uint256 amount1Out,\n address to,\n bytes calldata data\n ) external lock {\n require(!PairFactory(factory).isPaused());\n require(amount0Out > 0 || amount1Out > 0, \"IOA\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \"IL\"); // Pair: INSUFFICIENT_LIQUIDITY\n\n uint256 _balance0;\n uint256 _balance1;\n {\n // scope for _token{0,1}, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n require(to != _token0 && to != _token1, \"IT\"); // Pair: INVALID_TO\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0)\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\n _balance0 = IERC20(_token0).balanceOf(address(this));\n _balance1 = IERC20(_token1).balanceOf(address(this));\n }\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\n ? _balance0 - (_reserve0 - amount0Out)\n : 0;\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\n ? _balance1 - (_reserve1 - amount1Out)\n : 0;\n require(amount0In > 0 || amount1In > 0, \"IIA\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\n {\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n (address _token0, address _token1) = (token0, token1);\n if (amount0In > 0)\n _update0(\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token0 and move them out of pool\n if (amount1In > 0)\n _update1(\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\n ); // accrue fees for token1 and move them out of pool\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\n _balance1 = IERC20(_token1).balanceOf(address(this));\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \"K\"); // Pair: K\n }\n\n _update(_balance0, _balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n (address _token0, address _token1) = (token0, token1);\n _safeTransfer(\n _token0,\n to,\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\n );\n _safeTransfer(\n _token1,\n to,\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\n );\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(\n IERC20(token0).balanceOf(address(this)),\n IERC20(token1).balanceOf(address(this)),\n reserve0,\n reserve1\n );\n }\n\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\n 1e18 +\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\n 1e18;\n }\n\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\n return\n (3 * x0 * ((y * y) / 1e18)) /\n 1e18 +\n ((((x0 * x0) / 1e18) * x0) / 1e18);\n }\n\n function _get_y(\n uint256 x0,\n uint256 xy,\n uint256 y\n ) internal pure returns (uint256) {\n for (uint256 i = 0; i < 255; i++) {\n uint256 y_prev = y;\n uint256 k = _f(x0, y);\n if (k < xy) {\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\n y = y + dy;\n } else {\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getAmountOut(uint256 amountIn, address tokenIn)\n external\n view\n returns (uint256)\n {\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\n }\n\n function _getAmountOut(\n uint256 amountIn,\n address tokenIn,\n uint256 _reserve0,\n uint256 _reserve1\n ) internal view returns (uint256) {\n if (stable) {\n uint256 xy = _k(_reserve0, _reserve1);\n _reserve0 = (_reserve0 * 1e18) / decimals0;\n _reserve1 = (_reserve1 * 1e18) / decimals1;\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n amountIn = tokenIn == token0\n ? (amountIn * 1e18) / decimals0\n : (amountIn * 1e18) / decimals1;\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\n } else {\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\n ? (_reserve0, _reserve1)\n : (_reserve1, _reserve0);\n return (amountIn * reserveB) / (reserveA + amountIn);\n }\n }\n\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\n if (stable) {\n uint256 _x = (x * 1e18) / decimals0;\n uint256 _y = (y * 1e18) / decimals1;\n uint256 _a = (_x * _y) / 1e18;\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return (_a * _b) / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n\n function _mint(address dst, uint256 amount) internal {\n _updateFor(dst); // balances must be updated on mint/burn/transfer\n totalSupply += amount;\n balanceOf[dst] += amount;\n emit Transfer(address(0), dst, amount);\n }\n\n function _burn(address dst, uint256 amount) internal {\n _updateFor(dst);\n totalSupply -= amount;\n balanceOf[dst] -= amount;\n emit Transfer(dst, address(0), amount);\n }\n\n function approve(address spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"Pair: EXPIRED\");\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Pair: INVALID_SIGNATURE\"\n );\n allowance[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool) {\n address spender = msg.sender;\n uint256 spenderAllowance = allowance[src][spender];\n\n if (spender != src && spenderAllowance != type(uint256).max) {\n uint256 newAllowance = spenderAllowance - amount;\n allowance[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint256 amount\n ) internal {\n _updateFor(src); // update fee position for src\n _updateFor(dst); // update fee position for dst\n\n balanceOf[src] -= amount;\n balanceOf[dst] += amount;\n\n emit Transfer(src, dst, amount);\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/PairFees.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport 'contracts/interfaces/IERC20.sol';\n\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\ncontract PairFees {\n\n address internal immutable pair; // The pair it is bonded to\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\n\n constructor(address _token0, address _token1) {\n pair = msg.sender;\n token0 = _token0;\n token1 = _token1;\n }\n\n function _safeTransfer(address token,address to,uint256 value) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) =\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n // Allow the pair to transfer fees to users\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\n require(msg.sender == pair);\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\n }\n\n}\n" + }, + "contracts/redeem/MerkleClaim.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.13;\n\n/// ============ Imports ============\n\nimport {IFlow} from \"contracts/interfaces/IFlow.sol\";\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\"; // OZ: MerkleProof\n\n/// @title MerkleClaim\n/// @notice Claims FLOW for members of a merkle tree\n/// @author Modified from Merkle Airdrop Starter (https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/master/contracts/src/MerkleClaimERC20.sol)\ncontract MerkleClaim {\n /// ============ Immutable storage ============\n\n /// @notice FLOW token to claim\n IFlow public immutable FLOW;\n /// @notice ERC20-claimee inclusion root\n bytes32 public immutable merkleRoot;\n\n /// ============ Mutable storage ============\n\n /// @notice Mapping of addresses who have claimed tokens\n mapping(address => bool) public hasClaimed;\n\n /// ============ Constructor ============\n\n /// @notice Creates a new MerkleClaim contract\n /// @param _flow address\n /// @param _merkleRoot of claimees\n constructor(address _flow, bytes32 _merkleRoot) {\n FLOW = IFlow(_flow);\n merkleRoot = _merkleRoot;\n }\n\n /// ============ Events ============\n\n /// @notice Emitted after a successful token claim\n /// @param to recipient of claim\n /// @param amount of tokens claimed\n event Claim(address indexed to, uint256 amount);\n\n /// ============ Functions ============\n\n /// @notice Allows claiming tokens if address is part of merkle tree\n /// @param to address of claimee\n /// @param amount of tokens owed to claimee\n /// @param proof merkle proof to prove address and amount are in tree\n function claim(\n address to,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n // Throw if address has already claimed tokens\n require(!hasClaimed[to], \"ALREADY_CLAIMED\");\n\n // Verify merkle proof, or revert if not in tree\n bytes32 leaf = keccak256(abi.encodePacked(to, amount));\n bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf);\n require(isValidLeaf, \"NOT_IN_MERKLE\");\n\n // Set address to claimed\n hasClaimed[to] = true;\n\n // Claim tokens for address\n require(FLOW.claim(to, amount), \"CLAIM_FAILED\");\n\n // Emit claim event\n emit Claim(to, amount);\n }\n}\n" + }, + "contracts/redeem/RedemptionReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IFlow.sol\";\n\n/// @notice Part 2 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\n/// This contract is responsible for receiving the LZ message and distributing USDC + FLOW\ncontract RedemptionReceiver is ILayerZeroReceiver {\n IERC20 public immutable USDC;\n IFlow public immutable FLOW;\n\n uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet\n address public immutable endpoint;\n\n address public team;\n uint256 public immutable deployed;\n\n address public fantomSender;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint256 public redeemableUSDC;\n uint256 public redeemableFLOW;\n uint256 public leftoverFLOW;\n\n constructor(\n address _usdc,\n address _flow,\n uint16 _fantomChainId,\n address _endpoint\n ) {\n require(_fantomChainId == 12 || _fantomChainId == 10012, \"CHAIN_ID_NOT_FTM\");\n\n USDC = IERC20(_usdc);\n FLOW = IFlow(_flow);\n\n fantomChainId = _fantomChainId;\n endpoint = _endpoint;\n\n team = msg.sender;\n deployed = block.timestamp;\n }\n\n modifier onlyTeam() {\n require(msg.sender == team, \"ONLY_TEAM\");\n _;\n }\n\n event Initialized(address fantomSender, uint256 redeemableUSDC, uint256 redeemableFLOW);\n\n function initializeReceiverWith(\n address _fantomSender,\n uint256 _redeemableUSDC,\n uint256 _redeemableFLOW\n ) external onlyTeam {\n require(fantomSender == address(0), \"ALREADY_INITIALIZED\");\n require(\n USDC.transferFrom(msg.sender, address(this), _redeemableUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n fantomSender = _fantomSender;\n redeemableUSDC = _redeemableUSDC;\n redeemableFLOW = _redeemableFLOW;\n leftoverFLOW = _redeemableFLOW;\n\n emit Initialized(fantomSender, redeemableUSDC, redeemableFLOW);\n }\n\n function setTeam(address _team) external onlyTeam {\n team = _team;\n }\n\n function previewRedeem(uint256 amountWEVE)\n public\n view\n returns (uint256 shareOfUSDC, uint256 shareOfFLOW)\n {\n // pro rata USDC\n shareOfUSDC = (amountWEVE * redeemableUSDC) / ELIGIBLE_WEVE;\n // pro rata FLOW\n shareOfFLOW = (amountWEVE * redeemableFLOW) / ELIGIBLE_WEVE;\n }\n\n function lzReceive(\n uint16 srcChainId,\n bytes memory srcAddress,\n uint64,\n bytes memory payload\n ) external override {\n require(fantomSender != address(0), \"NOT_INITIALIZED\");\n require(\n msg.sender == endpoint &&\n srcChainId == fantomChainId &&\n addressFromPackedBytes(srcAddress) == fantomSender,\n \"UNAUTHORIZED_CALLER\"\n );\n\n (address redemptionAddress, uint256 amountWEVE) = abi.decode(\n payload,\n (address, uint256)\n );\n\n require(\n (redeemedWEVE += amountWEVE) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n (uint256 shareOfUSDC, uint256 shareOfFLOW) = previewRedeem(amountWEVE);\n\n require(\n USDC.transfer(redemptionAddress, shareOfUSDC),\n \"USDC_TRANSFER_FAILED\"\n );\n\n leftoverFLOW -= shareOfFLOW; // this will revert if underflows\n require(\n FLOW.claim(redemptionAddress, shareOfFLOW),\n \"CLAIM_FAILED\"\n );\n }\n\n function addressFromPackedBytes(bytes memory toAddressBytes)\n public\n pure\n returns (address toAddress)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n function claimLeftovers() external onlyTeam {\n require(block.timestamp >= deployed + 30 days, \"LEFTOVERS_NOT_CLAIMABLE\");\n require(\n USDC.transfer(msg.sender, USDC.balanceOf(address(this))),\n \"USDC_TRANSFER_FAILED\"\n );\n }\n}\n" + }, + "contracts/redeem/RedemptionSender.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\n\n/// @notice Part 1 of 2 in the WeVE (FTM) -> USDC + FLOW (OP) redemption process\n/// This contract is responsible for burning WeVE and sending the LZ message\ncontract RedemptionSender {\n address public immutable weve;\n uint256 public constant ELIGIBLE_WEVE = 375112540 * 1e18;\n uint256 public redeemedWEVE;\n uint16 public immutable optimismChainId; // 11 for OP, 10011 for OP Kovan\n address public immutable endpoint;\n address public immutable optimismReceiver;\n\n event SubmittedClaim(uint256 amount, uint64 indexed lzeNonce);\n\n constructor(\n address _weve,\n uint16 _optimismChainId,\n address _endpoint,\n address _optimismReceiver\n ) {\n require(_optimismChainId == 11 || _optimismChainId == 10011, \"CHAIN_ID_NOT_OP\");\n weve = _weve;\n optimismChainId = _optimismChainId;\n endpoint = _endpoint;\n optimismReceiver = _optimismReceiver;\n }\n\n function estimateLayerZeroFee() public view returns (uint256 ftm, uint256 lzo) {\n (ftm, lzo) = ILayerZeroEndpoint(endpoint).estimateFees(\n optimismChainId,\n address(this),\n abi.encode(msg.sender, 42690),\n false,\n bytes(\"\")\n );\n }\n\n function redeemWEVE(\n uint256 amount,\n address zroPaymentAddress,\n bytes memory zroTransactionParams\n ) public payable {\n require(amount != 0, \"AMOUNT_ZERO\");\n require(\n (redeemedWEVE += amount) <= ELIGIBLE_WEVE,\n \"cannot redeem more than eligible\"\n );\n require(\n IERC20(weve).transferFrom(\n msg.sender,\n 0x000000000000000000000000000000000000dEaD,\n amount\n ),\n \"WEVE: TRANSFER_FAILED\"\n );\n\n ILayerZeroEndpoint(endpoint).send{value: msg.value}(\n optimismChainId,\n abi.encodePacked(optimismReceiver),\n abi.encode(msg.sender, amount),\n payable(msg.sender),\n zroPaymentAddress,\n zroTransactionParams\n );\n\n uint64 nonce = ILayerZeroEndpoint(endpoint).getOutboundNonce(\n optimismChainId,\n address(this)\n );\n\n emit SubmittedClaim(amount, nonce);\n }\n}\n" + }, + "contracts/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IRewardsDistributor.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n/*\n\n@title Curve Fee Distribution modified for ve(3,3) emissions\n@author Curve Finance, andrecronje\n@license MIT\n\n*/\n\ncontract RewardsDistributor is IRewardsDistributor {\n event CheckpointToken(uint256 time, uint256 tokens);\n\n event Claimed(\n uint256 tokenId,\n uint256 amount,\n uint256 claim_epoch,\n uint256 max_epoch\n );\n\n uint256 constant WEEK = 7 * 86400;\n\n uint256 public start_time;\n uint256 public time_cursor;\n mapping(uint256 => uint256) public time_cursor_of;\n mapping(uint256 => uint256) public user_epoch_of;\n\n uint256 public last_token_time;\n uint256[1000000000000000] public tokens_per_week;\n\n address public voting_escrow;\n address public token;\n uint256 public token_last_balance;\n\n uint256[1000000000000000] public ve_supply;\n\n address public depositor;\n\n constructor(address _voting_escrow) {\n uint256 _t = (block.timestamp / WEEK) * WEEK;\n start_time = _t;\n last_token_time = _t;\n time_cursor = _t;\n address _token = IVotingEscrow(_voting_escrow).token();\n token = _token;\n voting_escrow = _voting_escrow;\n depositor = msg.sender;\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\n }\n\n function timestamp() external view returns (uint256) {\n return (block.timestamp / WEEK) * WEEK;\n }\n\n function _checkpoint_token() internal {\n uint256 token_balance = IERC20(token).balanceOf(address(this));\n uint256 to_distribute = token_balance - token_last_balance;\n token_last_balance = token_balance;\n\n uint256 t = last_token_time;\n uint256 since_last = block.timestamp - t;\n last_token_time = block.timestamp;\n uint256 this_week = (t / WEEK) * WEEK;\n uint256 next_week = 0;\n\n for (uint256 i = 0; i < 20; i++) {\n next_week = this_week + WEEK;\n if (block.timestamp < next_week) {\n if (since_last == 0 && block.timestamp == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (block.timestamp - t)) /\n since_last;\n }\n break;\n } else {\n if (since_last == 0 && next_week == t) {\n tokens_per_week[this_week] += to_distribute;\n } else {\n tokens_per_week[this_week] +=\n (to_distribute * (next_week - t)) /\n since_last;\n }\n }\n t = next_week;\n this_week = next_week;\n }\n emit CheckpointToken(block.timestamp, to_distribute);\n }\n\n function checkpoint_token() external {\n assert(msg.sender == depositor);\n _checkpoint_token();\n }\n\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\n internal\n view\n returns (uint256)\n {\n uint256 _min = 0;\n uint256 _max = IVotingEscrow(ve).epoch();\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n _mid\n );\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function _find_timestamp_user_epoch(\n address ve,\n uint256 tokenId,\n uint256 _timestamp,\n uint256 max_user_epoch\n ) internal view returns (uint256) {\n uint256 _min = 0;\n uint256 _max = max_user_epoch;\n for (uint256 i = 0; i < 128; i++) {\n if (_min >= _max) break;\n uint256 _mid = (_min + _max + 2) / 2;\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\n .user_point_history(tokenId, _mid);\n if (pt.ts <= _timestamp) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\n external\n view\n returns (uint256)\n {\n address ve = voting_escrow;\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _timestamp,\n max_user_epoch\n );\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\n _tokenId,\n epoch\n );\n return\n Math.max(\n uint256(\n int256(\n pt.bias -\n pt.slope *\n (int128(int256(_timestamp - pt.ts)))\n )\n ),\n 0\n );\n }\n\n function _checkpoint_total_supply() internal {\n address ve = voting_escrow;\n uint256 t = time_cursor;\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\n IVotingEscrow(ve).checkpoint();\n\n for (uint256 i = 0; i < 20; i++) {\n if (t > rounded_timestamp) {\n break;\n } else {\n uint256 epoch = _find_timestamp_epoch(ve, t);\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\n epoch\n );\n int128 dt = 0;\n if (t > pt.ts) {\n dt = int128(int256(t - pt.ts));\n }\n ve_supply[t] = Math.max(\n uint256(int256(pt.bias - pt.slope * dt)),\n 0\n );\n }\n t += WEEK;\n }\n time_cursor = t;\n }\n\n function checkpoint_total_supply() external {\n _checkpoint_total_supply();\n }\n\n function _claim(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = Math.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n user_epoch = Math.min(max_user_epoch, user_epoch - 1);\n user_epoch_of[_tokenId] = user_epoch;\n time_cursor_of[_tokenId] = week_cursor;\n\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\n\n return to_distribute;\n }\n\n function _claimable(\n uint256 _tokenId,\n address ve,\n uint256 _last_token_time\n ) internal view returns (uint256) {\n uint256 user_epoch = 0;\n uint256 to_distribute = 0;\n\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\n uint256 _start_time = start_time;\n\n if (max_user_epoch == 0) return 0;\n\n uint256 week_cursor = time_cursor_of[_tokenId];\n if (week_cursor == 0) {\n user_epoch = _find_timestamp_user_epoch(\n ve,\n _tokenId,\n _start_time,\n max_user_epoch\n );\n } else {\n user_epoch = user_epoch_of[_tokenId];\n }\n\n if (user_epoch == 0) user_epoch = 1;\n\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\n .user_point_history(_tokenId, user_epoch);\n\n if (week_cursor == 0)\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\n if (week_cursor >= last_token_time) return 0;\n if (week_cursor < _start_time) week_cursor = _start_time;\n\n IVotingEscrow.Point memory old_user_point;\n\n for (uint256 i = 0; i < 50; i++) {\n if (week_cursor >= _last_token_time) break;\n\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\n user_epoch += 1;\n old_user_point = user_point;\n if (user_epoch > max_user_epoch) {\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\n } else {\n user_point = IVotingEscrow(ve).user_point_history(\n _tokenId,\n user_epoch\n );\n }\n } else {\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\n uint256 balance_of = Math.max(\n uint256(\n int256(old_user_point.bias - dt * old_user_point.slope)\n ),\n 0\n );\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\n if (balance_of != 0) {\n to_distribute +=\n (balance_of * tokens_per_week[week_cursor]) /\n ve_supply[week_cursor];\n }\n week_cursor += WEEK;\n }\n }\n\n return to_distribute;\n }\n\n function claimable(uint256 _tokenId) external view returns (uint256) {\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\n return _claimable(_tokenId, voting_escrow, _last_token_time);\n }\n\n function claim(uint256 _tokenId) external returns (uint256) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\n token_last_balance -= amount;\n }\n return amount;\n }\n\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\n uint256 _last_token_time = last_token_time;\n _last_token_time = (_last_token_time / WEEK) * WEEK;\n address _voting_escrow = voting_escrow;\n uint256 total = 0;\n\n for (uint256 i = 0; i < _tokenIds.length; i++) {\n uint256 _tokenId = _tokenIds[i];\n if (_tokenId == 0) break;\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\n if (amount != 0) {\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\n total += amount;\n }\n }\n if (total != 0) {\n token_last_balance -= total;\n }\n\n return true;\n }\n\n // Once off event on contract initialize\n function setDepositor(address _depositor) external {\n require(msg.sender == depositor);\n depositor = _depositor;\n }\n}\n" + }, + "contracts/Router.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\nimport \"contracts/interfaces/IWETH.sol\";\n\ncontract Router is IRouter {\n struct route {\n address from;\n address to;\n bool stable;\n }\n\n address public immutable factory;\n IWETH public immutable weth;\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\n bytes32 immutable pairCodeHash;\n\n modifier ensure(uint256 deadline) {\n require(deadline >= block.timestamp, \"Router: EXPIRED\");\n _;\n }\n\n constructor(address _factory, address _weth) {\n factory = _factory;\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\n weth = IWETH(_weth);\n }\n\n receive() external payable {\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\n }\n\n function sortTokens(address tokenA, address tokenB)\n public\n pure\n returns (address token0, address token1)\n {\n require(tokenA != tokenB, \"Router: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB\n ? (tokenA, tokenB)\n : (tokenB, tokenA);\n require(token0 != address(0), \"Router: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1, stable)),\n pairCodeHash // init code hash\n )\n )\n )\n )\n );\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quoteLiquidity(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"Router: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"Router: INSUFFICIENT_LIQUIDITY\");\n amountB = (amountA * reserveB) / reserveA;\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address tokenA,\n address tokenB,\n bool stable\n ) public view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPair(\n pairFor(tokenA, tokenB, stable)\n ).getReserves();\n (reserveA, reserveB) = tokenA == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountOut(\n uint256 amountIn,\n address tokenIn,\n address tokenOut\n ) external view returns (uint256 amount, bool stable) {\n address pair = pairFor(tokenIn, tokenOut, true);\n uint256 amountStable;\n uint256 amountVolatile;\n if (IPairFactory(factory).isPair(pair)) {\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n pair = pairFor(tokenIn, tokenOut, false);\n if (IPairFactory(factory).isPair(pair)) {\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\n }\n return\n amountStable > amountVolatile\n ? (amountStable, true)\n : (amountVolatile, false);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(uint256 amountIn, route[] memory routes)\n public\n view\n returns (uint256[] memory amounts)\n {\n require(routes.length >= 1, \"Router: INVALID_PATH\");\n amounts = new uint256[](routes.length + 1);\n amounts[0] = amountIn;\n for (uint256 i = 0; i < routes.length; i++) {\n address pair = pairFor(\n routes[i].from,\n routes[i].to,\n routes[i].stable\n );\n if (IPairFactory(factory).isPair(pair)) {\n amounts[i + 1] = IPair(pair).getAmountOut(\n amounts[i],\n routes[i].from\n );\n }\n }\n }\n\n function isPair(address pair) external view returns (bool) {\n return IPairFactory(factory).isPair(pair);\n }\n\n function quoteAddLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired\n )\n external\n view\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n (uint256 reserveA, uint256 reserveB) = (0, 0);\n uint256 _totalSupply = 0;\n if (_pair != address(0)) {\n _totalSupply = IERC20(_pair).totalSupply();\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\n }\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n liquidity = Math.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n (amountA, amountB) = (amountADesired, amountBOptimal);\n liquidity = Math.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n liquidity = Math.min(\n (amountA * _totalSupply) / reserveA,\n (amountB * _totalSupply) / reserveB\n );\n }\n }\n }\n\n function quoteRemoveLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity\n ) external view returns (uint256 amountA, uint256 amountB) {\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n\n if (_pair == address(0)) {\n return (0, 0);\n }\n\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n uint256 _totalSupply = IERC20(_pair).totalSupply();\n\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\n }\n\n function _addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin\n ) internal returns (uint256 amountA, uint256 amountB) {\n require(amountADesired >= amountAMin);\n require(amountBDesired >= amountBMin);\n // create the pair if it doesn't exist yet\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\n if (_pair == address(0)) {\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\n }\n (uint256 reserveA, uint256 reserveB) = getReserves(\n tokenA,\n tokenB,\n stable\n );\n if (reserveA == 0 && reserveB == 0) {\n (amountA, amountB) = (amountADesired, amountBDesired);\n } else {\n uint256 amountBOptimal = quoteLiquidity(\n amountADesired,\n reserveA,\n reserveB\n );\n if (amountBOptimal <= amountBDesired) {\n require(\n amountBOptimal >= amountBMin,\n \"Router: INSUFFICIENT_B_AMOUNT\"\n );\n (amountA, amountB) = (amountADesired, amountBOptimal);\n } else {\n uint256 amountAOptimal = quoteLiquidity(\n amountBDesired,\n reserveB,\n reserveA\n );\n assert(amountAOptimal <= amountADesired);\n require(\n amountAOptimal >= amountAMin,\n \"Router: INSUFFICIENT_A_AMOUNT\"\n );\n (amountA, amountB) = (amountAOptimal, amountBDesired);\n }\n }\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n ensure(deadline)\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n (amountA, amountB) = _addLiquidity(\n tokenA,\n tokenB,\n stable,\n amountADesired,\n amountBDesired,\n amountAMin,\n amountBMin\n );\n address pair = pairFor(tokenA, tokenB, stable);\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\n liquidity = IPair(pair).mint(to);\n }\n\n function addLiquidityETH(\n address token,\n bool stable,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n ensure(deadline)\n returns (\n uint256 amountToken,\n uint256 amountETH,\n uint256 liquidity\n )\n {\n (amountToken, amountETH) = _addLiquidity(\n token,\n address(weth),\n stable,\n amountTokenDesired,\n msg.value,\n amountTokenMin,\n amountETHMin\n );\n address pair = pairFor(token, address(weth), stable);\n _safeTransferFrom(token, msg.sender, pair, amountToken);\n weth.deposit{value: amountETH}();\n assert(weth.transfer(pair, amountETH));\n liquidity = IPair(pair).mint(to);\n // refund dust eth, if any\n if (msg.value > amountETH)\n _safeTransferETH(msg.sender, msg.value - amountETH);\n }\n\n // **** REMOVE LIQUIDITY ****\n function removeLiquidity(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\n (address token0, ) = sortTokens(tokenA, tokenB);\n (amountA, amountB) = tokenA == token0\n ? (amount0, amount1)\n : (amount1, amount0);\n require(amountA >= amountAMin, \"Router: INSUFFICIENT_A_AMOUNT\");\n require(amountB >= amountBMin, \"Router: INSUFFICIENT_B_AMOUNT\");\n }\n\n function removeLiquidityETH(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\n (amountToken, amountETH) = removeLiquidity(\n token,\n address(weth),\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n address(this),\n deadline\n );\n _safeTransfer(token, to, amountToken);\n weth.withdraw(amountETH);\n _safeTransferETH(to, amountETH);\n }\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n bool stable,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB) {\n address pair = pairFor(tokenA, tokenB, stable);\n {\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(\n msg.sender,\n address(this),\n value,\n deadline,\n v,\n r,\n s\n );\n }\n\n (amountA, amountB) = removeLiquidity(\n tokenA,\n tokenB,\n stable,\n liquidity,\n amountAMin,\n amountBMin,\n to,\n deadline\n );\n }\n\n function removeLiquidityETHWithPermit(\n address token,\n bool stable,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH) {\n address pair = pairFor(token, address(weth), stable);\n uint256 value = approveMax ? type(uint256).max : liquidity;\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\n (amountToken, amountETH) = removeLiquidityETH(\n token,\n stable,\n liquidity,\n amountTokenMin,\n amountETHMin,\n to,\n deadline\n );\n }\n\n // **** SWAP ****\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n route[] memory routes,\n address _to\n ) internal virtual {\n for (uint256 i = 0; i < routes.length; i++) {\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < routes.length - 1\n ? pairFor(\n routes[i + 1].from,\n routes[i + 1].to,\n routes[i + 1].stable\n )\n : _to;\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\n amount0Out,\n amount1Out,\n to,\n new bytes(0)\n );\n }\n }\n\n function swapExactTokensForTokensSimple(\n uint256 amountIn,\n uint256 amountOutMin,\n address tokenFrom,\n address tokenTo,\n bool stable,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n route[] memory routes = new route[](1);\n routes[0].from = tokenFrom;\n routes[0].to = tokenTo;\n routes[0].stable = stable;\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactETHForTokens(\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\n require(routes[0].from == address(weth), \"Router: INVALID_PATH\");\n amounts = getAmountsOut(msg.value, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n weth.deposit{value: amounts[0]}();\n assert(\n weth.transfer(\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n )\n );\n _swap(amounts, routes, to);\n }\n\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory amounts) {\n require(\n routes[routes.length - 1].to == address(weth),\n \"Router: INVALID_PATH\"\n );\n amounts = getAmountsOut(amountIn, routes);\n require(\n amounts[amounts.length - 1] >= amountOutMin,\n \"Router: INSUFFICIENT_OUTPUT_AMOUNT\"\n );\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, address(this));\n weth.withdraw(amounts[amounts.length - 1]);\n _safeTransferETH(to, amounts[amounts.length - 1]);\n }\n\n function UNSAFE_swapExactTokensForTokens(\n uint256[] memory amounts,\n route[] calldata routes,\n address to,\n uint256 deadline\n ) external ensure(deadline) returns (uint256[] memory) {\n _safeTransferFrom(\n routes[0].from,\n msg.sender,\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\n amounts[0]\n );\n _swap(amounts, routes, to);\n return amounts;\n }\n\n function _safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/routerV.sol": { + "content": "" + }, + "contracts/VeArtProxy.sol": { + "content": "pragma solidity 0.8.13;\n\nimport {Base64} from \"contracts/libraries/Base64.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\n\ncontract VeArtProxy is IVeArtProxy {\n function toString(uint value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT license\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint temp = value;\n uint digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\n output = '';\n output = string(abi.encodePacked(output, \"token \", toString(_tokenId), ''));\n output = string(abi.encodePacked(output, \"balanceOf \", toString(_balanceOf), ''));\n output = string(abi.encodePacked(output, \"locked_end \", toString(_locked_end), ''));\n output = string(abi.encodePacked(output, \"value \", toString(_value), ''));\n\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\"name\": \"lock #', toString(_tokenId), '\", \"description\": \"Velocimeter locks, can be used to boost gauge yields, vote on token emission, and receive bribes\", \"image\": \"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\"}'))));\n output = string(abi.encodePacked('data:application/json;base64,', json));\n }\n}\n" + }, + "contracts/VelocimeterLibrary.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IRouter.sol\";\n\ncontract VelocimeterLibrary {\n IRouter internal immutable router;\n\n constructor(address _router) {\n router = IRouter(_router);\n }\n\n function _f(uint x0, uint y) internal pure returns (uint) {\n return x0*(y*y/1e18*y/1e18)/1e18+(x0*x0/1e18*x0/1e18)*y/1e18;\n }\n\n function _d(uint x0, uint y) internal pure returns (uint) {\n return 3*x0*(y*y/1e18)/1e18+(x0*x0/1e18*x0/1e18);\n }\n\n function _get_y(uint x0, uint xy, uint y) internal pure returns (uint) {\n for (uint i = 0; i < 255; i++) {\n uint y_prev = y;\n uint k = _f(x0, y);\n if (k < xy) {\n uint dy = (xy - k)*1e18/_d(x0, y);\n y = y + dy;\n } else {\n uint dy = (k - xy)*1e18/_d(x0, y);\n y = y - dy;\n }\n if (y > y_prev) {\n if (y - y_prev <= 1) {\n return y;\n }\n } else {\n if (y_prev - y <= 1) {\n return y;\n }\n }\n }\n return y;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getTradeDiff(uint amountIn, address tokenIn, address pair) external view returns (uint a, uint b) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(pair).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n a = _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n b = _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function getSample(address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return _getAmountOut(sample, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / sample;\n }\n\n function getMinimumValue(address tokenIn, address tokenOut, bool stable) external view returns (uint, uint, uint) {\n (uint dec0, uint dec1, uint r0, uint r1,, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n uint sample = tokenIn == t0 ? r0*dec1/r1 : r1*dec0/r0;\n return (sample, r0, r1);\n }\n\n function getAmountOut(uint amountIn, address tokenIn, address tokenOut, bool stable) external view returns (uint) {\n (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0,) = IPair(router.pairFor(tokenIn, tokenOut, stable)).metadata();\n return _getAmountOut(amountIn, tokenIn, r0, r1, t0, dec0, dec1, st) * 1e18 / amountIn;\n }\n\n function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1, address token0, uint decimals0, uint decimals1, bool stable) internal pure returns (uint) {\n if (stable) {\n uint xy = _k(_reserve0, _reserve1, stable, decimals0, decimals1);\n _reserve0 = _reserve0 * 1e18 / decimals0;\n _reserve1 = _reserve1 * 1e18 / decimals1;\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;\n uint y = reserveB - _get_y(amountIn+reserveA, xy, reserveB);\n return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;\n } else {\n (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);\n return amountIn * reserveB / (reserveA + amountIn);\n }\n }\n\n function _k(uint x, uint y, bool stable, uint decimals0, uint decimals1) internal pure returns (uint) {\n if (stable) {\n uint _x = x * 1e18 / decimals0;\n uint _y = y * 1e18 / decimals1;\n uint _a = (_x * _y) / 1e18;\n uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\n return _a * _b / 1e18; // x3y+y3x >= k\n } else {\n return x * y; // xy >= k\n }\n }\n \n}\n" + }, + "contracts/Voter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\";\nimport \"contracts/interfaces/IBribe.sol\";\nimport \"contracts/interfaces/IBribeFactory.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IGaugeFactory.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IMinter.sol\";\nimport \"contracts/interfaces/IPair.sol\";\nimport \"contracts/interfaces/IPairFactory.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\ncontract Voter is IVoter {\n address public immutable _ve; // the ve token that governs these contracts\n address public immutable factory; // the PairFactory\n address internal immutable base;\n address public immutable gaugefactory;\n address public immutable bribefactory;\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\n address public minter;\n address public governor; // should be set to an IGovernor\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\n\n uint256 public totalWeight; // total voting weight\n\n address[] public pools; // all pools viable for incentives\n mapping(address => address) public gauges; // pool => gauge\n mapping(address => address) public poolForGauge; // gauge => pool\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\n mapping(address => uint256) public weights; // pool => weight\n mapping(uint256 => mapping(address => uint256)) public votes; // nft => pool => votes\n mapping(uint256 => address[]) public poolVote; // nft => pools\n mapping(uint256 => uint256) public usedWeights; // nft => total voting weight of user\n mapping(uint256 => uint256) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\n mapping(address => bool) public isGauge;\n mapping(address => bool) public isWhitelisted;\n mapping(address => bool) public isAlive;\n\n event GaugeCreated(\n address indexed gauge,\n address creator,\n address internal_bribe,\n address indexed external_bribe,\n address indexed pool\n );\n event GaugeKilled(address indexed gauge);\n event GaugeRevived(address indexed gauge);\n event Voted(address indexed voter, uint256 tokenId, uint256 weight);\n event Abstained(uint256 tokenId, uint256 weight);\n event Deposit(\n address indexed lp,\n address indexed gauge,\n uint256 tokenId,\n uint256 amount\n );\n event Withdraw(\n address indexed lp,\n address indexed gauge,\n uint256 tokenId,\n uint256 amount\n );\n event NotifyReward(\n address indexed sender,\n address indexed reward,\n uint256 amount\n );\n event DistributeReward(\n address indexed sender,\n address indexed gauge,\n uint256 amount\n );\n event Attach(address indexed owner, address indexed gauge, uint256 tokenId);\n event Detach(address indexed owner, address indexed gauge, uint256 tokenId);\n event Whitelisted(address indexed whitelister, address indexed token);\n\n constructor(\n address __ve,\n address _factory,\n address _gauges,\n address _bribes\n ) {\n _ve = __ve;\n factory = _factory;\n base = IVotingEscrow(__ve).token();\n gaugefactory = _gauges;\n bribefactory = _bribes;\n minter = msg.sender;\n governor = msg.sender;\n emergencyCouncil = msg.sender;\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n modifier onlyNewEpoch(uint256 _tokenId) {\n // ensure new epoch since last vote\n require(\n (block.timestamp / DURATION) * DURATION > lastVoted[_tokenId],\n \"TOKEN_ALREADY_VOTED_THIS_EPOCH\"\n );\n _;\n }\n\n function initialize(address[] memory _tokens, address _minter) external {\n require(msg.sender == minter);\n for (uint256 i = 0; i < _tokens.length; i++) {\n _whitelist(_tokens[i]);\n }\n minter = _minter;\n }\n\n function setGovernor(address _governor) public {\n require(msg.sender == governor);\n governor = _governor;\n }\n\n function setEmergencyCouncil(address _council) public {\n require(msg.sender == emergencyCouncil);\n emergencyCouncil = _council;\n }\n\n function reset(uint256 _tokenId) external onlyNewEpoch(_tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n lastVoted[_tokenId] = block.timestamp;\n _reset(_tokenId);\n IVotingEscrow(_ve).abstain(_tokenId);\n }\n\n function _reset(uint256 _tokenId) internal {\n address[] storage _poolVote = poolVote[_tokenId];\n uint256 _poolVoteCnt = _poolVote.length;\n uint256 _totalWeight = 0;\n\n for (uint256 i = 0; i < _poolVoteCnt; i++) {\n address _pool = _poolVote[i];\n uint256 _votes = votes[_tokenId][_pool];\n\n if (_votes != 0) {\n _updateFor(gauges[_pool]);\n weights[_pool] -= _votes;\n votes[_tokenId][_pool] -= _votes;\n if (_votes > 0) {\n IBribe(internal_bribes[gauges[_pool]])._withdraw(\n uint256(_votes),\n _tokenId\n );\n IBribe(external_bribes[gauges[_pool]])._withdraw(\n uint256(_votes),\n _tokenId\n );\n _totalWeight += _votes;\n } else {\n _totalWeight -= _votes;\n }\n emit Abstained(_tokenId, _votes);\n }\n }\n totalWeight -= uint256(_totalWeight);\n usedWeights[_tokenId] = 0;\n delete poolVote[_tokenId];\n }\n\n // remove poke function\n\n function poke(uint256 _tokenId) external {\n require(\n IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId) ||\n msg.sender == governor\n );\n address[] memory _poolVote = poolVote[_tokenId];\n uint256 _poolCnt = _poolVote.length;\n uint256[] memory _weights = new uint256[](_poolCnt);\n\n for (uint256 i = 0; i < _poolCnt; i++) {\n _weights[i] = votes[_tokenId][_poolVote[i]];\n }\n\n _vote(_tokenId, _poolVote, _weights);\n }\n\n function _vote(\n uint256 _tokenId,\n address[] memory _poolVote,\n uint256[] memory _weights\n ) internal {\n _reset(_tokenId);\n uint256 _poolCnt = _poolVote.length;\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\n uint256 _totalVoteWeight = 0;\n uint256 _totalWeight = 0;\n uint256 _usedWeight = 0;\n\n for (uint256 i = 0; i < _poolCnt; i++) {\n _totalVoteWeight += _weights[i];\n }\n\n for (uint256 i = 0; i < _poolCnt; i++) {\n address _pool = _poolVote[i];\n address _gauge = gauges[_pool];\n\n if (isGauge[_gauge]) {\n uint256 _poolWeight = (_weights[i] * _weight) /\n _totalVoteWeight;\n require(votes[_tokenId][_pool] == 0);\n require(_poolWeight != 0);\n _updateFor(_gauge);\n\n poolVote[_tokenId].push(_pool);\n\n weights[_pool] += _poolWeight;\n votes[_tokenId][_pool] += _poolWeight;\n IBribe(internal_bribes[_gauge])._deposit(\n uint256(_poolWeight),\n _tokenId\n );\n IBribe(external_bribes[_gauge])._deposit(\n uint256(_poolWeight),\n _tokenId\n );\n _usedWeight += _poolWeight;\n _totalWeight += _poolWeight;\n emit Voted(msg.sender, _tokenId, _poolWeight);\n }\n }\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\n totalWeight += uint256(_totalWeight);\n usedWeights[_tokenId] = uint256(_usedWeight);\n }\n\n function vote(\n uint256 tokenId,\n address[] calldata _poolVote,\n uint256[] calldata _weights\n ) external onlyNewEpoch(tokenId) {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n require(_poolVote.length == _weights.length);\n lastVoted[tokenId] = block.timestamp;\n _vote(tokenId, _poolVote, _weights);\n }\n\n function whitelist(address _token) public {\n require(msg.sender == governor);\n _whitelist(_token);\n }\n\n function _whitelist(address _token) internal {\n require(!isWhitelisted[_token]);\n isWhitelisted[_token] = true;\n emit Whitelisted(msg.sender, _token);\n }\n\n function createGauge(address _pool) external returns (address) {\n require(gauges[_pool] == address(0x0), \"exists\");\n address[] memory allowedRewards = new address[](3);\n address[] memory internalRewards = new address[](2);\n bool isPair = IPairFactory(factory).isPair(_pool);\n address tokenA;\n address tokenB;\n\n if (isPair) {\n (tokenA, tokenB) = IPair(_pool).tokens();\n allowedRewards[0] = tokenA;\n allowedRewards[1] = tokenB;\n internalRewards[0] = tokenA;\n internalRewards[1] = tokenB;\n\n if (base != tokenA && base != tokenB) {\n allowedRewards[2] = base;\n }\n }\n\n if (msg.sender != governor) {\n // gov can create for any pool, even non-Velocimeter pairs\n require(isPair, \"!_pool\");\n require(\n isWhitelisted[tokenA] && isWhitelisted[tokenB],\n \"!whitelisted\"\n );\n }\n\n address _internal_bribe = IBribeFactory(bribefactory)\n .createInternalBribe(internalRewards);\n address _external_bribe = IBribeFactory(bribefactory)\n .createExternalBribe(allowedRewards);\n address _gauge = IGaugeFactory(gaugefactory).createGauge(\n _pool,\n _internal_bribe,\n _external_bribe,\n _ve,\n isPair,\n allowedRewards\n );\n\n IERC20(base).approve(_gauge, type(uint256).max);\n internal_bribes[_gauge] = _internal_bribe;\n external_bribes[_gauge] = _external_bribe;\n gauges[_pool] = _gauge;\n poolForGauge[_gauge] = _pool;\n isGauge[_gauge] = true;\n isAlive[_gauge] = true;\n _updateFor(_gauge);\n pools.push(_pool);\n emit GaugeCreated(\n _gauge,\n msg.sender,\n _internal_bribe,\n _external_bribe,\n _pool\n );\n return _gauge;\n }\n\n function killGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(isAlive[_gauge], \"gauge already dead\");\n isAlive[_gauge] = false;\n claimable[_gauge] = 0;\n emit GaugeKilled(_gauge);\n }\n\n function reviveGauge(address _gauge) external {\n require(msg.sender == emergencyCouncil, \"not emergency council\");\n require(!isAlive[_gauge], \"gauge already alive\");\n isAlive[_gauge] = true;\n emit GaugeRevived(_gauge);\n }\n\n function attachTokenToGauge(uint256 tokenId, address account) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\n emit Attach(account, msg.sender, tokenId);\n }\n\n function emitDeposit(\n uint256 tokenId,\n address account,\n uint256 amount\n ) external {\n require(isGauge[msg.sender]);\n require(isAlive[msg.sender]);\n emit Deposit(account, msg.sender, tokenId, amount);\n }\n\n function detachTokenFromGauge(uint256 tokenId, address account) external {\n require(isGauge[msg.sender]);\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\n emit Detach(account, msg.sender, tokenId);\n }\n\n function emitWithdraw(\n uint256 tokenId,\n address account,\n uint256 amount\n ) external {\n require(isGauge[msg.sender]);\n emit Withdraw(account, msg.sender, tokenId, amount);\n }\n\n function length() external view returns (uint256) {\n return pools.length;\n }\n\n uint256 internal index;\n mapping(address => uint256) internal supplyIndex;\n mapping(address => uint256) public claimable;\n\n function notifyRewardAmount(uint256 amount) external {\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\n uint256 _ratio = (amount * 1e18) / totalWeight; // 1e18 adjustment is removed during claim\n if (_ratio > 0) {\n index += _ratio;\n }\n emit NotifyReward(msg.sender, base, amount);\n }\n\n function updateFor(address[] memory _gauges) external {\n for (uint256 i = 0; i < _gauges.length; i++) {\n _updateFor(_gauges[i]);\n }\n }\n\n function updateForRange(uint256 start, uint256 end) public {\n for (uint256 i = start; i < end; i++) {\n _updateFor(gauges[pools[i]]);\n }\n }\n\n function updateAll() external {\n updateForRange(0, pools.length);\n }\n\n function updateGauge(address _gauge) external {\n _updateFor(_gauge);\n }\n\n function _updateFor(address _gauge) internal {\n address _pool = poolForGauge[_gauge];\n uint256 _supplied = weights[_pool];\n if (_supplied > 0) {\n uint256 _supplyIndex = supplyIndex[_gauge];\n uint256 _index = index; // get global index0 for accumulated distro\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\n uint256 _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\n if (_delta > 0) {\n uint256 _share = (uint256(_supplied) * _delta) / 1e18; // add accrued difference for each supplied token\n if (isAlive[_gauge]) {\n claimable[_gauge] += _share;\n }\n }\n } else {\n supplyIndex[_gauge] = index; // new users are set to the default global state\n }\n }\n\n function claimRewards(address[] memory _gauges, address[][] memory _tokens)\n external\n {\n for (uint256 i = 0; i < _gauges.length; i++) {\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\n }\n }\n\n function claimBribes(\n address[] memory _bribes,\n address[][] memory _tokens,\n uint256 _tokenId\n ) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint256 i = 0; i < _bribes.length; i++) {\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function claimFees(\n address[] memory _fees,\n address[][] memory _tokens,\n uint256 _tokenId\n ) external {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\n for (uint256 i = 0; i < _fees.length; i++) {\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\n }\n }\n\n function distributeFees(address[] memory _gauges) external {\n for (uint256 i = 0; i < _gauges.length; i++) {\n if (IGauge(_gauges[i]).isForPair()) {\n IGauge(_gauges[i]).claimFees();\n }\n }\n }\n\n function distribute(address _gauge) public lock {\n IMinter(minter).update_period();\n _updateFor(_gauge); // should set claimable to 0 if killed\n uint256 _claimable = claimable[_gauge];\n if (\n _claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0\n ) {\n claimable[_gauge] = 0;\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\n emit DistributeReward(msg.sender, _gauge, _claimable);\n }\n }\n\n function distro() external {\n distribute(0, pools.length);\n }\n\n function distribute() external {\n distribute(0, pools.length);\n }\n\n function distribute(uint256 start, uint256 finish) public {\n for (uint256 x = start; x < finish; x++) {\n distribute(gauges[pools[x]]);\n }\n }\n\n function distribute(address[] memory _gauges) external {\n for (uint256 x = 0; x < _gauges.length; x++) {\n distribute(_gauges[x]);\n }\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/VotingEscrow.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IERC721, IERC721Metadata} from \"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {IVotes} from \"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\";\nimport {IERC721Receiver} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC20} from \"contracts/interfaces/IERC20.sol\";\nimport {IVeArtProxy} from \"contracts/interfaces/IVeArtProxy.sol\";\nimport {IVotingEscrow} from \"contracts/interfaces/IVotingEscrow.sol\";\n\n/// @title Voting Escrow\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\n enum DepositType {\n DEPOSIT_FOR_TYPE,\n CREATE_LOCK_TYPE,\n INCREASE_LOCK_AMOUNT,\n INCREASE_UNLOCK_TIME,\n MERGE_TYPE\n }\n\n struct LockedBalance {\n int128 amount;\n uint end;\n }\n\n struct Point {\n int128 bias;\n int128 slope; // # -dweight / dt\n uint ts;\n uint blk; // block\n }\n /* We cannot really do block numbers per se b/c slope is per time, not per block\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\n * What we can do is to extrapolate ***At functions */\n\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\n struct Checkpoint {\n uint timestamp;\n uint[] tokenIds;\n }\n\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Deposit(\n address indexed provider,\n uint tokenId,\n uint value,\n uint indexed locktime,\n DepositType deposit_type,\n uint ts\n );\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\n event Supply(uint prevSupply, uint supply);\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n address public immutable token;\n address public voter;\n address public team;\n address public artProxy;\n\n mapping(uint => Point) public point_history; // epoch -> unsigned point\n\n /// @dev Mapping of interface id to bool about whether or not it's supported\n mapping(bytes4 => bool) internal supportedInterfaces;\n\n /// @dev ERC165 interface ID of ERC165\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\n\n /// @dev ERC165 interface ID of ERC721\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\n\n /// @dev ERC165 interface ID of ERC721Metadata\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\n\n /// @dev Current count of token\n uint internal tokenId;\n\n /// @notice Contract constructor\n /// @param token_addr `FLOW` token address\n constructor(address token_addr, address art_proxy) {\n token = token_addr;\n voter = msg.sender;\n team = msg.sender;\n artProxy = art_proxy;\n\n point_history[0].blk = block.number;\n point_history[0].ts = block.timestamp;\n\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\n\n // mint-ish\n emit Transfer(address(0), address(this), tokenId);\n // burn-ish\n emit Transfer(address(this), address(0), tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n MODIFIERS\n //////////////////////////////////////////////////////////////*/\n\n /// @dev reentrancy guard\n uint8 internal constant _not_entered = 1;\n uint8 internal constant _entered = 2;\n uint8 internal _entered_state = 1;\n modifier nonreentrant() {\n require(_entered_state == _not_entered);\n _entered_state = _entered;\n _;\n _entered_state = _not_entered;\n }\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string constant public name = \"veNFT\";\n string constant public symbol = \"veNFT\";\n string constant public version = \"1.0.0\";\n uint8 constant public decimals = 18;\n\n function setTeam(address _team) external {\n require(msg.sender == team);\n team = _team;\n }\n\n function setArtProxy(address _proxy) external {\n require(msg.sender == team);\n artProxy = _proxy;\n }\n\n /// @dev Returns current token URI metadata\n /// @param _tokenId Token ID to fetch URI for.\n function tokenURI(uint _tokenId) external view returns (string memory) {\n require(idToOwner[_tokenId] != address(0), \"Query for nonexistent token\");\n LockedBalance memory _locked = locked[_tokenId];\n return IVeArtProxy(artProxy)._tokenURI(\n _tokenId,\n _balanceOfNFT(_tokenId, block.timestamp),\n _locked.end,\n uint(int256(_locked.amount))\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 BALANCE/OWNER STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to the address that owns it.\n mapping(uint => address) internal idToOwner;\n\n /// @dev Mapping from owner address to count of his tokens.\n mapping(address => uint) internal ownerToNFTokenCount;\n\n /// @dev Returns the address of the owner of the NFT.\n /// @param _tokenId The identifier for an NFT.\n function ownerOf(uint _tokenId) public view returns (address) {\n return idToOwner[_tokenId];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function _balance(address _owner) internal view returns (uint) {\n return ownerToNFTokenCount[_owner];\n }\n\n /// @dev Returns the number of NFTs owned by `_owner`.\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\n /// @param _owner Address for whom to query the balance.\n function balanceOf(address _owner) external view returns (uint) {\n return _balance(_owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 APPROVAL STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from NFT ID to approved address.\n mapping(uint => address) internal idToApprovals;\n\n /// @dev Mapping from owner address to mapping of operator addresses.\n mapping(address => mapping(address => bool)) internal ownerToOperators;\n\n mapping(uint => uint) public ownership_change;\n\n /// @dev Get the approved address for a single NFT.\n /// @param _tokenId ID of the NFT to query the approval of.\n function getApproved(uint _tokenId) external view returns (address) {\n return idToApprovals[_tokenId];\n }\n\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\n /// @param _owner The address that owns the NFTs.\n /// @param _operator The address that acts on behalf of the owner.\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n return (ownerToOperators[_owner])[_operator];\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC721 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\n /// @param _approved Address to be approved for the given NFT ID.\n /// @param _tokenId ID of the token to be approved.\n function approve(address _approved, uint _tokenId) public {\n address owner = idToOwner[_tokenId];\n // Throws if `_tokenId` is not a valid NFT\n require(owner != address(0));\n // Throws if `_approved` is the current owner\n require(_approved != owner);\n // Check requirements\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\n require(senderIsOwner || senderIsApprovedForAll);\n // Set the approval\n idToApprovals[_tokenId] = _approved;\n emit Approval(owner, _approved, _tokenId);\n }\n\n /// @dev Enables or disables approval for a third party (\"operator\") to manage all of\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\n /// @notice This works even if sender doesn't own any tokens at the time.\n /// @param _operator Address to add to the set of authorized operators.\n /// @param _approved True if the operators is approved, false to revoke approval.\n function setApprovalForAll(address _operator, bool _approved) external {\n // Throws if `_operator` is the `msg.sender`\n assert(_operator != msg.sender);\n ownerToOperators[msg.sender][_operator] = _approved;\n emit ApprovalForAll(msg.sender, _operator, _approved);\n }\n\n /* TRANSFER FUNCTIONS */\n /// @dev Clear an approval of a given address\n /// Throws if `_owner` is not the current owner.\n function _clearApproval(address _owner, uint _tokenId) internal {\n // Throws if `_owner` is not the current owner\n assert(idToOwner[_tokenId] == _owner);\n if (idToApprovals[_tokenId] != address(0)) {\n // Reset approvals\n idToApprovals[_tokenId] = address(0);\n }\n }\n\n /// @dev Returns whether the given spender can transfer a given token ID\n /// @param _spender address of the spender to query\n /// @param _tokenId uint ID of the token to be transferred\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\n address owner = idToOwner[_tokenId];\n bool spenderIsOwner = owner == _spender;\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\n }\n\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\n return _isApprovedOrOwner(_spender, _tokenId);\n }\n\n /// @dev Exeute transfer of a NFT.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\n /// Throws if `_to` is the zero address.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_tokenId` is not a valid NFT.\n function _transferFrom(\n address _from,\n address _to,\n uint _tokenId,\n address _sender\n ) internal {\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n // Check requirements\n require(_isApprovedOrOwner(_sender, _tokenId));\n // Clear approval. Throws if `_from` is not the current owner\n _clearApproval(_from, _tokenId);\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\n _removeTokenFrom(_from, _tokenId);\n // auto re-delegate\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\n // Add NFT\n _addTokenTo(_to, _tokenId);\n // Set the block of ownership transfer (for Flash NFT protection)\n ownership_change[_tokenId] = block.number;\n // Log the transfer\n emit Transfer(_from, _to, _tokenId);\n }\n\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n /// they maybe be permanently lost.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function transferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId\n ) external {\n safeTransferFrom(_from, _to, _tokenId, \"\");\n }\n\n function _isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n uint size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /// @dev Transfers the ownership of an NFT from one address to another address.\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\n /// approved address for this NFT.\n /// Throws if `_from` is not the current owner.\n /// Throws if `_to` is the zero address.\n /// Throws if `_tokenId` is not a valid NFT.\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\n /// the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.\n /// @param _from The current owner of the NFT.\n /// @param _to The new owner.\n /// @param _tokenId The NFT to transfer.\n /// @param _data Additional data with no specified format, sent in call to `_to`.\n function safeTransferFrom(\n address _from,\n address _to,\n uint _tokenId,\n bytes memory _data\n ) public {\n _transferFrom(_from, _to, _tokenId, msg.sender);\n\n if (_isContract(_to)) {\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\n revert(\"ERC721: ERC721Receiver rejected tokens\");\n }\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert('ERC721: transfer to non ERC721Receiver implementer');\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC165 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Interface identification is specified in ERC-165.\n /// @param _interfaceID Id of the interface\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n return supportedInterfaces[_interfaceID];\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @dev Mapping from owner address to mapping of index to tokenIds\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\n\n /// @dev Mapping from NFT ID to index of owner\n mapping(uint => uint) internal tokenToOwnerIndex;\n\n /// @dev Get token by index\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\n return ownerToNFTokenIdList[_owner][_tokenIndex];\n }\n\n /// @dev Add a NFT to an index mapping to a given address\n /// @param _to address of the receiver\n /// @param _tokenId uint ID Of the token to be added\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\n uint current_count = _balance(_to);\n\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\n tokenToOwnerIndex[_tokenId] = current_count;\n }\n\n /// @dev Add a NFT to a given address\n /// Throws if `_tokenId` is owned by someone.\n function _addTokenTo(address _to, uint _tokenId) internal {\n // Throws if `_tokenId` is owned by someone\n assert(idToOwner[_tokenId] == address(0));\n // Change the owner\n idToOwner[_tokenId] = _to;\n // Update owner token index tracking\n _addTokenToOwnerList(_to, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_to] += 1;\n }\n\n /// @dev Function to mint tokens\n /// Throws if `_to` is zero address.\n /// Throws if `_tokenId` is owned by someone.\n /// @param _to The address that will receive the minted tokens.\n /// @param _tokenId The token id to mint.\n /// @return A boolean that indicates if the operation was successful.\n function _mint(address _to, uint _tokenId) internal returns (bool) {\n // Throws if `_to` is zero address\n assert(_to != address(0));\n // checkpoint for gov\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\n // Add NFT. Throws if `_tokenId` is owned by someone\n _addTokenTo(_to, _tokenId);\n emit Transfer(address(0), _to, _tokenId);\n return true;\n }\n\n /// @dev Remove a NFT from an index mapping to a given address\n /// @param _from address of the sender\n /// @param _tokenId uint ID Of the token to be removed\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\n // Delete\n uint current_count = _balance(_from) - 1;\n uint current_index = tokenToOwnerIndex[_tokenId];\n\n if (current_count == current_index) {\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n } else {\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\n\n // Add\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[lastTokenId] = current_index;\n\n // Delete\n // update ownerToNFTokenIdList\n ownerToNFTokenIdList[_from][current_count] = 0;\n // update tokenToOwnerIndex\n tokenToOwnerIndex[_tokenId] = 0;\n }\n }\n\n /// @dev Remove a NFT from a given address\n /// Throws if `_from` is not the current owner.\n function _removeTokenFrom(address _from, uint _tokenId) internal {\n // Throws if `_from` is not the current owner\n assert(idToOwner[_tokenId] == _from);\n // Change the owner\n idToOwner[_tokenId] = address(0);\n // Update owner token index tracking\n _removeTokenFromOwnerList(_from, _tokenId);\n // Change count tracking\n ownerToNFTokenCount[_from] -= 1;\n }\n\n function _burn(uint _tokenId) internal {\n require(_isApprovedOrOwner(msg.sender, _tokenId), \"caller is not owner nor approved\");\n\n address owner = ownerOf(_tokenId);\n\n // Clear approval\n approve(address(0), _tokenId);\n // checkpoint for gov\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\n // Remove token\n _removeTokenFrom(msg.sender, _tokenId);\n emit Transfer(owner, address(0), _tokenId);\n }\n\n /*//////////////////////////////////////////////////////////////\n ESCROW STORAGE\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public user_point_epoch;\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\n mapping(uint => LockedBalance) public locked;\n uint public epoch;\n mapping(uint => int128) public slope_changes; // time -> signed slope change\n uint public supply;\n\n uint internal constant WEEK = 1 weeks;\n uint internal constant MAXTIME = 4 * 365 * 86400;\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\n uint internal constant MULTIPLIER = 1 ether;\n\n /*//////////////////////////////////////////////////////////////\n ESCROW LOGIC\n //////////////////////////////////////////////////////////////*/\n\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @return Value of the slope\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\n uint uepoch = user_point_epoch[_tokenId];\n return user_point_history[_tokenId][uepoch].slope;\n }\n\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\n /// @param _tokenId token of the NFT\n /// @param _idx User epoch number\n /// @return Epoch time of the checkpoint\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\n return user_point_history[_tokenId][_idx].ts;\n }\n\n /// @notice Get timestamp when `_tokenId`'s lock finishes\n /// @param _tokenId User NFT\n /// @return Epoch time of the lock end\n function locked__end(uint _tokenId) external view returns (uint) {\n return locked[_tokenId].end;\n }\n\n /// @notice Record global and per-user data to checkpoint\n /// @param _tokenId NFT token ID. No user checkpoint if 0\n /// @param old_locked Pevious locked amount / end lock time for the user\n /// @param new_locked New locked amount / end lock time for the user\n function _checkpoint(\n uint _tokenId,\n LockedBalance memory old_locked,\n LockedBalance memory new_locked\n ) internal {\n Point memory u_old;\n Point memory u_new;\n int128 old_dslope = 0;\n int128 new_dslope = 0;\n uint _epoch = epoch;\n\n if (_tokenId != 0) {\n // Calculate slopes and biases\n // Kept at zero when they have to\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\n u_old.slope = old_locked.amount / iMAXTIME;\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\n }\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\n u_new.slope = new_locked.amount / iMAXTIME;\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\n }\n\n // Read values of scheduled changes in the slope\n // old_locked.end can be in the past and in the future\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\n old_dslope = slope_changes[old_locked.end];\n if (new_locked.end != 0) {\n if (new_locked.end == old_locked.end) {\n new_dslope = old_dslope;\n } else {\n new_dslope = slope_changes[new_locked.end];\n }\n }\n }\n\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\n if (_epoch > 0) {\n last_point = point_history[_epoch];\n }\n uint last_checkpoint = last_point.ts;\n // initial_last_point is used for extrapolation to calculate block number\n // (approximately, for *At methods) and save them\n // as we cannot figure that out exactly from inside the contract\n Point memory initial_last_point = last_point;\n uint block_slope = 0; // dblock/dt\n if (block.timestamp > last_point.ts) {\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\n }\n // If last point is already recorded in this block, slope=0\n // But that's ok b/c we know the block in such case\n\n // Go over weeks to fill history and calculate what the current point is\n {\n uint t_i = (last_checkpoint / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n // Hopefully it won't happen that this won't get used in 5 years!\n // If it does, users will be able to withdraw but vote weight will be broken\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > block.timestamp) {\n t_i = block.timestamp;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\n last_point.slope += d_slope;\n if (last_point.bias < 0) {\n // This can happen\n last_point.bias = 0;\n }\n if (last_point.slope < 0) {\n // This cannot happen - just in case\n last_point.slope = 0;\n }\n last_checkpoint = t_i;\n last_point.ts = t_i;\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\n _epoch += 1;\n if (t_i == block.timestamp) {\n last_point.blk = block.number;\n break;\n } else {\n point_history[_epoch] = last_point;\n }\n }\n }\n\n epoch = _epoch;\n // Now point_history is filled until t=now\n\n if (_tokenId != 0) {\n // If last point was in this block, the slope change has been applied already\n // But in such case we have 0 slope(s)\n last_point.slope += (u_new.slope - u_old.slope);\n last_point.bias += (u_new.bias - u_old.bias);\n if (last_point.slope < 0) {\n last_point.slope = 0;\n }\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n }\n\n // Record the changed point into history\n point_history[_epoch] = last_point;\n\n if (_tokenId != 0) {\n // Schedule the slope changes (slope is going down)\n // We subtract new_user_slope from [new_locked.end]\n // and add old_user_slope to [old_locked.end]\n if (old_locked.end > block.timestamp) {\n // old_dslope was - u_old.slope, so we cancel that\n old_dslope += u_old.slope;\n if (new_locked.end == old_locked.end) {\n old_dslope -= u_new.slope; // It was a new deposit, not extension\n }\n slope_changes[old_locked.end] = old_dslope;\n }\n\n if (new_locked.end > block.timestamp) {\n if (new_locked.end > old_locked.end) {\n new_dslope -= u_new.slope; // old slope disappeared at this point\n slope_changes[new_locked.end] = new_dslope;\n }\n // else: we recorded it already in old_dslope\n }\n // Now handle user history\n uint user_epoch = user_point_epoch[_tokenId] + 1;\n\n user_point_epoch[_tokenId] = user_epoch;\n u_new.ts = block.timestamp;\n u_new.blk = block.number;\n user_point_history[_tokenId][user_epoch] = u_new;\n }\n }\n\n /// @notice Deposit and lock tokens for a user\n /// @param _tokenId NFT that holds lock\n /// @param _value Amount to deposit\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\n /// @param locked_balance Previous locked amount / timestamp\n /// @param deposit_type The type of deposit\n function _deposit_for(\n uint _tokenId,\n uint _value,\n uint unlock_time,\n LockedBalance memory locked_balance,\n DepositType deposit_type\n ) internal {\n LockedBalance memory _locked = locked_balance;\n uint supply_before = supply;\n\n supply = supply_before + _value;\n LockedBalance memory old_locked;\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\n // Adding to existing lock, or if a lock is expired - creating a new one\n _locked.amount += int128(int256(_value));\n if (unlock_time != 0) {\n _locked.end = unlock_time;\n }\n locked[_tokenId] = _locked;\n\n // Possibilities:\n // Both old_locked.end could be current or expired (>/< block.timestamp)\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\n // _locked.end > block.timestamp (always)\n _checkpoint(_tokenId, old_locked, _locked);\n\n address from = msg.sender;\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\n assert(IERC20(token).transferFrom(from, address(this), _value));\n }\n\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\n emit Supply(supply_before, supply_before + _value);\n }\n\n function block_number() external view returns (uint) {\n return block.number;\n }\n\n /// @notice Record global data to checkpoint\n function checkpoint() external {\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\n }\n\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\n /// cannot extend their locktime and deposit for a brand new user\n /// @param _tokenId lock NFT\n /// @param _value Amount to add to user's lock\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\n LockedBalance memory _locked = locked[_tokenId];\n\n require(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_value > 0); // dev: need non-zero value\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n ++tokenId;\n uint _tokenId = tokenId;\n _mint(_to, _tokenId);\n\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\n return _tokenId;\n }\n\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, msg.sender);\n }\n\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\n /// @param _value Amount to deposit\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\n /// @param _to Address to deposit\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\n return _create_lock(_value, _lock_duration, _to);\n }\n\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\n /// @param _value Amount of tokens to deposit and add to the lock\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n\n assert(_value > 0); // dev: need non-zero value\n require(_locked.amount > 0, 'No existing lock found');\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\n\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\n }\n\n /// @notice Extend the unlock time for `_tokenId`\n /// @param _lock_duration New number of seconds until tokens unlock\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n\n LockedBalance memory _locked = locked[_tokenId];\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\n\n require(_locked.end > block.timestamp, 'Lock expired');\n require(_locked.amount > 0, 'Nothing is locked');\n require(unlock_time > _locked.end, 'Can only increase lock duration');\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\n\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\n }\n\n /// @notice Withdraw all tokens for `_tokenId`\n /// @dev Only possible if the lock has expired\n function withdraw(uint _tokenId) external nonreentrant {\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \"attached\");\n\n LockedBalance memory _locked = locked[_tokenId];\n require(block.timestamp >= _locked.end, \"The lock didn't expire\");\n uint value = uint(int256(_locked.amount));\n\n locked[_tokenId] = LockedBalance(0,0);\n uint supply_before = supply;\n supply = supply_before - value;\n\n // old_locked can have either expired <= timestamp or zero end\n // _locked has only 0 end\n // Both can have >= 0 amount\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\n\n assert(IERC20(token).transfer(msg.sender, value));\n\n // Burn the NFT\n _burn(_tokenId);\n\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\n emit Supply(supply_before, supply_before - value);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\n // They measure the weights for the purpose of voting, so they don't represent\n // real coins.\n\n /// @notice Binary search to estimate timestamp for block number\n /// @param _block Block to find\n /// @param max_epoch Don't go beyond this epoch\n /// @return Approximate timestamp for block\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\n // Binary search\n uint _min = 0;\n uint _max = max_epoch;\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (point_history[_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n return _min;\n }\n\n /// @notice Get the current voting power for `_tokenId`\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\n /// @param _tokenId NFT for lock\n /// @param _t Epoch time to return voting power at\n /// @return User voting power\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\n uint _epoch = user_point_epoch[_tokenId];\n if (_epoch == 0) {\n return 0;\n } else {\n Point memory last_point = user_point_history[_tokenId][_epoch];\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(int256(last_point.bias));\n }\n }\n\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\n if (ownership_change[_tokenId] == block.number) return 0;\n return _balanceOfNFT(_tokenId, block.timestamp);\n }\n\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\n return _balanceOfNFT(_tokenId, _t);\n }\n\n /// @notice Measure voting power of `_tokenId` at block height `_block`\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\n /// @param _tokenId User's wallet NFT\n /// @param _block Block to calculate the voting power at\n /// @return Voting power\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\n // Copying and pasting totalSupply code because Vyper cannot pass by\n // reference yet\n assert(_block <= block.number);\n\n // Binary search\n uint _min = 0;\n uint _max = user_point_epoch[_tokenId];\n for (uint i = 0; i < 128; ++i) {\n // Will be always enough for 128-bit numbers\n if (_min >= _max) {\n break;\n }\n uint _mid = (_min + _max + 1) / 2;\n if (user_point_history[_tokenId][_mid].blk <= _block) {\n _min = _mid;\n } else {\n _max = _mid - 1;\n }\n }\n\n Point memory upoint = user_point_history[_tokenId][_min];\n\n uint max_epoch = epoch;\n uint _epoch = _find_block_epoch(_block, max_epoch);\n Point memory point_0 = point_history[_epoch];\n uint d_block = 0;\n uint d_t = 0;\n if (_epoch < max_epoch) {\n Point memory point_1 = point_history[_epoch + 1];\n d_block = point_1.blk - point_0.blk;\n d_t = point_1.ts - point_0.ts;\n } else {\n d_block = block.number - point_0.blk;\n d_t = block.timestamp - point_0.ts;\n }\n uint block_time = point_0.ts;\n if (d_block != 0) {\n block_time += (d_t * (_block - point_0.blk)) / d_block;\n }\n\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\n if (upoint.bias >= 0) {\n return uint(uint128(upoint.bias));\n } else {\n return 0;\n }\n }\n\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\n return _balanceOfAtNFT(_tokenId, _block);\n }\n\n /// @notice Calculate total voting power at some point in the past\n /// @param _block Block to calculate the total voting power at\n /// @return Total voting power at `_block`\n function totalSupplyAt(uint _block) external view returns (uint) {\n assert(_block <= block.number);\n uint _epoch = epoch;\n uint target_epoch = _find_block_epoch(_block, _epoch);\n\n Point memory point = point_history[target_epoch];\n uint dt = 0;\n if (target_epoch < _epoch) {\n Point memory point_next = point_history[target_epoch + 1];\n if (point.blk != point_next.blk) {\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\n }\n } else {\n if (point.blk != block.number) {\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\n }\n }\n // Now dt contains info on how far are we beyond point\n return _supply_at(point, point.ts + dt);\n }\n /// @notice Calculate total voting power at some point in the past\n /// @param point The point (bias/slope) to start search from\n /// @param t Time to calculate the total voting power at\n /// @return Total voting power at that time\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\n Point memory last_point = point;\n uint t_i = (last_point.ts / WEEK) * WEEK;\n for (uint i = 0; i < 255; ++i) {\n t_i += WEEK;\n int128 d_slope = 0;\n if (t_i > t) {\n t_i = t;\n } else {\n d_slope = slope_changes[t_i];\n }\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\n if (t_i == t) {\n break;\n }\n last_point.slope += d_slope;\n last_point.ts = t_i;\n }\n\n if (last_point.bias < 0) {\n last_point.bias = 0;\n }\n return uint(uint128(last_point.bias));\n }\n\n function totalSupply() external view returns (uint) {\n return totalSupplyAtT(block.timestamp);\n }\n\n /// @notice Calculate total voting power\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\n /// @return Total voting power\n function totalSupplyAtT(uint t) public view returns (uint) {\n uint _epoch = epoch;\n Point memory last_point = point_history[_epoch];\n return _supply_at(last_point, t);\n }\n\n /*///////////////////////////////////////////////////////////////\n GAUGE VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n mapping(uint => uint) public attachments;\n mapping(uint => bool) public voted;\n\n function setVoter(address _voter) external {\n require(msg.sender == voter);\n voter = _voter;\n }\n\n function voting(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = true;\n }\n\n function abstain(uint _tokenId) external {\n require(msg.sender == voter);\n voted[_tokenId] = false;\n }\n\n function attach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] + 1;\n }\n\n function detach(uint _tokenId) external {\n require(msg.sender == voter);\n attachments[_tokenId] = attachments[_tokenId] - 1;\n }\n\n function merge(uint _from, uint _to) external {\n require(attachments[_from] == 0 && !voted[_from], \"attached\");\n require(_from != _to);\n require(_isApprovedOrOwner(msg.sender, _from));\n require(_isApprovedOrOwner(msg.sender, _to));\n\n LockedBalance memory _locked0 = locked[_from];\n LockedBalance memory _locked1 = locked[_to];\n uint value0 = uint(int256(_locked0.amount));\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\n\n locked[_from] = LockedBalance(0, 0);\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\n _burn(_from);\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING STORAGE\n //////////////////////////////////////////////////////////////*/\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of each accounts delegate\n mapping(address => address) private _delegates;\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\n\n /// @notice A record of delegated token checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /**\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\n * the delegator's own address if they haven't delegated.\n * This avoids having to delegate to oneself.\n */\n function delegates(address delegator) public view returns (address) {\n address current = _delegates[delegator];\n return current == address(0) ? delegator : current;\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getVotes(address account) external view returns (uint) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n votes = votes + _balanceOfNFT(tId, block.timestamp);\n }\n return votes;\n }\n\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\n return (nCheckpoints - 1);\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].timestamp > timestamp) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint storage cp = checkpoints[account][center];\n if (cp.timestamp == timestamp) {\n return center;\n } else if (cp.timestamp < timestamp) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return lower;\n }\n\n function getPastVotes(address account, uint timestamp)\n public\n view\n returns (uint)\n {\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\n // Sum votes\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\n uint votes = 0;\n for (uint i = 0; i < _tokenIds.length; i++) {\n uint tId = _tokenIds[i];\n // Use the provided input timestamp here to get the right decay\n votes = votes + _balanceOfNFT(tId, timestamp);\n }\n return votes;\n }\n\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\n return totalSupplyAtT(timestamp);\n }\n\n /*///////////////////////////////////////////////////////////////\n DAO VOTING LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _moveTokenDelegates(\n address srcRep,\n address dstRep,\n uint _tokenId\n ) internal {\n if (srcRep != dstRep && _tokenId > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except _tokenId\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (tId != _tokenId) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n // All the same plus _tokenId\n require(\n dstRepOld.length + 1 <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n dstRepNew.push(_tokenId);\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _findWhatCheckpointToWrite(address account)\n internal\n view\n returns (uint32)\n {\n uint _timestamp = block.timestamp;\n uint32 _nCheckPoints = numCheckpoints[account];\n\n if (\n _nCheckPoints > 0 &&\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\n ) {\n return _nCheckPoints - 1;\n } else {\n return _nCheckPoints;\n }\n }\n\n function _moveAllDelegates(\n address owner,\n address srcRep,\n address dstRep\n ) internal {\n // You can only redelegate what you own\n if (srcRep != dstRep) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint[] storage srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\n : checkpoints[srcRep][0].tokenIds;\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\n uint[] storage srcRepNew = checkpoints[srcRep][\n nextSrcRepNum\n ].tokenIds;\n // All the same except what owner owns\n for (uint i = 0; i < srcRepOld.length; i++) {\n uint tId = srcRepOld[i];\n if (idToOwner[tId] != owner) {\n srcRepNew.push(tId);\n }\n }\n\n numCheckpoints[srcRep] = srcRepNum + 1;\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint[] storage dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\n : checkpoints[dstRep][0].tokenIds;\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\n uint[] storage dstRepNew = checkpoints[dstRep][\n nextDstRepNum\n ].tokenIds;\n uint ownerTokenCount = ownerToNFTokenCount[owner];\n require(\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\n \"dstRep would have too many tokenIds\"\n );\n // All the same\n for (uint i = 0; i < dstRepOld.length; i++) {\n uint tId = dstRepOld[i];\n dstRepNew.push(tId);\n }\n // Plus all that's owned\n for (uint i = 0; i < ownerTokenCount; i++) {\n uint tId = ownerToNFTokenIdList[owner][i];\n dstRepNew.push(tId);\n }\n\n numCheckpoints[dstRep] = dstRepNum + 1;\n }\n }\n }\n\n function _delegate(address delegator, address delegatee) internal {\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n address currentDelegate = delegates(delegator);\n\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n _moveAllDelegates(delegator, currentDelegate, delegatee);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n if (delegatee == address(0)) delegatee = msg.sender;\n return _delegate(msg.sender, delegatee);\n }\n\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n block.chainid,\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"VotingEscrow::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"VotingEscrow::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"VotingEscrow::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n}\n" + }, + "contracts/WrappedExternalBribe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\";\nimport \"contracts/ExternalBribe.sol\";\nimport \"contracts/interfaces/IERC20.sol\";\nimport \"contracts/interfaces/IGauge.sol\";\nimport \"contracts/interfaces/IVoter.sol\";\nimport \"contracts/interfaces/IVotingEscrow.sol\";\n\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\ncontract WrappedExternalBribe {\n address public immutable voter;\n address public immutable _ve;\n ExternalBribe public underlying_bribe;\n\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\n uint256 internal constant MAX_REWARD_TOKENS = 16;\n\n uint256 internal constant PRECISION = 10**18;\n\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\n mapping(address => uint256) public periodFinish;\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\n\n address[] public rewards;\n mapping(address => bool) public isReward;\n\n /// @notice A checkpoint for marking balance\n struct RewardCheckpoint {\n uint256 timestamp;\n uint256 balance;\n }\n\n event NotifyReward(\n address indexed from,\n address indexed reward,\n uint256 epoch,\n uint256 amount\n );\n event ClaimRewards(\n address indexed from,\n address indexed reward,\n uint256 amount\n );\n\n constructor(address _voter, address _old_bribe) {\n voter = _voter;\n _ve = IVoter(_voter)._ve();\n underlying_bribe = ExternalBribe(_old_bribe);\n\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\n address underlying_reward = underlying_bribe.rewards(i);\n if (underlying_reward != address(0)) {\n isReward[underlying_reward] = true;\n rewards.push(underlying_reward);\n }\n }\n }\n\n // simple re-entrancy check\n uint256 internal _unlocked = 1;\n modifier lock() {\n require(_unlocked == 1);\n _unlocked = 2;\n _;\n _unlocked = 1;\n }\n\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\n return timestamp - (timestamp % (7 days));\n }\n\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\n uint256 bribeStart = _bribeStart(timestamp);\n uint256 bribeEnd = bribeStart + DURATION;\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\n }\n\n function rewardsListLength() external view returns (uint256) {\n return rewards.length;\n }\n\n // returns the last time the reward was modified or periodFinish if the reward has ended\n function lastTimeRewardApplicable(address token)\n public\n view\n returns (uint256)\n {\n return Math.min(block.timestamp, periodFinish[token]);\n }\n\n // allows a user to claim rewards for a given token\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\n\n emit ClaimRewards(msg.sender, tokens[i], _reward);\n }\n }\n\n // used by Voter to allow batched reward claims\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\n external\n lock\n {\n require(msg.sender == voter);\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\n for (uint256 i = 0; i < tokens.length; i++) {\n uint256 _reward = earned(tokens[i], tokenId);\n lastEarn[tokens[i]][tokenId] = block.timestamp;\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\n\n emit ClaimRewards(_owner, tokens[i], _reward);\n }\n }\n\n function earned(address token, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n uint256 _startTimestamp = lastEarn[token][tokenId];\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\n return 0;\n }\n\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\n tokenId,\n _startTimestamp\n );\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\n\n uint256 reward = 0;\n // you only earn once per epoch (after it's over)\n RewardCheckpoint memory prevRewards;\n prevRewards.timestamp = _bribeStart(_startTimestamp);\n uint256 _prevTs = 0;\n uint256 _prevBal = 0;\n uint256 _prevSupply = 1;\n\n if (_endIndex > 0) {\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\n uint256 _nextEpochStart = _bribeStart(_prevTs);\n // check that you've earned it\n // this won't happen until a week has passed\n if (_nextEpochStart > prevRewards.timestamp) {\n reward += prevRewards.balance;\n }\n\n prevRewards.timestamp = _nextEpochStart;\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(\n _nextEpochStart + DURATION\n )\n );\n prevRewards.balance =\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\n _prevSupply;\n }\n }\n\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\n uint256 _lastEpochStart = _bribeStart(_prevTs);\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\n\n if (\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\n ) {\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\n );\n reward +=\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\n _prevSupply;\n }\n\n return reward;\n }\n\n function left(address token) external view returns (uint256) {\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n return tokenRewardsPerEpoch[token][adjustedTstamp];\n }\n\n function notifyRewardAmount(address token, uint256 amount) external lock {\n require(amount > 0);\n if (!isReward[token]) {\n require(\n IVoter(voter).isWhitelisted(token),\n \"bribe tokens must be whitelisted\"\n );\n require(\n rewards.length < MAX_REWARD_TOKENS,\n \"too many rewards tokens\"\n );\n }\n // bribes kick in at the start of next bribe period\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\n\n _safeTransferFrom(token, msg.sender, address(this), amount);\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\n\n periodFinish[token] = adjustedTstamp + DURATION;\n\n if (!isReward[token]) {\n isReward[token] = true;\n rewards.push(token);\n }\n\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\n }\n\n function swapOutRewardToken(\n uint256 i,\n address oldToken,\n address newToken\n ) external {\n require(msg.sender == IVotingEscrow(_ve).team(), \"only team\");\n require(rewards[i] == oldToken);\n isReward[oldToken] = false;\n isReward[newToken] = true;\n rewards[i] = newToken;\n }\n\n function _safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n\n function _safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n require(token.code.length > 0);\n (bool success, bytes memory data) = token.call(\n abi.encodeWithSelector(\n IERC20.transferFrom.selector,\n from,\n to,\n value\n )\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))));\n }\n}\n" + }, + "contracts/WrappedExternalBribeV.sol": { + "content": "" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroEndpoint.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" + }, + "lib/LayerZero/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/IGovernor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Interface of the {Governor} core.\n *\n * _Available since v4.3._\n */\nabstract contract IGovernor is IERC165 {\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /**\n * @dev Emitted when a proposal is created.\n */\n event ProposalCreated(\n uint256 proposalId,\n address proposer,\n address[] targets,\n uint256[] values,\n string[] signatures,\n bytes[] calldatas,\n uint256 startBlock,\n uint256 endBlock,\n string description\n );\n\n /**\n * @dev Emitted when a proposal is canceled.\n */\n event ProposalCanceled(uint256 proposalId);\n\n /**\n * @dev Emitted when a proposal is executed.\n */\n event ProposalExecuted(uint256 proposalId);\n\n /**\n * @dev Emitted when a vote is cast without params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n */\n event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n /**\n * @dev Emitted when a vote is cast with params.\n *\n * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.\n * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.\n */\n event VoteCastWithParams(\n address indexed voter,\n uint256 proposalId,\n uint8 support,\n uint256 weight,\n string reason,\n bytes params\n );\n\n /**\n * @notice module:core\n * @dev Name of the governor instance (used in building the ERC712 domain separator).\n */\n function name() public view virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: \"1\"\n */\n function version() public view virtual returns (string memory);\n\n /**\n * @notice module:voting\n * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to\n * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of\n * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.\n *\n * There are 2 standard keys: `support` and `quorum`.\n *\n * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.\n * - `quorum=bravo` means that only For votes are counted towards quorum.\n * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.\n *\n * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique\n * name that describes the behavior. For example:\n *\n * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.\n * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.\n *\n * NOTE: The string can be decoded by the standard\n * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]\n * JavaScript class.\n */\n // solhint-disable-next-line func-name-mixedcase\n function COUNTING_MODE() public pure virtual returns (string memory);\n\n /**\n * @notice module:core\n * @dev Hashing function used to (re)build the proposal id from the proposal details..\n */\n function hashProposal(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public pure virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Current state of a proposal, following Compound's convention\n */\n function state(uint256 proposalId) public view virtual returns (ProposalState);\n\n /**\n * @notice module:core\n * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's\n * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the\n * beginning of the following block.\n */\n function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:core\n * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote\n * during this block.\n */\n function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to\n * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.\n */\n function votingDelay() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Delay, in number of blocks, between the vote start and vote ends.\n *\n * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting\n * duration compared to the voting delay.\n */\n function votingPeriod() public view virtual returns (uint256);\n\n /**\n * @notice module:user-config\n * @dev Minimum number of cast voted required for a proposal to be successful.\n *\n * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the\n * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).\n */\n function quorum(uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber`.\n *\n * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or\n * multiple), {ERC20Votes} tokens.\n */\n function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);\n\n /**\n * @notice module:reputation\n * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.\n */\n function getVotesWithParams(\n address account,\n uint256 blockNumber,\n bytes memory params\n ) public view virtual returns (uint256);\n\n /**\n * @notice module:voting\n * @dev Returns whether `account` has cast a vote on `proposalId`.\n */\n function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);\n\n /**\n * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends\n * {IGovernor-votingPeriod} blocks after the voting starts.\n *\n * Emits a {ProposalCreated} event.\n */\n function propose(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n string memory description\n ) public virtual returns (uint256 proposalId);\n\n /**\n * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the\n * deadline to be reached.\n *\n * Emits a {ProposalExecuted} event.\n *\n * Note: some module can modify the requirements for execution, for example by adding an additional timelock.\n */\n function execute(\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n bytes32 descriptionHash\n ) public payable virtual returns (uint256 proposalId);\n\n /**\n * @dev Cast a vote\n *\n * Emits a {VoteCast} event.\n */\n function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason\n *\n * Emits a {VoteCast} event.\n */\n function castVoteWithReason(\n uint256 proposalId,\n uint8 support,\n string calldata reason\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParams(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote using the user's cryptographic signature.\n *\n * Emits a {VoteCast} event.\n */\n function castVoteBySig(\n uint256 proposalId,\n uint8 support,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n\n /**\n * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.\n *\n * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.\n */\n function castVoteWithReasonAndParamsBySig(\n uint256 proposalId,\n uint8 support,\n string calldata reason,\n bytes memory params,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual returns (uint256 balance);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/draft-EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.4;\n\nimport \"../math/SafeCast.sol\";\n\n/**\n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary DoubleEndedQueue {\n /**\n * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n */\n error Empty();\n\n /**\n * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n */\n error OutOfBounds();\n\n /**\n * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n *\n * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n * lead to unexpected behavior.\n *\n * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n * data[end - 1].\n */\n struct Bytes32Deque {\n int128 _begin;\n int128 _end;\n mapping(int128 => bytes32) _data;\n }\n\n /**\n * @dev Inserts an item at the end of the queue.\n */\n function pushBack(Bytes32Deque storage deque, bytes32 value) internal {\n int128 backIndex = deque._end;\n deque._data[backIndex] = value;\n unchecked {\n deque._end = backIndex + 1;\n }\n }\n\n /**\n * @dev Removes the item at the end of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n value = deque._data[backIndex];\n delete deque._data[backIndex];\n deque._end = backIndex;\n }\n\n /**\n * @dev Inserts an item at the beginning of the queue.\n */\n function pushFront(Bytes32Deque storage deque, bytes32 value) internal {\n int128 frontIndex;\n unchecked {\n frontIndex = deque._begin - 1;\n }\n deque._data[frontIndex] = value;\n deque._begin = frontIndex;\n }\n\n /**\n * @dev Removes the item at the beginning of the queue and returns it.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n value = deque._data[frontIndex];\n delete deque._data[frontIndex];\n unchecked {\n deque._begin = frontIndex + 1;\n }\n }\n\n /**\n * @dev Returns the item at the beginning of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 frontIndex = deque._begin;\n return deque._data[frontIndex];\n }\n\n /**\n * @dev Returns the item at the end of the queue.\n *\n * Reverts with `Empty` if the queue is empty.\n */\n function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {\n if (empty(deque)) revert Empty();\n int128 backIndex;\n unchecked {\n backIndex = deque._end - 1;\n }\n return deque._data[backIndex];\n }\n\n /**\n * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n * `length(deque) - 1`.\n *\n * Reverts with `OutOfBounds` if the index is out of bounds.\n */\n function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {\n // int256(deque._begin) is a safe upcast\n int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));\n if (idx >= deque._end) revert OutOfBounds();\n return deque._data[idx];\n }\n\n /**\n * @dev Resets the queue back to being empty.\n *\n * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n * out on potential gas refunds.\n */\n function clear(Bytes32Deque storage deque) internal {\n deque._begin = 0;\n deque._end = 0;\n }\n\n /**\n * @dev Returns the number of items in the queue.\n */\n function length(Bytes32Deque storage deque) internal view returns (uint256) {\n // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n // We also assume there are at most int256.max items in the queue.\n unchecked {\n return uint256(int256(deque._end) - int256(deque._begin));\n }\n }\n\n /**\n * @dev Returns true if the queue is empty.\n */\n function empty(Bytes32Deque storage deque) internal view returns (bool) {\n return deque._end <= deque._begin;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/utils/Timers.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Tooling for timepoints, timers and delays\n */\nlibrary Timers {\n struct Timestamp {\n uint64 _deadline;\n }\n\n function getDeadline(Timestamp memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(Timestamp storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(Timestamp storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(Timestamp memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(Timestamp memory timer) internal view returns (bool) {\n return timer._deadline > block.timestamp;\n }\n\n function isExpired(Timestamp memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.timestamp;\n }\n\n struct BlockNumber {\n uint64 _deadline;\n }\n\n function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {\n return timer._deadline;\n }\n\n function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {\n timer._deadline = timestamp;\n }\n\n function reset(BlockNumber storage timer) internal {\n timer._deadline = 0;\n }\n\n function isUnset(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline == 0;\n }\n\n function isStarted(BlockNumber memory timer) internal pure returns (bool) {\n return timer._deadline > 0;\n }\n\n function isPending(BlockNumber memory timer) internal view returns (bool) {\n return timer._deadline > block.number;\n }\n\n function isExpired(BlockNumber memory timer) internal view returns (bool) {\n return isStarted(timer) && timer._deadline <= block.number;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + }, + "libraries": { + "": { + "__CACHE_BREAKER__": "0x0000000000000031363735353339323034313033" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumOneOLD/.chainId b/deployments/arbitrumOneOLD/.chainId new file mode 100644 index 00000000..7df83ecb --- /dev/null +++ b/deployments/arbitrumOneOLD/.chainId @@ -0,0 +1 @@ +42161 \ No newline at end of file diff --git a/deployments/arbitrumOneOLD/.migrations.json b/deployments/arbitrumOneOLD/.migrations.json new file mode 100644 index 00000000..92ece6a3 --- /dev/null +++ b/deployments/arbitrumOneOLD/.migrations.json @@ -0,0 +1,5 @@ +{ + "init_deploy": 1673992762, + "whitelist": 1673992764, + "initial_dist": 1673992767 +} \ No newline at end of file diff --git a/deployments/arbitrumOneOLD/BribeFactory.json b/deployments/arbitrumOneOLD/BribeFactory.json new file mode 100644 index 00000000..5986839d --- /dev/null +++ b/deployments/arbitrumOneOLD/BribeFactory.json @@ -0,0 +1,128 @@ +{ + "address": "0xBcC3c06e1D22E44Ac807D76A887fFB40765e0D16", + "abi": [ + { + "inputs": [ + { + "internalType": "address[]", + "name": "allowedRewards", + "type": "address[]" + } + ], + "name": "createExternalBribe", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "allowedRewards", + "type": "address[]" + } + ], + "name": "createInternalBribe", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "last_external_bribe", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "last_internal_bribe", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x7354518e1e037b7664110bd3a0f7ef13b1ee4eadbe7d059b4b536bf86b6250fa", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0xBcC3c06e1D22E44Ac807D76A887fFB40765e0D16", + "transactionIndex": 1, + "gasUsed": "26207536", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xfa162f78feb20b053135d6fb2f86d54a4dacf3af0fb526b6dd495cccbeb6e593", + "transactionHash": "0x7354518e1e037b7664110bd3a0f7ef13b1ee4eadbe7d059b4b536bf86b6250fa", + "logs": [], + "blockNumber": 53774033, + "cumulativeGasUsed": "26207536", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createExternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createInternalBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_external_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_internal_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/BribeFactory.sol\":\"BribeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/ExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract ExternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve; // \\u5929\\u4f7f\\u306e\\u305f\\u307e\\u3054\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balanceOf;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n _prevSupply = supplyCheckpoints[\\n getPriorSupplyIndex(_nextEpochStart + DURATION)\\n ].supply;\\n prevRewards.balanceOf =\\n (cp0.balanceOf *\\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (block.timestamp > _lastEpochEnd) {\\n reward +=\\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\\n }\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0xfe1e53dea8a63ce448c5856a740ed73038ad29a9dcd0f2a2752049b146bb4eb0\",\"license\":\"MIT\"},\"contracts/InternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract InternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve;\\n\\n uint256 public constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 public constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n mapping(address => mapping(uint256 => uint256))\\n public userRewardPerTokenStored;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][tokenId] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (totalSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / totalSupply);\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, endTime);\\n _startTimestamp = endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][tokenId],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n Checkpoint memory cp1 = checkpoints[tokenId][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][tokenId]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n // used to notify a gauge/bribe of a given reward, this can create griefing attacks by extending rewards\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n require(isReward[token]);\\n\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2dc302de5dfd95018d1fba7a3a1916d2c1fcf32859d19d38648767f13422a694\",\"license\":\"MIT\"},\"contracts/factories/BribeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/interfaces/IBribeFactory.sol\\\";\\nimport 'contracts/InternalBribe.sol';\\nimport 'contracts/ExternalBribe.sol';\\n\\ncontract BribeFactory is IBribeFactory {\\n address public last_internal_bribe;\\n address public last_external_bribe;\\n\\n function createInternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_internal_bribe = address(new InternalBribe(msg.sender, allowedRewards));\\n return last_internal_bribe;\\n }\\n\\n function createExternalBribe(address[] memory allowedRewards) external returns (address) {\\n last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards));\\n return last_external_bribe;\\n }\\n}\\n\\n// if this imports int and ext bribe why is the the gauge factory asking for those address as if they are deployed to an address.\\n\",\"keccak256\":\"0xd107fb5a520bae9b655bec4ad2eb11d598e74d0eeda0db547e2526a907dea7ec\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50614cca806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea26469706673582212205fdc0cbedbaeaa0ba11c8120c027b2bca65c182779d5bf888b06502050a1f54a64736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea2646970667358221220d5f0eaed47ec9cb0f7332a517560bcb420138d14d674caf3674831366bf225f464736f6c634300080d0033a264697066735822122050c7efc34434eca9041cf3c63b65797031e5608706da7fccb31aad9274a6c62c64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632a26b9eb146100515780636485f0c414610080578063b0ad856f14610093578063eb57738c146100a6575b600080fd5b61006461005f3660046101bf565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e3660046101bf565b610116565b600154610064906001600160a01b031681565b600054610064906001600160a01b031681565b600033826040516100c990610173565b6100d4929190610284565b604051809103906000f0801580156100f0573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6000338260405161012690610180565b610131929190610284565b604051809103906000f08015801561014d573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b0392909216918217905592915050565b612b31806102e183390190565b611e8380612e1283390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b03811681146101ba57600080fd5b919050565b600060208083850312156101d257600080fd5b823567ffffffffffffffff808211156101ea57600080fd5b818501915085601f8301126101fe57600080fd5b8135818111156102105761021061018d565b8060051b604051601f19603f830116810181811085821117156102355761023561018d565b60405291825284820192508381018501918883111561025357600080fd5b938501935b8285101561027857610269856101a3565b84529385019392850192610258565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156102d25785518516835294830194918301916001016102b4565b50909897505050505050505056fe60c060405260016010553480156200001657600080fd5b5060405162002b3138038062002b318339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016007600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060068282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05161279d620003946000396000818161042301528181610a0201528181610e82015261164301526000818161031101528181610c0d01528181610e3f015261154d015261279d6000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80639cc7f70811610125578063e6886396116100ad578063f301af421161007c578063f301af4214610595578063f3207723146105a8578063f5f8d365146105bb578063f7412baf146105ce578063fd314098146105f557600080fd5b8063e688639614610546578063e8111a121461054e578063f122977714610557578063f25e55a51461056a57600080fd5b8063a7852afa116100f4578063a7852afa146104d1578063aa479652146104e4578063aaf5eb6814610504578063b66503cf14610513578063da09d19d1461052657600080fd5b80639cc7f7081461046b5780639ce43f901461048b5780639e2bf22c146104ab578063a28d4c9c146104be57600080fd5b80634d5ce038116101a857806368fcee1a1161017757806368fcee1a146103f857806376f4be361461040b5780638dd598fb1461041e5780639418f9391461044557806399bcc0521461045857600080fd5b80634d5ce0381461037d57806350589793146103b05780635a45d052146103d0578063638634ee146103e557600080fd5b80632ce9aead116101ef5780632ce9aead146102ae5780633b881999146102ce5780633e491d47146102f957806346c96aac1461030c57806349dcc2041461034b57600080fd5b806301316ddf1461022157806318160ddd1461026d5780631be0528914610284578063221ca18c1461028e575b600080fd5b61025361022f366004612472565b600e6020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61027660085481565b604051908152602001610264565b61027662093a8081565b61027661029c36600461249e565b60006020819052908152604090205481565b6102766102bc36600461249e565b60026020526000908152604090205481565b6102766102dc366004612472565b600560209081526000928352604080842090915290825290205481565b610276610307366004612472565b610608565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610264565b6102536103593660046124bb565b600a6020908152600092835260408084209091529082529020805460019091015482565b6103a061038b36600461249e565b60076020526000908152604090205460ff1681565b6040519015158152602001610264565b6102766103be3660046124dd565b600b6020526000908152604090205481565b6103e36103de366004612472565b610864565b005b6102766103f336600461249e565b61089c565b6103e3610406366004612472565b6108c0565b6102766104193660046124dd565b6108cc565b6103337f000000000000000000000000000000000000000000000000000000000000000081565b6103e36104533660046124f6565b610a00565b61027661046636600461249e565b610b91565b6102766104793660046124dd565b60096020526000908152604090205481565b61027661049936600461249e565b60036020526000908152604090205481565b6103e36104b93660046124bb565b610c02565b6102766104cc3660046124bb565b610cdb565b6103e36104df36600461254e565b610e20565b6102766104f236600461249e565b600f6020526000908152604090205481565b610276670de0b6b3a764000081565b6103e3610521366004612472565b611165565b61027661053436600461249e565b60016020526000908152604090205481565b600654610276565b610276600d5481565b61027661056536600461249e565b61145b565b610276610578366004612472565b600460209081526000928352604080842090915290825290205481565b6103336105a33660046124dd565b611518565b6103e36105b63660046124bb565b611542565b6103e36105c936600461254e565b611613565b6102536105dc3660046124dd565b600c602052600090815260409020805460019091015482565b610253610603366004612472565b61191a565b6001600160a01b0382166000818152600460209081526040808320858452825280832054938352600e82528083208380529091528120549091829161064d9190611b3b565b6000848152600b60205260408120549192500361066e57600091505061085e565b600061067a8483610cdb565b6000858152600b60205260408120549192509061069990600190612635565b9050600081156107a257825b6106b0600184612635565b81116107a0576000878152600a60208181526040808420858552808352818520825180840190935280548352600190810154838501528c865293909252929182906106fc90869061264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600061073b8b846000015161191a565b509050600061074e8c846000015161191a565b509050670de0b6b3a76400006107648383612635565b85602001516107739190612664565b61077d9190612683565b610787908761264c565b9550505050508080610798906126a5565b9150506106a5565b505b6000868152600a602090815260408083208584528252808320815180830190925280548083526001909101549282019290925291906107e2908a9061191a565b506001600160a01b038a1660009081526005602090815260408083208c8452909152902054909150670de0b6b3a76400009061081f908390611b3b565b6108288b61145b565b6108329190612635565b83602001516108419190612664565b61084b9190612683565b610855908461264c565b96505050505050505b92915050565b61086e8282611b52565b6001600160a01b03909316600090815260036020908152604080832060029092529091209390935590915550565b6001600160a01b03811660009081526001602052604081205461085e904290611cb5565b61086e82826000611cc4565b600d546000908082036108e25750600092915050565b82600c60006108f2600185612635565b8152602001908152602001600020600001541161091b57610914600182612635565b9392505050565b60008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8548310156109565750600092915050565b600080610964600184612635565b90505b818111156109f8576000600261097d8484612635565b6109879190612683565b6109919083612635565b6000818152600c60209081526040918290208251808401909352805480845260019091015491830191909152919250908790036109d2575095945050505050565b80518711156109e3578193506109f1565b6109ee600183612635565b92505b5050610967565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8491906126be565b6001600160a01b0316336001600160a01b031614610ad55760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b031660068481548110610af257610af26126db565b6000918252602090912001546001600160a01b031614610b1157600080fd5b6001600160a01b03808316600090815260076020526040808220805460ff1990811690915592841682529020805490911660011790556006805482919085908110610b5e57610b5e6126db565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b0381166000908152600160205260408120544210610bb857506000919050565b6001600160a01b038216600090815260016020526040812054610bdc904290612635565b6001600160a01b0384166000908152602081905260409020549091506109149082612664565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3757600080fd5b610c3f611eb4565b8160086000828254610c519190612635565b909155505060008181526009602052604081208054849290610c74908490612635565b9091555050600081815260096020526040902054610c93908290611f3c565b610c9b612015565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b6000828152600b6020526040812054808203610cfb57600091505061085e565b6000848152600a602052604081208491610d16600185612635565b81526020019081526020016000206000015411610d4057610d38600182612635565b91505061085e565b6000848152600a60209081526040808320838052909152902054831015610d6b57600091505061085e565b600080610d79600184612635565b90505b81811115610e175760006002610d928484612635565b610d9c9190612683565b610da69083612635565b6000888152600a60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610df15750935061085e92505050565b8051871115610e0257819350610e10565b610e0d600183612635565b92505b5050610d7c565b50949350505050565b601054600114610e2f57600080fd5b6002601055336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e6957600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef591906126be565b905060005b825181101561115a57610f2a838281518110610f1857610f186126db565b60200260200101516000196001611cc4565b60036000868581518110610f4057610f406126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000888781518110610f8057610f806126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610fdb848381518110610fcd57610fcd6126db565b602002602001015186610608565b90504260046000868581518110610ff457610ff46126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000208190555060036000858481518110611047576110476126db565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460056000868581518110611086576110866126db565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156110e1576110e18483815181106110d2576110d26126db565b602002602001015184836120b9565b8382815181106110f3576110f36126db565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161113f91815260200190565b60405180910390a35080611152816126a5565b915050610efa565b505060016010555050565b60105460011461117457600080fd5b60026010558061118357600080fd5b6001600160a01b03821660009081526007602052604090205460ff166111a857600080fd5b6001600160a01b03821660009081526020819052604081205490036111d3576111d3826000426121a8565b6111e1826000196001611cc4565b6001600160a01b038416600090815260036020908152604080832060028352818420949094559390925560019091522054421061124f5761122482333084612297565b61123162093a8082612683565b6001600160a01b0383166000908152602081905260409020556112e8565b6001600160a01b038216600090815260016020526040812054611273904290612635565b6001600160a01b0384166000908152602081905260408120549192509061129a9083612664565b90508083116112a857600080fd5b6112b484333086612297565b62093a806112c2828561264c565b6112cc9190612683565b6001600160a01b03851660009081526020819052604090205550505b6001600160a01b03821660009081526020819052604090205461130a57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137591906126f1565b905061138462093a8082612683565b6001600160a01b03841660009081526020819052604090205411156113eb5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610acc565b6113f862093a804261264c565b6001600160a01b0384166000818152600160205260409081902092909255905133907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906114499086815260200190565b60405180910390a35050600160105550565b600060085460000361148357506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b0383166000908152602081815260408083205460028352818420546001909352922054670de0b6b3a764000092916114c491611cb5565b6114cd8661089c565b6114d79190612635565b6114e19190612664565b6114eb9190612664565b6114f59190612683565b6001600160a01b03831660009081526003602052604090205461085e919061264c565b6006818154811061152857600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461157757600080fd5b61157f611eb4565b8160086000828254611591919061264c565b9091555050600081815260096020526040812080548492906115b490849061264c565b90915550506000818152600960205260409020546115d3908290611f3c565b6115db612015565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610ccf565b60105460011461162257600080fd5b600260105560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b6919061270a565b6116bf57600080fd5b60005b8151811015611910576116e0828281518110610f1857610f186126db565b600360008585815181106116f6576116f66126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060026000878781518110611736576117366126db565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000611791838381518110611783576117836126db565b602002602001015185610608565b905042600460008585815181106117aa576117aa6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550600360008484815181106117fd576117fd6126db565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546005600085858151811061183c5761183c6126db565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561189757611897838381518110611888576118886126db565b602002602001015133836120b9565b8282815181106118a9576118a96126db565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516118f591815260200190565b60405180910390a35080611908816126a5565b9150506116c2565b5050600160105550565b6001600160a01b0382166000908152600f60205260408120548190808203611949576000809250925050611b34565b6001600160a01b0385166000908152600e60205260408120859161196e600185612635565b81526020019081526020016000206000015411611a0b576001600160a01b0385166000908152600e60205260408120906119a9600184612635565b815260200190815260200160002060010154600e6000876001600160a01b03166001600160a01b0316815260200190815260200160002060006001846119ef9190612635565b8152602001908152602001600020600001549250925050611b34565b6001600160a01b0385166000908152600e60209081526040808320838052909152902054841015611a43576000809250925050611b34565b600080611a51600184612635565b90505b81811115611b035760006002611a6a8484612635565b611a749190612683565b611a7e9083612635565b6001600160a01b0389166000908152600e60209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611add57602081015190519096509450611b349350505050565b8051881115611aee57819350611afc565b611af9600183612635565b92505b5050611a54565b506001600160a01b0386166000908152600e6020908152604080832093835292905220600181015490549093509150505b9250929050565b600081831015611b4b5781610914565b5090919050565b6001600160a01b0382166000908152600260209081526040808320546003909252822054600d54839291908303611b8c5792509050611b34565b6001600160a01b0386166000908152602081905260408120549003611bb7579250429150611b349050565b6000611bc2836108cc565b90506000611bde6001600d54611bd89190612635565b88611cb5565b9050815b81811015611ca6576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611c93576000600c81611c2785600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611c728d8460000151866000015187602001518d61238f565b9092509050611c81828961264c565b9750611c8e8d89836121a8565b975050505b5080611c9e816126a5565b915050611be2565b50919792965091945050505050565b6000818310611b4b5781610914565b6001600160a01b0383166000908152600260209081526040808320546003909252822054600d54839291908303611cfe5792509050611eac565b6001600160a01b0387166000908152602081905260408120549003611d29579250429150611eac9050565b6000611d34836108cc565b90506000611d506001600d54611d4a9190612635565b89611cb5565b90508015611e2957815b611d65600183612635565b8111611e27576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611e14576000600c81611da885600161264c565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050600080611df38e8460000151866000015187602001518d61238f565b9092509050611e02828961264c565b9750611e0f8e89836121a8565b975050505b5080611e1f816126a5565b915050611d5a565b505b8615611ea3576000818152600c60209081526040918290208251808401909352805483526001015490820181905215611ea1576000611e828b611e6b8d61089c565b8451611e77908a611b3b565b85602001518a61238f565b509050611e8f818661264c565b9450611e9c8b86426121a8565b429550505b505b50909350909150505b935093915050565b60065460005b81811015611f3857600060068281548110611ed757611ed76126db565b6000918252602090912001546001600160a01b03169050611efc816000196001611cc4565b6001600160a01b039092166000908152600360209081526040808320600290925290912092909255905580611f30816126a5565b915050611eba565b5050565b6000828152600b602052604090205442908015801590611f8657506000848152600a602052604081208391611f72600185612635565b815260200190815260200160002060000154145b15611fbf576000848152600a602052604081208491611fa6600185612635565b815260208101919091526040016000206001015561200f565b60408051808201825283815260208082018681526000888152600a8352848120868252909252929020905181559051600191820155611fff90829061264c565b6000858152600b60205260409020555b50505050565b600d54428115801590612047575080600c6000612033600186612635565b815260200190815260200160002060000154145b1561207657600854600c600061205e600186612635565b81526020810191909152604001600020600101555050565b60408051808201825282815260085460208083019182526000868152600c909152929092209051815590516001918201556120b290839061264c565b600d555050565b6000836001600160a01b03163b116120d057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161212c919061272c565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150818015612198575080511580612198575080806020019051810190612198919061270a565b6121a157600080fd5b5050505050565b6001600160a01b0383166000908152600f6020526040902054801580159061220457506001600160a01b0384166000908152600e6020526040812083916121f0600185612635565b815260200190815260200160002060000154145b1561222e576001600160a01b0384166000908152600e602052604081208491611fa6600185612635565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e835284812086825290925292902090518155905160019182015561227890829061264c565b6001600160a01b0385166000908152600f602052604090205550505050565b6000846001600160a01b03163b116122ae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612312919061272c565b6000604051808303816000865af19150503d806000811461234f576040519150601f19603f3d011682016040523d82523d6000602084013e612354565b606091505b509150915081801561237e57508051158061237e57508080602001905181019061237e919061270a565b61238757600080fd5b505050505050565b600080600061239e8785611b3b565b6001600160a01b0389166000908152602081905260409020549091508590670de0b6b3a7640000906123f16123d38a89611b3b565b6001600160a01b038d16600090815260016020526040902054611cb5565b6001600160a01b038c16600090815260016020526040902054612415908690611cb5565b61241f9190612635565b6124299190612664565b6124339190612664565b61243d9190612683565b9890975095505050505050565b6001600160a01b038116811461245f57600080fd5b50565b803561246d8161244a565b919050565b6000806040838503121561248557600080fd5b82356124908161244a565b946020939093013593505050565b6000602082840312156124b057600080fd5b81356109148161244a565b600080604083850312156124ce57600080fd5b50508035926020909101359150565b6000602082840312156124ef57600080fd5b5035919050565b60008060006060848603121561250b57600080fd5b83359250602084013561251d8161244a565b9150604084013561252d8161244a565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561256157600080fd5b8235915060208084013567ffffffffffffffff8082111561258157600080fd5b818601915086601f83011261259557600080fd5b8135818111156125a7576125a7612538565b8060051b604051601f19603f830116810181811085821117156125cc576125cc612538565b6040529182528482019250838101850191898311156125ea57600080fd5b938501935b8285101561260f5761260085612462565b845293850193928501926125ef565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000828210156126475761264761261f565b500390565b6000821982111561265f5761265f61261f565b500190565b600081600019048311821515161561267e5761267e61261f565b500290565b6000826126a057634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016126b7576126b761261f565b5060010190565b6000602082840312156126d057600080fd5b81516109148161244a565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561270357600080fd5b5051919050565b60006020828403121561271c57600080fd5b8151801515811461091457600080fd5b6000825160005b8181101561274d5760208186018101518583015201612733565b8181111561275c576000828501525b50919091019291505056fea26469706673582212205fdc0cbedbaeaa0ba11c8120c027b2bca65c182779d5bf888b06502050a1f54a64736f6c634300080d003360c06040526001600b553480156200001657600080fd5b5060405162001e8338038062001e838339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611ae86200039b600039600081816102d90152818161089b01528181610cda015261125c0152600081816101da01528181610a6e01528181610c9701528181610ed5015261116f0152611ae86000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639cc7f708116100de578063e688639611610097578063f301af4211610071578063f301af4214610416578063f320772314610429578063f5f8d3651461043c578063f7412baf1461044f57600080fd5b8063e6886396146103da578063e8111a12146103e2578063f25e55a5146103eb57600080fd5b80639cc7f7081461034e5780639e2bf22c1461036e578063a28d4c9c14610381578063a7852afa14610394578063b66503cf146103a7578063da09d19d146103ba57600080fd5b8063505897931161014b5780638dd598fb116101255780638dd598fb146102d457806392777b29146102fb5780639418f9391461032657806399bcc0521461033b57600080fd5b8063505897931461028e578063638634ee146102ae57806376f4be36146102c157600080fd5b80630175e23b1461019357806318160ddd146101b95780633e491d47146101c257806346c96aac146101d557806349dcc204146102145780634d5ce0381461025b575b600080fd5b6101a66101a1366004611792565b610476565b6040519081526020015b60405180910390f35b6101a660005481565b6101a66101d03660046117d3565b6104b8565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b0565b6102466102223660046117ff565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101b0565b61027e610269366004611821565b60066020526000908152604090205460ff1681565b60405190151581526020016101b0565b6101a661029c366004611792565b60086020526000908152604090205481565b6101a66102bc366004611821565b610741565b6101a66102cf366004611792565b610765565b6101fc7f000000000000000000000000000000000000000000000000000000000000000081565b6101a66103093660046117d3565b600260209081526000928352604080842090915290825290205481565b61033961033436600461183e565b610899565b005b6101a6610349366004611821565b610a2a565b6101a661035c366004611792565b60016020526000908152604090205481565b61033961037c3660046117ff565b610a63565b6101a661038f3660046117ff565b610b33565b6103396103a2366004611896565b610c78565b6103396103b53660046117d3565b610e78565b6101a66103c8366004611821565b60036020526000908152604090205481565b6005546101a6565b6101a6600a5481565b6101a66103f93660046117d3565b600460209081526000928352604080842090915290825290205481565b6101fc610424366004611792565b61113a565b6103396104373660046117ff565b611164565b61033961044a366004611896565b61122c565b61024661045d366004611792565b6009602052600090815260409020805460019091015482565b60008061048283611400565b9050600061049362093a808361197d565b90508084106104ae576104a98262093a8061197d565b6104b0565b815b949350505050565b6001600160a01b0382166000908152600460209081526040808320848452825280832054600890925282205482036104f457600091505061073b565b60006105008483610b33565b6000858152600860205260408120549192509061051f90600190611995565b90506000610540604051806040016040528060008152602001600081525090565b61054985611400565b81526001831561065a57845b610560600186611995565b81116106585760008981526007602090815260408083208484528252808320815180830190925280548083526001909101549282019290925291906105a490611400565b85519091508111156105c25760208501516105bf908761197d565b95505b808552600960006105d96102cf62093a808561197d565b815260200190815260200160002060010154935083600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054836020015161063491906119ac565b61063e91906119e1565b602086015250819050610650816119f5565b915050610555565b505b600088815260076020908152604080832087845282528083208151808301909252805480835260019091015492820192909252919061069890611400565b905060006106a962093a808361197d565b90508042111561072f57600960006106c083610765565b815260200190815260200160002060010154600260008e6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002054846020015161071891906119ac565b61072291906119e1565b61072c908761197d565b95505b50939750505050505050505b92915050565b6001600160a01b03811660009081526003602052604081205461073b904290611419565b600a5460009080820361077b5750600092915050565b826009600061078b600185611995565b815260200190815260200160002060000154116107b4576107ad600182611995565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b548310156107ef5750600092915050565b6000806107fd600184611995565b90505b8181111561089157600060026108168484611995565b61082091906119e1565b61082a9083611995565b60008181526009602090815260409182902082518084019093528054808452600190910154918301919091529192509087900361086b575095945050505050565b805187111561087c5781935061088a565b610887600183611995565b92505b5050610800565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156108f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190611a0e565b6001600160a01b0316336001600160a01b03161461096e5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b03166005848154811061098b5761098b611a2b565b6000918252602090912001546001600160a01b0316146109aa57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff19908116909155928416825290208054909116600117905560058054829190859081106109f7576109f7611a2b565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a3642610476565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a9857600080fd5b81600080828254610aa99190611995565b909155505060008181526001602052604081208054849290610acc908490611995565b9091555050600081815260016020526040902054610aeb90829061142f565b610af3611508565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610b5357600091505061073b565b60008481526007602052604081208491610b6e600185611995565b81526020019081526020016000206000015411610b9857610b90600182611995565b91505061073b565b6000848152600760209081526040808320838052909152902054831015610bc357600091505061073b565b600080610bd1600184611995565b90505b81811115610c6f5760006002610bea8484611995565b610bf491906119e1565b610bfe9083611995565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610c495750935061073b92505050565b8051871115610c5a57819350610c68565b610c65600183611995565b92505b5050610bd4565b50949350505050565b600b54600114610c8757600080fd5b6002600b55336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc157600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190611a0e565b905060005b8251811015610e6d576000610d80848381518110610d7257610d72611a2b565b6020026020010151866104b8565b90504260046000868581518110610d9957610d99611a2b565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610df457610df4848381518110610de557610de5611a2b565b602002602001015184836115ab565b838281518110610e0657610e06611a2b565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610e5291815260200190565b60405180910390a35080610e65816119f5565b915050610d52565b50506001600b555050565b600b54600114610e8757600080fd5b6002600b5580610e9657600080fd5b6001600160a01b03821660009081526006602052604090205460ff16610fde57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611a41565b610f8c5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c69737465646044820152606401610965565b600554601011610fde5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e730000000000000000006044820152606401610965565b6000610fe942610476565b6001600160a01b038416600090815260026020908152604080832084845290915290205490915061101c8433308661169a565b611026838261197d565b6001600160a01b038516600090815260026020908152604080832086845290915290205561105762093a808361197d565b6001600160a01b03851660009081526003602090815260408083209390935560069052205460ff166110e9576001600160a01b0384166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b555050565b6005818154811061114a57600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461119957600080fd5b816000808282546111aa919061197d565b9091555050600081815260016020526040812080548492906111cd90849061197d565b90915550506000818152600160205260409020546111ec90829061142f565b6111f4611508565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610b27565b600b5460011461123b57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cf9190611a41565b6112d857600080fd5b60005b81518110156113f65760006113098383815181106112fb576112fb611a2b565b6020026020010151856104b8565b9050426004600085858151811061132257611322611a2b565b6020908102919091018101516001600160a01b031682528181019290925260409081016000908120888252909252902055801561137d5761137d83838151811061136e5761136e611a2b565b602002602001015133836115ab565b82828151811061138f5761138f611a2b565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516113db91815260200190565b60405180910390a350806113ee816119f5565b9150506112db565b50506001600b5550565b600061140f62093a8083611a63565b61073b9083611995565b600081831061142857816107ad565b5090919050565b60008281526008602052604090205442908015801590611479575060008481526007602052604081208391611465600185611995565b815260200190815260200160002060000154145b156114b25760008481526007602052604081208491611499600185611995565b8152602081019190915260400160002060010155611502565b60408051808201825283815260208082018681526000888152600783528481208682529092529290209051815590516001918201556114f290829061197d565b6000858152600860205260409020555b50505050565b600a5442811580159061153a57508060096000611526600186611995565b815260200190815260200160002060000154145b1561156b57600054600960006001856115539190611995565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556115a490839061197d565b600a555050565b6000836001600160a01b03163b116115c257600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161161e9190611a77565b6000604051808303816000865af19150503d806000811461165b576040519150601f19603f3d011682016040523d82523d6000602084013e611660565b606091505b509150915081801561168a57508051158061168a57508080602001905181019061168a9190611a41565b61169357600080fd5b5050505050565b6000846001600160a01b03163b116116b157600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916117159190611a77565b6000604051808303816000865af19150503d8060008114611752576040519150601f19603f3d011682016040523d82523d6000602084013e611757565b606091505b50915091508180156117815750805115806117815750808060200190518101906117819190611a41565b61178a57600080fd5b505050505050565b6000602082840312156117a457600080fd5b5035919050565b6001600160a01b03811681146117c057600080fd5b50565b80356117ce816117ab565b919050565b600080604083850312156117e657600080fd5b82356117f1816117ab565b946020939093013593505050565b6000806040838503121561181257600080fd5b50508035926020909101359150565b60006020828403121561183357600080fd5b81356107ad816117ab565b60008060006060848603121561185357600080fd5b833592506020840135611865816117ab565b91506040840135611875816117ab565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156118a957600080fd5b8235915060208084013567ffffffffffffffff808211156118c957600080fd5b818601915086601f8301126118dd57600080fd5b8135818111156118ef576118ef611880565b8060051b604051601f19603f8301168101818110858211171561191457611914611880565b60405291825284820192508381018501918983111561193257600080fd5b938501935b8285101561195757611948856117c3565b84529385019392850192611937565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561199057611990611967565b500190565b6000828210156119a7576119a7611967565b500390565b60008160001904831182151516156119c6576119c6611967565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826119f0576119f06119cb565b500490565b600060018201611a0757611a07611967565b5060010190565b600060208284031215611a2057600080fd5b81516107ad816117ab565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a5357600080fd5b815180151581146107ad57600080fd5b600082611a7257611a726119cb565b500690565b6000825160005b81811015611a985760208186018101518583015201611a7e565b81811115611aa7576000828501525b50919091019291505056fea2646970667358221220d5f0eaed47ec9cb0f7332a517560bcb420138d14d674caf3674831366bf225f464736f6c634300080d0033a264697066735822122050c7efc34434eca9041cf3c63b65797031e5608706da7fccb31aad9274a6c62c64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 21321, + "contract": "contracts/factories/BribeFactory.sol:BribeFactory", + "label": "last_internal_bribe", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 21323, + "contract": "contracts/factories/BribeFactory.sol:BribeFactory", + "label": "last_external_bribe", + "offset": 0, + "slot": "1", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumOneOLD/GaugeFactory.json b/deployments/arbitrumOneOLD/GaugeFactory.json new file mode 100644 index 00000000..06d3737d --- /dev/null +++ b/deployments/arbitrumOneOLD/GaugeFactory.json @@ -0,0 +1,113 @@ +{ + "address": "0x2CCb061AD1b50211cF79f33e690452497941a2fe", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_pool", + "type": "address" + }, + { + "internalType": "address", + "name": "_internal_bribe", + "type": "address" + }, + { + "internalType": "address", + "name": "_external_bribe", + "type": "address" + }, + { + "internalType": "address", + "name": "_ve", + "type": "address" + }, + { + "internalType": "bool", + "name": "isPair", + "type": "bool" + }, + { + "internalType": "address[]", + "name": "allowedRewards", + "type": "address[]" + } + ], + "name": "createGauge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "last_gauge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x7ce753e4c58de4050464cc91803d46e3f6e11979f35747b219de8ced642739a6", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x2CCb061AD1b50211cF79f33e690452497941a2fe", + "transactionIndex": 2, + "gasUsed": "22465566", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x8411daf7bf6b95ca73cd5501cf340f0ad5b197b0b98168e0e20a0bf9a5405d66", + "transactionHash": "0x7ce753e4c58de4050464cc91803d46e3f6e11979f35747b219de8ced642739a6", + "logs": [], + "blockNumber": 53774021, + "cumulativeGasUsed": "23230219", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_internal_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_external_bribe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_ve\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isPair\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"allowedRewards\",\"type\":\"address[]\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_gauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/GaugeFactory.sol\":\"GaugeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Gauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens\\ncontract Gauge is IGauge {\\n address public immutable stake; // the LP token that needs to be staked for rewards\\n address public immutable _ve; // the ve token used for gauges\\n address public immutable internal_bribe;\\n address public immutable external_bribe;\\n address public immutable voter;\\n\\n uint256 public derivedSupply;\\n mapping(address => uint256) public derivedBalances;\\n\\n bool public isForPair;\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over 7 days\\n uint256 internal constant PRECISION = 10**18;\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n // default snx staking contract implementation\\n mapping(address => uint256) public rewardRate;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => uint256) public lastUpdateTime;\\n mapping(address => uint256) public rewardPerTokenStored;\\n\\n mapping(address => mapping(address => uint256)) public lastEarn;\\n mapping(address => mapping(address => uint256))\\n public userRewardPerTokenStored;\\n\\n mapping(address => uint256) public tokenIds;\\n\\n uint256 public totalSupply;\\n mapping(address => uint256) public balanceOf;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking reward rate\\n struct RewardPerTokenCheckpoint {\\n uint256 timestamp;\\n uint256 rewardPerToken;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))\\n public rewardPerTokenCheckpoints;\\n /// @notice The number of checkpoints for each token\\n mapping(address => uint256) public rewardPerTokenNumCheckpoints;\\n\\n uint256 public fees0;\\n uint256 public fees1;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(\\n address _stake,\\n address _internal_bribe,\\n address _external_bribe,\\n address __ve,\\n address _voter,\\n bool _forPair,\\n address[] memory _allowedRewardTokens\\n ) {\\n stake = _stake;\\n internal_bribe = _internal_bribe;\\n external_bribe = _external_bribe;\\n _ve = __ve;\\n voter = _voter;\\n isForPair = _forPair;\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function claimFees()\\n external\\n lock\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n return _claimFees();\\n }\\n\\n function _claimFees()\\n internal\\n returns (uint256 claimed0, uint256 claimed1)\\n {\\n if (!isForPair) {\\n return (0, 0);\\n }\\n (claimed0, claimed1) = IPair(stake).claimFees();\\n if (claimed0 > 0 || claimed1 > 0) {\\n uint256 _fees0 = fees0 + claimed0;\\n uint256 _fees1 = fees1 + claimed1;\\n (address _token0, address _token1) = IPair(stake).tokens();\\n if (\\n _fees0 > IBribe(internal_bribe).left(_token0) &&\\n _fees0 / DURATION > 0\\n ) {\\n fees0 = 0;\\n _safeApprove(_token0, internal_bribe, _fees0);\\n IBribe(internal_bribe).notifyRewardAmount(_token0, _fees0);\\n } else {\\n fees0 = _fees0;\\n }\\n if (\\n _fees1 > IBribe(internal_bribe).left(_token1) &&\\n _fees1 / DURATION > 0\\n ) {\\n fees1 = 0;\\n _safeApprove(_token1, internal_bribe, _fees1);\\n IBribe(internal_bribe).notifyRewardAmount(_token1, _fees1);\\n } else {\\n fees1 = _fees1;\\n }\\n\\n emit ClaimFees(msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(address account, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorRewardPerToken(address token, uint256 timestamp)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];\\n if (nCheckpoints == 0) {\\n return (0, 0);\\n }\\n\\n // First check most recent balance\\n if (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=\\n timestamp\\n ) {\\n return (\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1]\\n .rewardPerToken,\\n rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp\\n );\\n }\\n\\n // Next check implicit zero balance\\n if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {\\n return (0, 0);\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[\\n token\\n ][center];\\n if (cp.timestamp == timestamp) {\\n return (cp.rewardPerToken, cp.timestamp);\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return (\\n rewardPerTokenCheckpoints[token][lower].rewardPerToken,\\n rewardPerTokenCheckpoints[token][lower].timestamp\\n );\\n }\\n\\n function _writeCheckpoint(address account, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[account][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[account][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[account] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeRewardPerTokenCheckpoint(\\n address token,\\n uint256 reward,\\n uint256 timestamp\\n ) internal {\\n uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];\\n\\n if (\\n _nCheckPoints > 0 &&\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==\\n timestamp\\n ) {\\n rewardPerTokenCheckpoints[token][_nCheckPoints - 1]\\n .rewardPerToken = reward;\\n } else {\\n rewardPerTokenCheckpoints[token][\\n _nCheckPoints\\n ] = RewardPerTokenCheckpoint(timestamp, reward);\\n rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = derivedSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n derivedSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n function getReward(address account, address[] memory tokens) external lock {\\n require(msg.sender == account || msg.sender == voter);\\n _unlocked = 1;\\n IVoter(voter).distribute(address(this));\\n _unlocked = 2;\\n\\n for (uint256 i = 0; i < tokens.length; i++) {\\n (\\n rewardPerTokenStored[tokens[i]],\\n lastUpdateTime[tokens[i]]\\n ) = _updateRewardPerToken(tokens[i], type(uint256).max, true);\\n\\n uint256 _reward = earned(tokens[i], account);\\n lastEarn[tokens[i]][account] = block.timestamp;\\n userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[\\n tokens[i]\\n ];\\n if (_reward > 0) _safeTransfer(tokens[i], account, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n\\n uint256 _derivedBalance = derivedBalances[account];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(account);\\n derivedBalances[account] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(account, derivedBalances[account]);\\n _writeSupplyCheckpoint();\\n }\\n\\n function rewardPerToken(address token) public view returns (uint256) {\\n if (derivedSupply == 0) {\\n return rewardPerTokenStored[token];\\n }\\n return\\n rewardPerTokenStored[token] +\\n (((lastTimeRewardApplicable(token) -\\n MathDunks.min(lastUpdateTime[token], periodFinish[token])) *\\n rewardRate[token] *\\n PRECISION) / derivedSupply);\\n }\\n\\n function derivedBalance(address account) public view returns (uint256) {\\n return balanceOf[account];\\n }\\n\\n function batchRewardPerToken(address token, uint256 maxRuns) external {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _batchRewardPerToken(token, maxRuns);\\n }\\n\\n function _batchRewardPerToken(address token, uint256 maxRuns)\\n internal\\n returns (uint256, uint256)\\n {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n for (uint256 i = _startIndex; i < _endIndex; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n function _calcRewardPerToken(\\n address token,\\n uint256 timestamp1,\\n uint256 timestamp0,\\n uint256 supply,\\n uint256 startTimestamp\\n ) internal view returns (uint256, uint256) {\\n uint256 endTime = MathDunks.max(timestamp1, startTimestamp);\\n return (\\n (((MathDunks.min(endTime, periodFinish[token]) -\\n MathDunks.min(\\n MathDunks.max(timestamp0, startTimestamp),\\n periodFinish[token]\\n )) *\\n rewardRate[token] *\\n PRECISION) / supply),\\n endTime\\n );\\n }\\n\\n /// @dev Update stored rewardPerToken values without the last one snapshot\\n /// If the contract will get \\\"out of gas\\\" error on users actions this will be helpful\\n function batchUpdateRewardPerToken(address token, uint256 maxRuns)\\n external\\n {\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, maxRuns, false);\\n }\\n\\n function _updateRewardForAllTokens() internal {\\n uint256 length = rewards.length;\\n for (uint256 i; i < length; i++) {\\n address token = rewards[i];\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n }\\n }\\n\\n function _updateRewardPerToken(\\n address token,\\n uint256 maxRuns,\\n bool actualLast\\n ) internal returns (uint256, uint256) {\\n uint256 _startTimestamp = lastUpdateTime[token];\\n uint256 reward = rewardPerTokenStored[token];\\n\\n if (supplyNumCheckpoints == 0) {\\n return (reward, _startTimestamp);\\n }\\n\\n if (rewardRate[token] == 0) {\\n return (reward, block.timestamp);\\n }\\n\\n uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);\\n uint256 _endIndex = MathDunks.min(supplyNumCheckpoints - 1, maxRuns);\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n SupplyCheckpoint memory sp0 = supplyCheckpoints[i];\\n if (sp0.supply > 0) {\\n SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];\\n (uint256 _reward, uint256 _endTime) = _calcRewardPerToken(\\n token,\\n sp1.timestamp,\\n sp0.timestamp,\\n sp0.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, _endTime);\\n _startTimestamp = _endTime;\\n }\\n }\\n }\\n\\n // need to override the last value with actual numbers only on deposit/withdraw/claim/notify actions\\n if (actualLast) {\\n SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];\\n if (sp.supply > 0) {\\n (uint256 _reward, ) = _calcRewardPerToken(\\n token,\\n lastTimeRewardApplicable(token),\\n MathDunks.max(sp.timestamp, _startTimestamp),\\n sp.supply,\\n _startTimestamp\\n );\\n reward += _reward;\\n _writeRewardPerTokenCheckpoint(token, reward, block.timestamp);\\n _startTimestamp = block.timestamp;\\n }\\n }\\n\\n return (reward, _startTimestamp);\\n }\\n\\n // earned is an estimation, it won't be exact till the supply > rewardPerToken calculations have run\\n function earned(address token, address account)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = MathDunks.max(\\n lastEarn[token][account],\\n rewardPerTokenCheckpoints[token][0].timestamp\\n );\\n if (numCheckpoints[account] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(account, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[account] - 1;\\n\\n uint256 reward = 0;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[account][i];\\n Checkpoint memory cp1 = checkpoints[account][i + 1];\\n (uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(\\n token,\\n cp0.timestamp\\n );\\n (uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(\\n token,\\n cp1.timestamp\\n );\\n reward +=\\n (cp0.balanceOf *\\n (_rewardPerTokenStored1 - _rewardPerTokenStored0)) /\\n PRECISION;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[account][_endIndex];\\n (uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(\\n token,\\n cp.timestamp\\n );\\n reward +=\\n (cp.balanceOf *\\n (rewardPerToken(token) -\\n MathDunks.max(\\n _rewardPerTokenStored,\\n userRewardPerTokenStored[token][account]\\n ))) /\\n PRECISION;\\n\\n return reward;\\n }\\n\\n function depositAll(uint256 tokenId) external {\\n deposit(IERC20(stake).balanceOf(msg.sender), tokenId);\\n }\\n\\n function deposit(uint256 amount, uint256 tokenId) public lock {\\n require(amount > 0);\\n _updateRewardForAllTokens();\\n\\n _safeTransferFrom(stake, msg.sender, address(this), amount);\\n totalSupply += amount;\\n balanceOf[msg.sender] += amount;\\n\\n if (tokenId > 0) {\\n require(IVotingEscrow(_ve).ownerOf(tokenId) == msg.sender);\\n if (tokenIds[msg.sender] == 0) {\\n tokenIds[msg.sender] = tokenId;\\n IVoter(voter).attachTokenToGauge(tokenId, msg.sender);\\n }\\n require(tokenIds[msg.sender] == tokenId);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, _derivedBalance);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitDeposit(tokenId, msg.sender, amount);\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function withdrawAll() external {\\n withdraw(balanceOf[msg.sender]);\\n }\\n\\n function withdraw(uint256 amount) public {\\n uint256 tokenId = 0;\\n if (amount == balanceOf[msg.sender]) {\\n tokenId = tokenIds[msg.sender];\\n }\\n withdrawToken(amount, tokenId);\\n }\\n\\n function withdrawToken(uint256 amount, uint256 tokenId) public lock {\\n _updateRewardForAllTokens();\\n\\n totalSupply -= amount;\\n balanceOf[msg.sender] -= amount;\\n _safeTransfer(stake, msg.sender, amount);\\n\\n if (tokenId > 0) {\\n require(tokenId == tokenIds[msg.sender]);\\n tokenIds[msg.sender] = 0;\\n IVoter(voter).detachTokenFromGauge(tokenId, msg.sender);\\n } else {\\n tokenId = tokenIds[msg.sender];\\n }\\n\\n uint256 _derivedBalance = derivedBalances[msg.sender];\\n derivedSupply -= _derivedBalance;\\n _derivedBalance = derivedBalance(msg.sender);\\n derivedBalances[msg.sender] = _derivedBalance;\\n derivedSupply += _derivedBalance;\\n\\n _writeCheckpoint(msg.sender, derivedBalances[msg.sender]);\\n _writeSupplyCheckpoint();\\n\\n IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n if (block.timestamp >= periodFinish[token]) return 0;\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n return _remaining * rewardRate[token];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(token != stake);\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"rewards tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n if (rewardRate[token] == 0)\\n _writeRewardPerTokenCheckpoint(token, 0, block.timestamp);\\n (\\n rewardPerTokenStored[token],\\n lastUpdateTime[token]\\n ) = _updateRewardPerToken(token, type(uint256).max, true);\\n _claimFees();\\n\\n if (block.timestamp >= periodFinish[token]) {\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = amount / DURATION;\\n } else {\\n uint256 _remaining = periodFinish[token] - block.timestamp;\\n uint256 _left = _remaining * rewardRate[token];\\n require(amount > _left);\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n rewardRate[token] = (amount + _left) / DURATION;\\n }\\n require(rewardRate[token] > 0);\\n uint256 balance = IERC20(token).balanceOf(address(this));\\n require(\\n rewardRate[token] <= balance / DURATION,\\n \\\"Provided reward too high\\\"\\n );\\n periodFinish[token] = block.timestamp + DURATION;\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeApprove(\\n address token,\\n address spender,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.approve.selector, spender, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x38cc0284dd60d8a1418d9c34e6be84911ca4a1b479dc129f19b9027e4c670e1f\",\"license\":\"MIT\"},\"contracts/factories/GaugeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/Gauge.sol';\\n\\ncontract GaugeFactory is IGaugeFactory {\\n address public last_gauge;\\n\\n function createGauge(address _pool, address _internal_bribe, address _external_bribe, address _ve, bool isPair, address[] memory allowedRewards) external returns (address) {\\n last_gauge = address(new Gauge(_pool, _internal_bribe, _external_bribe, _ve, msg.sender, isPair, allowedRewards));\\n return last_gauge;\\n }\\n}\\n\",\"keccak256\":\"0x34f6ac4bdace9ef01d8cffda9b45842efae88b519230c67759b9936aee6acc9b\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50613b19806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea2646970667358221220656ccf09ce656ea8ebfb044a59e62cffea98cb78d8b1c3228ccdcceab4e0aee364736f6c634300080d0033a2646970667358221220b102ed748ff42223948c2bba31684751618fee0a65b5917ca364d53fe7ff82cd64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80630bc25f4f1461003b578063730a8bdb1461006a575b600080fd5b61004e610049366004610128565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b600086868686338787604051610092906100e9565b6100a29796959493929190610248565b604051809103906000f0801580156100be573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169182179055979650505050505050565b613813806102d183390190565b80356001600160a01b038116811461010d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c0878903121561014157600080fd5b61014a876100f6565b955060206101598189016100f6565b9550610167604089016100f6565b9450610175606089016100f6565b93506080880135801515811461018a57600080fd5b925060a088013567ffffffffffffffff808211156101a757600080fd5b818a0191508a601f8301126101bb57600080fd5b8135818111156101cd576101cd610112565b8060051b604051601f19603f830116810181811085821117156101f2576101f2610112565b60405291825284820192508381018501918d83111561021057600080fd5b938501935b8285101561023557610226856100f6565b84529385019392850192610215565b8096505050505050509295509295509295565b600060e0820160018060a01b03808b1684526020818b1681860152818a1660408601528189166060860152818816608086015286151560a086015260e060c086015282865180855261010087019150828801945060005b818110156102bd57855185168352948301949183019160010161029f565b50909d9c5050505050505050505050505056fe61012060405260016016553480156200001757600080fd5b5060405162003813380380620038138339810160408190526200003a91620001b5565b6001600160a01b0387811660805286811660c05285811660e05284811660a0528316610100526002805460ff191683151517905560005b8151811015620001745760006001600160a01b03168282815181106200009b576200009b62000300565b60200260200101516001600160a01b0316146200015f576001600d6000848481518110620000cd57620000cd62000300565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c82828151811062000123576200012362000300565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b806200016b8162000316565b91505062000071565b50505050505050506200033e565b80516001600160a01b03811681146200019a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060e0888a031215620001d157600080fd5b620001dc8862000182565b96506020620001ed818a0162000182565b9650620001fd60408a0162000182565b95506200020d60608a0162000182565b94506200021d60808a0162000182565b935060a089015180151581146200023357600080fd5b60c08a01519093506001600160401b03808211156200025157600080fd5b818b0191508b601f8301126200026657600080fd5b8151818111156200027b576200027b6200019f565b8060051b604051601f19603f83011681018181108582111715620002a357620002a36200019f565b60405291825284820192508381018501918e831115620002c257600080fd5b938501935b82851015620002eb57620002db8562000182565b84529385019392850192620002c7565b80965050505050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033757634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e051610100516133fd620004166000396000818161045301528181610beb01528181610c300152818161140b01528181611aa501528181611bc9015281816120590152612170015260006102eb01526000818161056201528181612aa401528181612b3b01528181612b8601528181612c0c01528181612ca10152612cec0152600081816105910152818161117301526119d9015260008181610401015281816113910152818161187e0152818161195101528181611fda0152818161293c01526129fe01526133fd6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063853828b611610167578063d7da4bb0116100ce578063f122977711610087578063f1229777146106fe578063f301af4214610711578063f7412baf14610724578063fc97a3031461074b578063fd3140981461076b578063fdb483c71461077e57600080fd5b8063d7da4bb0146106a4578063da09d19d146106ad578063e2bbb158146106cd578063e5748213146106e0578063e6886396146106ed578063e8111a12146106f557600080fd5b8063a495e5b511610120578063a495e5b514610602578063aa4796521461062d578063b66503cf1461064d578063c6f678bd14610660578063d294f09314610673578063d35e25441461067b57600080fd5b8063853828b6146105845780638dd598fb1461058c57806393f1c442146105b35780639418f939146105bc57806399bcc052146105cf5780639ce43f90146105e257600080fd5b80633ca068b61161020b57806363fb415b116101c457806363fb415b146104d757806368fcee1a146104f75780636fcfff451461050a57806370a082311461052a57806376f4be361461054a578063770f85711461055d57600080fd5b80633ca068b61461042357806346c96aac1461044e5780634c02a21c146104755780634d5ce0381461047e5780635a45d052146104b1578063638634ee146104c457600080fd5b8063211dc32d1161025d578063211dc32d14610381578063221ca18c146103945780632ce9aead146103b45780632e1a7d4d146103d457806331279d3d146103e95780633a4b66f1146103fc57600080fd5b806301316ddf1461029a57806303fbf83a146102e65780630cdfebfa14610325578063115c6f391461035757806318160ddd14610378575b600080fd5b6102cc6102a836600461303d565b60126020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dd565b6102cc61033336600461303d565b600e6020908152600092835260408084209091529082529020805460019091015482565b61036a61036536600461303d565b610791565b6040519081526020016102dd565b61036a600a5481565b61036a61038f366004613069565b610900565b61036a6103a23660046130a2565b60036020526000908152604090205481565b61036a6103c23660046130a2565b60056020526000908152604090205481565b6103e76103e23660046130bf565b610b84565b005b6103e76103f73660046130ee565b610bba565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610431366004613069565b600860209081526000928352604080842090915290825290205481565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60155481565b6104a161048c3660046130a2565b600d6020526000908152604090205460ff1681565b60405190151581526020016102dd565b6103e76104bf36600461303d565b610fba565b61036a6104d23660046130a2565b610ff2565b61036a6104e53660046130a2565b60016020526000908152604090205481565b6103e761050536600461303d565b611016565b61036a6105183660046130a2565b600f6020526000908152604090205481565b61036a6105383660046130a2565b600b6020526000908152604090205481565b61036a6105583660046130bf565b611022565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b6103e7611156565b61030d7f000000000000000000000000000000000000000000000000000000000000000081565b61036a60145481565b6103e76105ca3660046131c8565b611171565b61036a6105dd3660046130a2565b611302565b61036a6105f03660046130a2565b60066020526000908152604090205481565b61036a610610366004613069565b600760209081526000928352604080842090915290825290205481565b61036a61063b3660046130a2565b60136020526000908152604090205481565b6103e761065b36600461303d565b611373565b6103e761066e3660046130bf565b611865565b6102cc6118fa565b61036a6106893660046130a2565b6001600160a01b03166000908152600b602052604090205490565b61036a60005481565b61036a6106bb3660046130a2565b60046020526000908152604090205481565b6103e76106db36600461320a565b611926565b6002546104a19060ff1681565b600c5461036a565b61036a60115481565b61036a61070c3660046130a2565b611c73565b61030d61071f3660046130bf565b611d32565b6102cc6107323660046130bf565b6010602052600090815260409020805460019091015482565b61036a6107593660046130a2565b60096020526000908152604090205481565b6102cc61077936600461303d565b611d5c565b6103e761078c36600461320a565b611f7d565b6001600160a01b0382166000908152600f60205260408120548082036107bb5760009150506108fa565b6001600160a01b0384166000908152600e6020526040812084916107e0600185613242565b8152602001908152602001600020600001541161080a57610802600182613242565b9150506108fa565b6001600160a01b0384166000908152600e6020908152604080832083805290915290205483101561083f5760009150506108fa565b60008061084d600184613242565b90505b818111156108f557600060026108668484613242565b6108709190613259565b61087a9083613242565b6001600160a01b0388166000908152600e602090815260408083208484528252918290208251808401909352805480845260019091015491830191909152919250908790036108cf575093506108fa92505050565b80518711156108e0578193506108ee565b6108eb600183613242565b92505b5050610850565b509150505b92915050565b6001600160a01b0380831660008181526007602090815260408083209486168352938152838220549282526012815283822082805290529182205482916109469161220c565b6001600160a01b0384166000908152600f6020526040812054919250036109715760009150506108fa565b600061097d8483610791565b6001600160a01b0385166000908152600f6020526040812054919250906109a690600190613242565b905060008115610ab857825b6109bd600184613242565b8111610ab6576001600160a01b0387166000818152600e602081815260408084208685528083528185208251808401909352805483526001908101548385015295855292909152928290610a1290869061327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000610a518b8460000151611d5c565b5090506000610a648c8460000151611d5c565b509050670de0b6b3a7640000610a7a8383613242565b8560200151610a899190613293565b610a939190613259565b610a9d908761327b565b9550505050508080610aae906132b2565b9150506109b2565b505b6001600160a01b0386166000908152600e60209081526040808320858452825280832081518083019092528054808352600190910154928201929092529190610b02908a90611d5c565b506001600160a01b03808b166000908152600860209081526040808320938d1683529290522054909150670de0b6b3a764000090610b4190839061220c565b610b4a8b611c73565b610b549190613242565b8360200151610b639190613293565b610b6d9190613259565b610b77908461327b565b9998505050505050505050565b336000908152600b60205260408120548203610bac5750336000908152600960205260409020545b610bb68282611f7d565b5050565b601654600114610bc957600080fd5b6002601655336001600160a01b0383161480610c0d5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610c1657600080fd5b60016016556040516363453ae160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906363453ae190602401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050600260165550600090505b8151811015610f1357610ccd828281518110610cbb57610cbb6132cb565b60200260200101516000196001612223565b60066000858581518110610ce357610ce36132cb565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600060056000878781518110610d2357610d236132cb565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008491905055839190505550506000610d7e838381518110610d7057610d706132cb565b602002602001015185610900565b90504260076000858581518110610d9757610d976132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000208190555060066000848481518110610dfc57610dfc6132cb565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205460086000858581518110610e3b57610e3b6132cb565b6020908102919091018101516001600160a01b039081168352828201939093526040918201600090812093891681529290529020558015610e9a57610e9a838381518110610e8b57610e8b6132cb565b60200260200101518583612413565b828281518110610eac57610eac6132cb565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610ef891815260200190565b60405180910390a35080610f0b816132b2565b915050610c9d565b506001600160a01b0382166000908152600160205260408120548154909182918190610f40908490613242565b9091555050506001600160a01b0382166000908152600b6020908152604080832054600190925282208190558154909182918190610f7f90849061327b565b90915550506001600160a01b038316600090815260016020526040902054610fa8908490612513565b610fb061261e565b5050600160165550565b610fc482826126c1565b6001600160a01b03909316600090815260066020908152604080832060059092529091209390935590915550565b6001600160a01b0381166000908152600460205260408120546108fa904290612824565b610fc482826000612223565b6011546000908082036110385750600092915050565b8260106000611048600185613242565b815260200190815260200160002060000154116110715761106a600182613242565b9392505050565b6000805260106020527f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01548310156110ac5750600092915050565b6000806110ba600184613242565b90505b8181111561114e57600060026110d38484613242565b6110dd9190613259565b6110e79083613242565b600081815260106020908152604091829020825180840190935280548084526001909101549183019190915291925090879003611128575095945050505050565b805187111561113957819350611147565b611144600183613242565b92505b50506110bd565b509392505050565b336000908152600b602052604090205461116f90610b84565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af11580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906132e1565b6001600160a01b0316336001600160a01b0316146112465760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600c8481548110611263576112636132cb565b6000918252602090912001546001600160a01b03161461128257600080fd5b6001600160a01b038083166000908152600d6020526040808220805460ff199081169091559284168252902080549091166001179055600c8054829190859081106112cf576112cf6132cb565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6001600160a01b038116600090815260046020526040812054421061132957506000919050565b6001600160a01b03821660009081526004602052604081205461134d904290613242565b6001600160a01b03841660009081526003602052604090205490915061106a9082613293565b60165460011461138257600080fd5b60026016556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036113bf57600080fd5b600081116113cc57600080fd5b6001600160a01b0382166000908152600d602052604090205460ff1661151f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906132fe565b6114cd5760405162461bcd60e51b815260206004820152602260248201527f7265776172647320746f6b656e73206d7573742062652077686974656c697374604482015261195960f21b606482015260840161123d565b600c5460101161151f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e73000000000000000000604482015260640161123d565b6001600160a01b038216600090815260036020526040812054900361154a5761154a82600042612833565b611558826000196001612223565b6001600160a01b038416600090815260066020908152604080832060059092529091209190915555611588612922565b50506001600160a01b03821660009081526004602052604090205442106115e0576115b582333084612d97565b6115c262093a8082613259565b6001600160a01b038316600090815260036020526040902055611679565b6001600160a01b038216600090815260046020526040812054611604904290613242565b6001600160a01b0384166000908152600360205260408120549192509061162b9083613293565b905080831161163957600080fd5b61164584333086612d97565b62093a80611653828561327b565b61165d9190613259565b6001600160a01b03851660009081526003602052604090205550505b6001600160a01b03821660009081526003602052604090205461169b57600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117069190613320565b905061171562093a8082613259565b6001600160a01b038416600090815260036020526040902054111561177c5760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015260640161123d565b61178962093a804261327b565b6001600160a01b038416600090815260046020908152604080832093909355600d9052205460ff1661181b576001600160a01b0383166000818152600d60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b03191690911790555b6040518281526001600160a01b0384169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf508269060200160405180910390a35050600160165550565b6040516370a0823160e01b81523360048201526118f7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613320565b82611926565b50565b60008060165460011461190c57600080fd5b6002601655611919612922565b9150915060016016559091565b60165460011461193557600080fd5b60026016558161194457600080fd5b61194c612e8f565b6119787f0000000000000000000000000000000000000000000000000000000000000000333085612d97565b81600a600082825461198a919061327b565b9091555050336000908152600b6020526040812080548492906119ae90849061327b565b90915550508015611b22576040516331a9108f60e11b81526004810182905233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4491906132e1565b6001600160a01b031614611a5757600080fd5b336000908152600960205260408120549003611b025733600081815260096020526040908190208390555163698473e360e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063698473e390604401600060405180830381600087803b158015611ae957600080fd5b505af1158015611afd573d6000803e3d6000fd5b505050505b336000908152600960205260409020548114611b1d57600080fd5b611b34565b50336000908152600960205260409020545b336000908152600160205260408120548154909182918190611b57908490613242565b9091555050336000908152600b60209081526040808320546001909252822081905581549092508291908190611b8e90849061327b565b90915550611b9e90503382612513565b611ba661261e565b60405163530e389d60e11b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a61c713a90606401600060405180830381600087803b158015611c1557600080fd5b505af1158015611c29573d6000803e3d6000fd5b505060408051858152602081018790523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159250015b60405180910390a25050600160165550565b60008054600003611c9a57506001600160a01b031660009081526006602052604090205490565b600080546001600160a01b038416825260036020908152604080842054600583528185205460049093529320549192670de0b6b3a7640000929091611cde91612824565b611ce786610ff2565b611cf19190613242565b611cfb9190613293565b611d059190613293565b611d0f9190613259565b6001600160a01b0383166000908152600660205260409020546108fa919061327b565b600c8181548110611d4257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b0382166000908152601360205260408120548190808203611d8b576000809250925050611f76565b6001600160a01b03851660009081526012602052604081208591611db0600185613242565b81526020019081526020016000206000015411611e4d576001600160a01b038516600090815260126020526040812090611deb600184613242565b81526020019081526020016000206001015460126000876001600160a01b03166001600160a01b031681526020019081526020016000206000600184611e319190613242565b8152602001908152602001600020600001549250925050611f76565b6001600160a01b0385166000908152601260209081526040808320838052909152902054841015611e85576000809250925050611f76565b600080611e93600184613242565b90505b81811115611f455760006002611eac8484613242565b611eb69190613259565b611ec09083613242565b6001600160a01b0389166000908152601260209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090889003611f1f57602081015190519096509450611f769350505050565b8051881115611f3057819350611f3e565b611f3b600183613242565b92505b5050611e96565b506001600160a01b038616600090815260126020908152604080832093835292905220600181015490549093509150505b9250929050565b601654600114611f8c57600080fd5b6002601655611f99612e8f565b81600a6000828254611fab9190613242565b9091555050336000908152600b602052604081208054849290611fcf908490613242565b9091555061200090507f00000000000000000000000000000000000000000000000000000000000000003384612413565b80156120ba5733600090815260096020526040902054811461202157600080fd5b33600081815260096020526040808220919091555163411b1f7760e01b81526004810183905260248101919091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063411b1f7790604401600060405180830381600087803b15801561209d57600080fd5b505af11580156120b1573d6000803e3d6000fd5b505050506120cc565b50336000908152600960205260409020545b3360009081526001602052604081205481549091829181906120ef908490613242565b9091555050336000908152600b6020908152604080832054600190925282208190558154909250829190819061212690849061327b565b9091555050336000818152600160205260409020546121459190612513565b61214d61261e565b604051633aa53b9160e21b815260048101839052336024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea94ee4490606401600060405180830381600087803b1580156121bc57600080fd5b505af11580156121d0573d6000803e3d6000fd5b505060408051858152602081018790523393507ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568925001611c61565b60008183101561221c578161106a565b5090919050565b6001600160a01b038316600090815260056020908152604080832054600690925282205460115483929190830361225d579250905061240b565b6001600160a01b038716600090815260036020526040812054900361228857925042915061240b9050565b600061229383611022565b905060006122af60016011546122a99190613242565b89612824565b9050801561238857815b6122c4600183613242565b811161238657600081815260106020908152604091829020825180840190935280548352600101549082018190521561237357600060108161230785600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806123528e8460000151866000015187602001518d612f13565b9092509050612361828961327b565b975061236e8e8983612833565b975050505b508061237e816132b2565b9150506122b9565b505b86156124025760008181526010602090815260409182902082518084019093528054835260010154908201819052156124005760006123e18b6123ca8d610ff2565b84516123d6908a61220c565b85602001518a612f13565b5090506123ee818661327b565b94506123fb8b8642612833565b429550505b505b50909350909150505b935093915050565b6000836001600160a01b03163b1161242a57600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063a9059cbb60e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516124979190613339565b6000604051808303816000865af19150503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b509150915081801561250357508051158061250357508080602001905181019061250391906132fe565b61250c57600080fd5b5050505050565b6001600160a01b0382166000908152600f60205260409020544290801580159061257157506001600160a01b0384166000908152600e60205260408120839161255d600185613242565b815260200190815260200160002060000154145b156125b4576001600160a01b0384166000908152600e60205260408120849161259b600185613242565b8152602081019190915260400160002060010155612618565b60408051808201825283815260208082018681526001600160a01b0388166000908152600e83528481208682529092529290209051815590516001918201556125fe90829061327b565b6001600160a01b0385166000908152600f60205260409020555b50505050565b6011544281158015906126505750806010600061263c600186613242565b815260200190815260200160002060000154145b1561268157600054601060006001856126699190613242565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352601090529290209051815590516001918201556126ba90839061327b565b6011555050565b6001600160a01b03821660009081526005602090815260408083205460069092528220546011548392919083036126fb5792509050611f76565b6001600160a01b0386166000908152600360205260408120549003612726579250429150611f769050565b600061273183611022565b9050600061274d60016011546127479190613242565b88612824565b9050815b8181101561281557600081815260106020908152604091829020825180840190935280548352600101549082018190521561280257600060108161279685600161327b565b81526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506000806127e18d8460000151866000015187602001518d612f13565b90925090506127f0828961327b565b97506127fd8d8983612833565b975050505b508061280d816132b2565b915050612751565b50919792965091945050505050565b600081831061221c578161106a565b6001600160a01b038316600090815260136020526040902054801580159061288f57506001600160a01b0384166000908152601260205260408120839161287b600185613242565b815260200190815260200160002060000154145b156128b9576001600160a01b0384166000908152601260205260408120849161259b600185613242565b60408051808201825283815260208082018681526001600160a01b03881660009081526012835284812086825290925292902090518155905160019182015561290390829061327b565b6001600160a01b03851660009081526013602052604090205550505050565b600254600090819060ff1661293a5750600091829150565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bd9190613374565b9092509050811515806129d05750600081115b15612d93576000826014546129e5919061327b565b90506000826015546129f7919061327b565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190613398565b604051634cde602960e11b81526001600160a01b0380841660048301529294509092507f0000000000000000000000000000000000000000000000000000000000000000909116906399bcc05290602401602060405180830381865afa158015612aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b119190613320565b84118015612b2b57506000612b2962093a8086613259565b115b15612be7576000601455612b60827f000000000000000000000000000000000000000000000000000000000000000086612fce565b60405163b66503cf60e01b81526001600160a01b038381166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612bca57600080fd5b505af1158015612bde573d6000803e3d6000fd5b50505050612bed565b60148490555b604051634cde602960e11b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906399bcc05290602401602060405180830381865afa158015612c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c779190613320565b83118015612c9157506000612c8f62093a8085613259565b115b15612d4d576000601555612cc6817f000000000000000000000000000000000000000000000000000000000000000085612fce565b60405163b66503cf60e01b81526001600160a01b038281166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063b66503cf90604401600060405180830381600087803b158015612d3057600080fd5b505af1158015612d44573d6000803e3d6000fd5b50505050612d53565b60158390555b604080518781526020810187905233917fbc567d6cbad26368064baa0ab5a757be46aae4d70f707f9203d9d9b6c8ccbfa3910160405180910390a2505050505b9091565b6000846001600160a01b03163b11612dae57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612e129190613339565b6000604051808303816000865af19150503d8060008114612e4f576040519150601f19603f3d011682016040523d82523d6000602084013e612e54565b606091505b5091509150818015612e7e575080511580612e7e575080806020019051810190612e7e91906132fe565b612e8757600080fd5b505050505050565b600c5460005b81811015610bb6576000600c8281548110612eb257612eb26132cb565b6000918252602090912001546001600160a01b03169050612ed7816000196001612223565b6001600160a01b039092166000908152600660209081526040808320600590925290912092909255905580612f0b816132b2565b915050612e95565b6000806000612f22878561220c565b6001600160a01b0389166000908152600360205260409020549091508590670de0b6b3a764000090612f75612f578a8961220c565b6001600160a01b038d16600090815260046020526040902054612824565b6001600160a01b038c16600090815260046020526040902054612f99908690612824565b612fa39190613242565b612fad9190613293565b612fb79190613293565b612fc19190613259565b9890975095505050505050565b6000836001600160a01b03163b11612fe557600080fd5b6040516001600160a01b03838116602483015260448201839052600091829186169063095ea7b360e01b90606401612459565b6001600160a01b03811681146118f757600080fd5b803561303881613018565b919050565b6000806040838503121561305057600080fd5b823561305b81613018565b946020939093013593505050565b6000806040838503121561307c57600080fd5b823561308781613018565b9150602083013561309781613018565b809150509250929050565b6000602082840312156130b457600080fd5b813561106a81613018565b6000602082840312156130d157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561310157600080fd5b823561310c81613018565b915060208381013567ffffffffffffffff8082111561312a57600080fd5b818601915086601f83011261313e57600080fd5b813581811115613150576131506130d8565b8060051b604051601f19603f83011681018181108582111715613175576131756130d8565b60405291825284820192508381018501918983111561319357600080fd5b938501935b828510156131b8576131a98561302d565b84529385019392850192613198565b8096505050505050509250929050565b6000806000606084860312156131dd57600080fd5b8335925060208401356131ef81613018565b915060408401356131ff81613018565b809150509250925092565b6000806040838503121561321d57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b6000828210156132545761325461322c565b500390565b60008261327657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561328e5761328e61322c565b500190565b60008160001904831182151516156132ad576132ad61322c565b500290565b6000600182016132c4576132c461322c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156132f357600080fd5b815161106a81613018565b60006020828403121561331057600080fd5b8151801515811461106a57600080fd5b60006020828403121561333257600080fd5b5051919050565b6000825160005b8181101561335a5760208186018101518583015201613340565b81811115613369576000828501525b509190910192915050565b6000806040838503121561338757600080fd5b505080516020909101519092909150565b600080604083850312156133ab57600080fd5b82516133b681613018565b60208401519092506130978161301856fea2646970667358221220656ccf09ce656ea8ebfb044a59e62cffea98cb78d8b1c3228ccdcceab4e0aee364736f6c634300080d0033a2646970667358221220b102ed748ff42223948c2bba31684751618fee0a65b5917ca364d53fe7ff82cd64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 21380, + "contract": "contracts/factories/GaugeFactory.sol:GaugeFactory", + "label": "last_gauge", + "offset": 0, + "slot": "0", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumOne/MerkleClaim.json b/deployments/arbitrumOneOLD/MerkleClaim.json similarity index 100% rename from deployments/arbitrumOne/MerkleClaim.json rename to deployments/arbitrumOneOLD/MerkleClaim.json diff --git a/deployments/arbitrumOneOLD/Minter.json b/deployments/arbitrumOneOLD/Minter.json new file mode 100644 index 00000000..200f1a09 --- /dev/null +++ b/deployments/arbitrumOneOLD/Minter.json @@ -0,0 +1,427 @@ +{ + "address": "0x68352C1560B43AFE60413E6caf9900d77988E44f", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "__voter", + "type": "address" + }, + { + "internalType": "address", + "name": "__ve", + "type": "address" + }, + { + "internalType": "address", + "name": "__rewards_distributor", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weekly", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "circulating_supply", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "circulating_emission", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "inputs": [], + "name": "MAX_TEAM_RATE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_rewards_distributor", + "outputs": [ + { + "internalType": "contract IRewardsDistributor", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_ve", + "outputs": [ + { + "internalType": "contract IVotingEscrow", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_velo", + "outputs": [ + { + "internalType": "contract IVelo", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_voter", + "outputs": [ + { + "internalType": "contract IVoter", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "active_period", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "calculate_emission", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_minted", + "type": "uint256" + } + ], + "name": "calculate_growth", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "circulating_emission", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "circulating_supply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "claimants", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "max", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingTeam", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_team", + "type": "address" + } + ], + "name": "setTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_teamRate", + "type": "uint256" + } + ], + "name": "setTeamRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "team", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "teamRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "update_period", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "weekly", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "weekly_emission", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x47bfaf1e72075b00d5a115b9f499c65033c3e758846fc068abae3d30ebe58f6b", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x68352C1560B43AFE60413E6caf9900d77988E44f", + "transactionIndex": 1, + "gasUsed": "8497822", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x182dfc9178650a0120d8627568d8f4bbd2cff0a2dd095e6931def59f5761e34b", + "transactionHash": "0x47bfaf1e72075b00d5a115b9f499c65033c3e758846fc068abae3d30ebe58f6b", + "logs": [], + "blockNumber": 53774119, + "cumulativeGasUsed": "8497822", + "status": 1, + "byzantium": true + }, + "args": [ + "0x29C487a354D11315059204Df4F7d8AB1aa008ebb", + "0x10Df81252069C1095F541FAca61646cb9Ae76703", + "0xd9891738458A5b1F1EfB5f82183b77c666d9064E" + ], + "numDeployments": 1, + "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__voter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__rewards_distributor\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weekly\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_supply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"circulating_emission\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_TEAM_RATE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_rewards_distributor\",\"outputs\":[{\"internalType\":\"contract IRewardsDistributor\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"contract IVotingEscrow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_velo\",\"outputs\":[{\"internalType\":\"contract IVelo\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_voter\",\"outputs\":[{\"internalType\":\"contract IVoter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"active_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"calculate_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minted\",\"type\":\"uint256\"}],\"name\":\"calculate_growth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circulating_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"claimants\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingTeam\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_teamRate\",\"type\":\"uint256\"}],\"name\":\"setTeamRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"teamRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"update_period\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weekly_emission\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Minter.sol\":\"Minter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Minter.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IMinter.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVelo.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// codifies the minting rules as per ve(3,3), abstracted from the token to support any token that allows minting\\n\\ncontract Minter is IMinter {\\n uint256 internal constant WEEK = 86400 * 7; // allows minting once per week (reset every Thursday 00:00 UTC)\\n uint256 internal constant EMISSION = 990;\\n uint256 internal constant TAIL_EMISSION = 2;\\n uint256 internal constant PRECISION = 1000;\\n IVelo public immutable _velo;\\n IVoter public immutable _voter;\\n IVotingEscrow public immutable _ve;\\n IRewardsDistributor public immutable _rewards_distributor;\\n uint256 public weekly = 15_000_000 * 1e18; // represents a starting weekly emission of 15M VELO (VELO has 18 decimals)\\n uint256 public active_period;\\n uint256 internal constant LOCK = 86400 * 7 * 52 * 4;\\n\\n address internal initializer;\\n address public team;\\n address public pendingTeam;\\n uint256 public teamRate;\\n uint256 public constant MAX_TEAM_RATE = 50; // 50 bps = 0.05%\\n\\n event Mint(\\n address indexed sender,\\n uint256 weekly,\\n uint256 circulating_supply,\\n uint256 circulating_emission\\n );\\n\\n constructor(\\n address __voter, // the voting & distribution system\\n address __ve, // the ve(3,3) system that will be locked into\\n address __rewards_distributor // the distribution system that ensures users aren't diluted\\n ) {\\n initializer = msg.sender;\\n team = msg.sender;\\n teamRate = 30; // 30 bps = 0.03%\\n _velo = IVelo(IVotingEscrow(__ve).token());\\n _voter = IVoter(__voter);\\n _ve = IVotingEscrow(__ve);\\n _rewards_distributor = IRewardsDistributor(__rewards_distributor);\\n active_period = ((block.timestamp + (2 * WEEK)) / WEEK) * WEEK;\\n }\\n\\n function initialize(\\n address[] memory claimants,\\n uint256[] memory amounts,\\n uint256 max // sum amounts / max = % ownership of top protocols, so if initial 20m is distributed, and target is 25% protocol ownership, then max - 4 x 20m = 80m\\n ) external {\\n require(initializer == msg.sender);\\n _velo.mint(address(this), max);\\n _velo.approve(address(_ve), type(uint256).max);\\n for (uint256 i = 0; i < claimants.length; i++) {\\n _ve.create_lock_for(amounts[i], LOCK, claimants[i]);\\n }\\n initializer = address(0);\\n active_period = ((block.timestamp) / WEEK) * WEEK; // allow minter.update_period() to mint new emissions THIS Thursday\\n }\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team, \\\"not team\\\");\\n pendingTeam = _team;\\n }\\n\\n function acceptTeam() external {\\n require(msg.sender == pendingTeam, \\\"not pending team\\\");\\n team = pendingTeam;\\n }\\n\\n function setTeamRate(uint256 _teamRate) external {\\n require(msg.sender == team, \\\"not team\\\");\\n require(_teamRate <= MAX_TEAM_RATE, \\\"rate too high\\\");\\n teamRate = _teamRate;\\n }\\n\\n // calculate circulating supply as total token supply - locked supply\\n function circulating_supply() public view returns (uint256) {\\n return _velo.totalSupply() - _ve.totalSupply();\\n }\\n\\n // emission calculation is 1% of available supply to mint adjusted by circulating / total supply\\n function calculate_emission() public view returns (uint256) {\\n return (weekly * EMISSION) / PRECISION;\\n }\\n\\n // weekly emission takes the max of calculated (aka target) emission versus circulating tail end emission\\n function weekly_emission() public view returns (uint256) {\\n return MathDunks.max(calculate_emission(), circulating_emission());\\n }\\n\\n // calculates tail end (infinity) emissions as 0.2% of total supply\\n function circulating_emission() public view returns (uint256) {\\n return (circulating_supply() * TAIL_EMISSION) / PRECISION;\\n }\\n\\n // calculate inflation and adjust ve balances accordingly\\n function calculate_growth(uint256 _minted) public view returns (uint256) {\\n uint256 _veTotal = _ve.totalSupply();\\n uint256 _veloTotal = _velo.totalSupply();\\n return\\n (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) *\\n _veTotal) /\\n _veloTotal /\\n 2;\\n }\\n\\n // update period can only be called once per cycle (1 week)\\n function update_period() external returns (uint256) {\\n uint256 _period = active_period;\\n if (block.timestamp >= _period + WEEK && initializer == address(0)) {\\n // only trigger if new week\\n _period = (block.timestamp / WEEK) * WEEK;\\n active_period = _period;\\n weekly = weekly_emission();\\n\\n uint256 _growth = calculate_growth(weekly);\\n uint256 _teamEmissions = (teamRate * (_growth + weekly)) /\\n (PRECISION - teamRate);\\n uint256 _required = _growth + weekly + _teamEmissions;\\n uint256 _balanceOf = _velo.balanceOf(address(this));\\n if (_balanceOf < _required) {\\n _velo.mint(address(this), _required - _balanceOf);\\n }\\n\\n require(_velo.transfer(team, _teamEmissions));\\n require(_velo.transfer(address(_rewards_distributor), _growth));\\n _rewards_distributor.checkpoint_token(); // checkpoint token balance that was just minted in rewards distributor\\n _rewards_distributor.checkpoint_total_supply(); // checkpoint supply\\n\\n _velo.approve(address(_voter), weekly);\\n _voter.notifyRewardAmount(weekly);\\n\\n emit Mint(\\n msg.sender,\\n weekly,\\n circulating_supply(),\\n circulating_emission()\\n );\\n }\\n return _period;\\n }\\n}\\n\",\"keccak256\":\"0x8dce50c09815e53982006f9ddc46cd52cf7ac86b0c1b7bb15c817f86fb990580\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVelo.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVelo {\\n function totalSupply() external view returns (uint);\\n function balanceOf(address) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address, uint) external returns (bool);\\n function transferFrom(address,address,uint) external returns (bool);\\n function mint(address, uint) external returns (bool);\\n function minter() external returns (address);\\n function claim(address, uint) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4372772b06c7acb09381d2d722fbc927d580c8d8022512e2949bb7aded4f1699\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x6101006040526a0c685fa11e01ec6f0000006000553480156200002157600080fd5b506040516200158938038062001589833981016040819052620000449162000156565b60028054336001600160a01b03199182168117909255600380549091169091179055601e60055560408051637e062a3560e11b815290516001600160a01b0384169163fc0c546a9160048083019260209291908290030181865afa158015620000b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d79190620001a0565b6001600160a01b0390811660805283811660a05282811660c052811660e05262093a808062000108816002620001db565b620001149042620001fd565b62000120919062000218565b6200012c9190620001db565b600155506200023b915050565b80516001600160a01b03811681146200015157600080fd5b919050565b6000806000606084860312156200016c57600080fd5b620001778462000139565b9250620001876020850162000139565b9150620001976040850162000139565b90509250925092565b600060208284031215620001b357600080fd5b620001be8262000139565b9392505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620001f857620001f8620001c5565b500290565b60008219821115620002135762000213620001c5565b500190565b6000826200023657634e487b7160e01b600052601260045260246000fd5b500490565b60805160a05160c05160e051611296620002f3600039600081816101f801528181610c3701528181610cde0152610d51015260008181610261015281816104b30152818161055f0152818161068901526108750152600081816101d101528181610e090152610ea301526000818161015101528181610426015281816104e30152818161070f015281816108f701528181610a5f01528181610ade01528181610ba801528181610c660152610dda01526112966000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c806378ef7f02116100ad578063b5cc143a11610071578063b5cc143a14610296578063cfc6c8ff1461029e578063d1399608146102a6578063e038c75a146102af578063ed29fc11146102b757600080fd5b806378ef7f021461022d578063851708131461023657806385f2aef2146102495780638dd598fb1461025c5780638e01fbfa1461028357600080fd5b80632e8f7b1f116100f45780632e8f7b1f146101b157806336d96faf146101c45780633db9b42a146101cc5780634b1cd5da146101f357806359d46ffc1461021a57600080fd5b806301c8e6fd1461013157806308aa44581461014c578063095cf5c61461018b5780631eebae80146101a057806326cfc17b146101a8575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b61019e610199366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61019e6101bf366004610fb8565b610353565b6101396103de565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b600454610173906001600160a01b031681565b61013960055481565b61019e6102443660046110a7565b6103f3565b600354610173906001600160a01b031681565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b610139610291366004610fb8565b610684565b61019e6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea2646970667358221220ca2234c7f93e2440b9fbf0fec3a7db175caf6e9740b210ee968450b35cc8333b64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c806378ef7f02116100ad578063b5cc143a11610071578063b5cc143a14610296578063cfc6c8ff1461029e578063d1399608146102a6578063e038c75a146102af578063ed29fc11146102b757600080fd5b806378ef7f021461022d578063851708131461023657806385f2aef2146102495780638dd598fb1461025c5780638e01fbfa1461028357600080fd5b80632e8f7b1f116100f45780632e8f7b1f146101b157806336d96faf146101c45780633db9b42a146101cc5780634b1cd5da146101f357806359d46ffc1461021a57600080fd5b806301c8e6fd1461013157806308aa44581461014c578063095cf5c61461018b5780631eebae80146101a057806326cfc17b146101a8575b600080fd5b610139603281565b6040519081526020015b60405180910390f35b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610143565b61019e610199366004610f9d565b6102bf565b005b61013961032b565b61013960005481565b61019e6101bf366004610fb8565b610353565b6101396103de565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b600454610173906001600160a01b031681565b61013960055481565b61019e6102443660046110a7565b6103f3565b600354610173906001600160a01b031681565b6101737f000000000000000000000000000000000000000000000000000000000000000081565b610139610291366004610fb8565b610684565b61019e6107e6565b610139610857565b61013960015481565b610139610871565b610139610981565b6003546001600160a01b031633146103095760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b60448201526064015b60405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b60006103e8600261033a610871565b6103449190611186565b61034e91906111a5565b905090565b6003546001600160a01b031633146103985760405162461bcd60e51b81526020600482015260086024820152676e6f74207465616d60c01b6044820152606401610300565b60328111156103d95760405162461bcd60e51b815260206004820152600d60248201526c0e4c2e8ca40e8dede40d0d2ced609b1b6044820152606401610300565b600555565b60006103e86103de6000546103449190611186565b6002546001600160a01b0316331461040a57600080fd5b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044016020604051808303816000875af1158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b91906111c7565b5060405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561052c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055091906111c7565b5060005b8351811015610653577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d4e54c3b84838151811061059e5761059e6111e9565b602002602001015163077f88008785815181106105bd576105bd6111e9565b60200260200101516040518463ffffffff1660e01b81526004016105fd9392919092835260208301919091526001600160a01b0316604082015260600190565b6020604051808303816000875af115801561061c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064091906111ff565b508061064b81611218565b915050610554565b50600280546001600160a01b031916905562093a8061067281426111a5565b61067c9190611186565b600155505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070991906111ff565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078f91906111ff565b9050600281838181816107a2828b611186565b6107ac91906111a5565b6107b69190611186565b6107c091906111a5565b6107ca9190611186565b6107d491906111a5565b6107de91906111a5565b949350505050565b6004546001600160a01b031633146108335760405162461bcd60e51b815260206004820152601060248201526f6e6f742070656e64696e67207465616d60801b6044820152606401610300565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b600061034e6108646103de565b61086c61032b565b610f6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f591906111ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097791906111ff565b61034e9190611231565b60015460009061099462093a8082611248565b42101580156109ac57506002546001600160a01b0316155b15610f685762093a806109bf81426111a5565b6109c99190611186565b600181905590506109d8610857565b6000818155906109e790610684565b905060006005546103e86109fb9190611231565b600054610a089084611248565b600554610a159190611186565b610a1f91906111a5565b905060008160005484610a329190611248565b610a3c9190611248565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610aa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aca91906111ff565b905081811015610b7f576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b0e8486611231565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906111c7565b505b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906111c7565b610c2057600080fd5b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd391906111c7565b610cdc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663811a40fe6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d3757600080fd5b505af1158015610d4b573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b21ed5026040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505060005460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063095ea7b39250610e45917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906111c7565b50600054604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab90602401600060405180830381600087803b158015610eef57600080fd5b505af1158015610f03573d6000803e3d6000fd5b50505050336001600160a01b03167fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb600054610f3d610871565b610f4561032b565b6040805193845260208401929092529082015260600160405180910390a2505050505b919050565b600081831015610f7d5781610f7f565b825b9392505050565b80356001600160a01b0381168114610f6857600080fd5b600060208284031215610faf57600080fd5b610f7f82610f86565b600060208284031215610fca57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561101057611010610fd1565b604052919050565b600067ffffffffffffffff82111561103257611032610fd1565b5060051b60200190565b600082601f83011261104d57600080fd5b8135602061106261105d83611018565b610fe7565b82815260059290921b8401810191818101908684111561108157600080fd5b8286015b8481101561109c5780358352918301918301611085565b509695505050505050565b6000806000606084860312156110bc57600080fd5b833567ffffffffffffffff808211156110d457600080fd5b818601915086601f8301126110e857600080fd5b813560206110f861105d83611018565b82815260059290921b8401810191818101908a84111561111757600080fd5b948201945b8386101561113c5761112d86610f86565b8252948201949082019061111c565b9750508701359250508082111561115257600080fd5b5061115f8682870161103c565b925050604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156111a0576111a0611170565b500290565b6000826111c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156111d957600080fd5b81518015158114610f7f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561121157600080fd5b5051919050565b60006001820161122a5761122a611170565b5060010190565b60008282101561124357611243611170565b500390565b6000821982111561125b5761125b611170565b50019056fea2646970667358221220ca2234c7f93e2440b9fbf0fec3a7db175caf6e9740b210ee968450b35cc8333b64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 6187, + "contract": "contracts/Minter.sol:Minter", + "label": "weekly", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 6189, + "contract": "contracts/Minter.sol:Minter", + "label": "active_period", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 6200, + "contract": "contracts/Minter.sol:Minter", + "label": "initializer", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 6202, + "contract": "contracts/Minter.sol:Minter", + "label": "team", + "offset": 0, + "slot": "3", + "type": "t_address" + }, + { + "astId": 6204, + "contract": "contracts/Minter.sol:Minter", + "label": "pendingTeam", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 6206, + "contract": "contracts/Minter.sol:Minter", + "label": "teamRate", + "offset": 0, + "slot": "5", + "type": "t_uint256" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumOneOLD/PairFactory.json b/deployments/arbitrumOneOLD/PairFactory.json new file mode 100644 index 00000000..c724ba2f --- /dev/null +++ b/deployments/arbitrumOneOLD/PairFactory.json @@ -0,0 +1,577 @@ +{ + "address": "0xA2db791281CdeeBb1EEDc78a34989df2Bfd479bE", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token0", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token1", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "indexed": false, + "internalType": "address", + "name": "pair", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "PairCreated", + "type": "event" + }, + { + "inputs": [], + "name": "MAX_FEE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptFeeManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "acceptPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allPairs", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPairsLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "createPair", + "outputs": [ + { + "internalType": "address", + "name": "pair", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "feeManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_stable", + "type": "bool" + } + ], + "name": "getFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getInitializable", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "name": "getPair", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isPair", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pairCodeHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "pauser", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingFeeManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingPauser", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "_fee", + "type": "uint256" + } + ], + "name": "setFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_feeManager", + "type": "address" + } + ], + "name": "setFeeManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_state", + "type": "bool" + } + ], + "name": "setPause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_pauser", + "type": "address" + } + ], + "name": "setPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "stableFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "volatileFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x306e2d821d9c59dcbab8293e7535aa6a69903b449e099338d70dd1634e6e431f", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0xA2db791281CdeeBb1EEDc78a34989df2Bfd479bE", + "transactionIndex": 1, + "gasUsed": "30339230", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x9a41d528ac53283549a72da1405ffe146c73ff66abf7986ace7249bf7cd5fc1c", + "transactionHash": "0x306e2d821d9c59dcbab8293e7535aa6a69903b449e099338d70dd1634e6e431f", + "logs": [], + "blockNumber": 53774047, + "cumulativeGasUsed": "30339230", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"PairCreated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_FEE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allPairs\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"allPairsLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"createPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getInitializable\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"name\":\"getPair\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pairCodeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingFeeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingPauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_feeManager\",\"type\":\"address\"}],\"name\":\"setFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_state\",\"type\":\"bool\"}],\"name\":\"setPause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pauser\",\"type\":\"address\"}],\"name\":\"setPauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stableFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"volatileFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/PairFactory.sol\":\"PairFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Pair.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairCallee.sol\\\";\\nimport \\\"contracts/factories/PairFactory.sol\\\";\\nimport \\\"contracts/PairFees.sol\\\";\\n\\n// The base pair of pools, either stable or volatile\\ncontract Pair is IPair {\\n string public name;\\n string public symbol;\\n uint8 public constant decimals = 18;\\n\\n // Used to denote stable or volatile pair, not immutable since construction happens in the initialize method for CREATE2 deterministic addresses\\n bool public immutable stable;\\n\\n uint256 public totalSupply = 0;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n mapping(address => uint256) public balanceOf;\\n\\n bytes32 internal DOMAIN_SEPARATOR;\\n // keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 internal constant PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n mapping(address => uint256) public nonces;\\n\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n\\n address public immutable token0;\\n address public immutable token1;\\n address public immutable fees;\\n address immutable factory;\\n\\n // Structure to capture time period obervations every 30 minutes, used for local oracles\\n struct Observation {\\n uint256 timestamp;\\n uint256 reserve0Cumulative;\\n uint256 reserve1Cumulative;\\n }\\n\\n // Capture oracle reading every 30 minutes\\n uint256 constant periodSize = 1800;\\n\\n Observation[] public observations;\\n\\n uint256 internal immutable decimals0;\\n uint256 internal immutable decimals1;\\n\\n uint256 public reserve0;\\n uint256 public reserve1;\\n uint256 public blockTimestampLast;\\n\\n uint256 public reserve0CumulativeLast;\\n uint256 public reserve1CumulativeLast;\\n\\n // index0 and index1 are used to accumulate fees, this is split out from normal trades to keep the swap \\\"clean\\\"\\n // this further allows LP holders to easily claim fees for tokens they have/staked\\n uint256 public index0 = 0;\\n uint256 public index1 = 0;\\n\\n // position assigned to each LP to track their current index0 & index1 vs the global position\\n mapping(address => uint256) public supplyIndex0;\\n mapping(address => uint256) public supplyIndex1;\\n\\n // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1\\n mapping(address => uint256) public claimable0;\\n mapping(address => uint256) public claimable1;\\n\\n event Fees(address indexed sender, uint256 amount0, uint256 amount1);\\n event Mint(address indexed sender, uint256 amount0, uint256 amount1);\\n event Burn(\\n address indexed sender,\\n uint256 amount0,\\n uint256 amount1,\\n address indexed to\\n );\\n event Swap(\\n address indexed sender,\\n uint256 amount0In,\\n uint256 amount1In,\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address indexed to\\n );\\n event Sync(uint256 reserve0, uint256 reserve1);\\n event Claim(\\n address indexed sender,\\n address indexed recipient,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 amount\\n );\\n\\n constructor() {\\n factory = msg.sender;\\n (address _token0, address _token1, bool _stable) = PairFactory(\\n msg.sender\\n ).getInitializable();\\n (token0, token1, stable) = (_token0, _token1, _stable);\\n fees = address(new PairFees(_token0, _token1));\\n if (_stable) {\\n name = string(\\n abi.encodePacked(\\n \\\"StableV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"sAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n } else {\\n name = string(\\n abi.encodePacked(\\n \\\"VolatileV1 AMM - \\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n symbol = string(\\n abi.encodePacked(\\n \\\"vAMM-\\\",\\n IERC20(_token0).symbol(),\\n \\\"/\\\",\\n IERC20(_token1).symbol()\\n )\\n );\\n }\\n\\n decimals0 = 10**IERC20(_token0).decimals();\\n decimals1 = 10**IERC20(_token1).decimals();\\n\\n observations.push(Observation(block.timestamp, 0, 0));\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function observationLength() external view returns (uint256) {\\n return observations.length;\\n }\\n\\n function lastObservation() public view returns (Observation memory) {\\n return observations[observations.length - 1];\\n }\\n\\n function metadata()\\n external\\n view\\n returns (\\n uint256 dec0,\\n uint256 dec1,\\n uint256 r0,\\n uint256 r1,\\n bool st,\\n address t0,\\n address t1\\n )\\n {\\n return (\\n decimals0,\\n decimals1,\\n reserve0,\\n reserve1,\\n stable,\\n token0,\\n token1\\n );\\n }\\n\\n function tokens() external view returns (address, address) {\\n return (token0, token1);\\n }\\n\\n // claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)\\n function claimFees() external returns (uint256 claimed0, uint256 claimed1) {\\n _updateFor(msg.sender);\\n\\n claimed0 = claimable0[msg.sender];\\n claimed1 = claimable1[msg.sender];\\n\\n if (claimed0 > 0 || claimed1 > 0) {\\n claimable0[msg.sender] = 0;\\n claimable1[msg.sender] = 0;\\n\\n PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);\\n\\n emit Claim(msg.sender, msg.sender, claimed0, claimed1);\\n }\\n }\\n\\n // Accrue fees on token0\\n function _update0(uint256 amount) internal {\\n _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees\\n uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index0 += _ratio;\\n }\\n emit Fees(msg.sender, amount, 0);\\n }\\n\\n // Accrue fees on token1\\n function _update1(uint256 amount) internal {\\n _safeTransfer(token1, fees, amount);\\n uint256 _ratio = (amount * 1e18) / totalSupply;\\n if (_ratio > 0) {\\n index1 += _ratio;\\n }\\n emit Fees(msg.sender, 0, amount);\\n }\\n\\n // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees\\n // Fees are segregated from core funds, so fees can never put liquidity at risk\\n function _updateFor(address recipient) internal {\\n uint256 _supplied = balanceOf[recipient]; // get LP balance of `recipient`\\n if (_supplied > 0) {\\n uint256 _supplyIndex0 = supplyIndex0[recipient]; // get last adjusted index0 for recipient\\n uint256 _supplyIndex1 = supplyIndex1[recipient];\\n uint256 _index0 = index0; // get global index0 for accumulated fees\\n uint256 _index1 = index1;\\n supplyIndex0[recipient] = _index0; // update user current position to global position\\n supplyIndex1[recipient] = _index1;\\n uint256 _delta0 = _index0 - _supplyIndex0; // see if there is any difference that need to be accrued\\n uint256 _delta1 = _index1 - _supplyIndex1;\\n if (_delta0 > 0) {\\n uint256 _share = (_supplied * _delta0) / 1e18; // add accrued difference for each supplied token\\n claimable0[recipient] += _share;\\n }\\n if (_delta1 > 0) {\\n uint256 _share = (_supplied * _delta1) / 1e18;\\n claimable1[recipient] += _share;\\n }\\n } else {\\n supplyIndex0[recipient] = index0; // new users are set to the default global state\\n supplyIndex1[recipient] = index1;\\n }\\n }\\n\\n function getReserves()\\n public\\n view\\n returns (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n )\\n {\\n _reserve0 = reserve0;\\n _reserve1 = reserve1;\\n _blockTimestampLast = blockTimestampLast;\\n }\\n\\n // update reserves and, on the first call per block, price accumulators\\n function _update(\\n uint256 balance0,\\n uint256 balance1,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal {\\n uint256 blockTimestamp = block.timestamp;\\n uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\\n reserve0CumulativeLast += _reserve0 * timeElapsed;\\n reserve1CumulativeLast += _reserve1 * timeElapsed;\\n }\\n\\n Observation memory _point = lastObservation();\\n timeElapsed = blockTimestamp - _point.timestamp; // compare the last observation with current timestamp, if greater than 30 minutes, record a new event\\n if (timeElapsed > periodSize) {\\n observations.push(\\n Observation(\\n blockTimestamp,\\n reserve0CumulativeLast,\\n reserve1CumulativeLast\\n )\\n );\\n }\\n reserve0 = balance0;\\n reserve1 = balance1;\\n blockTimestampLast = blockTimestamp;\\n emit Sync(reserve0, reserve1);\\n }\\n\\n // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.\\n function currentCumulativePrices()\\n public\\n view\\n returns (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n uint256 blockTimestamp\\n )\\n {\\n blockTimestamp = block.timestamp;\\n reserve0Cumulative = reserve0CumulativeLast;\\n reserve1Cumulative = reserve1CumulativeLast;\\n\\n // if time has elapsed since the last update on the pair, mock the accumulated price values\\n (\\n uint256 _reserve0,\\n uint256 _reserve1,\\n uint256 _blockTimestampLast\\n ) = getReserves();\\n if (_blockTimestampLast != blockTimestamp) {\\n // subtraction overflow is desired\\n uint256 timeElapsed = blockTimestamp - _blockTimestampLast;\\n reserve0Cumulative += _reserve0 * timeElapsed;\\n reserve1Cumulative += _reserve1 * timeElapsed;\\n }\\n }\\n\\n // gives the current twap price measured from amountIn * tokenIn gives amountOut\\n function current(address tokenIn, uint256 amountIn)\\n external\\n view\\n returns (uint256 amountOut)\\n {\\n Observation memory _observation = lastObservation();\\n (\\n uint256 reserve0Cumulative,\\n uint256 reserve1Cumulative,\\n\\n ) = currentCumulativePrices();\\n if (block.timestamp == _observation.timestamp) {\\n _observation = observations[observations.length - 2];\\n }\\n\\n uint256 timeElapsed = block.timestamp - _observation.timestamp;\\n uint256 _reserve0 = (reserve0Cumulative -\\n _observation.reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (reserve1Cumulative -\\n _observation.reserve1Cumulative) / timeElapsed;\\n amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n // as per `current`, however allows user configured granularity, up to the full window size\\n function quote(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 granularity\\n ) external view returns (uint256 amountOut) {\\n uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);\\n uint256 priceAverageCumulative;\\n for (uint256 i = 0; i < _prices.length; i++) {\\n priceAverageCumulative += _prices[i];\\n }\\n return priceAverageCumulative / granularity;\\n }\\n\\n // returns a memory set of twap prices\\n function prices(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points\\n ) external view returns (uint256[] memory) {\\n return sample(tokenIn, amountIn, points, 1);\\n }\\n\\n function sample(\\n address tokenIn,\\n uint256 amountIn,\\n uint256 points,\\n uint256 window\\n ) public view returns (uint256[] memory) {\\n uint256[] memory _prices = new uint256[](points);\\n\\n uint256 length = observations.length - 1;\\n uint256 i = length - (points * window);\\n uint256 nextIndex = 0;\\n uint256 index = 0;\\n\\n for (; i < length; i += window) {\\n nextIndex = i + window;\\n uint256 timeElapsed = observations[nextIndex].timestamp -\\n observations[i].timestamp;\\n uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -\\n observations[i].reserve0Cumulative) / timeElapsed;\\n uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -\\n observations[i].reserve1Cumulative) / timeElapsed;\\n _prices[index] = _getAmountOut(\\n amountIn,\\n tokenIn,\\n _reserve0,\\n _reserve1\\n );\\n // index < length; length cannot overflow\\n unchecked {\\n index = index + 1;\\n }\\n }\\n return _prices;\\n }\\n\\n // this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks\\n // standard uniswap v2 implementation\\n function mint(address to) external lock returns (uint256 liquidity) {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n uint256 _balance0 = IERC20(token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(token1).balanceOf(address(this));\\n uint256 _amount0 = _balance0 - _reserve0;\\n uint256 _amount1 = _balance1 - _reserve1;\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n if (_totalSupply == 0) {\\n liquidity = MathDunks.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;\\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\\n } else {\\n liquidity = MathDunks.min(\\n (_amount0 * _totalSupply) / _reserve0,\\n (_amount1 * _totalSupply) / _reserve1\\n );\\n }\\n require(liquidity > 0, \\\"ILM\\\"); // Pair: INSUFFICIENT_LIQUIDITY_MINTED\\n _mint(to, liquidity);\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Mint(msg.sender, _amount0, _amount1);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n // standard uniswap v2 implementation\\n function burn(address to)\\n external\\n lock\\n returns (uint256 amount0, uint256 amount1)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n (address _token0, address _token1) = (token0, token1);\\n uint256 _balance0 = IERC20(_token0).balanceOf(address(this));\\n uint256 _balance1 = IERC20(_token1).balanceOf(address(this));\\n uint256 _liquidity = balanceOf[address(this)];\\n\\n uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\\n amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution\\n amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution\\n require(amount0 > 0 && amount1 > 0, \\\"ILB\\\"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED\\n _burn(address(this), _liquidity);\\n _safeTransfer(_token0, to, amount0);\\n _safeTransfer(_token1, to, amount1);\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Burn(msg.sender, amount0, amount1, to);\\n }\\n\\n // this low-level function should be called from a contract which performs important safety checks\\n function swap(\\n uint256 amount0Out,\\n uint256 amount1Out,\\n address to,\\n bytes calldata data\\n ) external lock {\\n require(!PairFactory(factory).isPaused());\\n require(amount0Out > 0 || amount1Out > 0, \\\"IOA\\\"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n require(amount0Out < _reserve0 && amount1Out < _reserve1, \\\"IL\\\"); // Pair: INSUFFICIENT_LIQUIDITY\\n\\n uint256 _balance0;\\n uint256 _balance1;\\n {\\n // scope for _token{0,1}, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n require(to != _token0 && to != _token1, \\\"IT\\\"); // Pair: INVALID_TO\\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\\n if (data.length > 0)\\n IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans\\n _balance0 = IERC20(_token0).balanceOf(address(this));\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n }\\n uint256 amount0In = _balance0 > _reserve0 - amount0Out\\n ? _balance0 - (_reserve0 - amount0Out)\\n : 0;\\n uint256 amount1In = _balance1 > _reserve1 - amount1Out\\n ? _balance1 - (_reserve1 - amount1Out)\\n : 0;\\n require(amount0In > 0 || amount1In > 0, \\\"IIA\\\"); // Pair: INSUFFICIENT_INPUT_AMOUNT\\n {\\n // scope for reserve{0,1}Adjusted, avoids stack too deep errors\\n (address _token0, address _token1) = (token0, token1);\\n if (amount0In > 0)\\n _update0(\\n (amount0In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token0 and move them out of pool\\n if (amount1In > 0)\\n _update1(\\n (amount1In * PairFactory(factory).getFee(stable)) / 10000\\n ); // accrue fees for token1 and move them out of pool\\n _balance0 = IERC20(_token0).balanceOf(address(this)); // since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check\\n _balance1 = IERC20(_token1).balanceOf(address(this));\\n // The curve, either x3y+y3x for stable pools, or x*y for volatile pools\\n require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), \\\"K\\\"); // Pair: K\\n }\\n\\n _update(_balance0, _balance1, _reserve0, _reserve1);\\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\\n }\\n\\n // force balances to match reserves\\n function skim(address to) external lock {\\n (address _token0, address _token1) = (token0, token1);\\n _safeTransfer(\\n _token0,\\n to,\\n IERC20(_token0).balanceOf(address(this)) - (reserve0)\\n );\\n _safeTransfer(\\n _token1,\\n to,\\n IERC20(_token1).balanceOf(address(this)) - (reserve1)\\n );\\n }\\n\\n // force reserves to match balances\\n function sync() external lock {\\n _update(\\n IERC20(token0).balanceOf(address(this)),\\n IERC20(token1).balanceOf(address(this)),\\n reserve0,\\n reserve1\\n );\\n }\\n\\n function _f(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (x0 * ((((y * y) / 1e18) * y) / 1e18)) /\\n 1e18 +\\n (((((x0 * x0) / 1e18) * x0) / 1e18) * y) /\\n 1e18;\\n }\\n\\n function _d(uint256 x0, uint256 y) internal pure returns (uint256) {\\n return\\n (3 * x0 * ((y * y) / 1e18)) /\\n 1e18 +\\n ((((x0 * x0) / 1e18) * x0) / 1e18);\\n }\\n\\n function _get_y(\\n uint256 x0,\\n uint256 xy,\\n uint256 y\\n ) internal pure returns (uint256) {\\n for (uint256 i = 0; i < 255; i++) {\\n uint256 y_prev = y;\\n uint256 k = _f(x0, y);\\n if (k < xy) {\\n uint256 dy = ((xy - k) * 1e18) / _d(x0, y);\\n y = y + dy;\\n } else {\\n uint256 dy = ((k - xy) * 1e18) / _d(x0, y);\\n y = y - dy;\\n }\\n if (y > y_prev) {\\n if (y - y_prev <= 1) {\\n return y;\\n }\\n } else {\\n if (y_prev - y <= 1) {\\n return y;\\n }\\n }\\n }\\n return y;\\n }\\n\\n function getAmountOut(uint256 amountIn, address tokenIn)\\n external\\n view\\n returns (uint256)\\n {\\n (uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);\\n amountIn -= (amountIn * PairFactory(factory).getFee(stable)) / 10000; // remove fee from amount received\\n return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);\\n }\\n\\n function _getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal view returns (uint256) {\\n if (stable) {\\n uint256 xy = _k(_reserve0, _reserve1);\\n _reserve0 = (_reserve0 * 1e18) / decimals0;\\n _reserve1 = (_reserve1 * 1e18) / decimals1;\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n amountIn = tokenIn == token0\\n ? (amountIn * 1e18) / decimals0\\n : (amountIn * 1e18) / decimals1;\\n uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);\\n return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;\\n } else {\\n (uint256 reserveA, uint256 reserveB) = tokenIn == token0\\n ? (_reserve0, _reserve1)\\n : (_reserve1, _reserve0);\\n return (amountIn * reserveB) / (reserveA + amountIn);\\n }\\n }\\n\\n function _k(uint256 x, uint256 y) internal view returns (uint256) {\\n if (stable) {\\n uint256 _x = (x * 1e18) / decimals0;\\n uint256 _y = (y * 1e18) / decimals1;\\n uint256 _a = (_x * _y) / 1e18;\\n uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);\\n return (_a * _b) / 1e18; // x3y+y3x >= k\\n } else {\\n return x * y; // xy >= k\\n }\\n }\\n\\n function _mint(address dst, uint256 amount) internal {\\n _updateFor(dst); // balances must be updated on mint/burn/transfer\\n totalSupply += amount;\\n balanceOf[dst] += amount;\\n emit Transfer(address(0), dst, amount);\\n }\\n\\n function _burn(address dst, uint256 amount) internal {\\n _updateFor(dst);\\n totalSupply -= amount;\\n balanceOf[dst] -= amount;\\n emit Transfer(dst, address(0), amount);\\n }\\n\\n function approve(address spender, uint256 amount) external returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external {\\n require(deadline >= block.timestamp, \\\"Pair: EXPIRED\\\");\\n DOMAIN_SEPARATOR = keccak256(\\n abi.encode(\\n keccak256(\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n ),\\n keccak256(bytes(name)),\\n keccak256(bytes(\\\"1\\\")),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR,\\n keccak256(\\n abi.encode(\\n PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n );\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n require(\\n recoveredAddress != address(0) && recoveredAddress == owner,\\n \\\"Pair: INVALID_SIGNATURE\\\"\\n );\\n allowance[owner][spender] = value;\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function transfer(address dst, uint256 amount) external returns (bool) {\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 amount\\n ) external returns (bool) {\\n address spender = msg.sender;\\n uint256 spenderAllowance = allowance[src][spender];\\n\\n if (spender != src && spenderAllowance != type(uint256).max) {\\n uint256 newAllowance = spenderAllowance - amount;\\n allowance[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n function _transferTokens(\\n address src,\\n address dst,\\n uint256 amount\\n ) internal {\\n _updateFor(src); // update fee position for src\\n _updateFor(dst); // update fee position for dst\\n\\n balanceOf[src] -= amount;\\n balanceOf[dst] += amount;\\n\\n emit Transfer(src, dst, amount);\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x4f508747645f4480e0b0f23d952fa9b82af1d9bc60b15b8cd1f542ee136043d1\",\"license\":\"MIT\"},\"contracts/PairFees.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IERC20.sol';\\n\\n// Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares\\ncontract PairFees {\\n\\n address internal immutable pair; // The pair it is bonded to\\n address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization\\n address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization\\n\\n constructor(address _token0, address _token1) {\\n pair = msg.sender;\\n token0 = _token0;\\n token1 = _token1;\\n }\\n\\n function _safeTransfer(address token,address to,uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n // Allow the pair to transfer fees to users\\n function claimFeesFor(address recipient, uint amount0, uint amount1) external {\\n require(msg.sender == pair);\\n if (amount0 > 0) _safeTransfer(token0, recipient, amount0);\\n if (amount1 > 0) _safeTransfer(token1, recipient, amount1);\\n }\\n\\n}\\n\",\"keccak256\":\"0xb772e192bab353f8642e89a95ef4ef0255d1caef08444101d7fe34469c1000ca\",\"license\":\"MIT\"},\"contracts/factories/PairFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/Pair.sol';\\n\\ncontract PairFactory is IPairFactory {\\n\\n bool public isPaused;\\n address public pauser;\\n address public pendingPauser;\\n\\n uint256 public stableFee;\\n uint256 public volatileFee;\\n uint256 public constant MAX_FEE = 5; // 0.05%\\n address public feeManager;\\n address public pendingFeeManager;\\n\\n mapping(address => mapping(address => mapping(bool => address))) public getPair;\\n address[] public allPairs;\\n mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals\\n\\n address internal _temp0;\\n address internal _temp1;\\n bool internal _temp;\\n\\n event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);\\n\\n constructor() {\\n pauser = msg.sender;\\n isPaused = false;\\n feeManager = msg.sender;\\n stableFee = 2; // 0.02%\\n volatileFee = 2;\\n }\\n\\n function allPairsLength() external view returns (uint) {\\n return allPairs.length;\\n }\\n\\n function setPauser(address _pauser) external {\\n require(msg.sender == pauser);\\n pendingPauser = _pauser;\\n }\\n\\n function acceptPauser() external {\\n require(msg.sender == pendingPauser);\\n pauser = pendingPauser;\\n }\\n\\n function setPause(bool _state) external {\\n require(msg.sender == pauser);\\n isPaused = _state;\\n }\\n\\n function setFeeManager(address _feeManager) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n pendingFeeManager = _feeManager;\\n }\\n\\n function acceptFeeManager() external {\\n require(msg.sender == pendingFeeManager, 'not pending fee manager');\\n feeManager = pendingFeeManager;\\n }\\n\\n function setFee(bool _stable, uint256 _fee) external {\\n require(msg.sender == feeManager, 'not fee manager');\\n require(_fee <= MAX_FEE, 'fee too high');\\n require(_fee != 0, 'fee must be nonzero');\\n if (_stable) {\\n stableFee = _fee;\\n } else {\\n volatileFee = _fee;\\n }\\n }\\n\\n function getFee(bool _stable) public view returns(uint256) {\\n return _stable ? stableFee : volatileFee;\\n }\\n\\n function pairCodeHash() external pure returns (bytes32) {\\n return keccak256(type(Pair).creationCode);\\n }\\n\\n function getInitializable() external view returns (address, address, bool) {\\n return (_temp0, _temp1, _temp);\\n }\\n\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair) {\\n require(tokenA != tokenB, 'IA'); // Pair: IDENTICAL_ADDRESSES\\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\\n require(token0 != address(0), 'ZA'); // Pair: ZERO_ADDRESS\\n require(getPair[token0][token1][stable] == address(0), 'PE'); // Pair: PAIR_EXISTS - single check is sufficient\\n bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters\\n (_temp0, _temp1, _temp) = (token0, token1, stable);\\n pair = address(new Pair{salt:salt}());\\n getPair[token0][token1][stable] = pair;\\n getPair[token1][token0][stable] = pair; // populate mapping in the reverse direction\\n allPairs.push(pair);\\n isPair[pair] = true;\\n emit PairCreated(token0, token1, stable, pair, allPairs.length);\\n }\\n}\\n\",\"keccak256\":\"0x9b7984117a5a32188aa9ddf42b6cff024240579ab30f3776f7a201285d813e4f\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairCallee.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairCallee {\\n function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x3ac2de2c7a08bf59fd1006e4d108b247916369de15fbd048b72ca2b7814023ca\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50600080546001600160a81b03191633610100810260ff1916919091178255600480546001600160a01b0319169091179055600280805560035561519190819061005a90396000f3fe60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea2646970667358221220270f4e3352962d1c128c52f446c9e0a94cfd4293f1f3d44b28a148af57736d1a64736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea26469706673582212204d9e84053035e063a46827cca65ab59fad4e23ed0078ae98f8e2cc371de9f9ef64736f6c634300080d0033a2646970667358221220dfffcd46a9d232648bdc2dd9222c658d5554eef6a609556964e00d872e0d720d64736f6c634300080d0033", + "deployedBytecode": "0x60806040523480156200001157600080fd5b50600436106200015d5760003560e01c80639a7165e411620000c7578063bedb86fb1162000086578063bedb86fb14620002da578063d0fb020314620002f1578063e1f76b441462000305578063e5e31b13146200031c578063eb13c4cf1462000342578063f94c53c7146200037b57600080fd5b80639a7165e4146200027b5780639aab9248146200028f5780639fd0506d1462000299578063b187bd2614620002b2578063bc063e1a14620002d157600080fd5b80635084ed0311620001205780635084ed0314620001e9578063512b45ea14620001f3578063574f2ba3146200020a5780636801cc30146200021357806382dfdce414620002505780638a4fa0d2146200026757600080fd5b8063167a6f9014620001625780631e3dd18b146200016e5780632d88af4a14620001a257806340bbd77514620001b9578063472d35b914620001d2575b600080fd5b6200016c62000385565b005b620001856200017f36600462000989565b620003c8565b6040516001600160a01b0390911681526020015b60405180910390f35b6200016c620001b3366004620009c0565b620003f3565b620001c360025481565b60405190815260200162000199565b6200016c620001e3366004620009c0565b62000432565b620001c360035481565b620001c362000204366004620009f6565b620004a6565b600754620001c3565b620001856200022436600462000a14565b60066020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b620001856200026136600462000a14565b620004c1565b60055462000185906001600160a01b031681565b60015462000185906001600160a01b031681565b620001c3620007ac565b600054620001859061010090046001600160a01b031681565b600054620002c09060ff1681565b604051901515815260200162000199565b620001c3600581565b6200016c620002eb366004620009f6565b620007e0565b60045462000185906001600160a01b031681565b6200016c6200031636600462000a5e565b62000810565b620002c06200032d366004620009c0565b60086020526000908152604090205460ff1681565b600954600a54604080516001600160a01b0393841681529282166020840152600160a01b90910460ff1615159082015260600162000199565b6200016c620008fb565b6001546001600160a01b031633146200039d57600080fd5b600154600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60078181548110620003d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60005461010090046001600160a01b031633146200041057600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314620004845760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600081620004b757600354620004bb565b6002545b92915050565b6000826001600160a01b0316846001600160a01b0316036200050b5760405162461bcd60e51b8152602060048201526002602482015261494160f01b60448201526064016200047b565b600080846001600160a01b0316866001600160a01b0316106200053057848662000533565b85855b90925090506001600160a01b038216620005755760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016200047b565b6001600160a01b0382811660009081526006602090815260408083208585168452825280832088151584529091529020541615620005db5760405162461bcd60e51b8152602060048201526002602482015261504560f01b60448201526064016200047b565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015284151560f81b604882015260009060490160408051601f19818403018152908290528051602090910120600a80546001600160a01b038087166001600160a01b03198b1515600160a01b0281166001600160a81b0319909416939093171790925560098054928816929091169190911790559150819062000682906200097b565b8190604051809103906000f5905080158015620006a3573d6000803e3d6000fd5b506001600160a01b0384811660008181526006602081815260408084208987168086529083528185208d15158087529084528286208054988a166001600160a01b0319998a16811790915582875294845282862087875284528286208187528452828620805489168617905560078054600181810183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889091018054909a1687179099558587526008855295839020805460ff1916909817909755935481519687529186019290925290840152929650907fc4805696c66d7cf352fc1d6bb633ad5ee82f6cb577c453024b6e0eb8306c6fc99060600160405180910390a35050509392505050565b600060405180602001620007c0906200097b565b6020820181038252601f19601f8201166040525080519060200120905090565b60005461010090046001600160a01b03163314620007fd57600080fd5b6000805460ff1916911515919091179055565b6004546001600160a01b031633146200085e5760405162461bcd60e51b815260206004820152600f60248201526e3737ba103332b29036b0b730b3b2b960891b60448201526064016200047b565b6005811115620008a05760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b60448201526064016200047b565b80600003620008e85760405162461bcd60e51b8152602060048201526013602482015272666565206d757374206265206e6f6e7a65726f60681b60448201526064016200047b565b8115620008f55760025550565b60035550565b6005546001600160a01b03163314620009575760405162461bcd60e51b815260206004820152601760248201527f6e6f742070656e64696e6720666565206d616e6167657200000000000000000060448201526064016200047b565b600554600480546001600160a01b0319166001600160a01b03909216919091179055565b6146d08062000a8c83390190565b6000602082840312156200099c57600080fd5b5035919050565b80356001600160a01b0381168114620009bb57600080fd5b919050565b600060208284031215620009d357600080fd5b620009de82620009a3565b9392505050565b80358015158114620009bb57600080fd5b60006020828403121562000a0957600080fd5b620009de82620009e5565b60008060006060848603121562000a2a57600080fd5b62000a3584620009a3565b925062000a4560208501620009a3565b915062000a5560408501620009e5565b90509250925092565b6000806040838503121562000a7257600080fd5b62000a7d83620009e5565b94602093909301359350505056fe61016060405260006002556000600d556000600e5560016013553480156200002657600080fd5b50336001600160a01b0316610100816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac9190620007c8565b8015156080526001600160a01b0380831660c052831660a052604051929550909350915083908390620000df90620006f7565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562000113573d6000803e3d6000fd5b506001600160a01b031660e05280156200034557826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000166573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000190919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001f9919081019062000863565b6040516020016200020c9291906200091b565b604051602081830303815290604052600090805190602001906200023292919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000272573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200029c919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000305919081019062000863565b6040516020016200031892919062000976565b604051602081830303815290604052600190805190602001906200033e92919062000705565b506200055e565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000384573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620003ae919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000417919081019062000863565b6040516020016200042a929190620009c7565b604051602081830303815290604052600090805190602001906200045092919062000705565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000490573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004ba919081019062000863565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000863565b6040516020016200053692919062000a24565b604051602081830303815290604052600190805190602001906200055c92919062000705565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200059d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c3919062000a46565b620005d090600a62000b87565b6101208181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000617573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200063d919062000a46565b6200064a90600a62000b87565b6101405250506040805160608101825242815260006020820181815292820181815260078054600181018255925291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039092029182015591517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555062000bd4565b610370806200436083390190565b828054620007139062000b98565b90600052602060002090601f01602090048101928262000737576000855562000782565b82601f106200075257805160ff191683800117855562000782565b8280016001018555821562000782579182015b828111156200078257825182559160200191906001019062000765565b506200079092915062000794565b5090565b5b8082111562000790576000815560010162000795565b80516001600160a01b0381168114620007c357600080fd5b919050565b600080600060608486031215620007de57600080fd5b620007e984620007ab565b9250620007f960208501620007ab565b9150604084015180151581146200080f57600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200084d57818101518382015260200162000833565b838111156200085d576000848401525b50505050565b6000602082840312156200087657600080fd5b81516001600160401b03808211156200088e57600080fd5b818401915084601f830112620008a357600080fd5b815181811115620008b857620008b86200081a565b604051601f8201601f19908116603f01168101908382118183101715620008e357620008e36200081a565b81604052828152876020848701011115620008fd57600080fd5b6200091083602083016020880162000830565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b8152600083516200094781600f85016020880162000830565b602f60f81b600f9184019182015283516200096a81601084016020880162000830565b01601001949350505050565b6473414d4d2d60d81b8152600083516200099881600585016020880162000830565b602f60f81b6005918401918201528351620009bb81600684016020880162000830565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b815260008351620009f581601185016020880162000830565b602f60f81b601191840191820152835162000a1881601284016020880162000830565b01601201949350505050565b6476414d4d2d60d81b8152600083516200099881600585016020880162000830565b60006020828403121562000a5957600080fd5b815160ff8116811462000a6b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ac957816000190482111562000aad5762000aad62000a72565b8085161562000abb57918102915b93841c939080029062000a8d565b509250929050565b60008262000ae25750600162000b81565b8162000af15750600062000b81565b816001811462000b0a576002811462000b155762000b35565b600191505062000b81565b60ff84111562000b295762000b2962000a72565b50506001821b62000b81565b5060208310610133831016604e8410600b841016171562000b5a575081810a62000b81565b62000b66838362000a88565b806000190482111562000b7d5762000b7d62000a72565b0290505b92915050565b600062000a6b60ff84168362000ad1565b600181811c9082168062000bad57607f821691505b60208210810362000bce57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161360b62000d55600039600081816104310152818161253701528181612821015281816128e301526129ee01526000818161040e015281816124f6015281816127e20152818161292501526129c80152600081816107b801528181610c0701528181610cd801526120660152600081816105f201528181611c7a0152818161235d015261242a0152600081816104bb0152818161064701528181610714015281816108f301528181610b9b0152818161150f015281816116fa01528181611b21015281816121c301526124090152600081816102f90152818161049301528181610622015281816108d201528181610b7a01528181611479015281816116d801528181611aff0152818161213b0152818161233c01528181612863015281816128aa0152818161298f0152612a320152600081816103970152818161046301528181610bcf01528181610ca001528181612035015281816124ce01526127ae015261360b6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637ecebe0011610151578063bda39cad116100c3578063d294f09311610087578063d294f09314610736578063d505accf1461073e578063dd62ed3e14610751578063ebeb31db1461077c578063f140a35a14610784578063fff6cae91461079757600080fd5b8063bda39cad146106eb578063bf944dbc146106f4578063c245febc146106fd578063c5700a0214610706578063d21220a71461070f57600080fd5b80639d63848a116101155780639d63848a146106145780639e8cc04b146106725780639f767c8814610685578063a1ac4d13146106a5578063a9059cbb146106c5578063bc25cf77146106d857600080fd5b80637ecebe001461057357806389afcb44146105935780638a7b8cf2146105bb57806395d89b41146105e55780639af1d35a146105ed57600080fd5b8063252c09d7116101ea5780634d5a9f8a116101ae5780634d5a9f8a146104f1578063517b3f82146105115780635881c475146105245780635a76f25e146105375780636a6278421461054057806370a082311461055357600080fd5b8063252c09d7146103cc578063313ce567146103df57806332c0defd146103f9578063392f37e914610402578063443cb4bc146104e857600080fd5b806313345fe11161023c57806313345fe11461033357806318160ddd146103535780631df8c7171461036a578063205aabf11461037257806322be3de11461039257806323b872dd146103b957600080fd5b8063022c0d9f1461027957806306fdde031461028e5780630902f1ac146102ac578063095ea7b3146102d15780630dfe1681146102f4575b600080fd5b61028c61028736600461308e565b61079f565b005b610296610eec565b6040516102a39190613152565b60405180910390f35b600854600954600a545b604080519384526020840192909252908201526060016102a3565b6102e46102df366004613185565b610f7a565b60405190151581526020016102a3565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102a3565b6103466103413660046131af565b610fe7565b6040516102a391906131e8565b61035c60025481565b6040519081526020016102a3565b6102b66111e3565b61035c61038036600461322c565b60106020526000908152604090205481565b6102e47f000000000000000000000000000000000000000000000000000000000000000081565b6102e46103c7366004613247565b611252565b6102b66103da366004613283565b61131b565b6103e7601281565b60405160ff90911681526020016102a3565b61035c600d5481565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102a3565b61035c60085481565b61035c6104ff36600461322c565b60116020526000908152604090205481565b61035c61051f366004613185565b61134e565b61034661053236600461329c565b611436565b61035c60095481565b61035c61054e36600461322c565b611445565b61035c61056136600461322c565b60046020526000908152604090205481565b61035c61058136600461322c565b60066020526000908152604090205481565b6105a66105a136600461322c565b6116a6565b604080519283526020830191909152016102a3565b6105c36119c3565b60408051825181526020808401519082015291810151908201526060016102a3565b610296611a43565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102a3565b61035c61068036600461329c565b611a50565b61035c61069336600461322c565b600f6020526000908152604090205481565b61035c6106b336600461322c565b60126020526000908152604090205481565b6102e46106d3366004613185565b611abd565b61028c6106e636600461322c565b611ad3565b61035c600e5481565b61035c600b5481565b61035c600c5481565b61035c600a5481565b61031b7f000000000000000000000000000000000000000000000000000000000000000081565b6105a6611bf1565b61028c61074c3660046132cf565b611d18565b61035c61075f366004613342565b600360209081526000928352604080842090915290825290205481565b60075461035c565b61035c610792366004613375565b612020565b61028c61210e565b6013546001146107ae57600080fd5b60026013819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190613398565b1561084257600080fd5b60008511806108515750600084115b6108885760405162461bcd60e51b8152602060048201526003602482015262494f4160e81b60448201526064015b60405180910390fd5b600854600954818710801561089c57508086105b6108cd5760405162461bcd60e51b8152602060048201526002602482015261125360f21b604482015260640161087f565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03898116908316148015906109405750806001600160a01b0316896001600160a01b031614155b6109715760405162461bcd60e51b8152602060048201526002602482015261125560f21b604482015260640161087f565b8a1561098257610982828a8d612248565b891561099357610993818a8c612248565b8615610a0057604051639a7bff7960e01b81526001600160a01b038a1690639a7bff79906109cd9033908f908f908e908e906004016133ba565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad39190613406565b9250505060008985610ae59190613435565b8311610af2576000610b06565b610afc8a86613435565b610b069084613435565b90506000610b148a86613435565b8311610b21576000610b35565b610b2b8a86613435565b610b359084613435565b90506000821180610b465750600081115b610b785760405162461bcd60e51b815260206004820152600360248201526249494160e81b604482015260640161087f565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610c8b57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610c8b90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c729190613406565b610c7c908761344c565b610c86919061346b565b612337565b8215610d5c57604051632895a2f560e11b81527f000000000000000000000000000000000000000000000000000000000000000015156004820152610d5c90612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063512b45ea90602401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190613406565b610d4d908661344c565b610d57919061346b565b612404565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613406565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f9190613406565b9450610e3b88886124ca565b610e4587876124ca565b1015610e775760405162461bcd60e51b81526020600482015260016024820152604b60f81b604482015260640161087f565b5050610e8584848888612616565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001601355505050505050505050565b60008054610ef99061348d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f259061348d565b8015610f725780601f10610f4757610100808354040283529160200191610f72565b820191906000526020600020905b815481529060010190602001808311610f5557829003601f168201915b505050505081565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610fd59086815260200190565b60405180910390a35060015b92915050565b606060008367ffffffffffffffff811115611004576110046134c1565b60405190808252806020026020018201604052801561102d578160200160208202803683370190505b5060075490915060009061104390600190613435565b90506000611051858761344c565b61105b9083613435565b90506000805b838310156111d35761107387846134d7565b915060006007848154811061108a5761108a6134ef565b906000526020600020906003020160000154600784815481106110af576110af6134ef565b9060005260206000209060030201600001546110cb9190613435565b9050600081600786815481106110e3576110e36134ef565b90600052602060002090600302016001015460078681548110611108576111086134ef565b9060005260206000209060030201600101546111249190613435565b61112e919061346b565b905060008260078781548110611146576111466134ef565b9060005260206000209060030201600201546007878154811061116b5761116b6134ef565b9060005260206000209060030201600201546111879190613435565b611191919061346b565b905061119f8c8e84846127aa565b8885815181106111b1576111b16134ef565b60209081029190910101525050506001016111cc87846134d7565b9250611061565b509293505050505b949350505050565b600b54600c544260008080611201600854600954600a549192909190565b92509250925083811461124a57600061121a8286613435565b9050611226818561344c565b61123090886134d7565b965061123c818461344c565b61124690876134d7565b9550505b505050909192565b6001600160a01b03831660008181526003602090815260408083203380855292528220549192909190821480159061128c57506000198114155b1561130257600061129d8583613435565b6001600160a01b038881166000818152600360209081526040808320948916808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61130d868686612a9f565b6001925050505b9392505050565b6007818154811061132b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806113596119c3565b90506000806113666111e3565b508451919350915042036113ce576007805461138490600290613435565b81548110611394576113946134ef565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b82516000906113dd9042613435565b90506000818560200151856113f29190613435565b6113fc919061346b565b90506000828660400151856114119190613435565b61141b919061346b565b9050611429888a84846127aa565b9998505050505050505050565b60606111db8484846001610fe7565b600060135460011461145657600080fd5b60026013556008546009546040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156114c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ec9190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611556573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157a9190613406565b905060006115888584613435565b905060006115968584613435565b60025490915060008190036115d8576103e86115ba6115b5848661344c565b612b5f565b6115c49190613435565b97506115d360006103e8612bcf565b61160d565b61160a876115e6838661344c565b6115f0919061346b565b876115fb848661344c565b611605919061346b565b612c62565b97505b600088116116435760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b604482015260640161087f565b61164d8989612bcf565b61165985858989612616565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001601355509395945050505050565b6000806013546001146116b857600080fd5b60026013556008546009546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190613406565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e09190613406565b306000908152600460205260409020546002549192509080611802858461344c565b61180c919061346b565b995080611819848461344c565b611823919061346b565b985060008a1180156118355750600089115b6118675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b604482015260640161087f565b6118713083612c78565b61187c868c8c612248565b611887858c8b612248565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa1580156118cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ef9190613406565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a9190613406565b925061196884848a8a612616565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001601381905550915091565b6119e760405180606001604052806000815260200160008152602001600081525090565b600780546119f790600190613435565b81548110611a0757611a076134ef565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60018054610ef99061348d565b600080611a608585856001610fe7565b90506000805b8251811015611aa857828181518110611a8157611a816134ef565b602002602001015182611a9491906134d7565b915080611aa081613505565b915050611a66565b50611ab3848261346b565b9695505050505050565b6000611aca338484612a9f565b50600192915050565b601354600114611ae257600080fd5b60026013556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611baf9184918691906001600160a01b038416906370a08231906024015b602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba09190613406565b611baa9190613435565b612248565b6009546040516370a0823160e01b8152306004820152611be79183918691906001600160a01b038416906370a0823190602401611b5f565b5050600160135550565b600080611bfd33612d03565b50503360009081526011602090815260408083205460129092529091205481151580611c295750600081115b15611d14573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611cbe57600080fd5b505af1158015611cd2573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611d585760405162461bcd60e51b815260206004820152600d60248201526c14185a5c8e8811561412549151609a1b604482015260640161087f565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611d88919061351e565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152918152815160209283012060058190556001600160a01b038a166000908152600690935290822080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611e5383613505565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ecc92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611f37573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611f6d5750886001600160a01b0316816001600160a01b0316145b611fb95760405162461bcd60e51b815260206004820152601760248201527f506169723a20494e56414c49445f5349474e4154555245000000000000000000604482015260640161087f565b6001600160a01b038981166000818152600360209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954604051632895a2f560e11b81527f0000000000000000000000000000000000000000000000000000000000000000151560048201526000929190612710907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063512b45ea90602401602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190613406565b6120e3908761344c565b6120ed919061346b565b6120f79086613435565b9450612105858584846127aa565b95945050505050565b60135460011461211d57600080fd5b60026013556040516370a0823160e01b8152306004820152612241907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ae9190613406565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122369190613406565b600854600954612616565b6001601355565b6000836001600160a01b03163b1161225f57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916122bb91906135b9565b6000604051808303816000865af19150503d80600081146122f8576040519150601f19603f3d011682016040523d82523d6000602084013e6122fd565b606091505b50915091508180156123275750805115806123275750808060200190518101906123279190613398565b61233057600080fd5b5050505050565b6123827f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061239a83670de0b6b3a764000061344c565b6123a4919061346b565b905080156123c45780600d60008282546123be91906134d7565b90915550505b604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a25050565b61244f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083612248565b60025460009061246783670de0b6b3a764000061344c565b612471919061346b565b905080156124915780600e600082825461248b91906134d7565b90915550505b60408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291016123f8565b60007f0000000000000000000000000000000000000000000000000000000000000000156126055760007f000000000000000000000000000000000000000000000000000000000000000061252785670de0b6b3a764000061344c565b612531919061346b565b905060007f000000000000000000000000000000000000000000000000000000000000000061256885670de0b6b3a764000061344c565b612572919061346b565b90506000670de0b6b3a7640000612589838561344c565b612593919061346b565b90506000670de0b6b3a76400006125aa848061344c565b6125b4919061346b565b670de0b6b3a76400006125c7868061344c565b6125d1919061346b565b6125db91906134d7565b9050670de0b6b3a76400006125f0828461344c565b6125fa919061346b565b945050505050610fe1565b61260f828461344c565b9050610fe1565b600a5442906000906126289083613435565b905060008111801561263957508315155b801561264457508215155b1561268b57612653818561344c565b600b600082825461266491906134d7565b909155506126749050818461344c565b600c600082825461268591906134d7565b90915550505b60006126956119c3565b80519091506126a49084613435565b91506107088211156127595760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612a2d5760006127de84846124ca565b90507f000000000000000000000000000000000000000000000000000000000000000061281385670de0b6b3a764000061344c565b61281d919061346b565b93507f000000000000000000000000000000000000000000000000000000000000000061285284670de0b6b3a764000061344c565b61285c919061346b565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146128a15784866128a4565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612923577f000000000000000000000000000000000000000000000000000000000000000061291489670de0b6b3a764000061344c565b61291e919061346b565b612960565b7f000000000000000000000000000000000000000000000000000000000000000061295689670de0b6b3a764000061344c565b612960919061346b565b97506000612978612971848b6134d7565b8584612e63565b6129829083613435565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316146129ec577f0000000000000000000000000000000000000000000000000000000000000000612a0e565b7f00000000000000000000000000000000000000000000000000000000000000005b612a18908361344c565b612a22919061346b565b9450505050506111db565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612a70578385612a73565b84845b9092509050612a8287836134d7565b612a8c828961344c565b612a96919061346b565b925050506111db565b612aa883612d03565b612ab182612d03565b6001600160a01b03831660009081526004602052604081208054839290612ad9908490613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612b069084906134d7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612b5291815260200190565b60405180910390a3505050565b60006003821115612bc05750806000612b7960028361346b565b612b849060016134d7565b90505b81811015612bba57905080600281612b9f818661346b565b612ba991906134d7565b612bb3919061346b565b9050612b87565b50919050565b8115612bca575060015b919050565b612bd882612d03565b8060026000828254612bea91906134d7565b90915550506001600160a01b03821660009081526004602052604081208054839290612c179084906134d7565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612c715781611314565b5090919050565b612c8182612d03565b8060026000828254612c939190613435565b90915550506001600160a01b03821660009081526004602052604081208054839290612cc0908490613435565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c56565b6001600160a01b0381166000908152600460205260409020548015612e31576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612d658584613435565b90506000612d738584613435565b90508115612dce576000670de0b6b3a7640000612d90848a61344c565b612d9a919061346b565b6001600160a01b038a16600090815260116020526040812080549293508392909190612dc79084906134d7565b9091555050505b8015612e27576000670de0b6b3a7640000612de9838a61344c565b612df3919061346b565b6001600160a01b038a16600090815260126020526040812080549293508392909190612e209084906134d7565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b6000805b60ff811015612f6957826000612e7d8783612f72565b905085811015612ecd576000612e93888761300f565b612e9d8389613435565b612eaf90670de0b6b3a764000061344c565b612eb9919061346b565b9050612ec581876134d7565b955050612f0f565b6000612ed9888761300f565b612ee38884613435565b612ef590670de0b6b3a764000061344c565b612eff919061346b565b9050612f0b8187613435565b9550505b81851115612f38576001612f238387613435565b11612f3357849350505050611314565b612f54565b6001612f448684613435565b11612f5457849350505050611314565b50508080612f6190613505565b915050612e67565b50909392505050565b6000670de0b6b3a764000082818581612f8b828061344c565b612f95919061346b565b612f9f919061344c565b612fa9919061346b565b612fb3919061344c565b612fbd919061346b565b670de0b6b3a7640000808481612fd3828061344c565b612fdd919061346b565b612fe7919061344c565b612ff1919061346b565b612ffb908661344c565b613005919061346b565b61131491906134d7565b6000670de0b6b3a76400008381613026828061344c565b613030919061346b565b61303a919061344c565b613044919061346b565b670de0b6b3a764000080613058858061344c565b613062919061346b565b61306d86600361344c565b612ffb919061344c565b80356001600160a01b0381168114612bca57600080fd5b6000806000806000608086880312156130a657600080fd5b85359450602086013593506130bd60408701613077565b9250606086013567ffffffffffffffff808211156130da57600080fd5b818801915088601f8301126130ee57600080fd5b8135818111156130fd57600080fd5b89602082850101111561310f57600080fd5b9699959850939650602001949392505050565b60005b8381101561313d578181015183820152602001613125565b8381111561314c576000848401525b50505050565b6020815260008251806020840152613171816040850160208701613122565b601f01601f19169190910160400192915050565b6000806040838503121561319857600080fd5b6131a183613077565b946020939093013593505050565b600080600080608085870312156131c557600080fd5b6131ce85613077565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b8181101561322057835183529284019291840191600101613204565b50909695505050505050565b60006020828403121561323e57600080fd5b61131482613077565b60008060006060848603121561325c57600080fd5b61326584613077565b925061327360208501613077565b9150604084013590509250925092565b60006020828403121561329557600080fd5b5035919050565b6000806000606084860312156132b157600080fd5b6132ba84613077565b95602085013595506040909401359392505050565b600080600080600080600060e0888a0312156132ea57600080fd5b6132f388613077565b965061330160208901613077565b95506040880135945060608801359350608088013560ff8116811461332557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561335557600080fd5b61335e83613077565b915061336c60208401613077565b90509250929050565b6000806040838503121561338857600080fd5b8235915061336c60208401613077565b6000602082840312156133aa57600080fd5b8151801515811461131457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020828403121561341857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156134475761344761341f565b500390565b60008160001904831182151516156134665761346661341f565b500290565b60008261348857634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806134a157607f821691505b602082108103612bba57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600082198211156134ea576134ea61341f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016135175761351761341f565b5060010190565b600080835481600182811c91508083168061353a57607f831692505b6020808410820361355957634e487b7160e01b86526022600452602486fd5b81801561356d576001811461357e576135ab565b60ff198616895284890196506135ab565b60008a81526020902060005b868110156135a35781548b82015290850190830161358a565b505084890196505b509498975050505050505050565b600082516135cb818460208701613122565b919091019291505056fea2646970667358221220270f4e3352962d1c128c52f446c9e0a94cfd4293f1f3d44b28a148af57736d1a64736f6c634300080d003360e060405234801561001057600080fd5b5060405161037038038061037083398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516102ab6100c5600039600060b601526000608501526000605001526102ab6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e3660046101d0565b610045565b005b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461007a57600080fd5b81156100ab576100ab7f000000000000000000000000000000000000000000000000000000000000000084846100e1565b80156100dc576100dc7f000000000000000000000000000000000000000000000000000000000000000084836100e1565b505050565b6000836001600160a01b03163b116100f857600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916101549190610211565b6000604051808303816000865af19150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50915091508180156101c05750805115806101c05750808060200190518101906101c0919061024c565b6101c957600080fd5b5050505050565b6000806000606084860312156101e557600080fd5b83356001600160a01b03811681146101fc57600080fd5b95602085013595506040909401359392505050565b6000825160005b818110156102325760208186018101518583015201610218565b81811115610241576000828501525b509190910192915050565b60006020828403121561025e57600080fd5b8151801515811461026e57600080fd5b939250505056fea26469706673582212204d9e84053035e063a46827cca65ab59fad4e23ed0078ae98f8e2cc371de9f9ef64736f6c634300080d0033a2646970667358221220dfffcd46a9d232648bdc2dd9222c658d5554eef6a609556964e00d872e0d720d64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 21428, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "isPaused", + "offset": 0, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 21430, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "pauser", + "offset": 1, + "slot": "0", + "type": "t_address" + }, + { + "astId": 21432, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "pendingPauser", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 21434, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "stableFee", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 21436, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "volatileFee", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 21441, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "feeManager", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 21443, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "pendingFeeManager", + "offset": 0, + "slot": "5", + "type": "t_address" + }, + { + "astId": 21451, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "getPair", + "offset": 0, + "slot": "6", + "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_bool,t_address)))" + }, + { + "astId": 21454, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "allPairs", + "offset": 0, + "slot": "7", + "type": "t_array(t_address)dyn_storage" + }, + { + "astId": 21458, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "isPair", + "offset": 0, + "slot": "8", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 21460, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "_temp0", + "offset": 0, + "slot": "9", + "type": "t_address" + }, + { + "astId": 21462, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "_temp1", + "offset": 0, + "slot": "10", + "type": "t_address" + }, + { + "astId": 21464, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "_temp", + "offset": 20, + "slot": "10", + "type": "t_bool" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "base": "t_address", + "encoding": "dynamic_array", + "label": "address[]", + "numberOfBytes": "32" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_address,t_mapping(t_address,t_mapping(t_bool,t_address)))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => mapping(bool => address)))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_mapping(t_bool,t_address))" + }, + "t_mapping(t_address,t_mapping(t_bool,t_address))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(bool => address))", + "numberOfBytes": "32", + "value": "t_mapping(t_bool,t_address)" + }, + "t_mapping(t_bool,t_address)": { + "encoding": "mapping", + "key": "t_bool", + "label": "mapping(bool => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumOne/RedemptionReceiver.json b/deployments/arbitrumOneOLD/RedemptionReceiver.json similarity index 100% rename from deployments/arbitrumOne/RedemptionReceiver.json rename to deployments/arbitrumOneOLD/RedemptionReceiver.json diff --git a/deployments/arbitrumOneOLD/RewardsDistributor.json b/deployments/arbitrumOneOLD/RewardsDistributor.json new file mode 100644 index 00000000..2536ab7d --- /dev/null +++ b/deployments/arbitrumOneOLD/RewardsDistributor.json @@ -0,0 +1,520 @@ +{ + "address": "0xd9891738458A5b1F1EfB5f82183b77c666d9064E", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_voting_escrow", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "time", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "CheckpointToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "claim_epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "max_epoch", + "type": "uint256" + } + ], + "name": "Claimed", + "type": "event" + }, + { + "inputs": [], + "name": "checkpoint_token", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "checkpoint_total_supply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "claim", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "_tokenIds", + "type": "uint256[]" + } + ], + "name": "claim_many", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "claimable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "depositor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "last_token_time", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_depositor", + "type": "address" + } + ], + "name": "setDepositor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "start_time", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "time_cursor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "time_cursor_of", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "timestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token_last_balance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "tokens_per_week", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "user_epoch_of", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_timestamp", + "type": "uint256" + } + ], + "name": "ve_for_at", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "ve_supply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "voting_escrow", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xe554178d001c647246f9fa171b880e693ee215d6d4368948f9b6ceaab032ad0e", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0xd9891738458A5b1F1EfB5f82183b77c666d9064E", + "transactionIndex": 1, + "gasUsed": "11169043", + "logsBloom": "0x00000000000000000000000008000000000000000000000000000000000000000000000000000000000000002000000000000008000000000000000000240000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000408000000001000000000000000000000000000000000000", + "blockHash": "0xa69e0e8d19a1dbf3e8917d55c7d42c64e52fd279b93d02d2c7eda3a98a2ed9b6", + "transactionHash": "0xe554178d001c647246f9fa171b880e693ee215d6d4368948f9b6ceaab032ad0e", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 53774100, + "transactionHash": "0xe554178d001c647246f9fa171b880e693ee215d6d4368948f9b6ceaab032ad0e", + "address": "0xC33f7f83CbB021846Cb9c58f2d8E3df428dbC8C1", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000d9891738458a5b1f1efb5f82183b77c666d9064e", + "0x00000000000000000000000010df81252069c1095f541faca61646cb9ae76703" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 0, + "blockHash": "0xa69e0e8d19a1dbf3e8917d55c7d42c64e52fd279b93d02d2c7eda3a98a2ed9b6" + } + ], + "blockNumber": 53774100, + "cumulativeGasUsed": "11169043", + "status": 1, + "byzantium": true + }, + "args": [ + "0x10Df81252069C1095F541FAca61646cb9Ae76703" + ], + "numDeployments": 1, + "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voting_escrow\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"time\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"CheckpointToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"claim_epoch\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"max_epoch\",\"type\":\"uint256\"}],\"name\":\"Claimed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"checkpoint_token\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint_total_supply\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"_tokenIds\",\"type\":\"uint256[]\"}],\"name\":\"claim_many\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_token_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"}],\"name\":\"setDepositor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"start_time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"time_cursor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"time_cursor_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token_last_balance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"tokens_per_week\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_epoch_of\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"ve_for_at\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ve_supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voting_escrow\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RewardsDistributor.sol\":\"RewardsDistributor\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IRewardsDistributor.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/*\\n\\n@title Curve Fee Distribution modified for ve(3,3) emissions\\n@author Curve Finance, andrecronje\\n@license MIT\\n\\n*/\\n\\ncontract RewardsDistributor is IRewardsDistributor {\\n event CheckpointToken(uint256 time, uint256 tokens);\\n\\n event Claimed(\\n uint256 tokenId,\\n uint256 amount,\\n uint256 claim_epoch,\\n uint256 max_epoch\\n );\\n\\n uint256 constant WEEK = 7 * 86400;\\n\\n uint256 public start_time;\\n uint256 public time_cursor;\\n mapping(uint256 => uint256) public time_cursor_of;\\n mapping(uint256 => uint256) public user_epoch_of;\\n\\n uint256 public last_token_time;\\n uint256[1000000000000000] public tokens_per_week;\\n\\n address public voting_escrow;\\n address public token;\\n uint256 public token_last_balance;\\n\\n uint256[1000000000000000] public ve_supply;\\n\\n address public depositor;\\n\\n constructor(address _voting_escrow) {\\n uint256 _t = (block.timestamp / WEEK) * WEEK;\\n start_time = _t;\\n last_token_time = _t;\\n time_cursor = _t;\\n address _token = IVotingEscrow(_voting_escrow).token();\\n token = _token;\\n voting_escrow = _voting_escrow;\\n depositor = msg.sender;\\n require(IERC20(_token).approve(_voting_escrow, type(uint256).max));\\n }\\n\\n function timestamp() external view returns (uint256) {\\n return (block.timestamp / WEEK) * WEEK;\\n }\\n\\n function _checkpoint_token() internal {\\n uint256 token_balance = IERC20(token).balanceOf(address(this));\\n uint256 to_distribute = token_balance - token_last_balance;\\n token_last_balance = token_balance;\\n\\n uint256 t = last_token_time;\\n uint256 since_last = block.timestamp - t;\\n last_token_time = block.timestamp;\\n uint256 this_week = (t / WEEK) * WEEK;\\n uint256 next_week = 0;\\n\\n for (uint256 i = 0; i < 20; i++) {\\n next_week = this_week + WEEK;\\n if (block.timestamp < next_week) {\\n if (since_last == 0 && block.timestamp == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (block.timestamp - t)) /\\n since_last;\\n }\\n break;\\n } else {\\n if (since_last == 0 && next_week == t) {\\n tokens_per_week[this_week] += to_distribute;\\n } else {\\n tokens_per_week[this_week] +=\\n (to_distribute * (next_week - t)) /\\n since_last;\\n }\\n }\\n t = next_week;\\n this_week = next_week;\\n }\\n emit CheckpointToken(block.timestamp, to_distribute);\\n }\\n\\n function checkpoint_token() external {\\n assert(msg.sender == depositor);\\n _checkpoint_token();\\n }\\n\\n function _find_timestamp_epoch(address ve, uint256 _timestamp)\\n internal\\n view\\n returns (uint256)\\n {\\n uint256 _min = 0;\\n uint256 _max = IVotingEscrow(ve).epoch();\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n _mid\\n );\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function _find_timestamp_user_epoch(\\n address ve,\\n uint256 tokenId,\\n uint256 _timestamp,\\n uint256 max_user_epoch\\n ) internal view returns (uint256) {\\n uint256 _min = 0;\\n uint256 _max = max_user_epoch;\\n for (uint256 i = 0; i < 128; i++) {\\n if (_min >= _max) break;\\n uint256 _mid = (_min + _max + 2) / 2;\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve)\\n .user_point_history(tokenId, _mid);\\n if (pt.ts <= _timestamp) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n function ve_for_at(uint256 _tokenId, uint256 _timestamp)\\n external\\n view\\n returns (uint256)\\n {\\n address ve = voting_escrow;\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _timestamp,\\n max_user_epoch\\n );\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n epoch\\n );\\n return\\n MathDunks.max(\\n uint256(\\n int256(\\n pt.bias -\\n pt.slope *\\n (int128(int256(_timestamp - pt.ts)))\\n )\\n ),\\n 0\\n );\\n }\\n\\n function _checkpoint_total_supply() internal {\\n address ve = voting_escrow;\\n uint256 t = time_cursor;\\n uint256 rounded_timestamp = (block.timestamp / WEEK) * WEEK;\\n IVotingEscrow(ve).checkpoint();\\n\\n for (uint256 i = 0; i < 20; i++) {\\n if (t > rounded_timestamp) {\\n break;\\n } else {\\n uint256 epoch = _find_timestamp_epoch(ve, t);\\n IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(\\n epoch\\n );\\n int128 dt = 0;\\n if (t > pt.ts) {\\n dt = int128(int256(t - pt.ts));\\n }\\n ve_supply[t] = MathDunks.max(\\n uint256(int256(pt.bias - pt.slope * dt)),\\n 0\\n );\\n }\\n t += WEEK;\\n }\\n time_cursor = t;\\n }\\n\\n function checkpoint_total_supply() external {\\n _checkpoint_total_supply();\\n }\\n\\n function _claim(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n user_epoch = MathDunks.min(max_user_epoch, user_epoch - 1);\\n user_epoch_of[_tokenId] = user_epoch;\\n time_cursor_of[_tokenId] = week_cursor;\\n\\n emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);\\n\\n return to_distribute;\\n }\\n\\n function _claimable(\\n uint256 _tokenId,\\n address ve,\\n uint256 _last_token_time\\n ) internal view returns (uint256) {\\n uint256 user_epoch = 0;\\n uint256 to_distribute = 0;\\n\\n uint256 max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);\\n uint256 _start_time = start_time;\\n\\n if (max_user_epoch == 0) return 0;\\n\\n uint256 week_cursor = time_cursor_of[_tokenId];\\n if (week_cursor == 0) {\\n user_epoch = _find_timestamp_user_epoch(\\n ve,\\n _tokenId,\\n _start_time,\\n max_user_epoch\\n );\\n } else {\\n user_epoch = user_epoch_of[_tokenId];\\n }\\n\\n if (user_epoch == 0) user_epoch = 1;\\n\\n IVotingEscrow.Point memory user_point = IVotingEscrow(ve)\\n .user_point_history(_tokenId, user_epoch);\\n\\n if (week_cursor == 0)\\n week_cursor = ((user_point.ts + WEEK - 1) / WEEK) * WEEK;\\n if (week_cursor >= last_token_time) return 0;\\n if (week_cursor < _start_time) week_cursor = _start_time;\\n\\n IVotingEscrow.Point memory old_user_point;\\n\\n for (uint256 i = 0; i < 50; i++) {\\n if (week_cursor >= _last_token_time) break;\\n\\n if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {\\n user_epoch += 1;\\n old_user_point = user_point;\\n if (user_epoch > max_user_epoch) {\\n user_point = IVotingEscrow.Point(0, 0, 0, 0);\\n } else {\\n user_point = IVotingEscrow(ve).user_point_history(\\n _tokenId,\\n user_epoch\\n );\\n }\\n } else {\\n int128 dt = int128(int256(week_cursor - old_user_point.ts));\\n uint256 balance_of = MathDunks.max(\\n uint256(\\n int256(old_user_point.bias - dt * old_user_point.slope)\\n ),\\n 0\\n );\\n if (balance_of == 0 && user_epoch > max_user_epoch) break;\\n if (balance_of != 0) {\\n to_distribute +=\\n (balance_of * tokens_per_week[week_cursor]) /\\n ve_supply[week_cursor];\\n }\\n week_cursor += WEEK;\\n }\\n }\\n\\n return to_distribute;\\n }\\n\\n function claimable(uint256 _tokenId) external view returns (uint256) {\\n uint256 _last_token_time = (last_token_time / WEEK) * WEEK;\\n return _claimable(_tokenId, voting_escrow, _last_token_time);\\n }\\n\\n function claim(uint256 _tokenId) external returns (uint256) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n uint256 amount = _claim(_tokenId, voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);\\n token_last_balance -= amount;\\n }\\n return amount;\\n }\\n\\n function claim_many(uint256[] memory _tokenIds) external returns (bool) {\\n if (block.timestamp >= time_cursor) _checkpoint_total_supply();\\n uint256 _last_token_time = last_token_time;\\n _last_token_time = (_last_token_time / WEEK) * WEEK;\\n address _voting_escrow = voting_escrow;\\n uint256 total = 0;\\n\\n for (uint256 i = 0; i < _tokenIds.length; i++) {\\n uint256 _tokenId = _tokenIds[i];\\n if (_tokenId == 0) break;\\n uint256 amount = _claim(_tokenId, _voting_escrow, _last_token_time);\\n if (amount != 0) {\\n IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);\\n total += amount;\\n }\\n }\\n if (total != 0) {\\n token_last_balance -= total;\\n }\\n\\n return true;\\n }\\n\\n // Once off event on contract initialize\\n function setDepositor(address _depositor) external {\\n require(msg.sender == depositor);\\n depositor = _depositor;\\n }\\n}\\n\",\"keccak256\":\"0xdbcfb11d65c6ca7d63baba42fb2f1222478c6ca78d8e81970032eff5e034e09b\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IRewardsDistributor.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRewardsDistributor {\\n function checkpoint_token() external;\\n function checkpoint_total_supply() external;\\n}\\n\",\"keccak256\":\"0x34c330b70b2b8847a6afce921a69eed82d1ecb3d2a0ee61401619a7b28e69243\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b5060405162001b9f38038062001b9f83398101604081905262000034916200019f565b600062093a80620000468142620001d1565b620000529190620001f4565b90508060008190555080600481905550806001819055506000826001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000aa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d091906200019f565b66038d7ea4c6800680546001600160a01b038381166001600160a01b0319928316811790935566038d7ea4c6800580549188169183168217905566071afd498d00088054909216331790915560405163095ea7b360e01b8152600481019190915260001960248201529192509063095ea7b3906044016020604051808303816000875af115801562000166573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200018c919062000222565b6200019657600080fd5b50505062000246565b600060208284031215620001b257600080fd5b81516001600160a01b0381168114620001ca57600080fd5b9392505050565b600082620001ef57634e487b7160e01b600052601260045260246000fd5b500490565b60008160001904831182151516156200021d57634e487b7160e01b600052601160045260246000fd5b500290565b6000602082840312156200023557600080fd5b81518015158114620001ca57600080fd5b61194980620002566000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea26469706673582212201bd70ac15ed6cd0b251036f174a839aeb92aa432fe7d09fa6cb45a0a25d2cda964736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611567565b60036020526000908152604090205481565b6101756101703660046115c7565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611567565b6103fb565b61012f6101b5366004611567565b60026020526000908152604090205481565b61012f6101d536600461166d565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611567565b610679565b61012f610258366004611567565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611567565b6106dc565b6101eb61029736600461168f565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116ce565b6102e391906116f0565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170f565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611725565b93505b505080806103c39061173d565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611756565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116ce565b61042991906116f0565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611756565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176d565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179d565b905061061d8160400151876105f89190611756565b8260200151610607919061180f565b825161061391906118ad565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fd565b610650610e09565b565b610650610737565b600062093a8061066a81426116ce565b61067491906116f0565b905090565b60008062093a808060045461068e91906116ce565b61069891906116f0565b66038d7ea4c68005549091506104de9084906001600160a01b031683611066565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116ce565b61076991906116f0565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611403565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179d565b90506000816040015186111561086e57604082015161086b9087611756565b90505b61088d818360200151610881919061180f565b835161061391906118ad565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170f565b01555050506108be62093a8084611725565b9250806108ca8161173d565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176d565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179d565b905081600003610a685762093a8080600162093a808460400151610a479190611725565b610a519190611756565b610a5b91906116ce565b610a6591906116f0565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611725565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179d565b9250610c61565b6000826040015185610bae9190611756565b90506000610bd1846020015183610bc5919061180f565b855161061391906118ad565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170f565b015460058766038d7ea4c680008110610c2c57610c2c61170f565b0154610c3890836116f0565b610c4291906116ce565b610c4c908a611725565b98505b610c5c62093a8087611725565b955050505b80610c6b8161173d565b915050610ab1565b50610c8885610c8360018a611756565b611558565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611725565b610d2e906002611725565b610d3891906116ce565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179d565b905087816040015111610dc357819450610dd1565b610dce600183611756565b93505b50508080610dde9061173d565b915050610d04565b50909695505050505050565b600081831015610e0257816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c919061176d565b9050600066038d7ea4c680075482610e949190611756565b66038d7ea4c680078390556004549091506000610eb18242611756565b426004559050600062093a80610ec781856116ce565b610ed191906116f0565b90506000805b601481101561102457610eed62093a8084611725565b915081421015610f765783158015610f0457508442145b15610f3e578560058466038d7ea4c680008110610f2357610f2361170f565b016000828254610f339190611725565b909155506110249050565b83610f498642611756565b610f5390886116f0565b610f5d91906116ce565b60058466038d7ea4c680008110610f2357610f2361170f565b83158015610f8357508482145b15610fbd578560058466038d7ea4c680008110610fa257610fa261170f565b016000828254610fb29190611725565b9091555061100b9050565b83610fc88684611756565b610fd290886116f0565b610fdc91906116ce565b60058466038d7ea4c680008110610ff557610ff561170f565b0160008282546110059190611725565b90915550505b819450819250808061101c9061173d565b915050610ed7565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d8919061176d565b600080549192508290036110f35760009450505050506104de565b6000888152600260205260408120549081900361111d57611116888a8486610cfe565b945061112f565b60008981526003602052604090205494505b8460000361113c57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af919061179d565b9050816000036111f45762093a8080600162093a8084604001516111d39190611725565b6111dd9190611756565b6111e791906116ce565b6111f191906116f0565b91505b600454821061120c57600096505050505050506104de565b82821015611218578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f357898410156113f357826040015184101580156112625750858811155b1561132857611272600189611725565b9750829150858811156112b15760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e1565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611321919061179d565b92506113e1565b600082604001518561133a9190611756565b90506000611351846020015183610bc5919061180f565b9050801580156113605750878a115b1561136c5750506113f3565b80156113cf5766038d7ea4c680088666038d7ea4c6800081106113915761139161170f565b015460058766038d7ea4c6800081106113ac576113ac61170f565b01546113b890836116f0565b6113c291906116ce565b6113cc908a611725565b98505b6113dc62093a8087611725565b955050505b806113eb8161173d565b91505061123d565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e919061176d565b905060005b608081101561154e578183101561154e57600060026114928486611725565b61149d906002611725565b6114a791906116ce565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611516919061179d565b90508681604001511161152b57819450611539565b611536600183611756565b93505b505080806115469061173d565b915050611473565b5090949350505050565b6000818310610e0257816104de565b60006020828403121561157957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115bf576115bf611580565b604052919050565b600060208083850312156115da57600080fd5b823567ffffffffffffffff808211156115f257600080fd5b818501915085601f83011261160657600080fd5b81358181111561161857611618611580565b8060051b9150611629848301611596565b818152918301840191848101908884111561164357600080fd5b938501935b8385101561166157843582529385019390850190611648565b98975050505050505050565b6000806040838503121561168057600080fd5b50508035926020909101359150565b6000602082840312156116a157600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116eb57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561170a5761170a6116b8565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611738576117386116b8565b500190565b60006001820161174f5761174f6116b8565b5060010190565b600082821015611768576117686116b8565b500390565b60006020828403121561177f57600080fd5b5051919050565b8051600f81900b811461179857600080fd5b919050565b6000608082840312156117af57600080fd5b6040516080810181811067ffffffffffffffff821117156117d2576117d2611580565b6040526117de83611786565b81526117ec60208401611786565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183f5761183f6116b8565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186b5761186b6116b8565b60008712925085820587128484161615611887576118876116b8565b8585058712818416161561189d5761189d6116b8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d8576118d86116b8565b8160016001607f1b030183138116156118f3576118f36116b8565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea26469706673582212201bd70ac15ed6cd0b251036f174a839aeb92aa432fe7d09fa6cb45a0a25d2cda964736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 9410, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "start_time", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 9412, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "time_cursor", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 9416, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "time_cursor_of", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 9420, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "user_epoch_of", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 9422, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "last_token_time", + "offset": 0, + "slot": "4", + "type": "t_uint256" + }, + { + "astId": 9426, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "tokens_per_week", + "offset": 0, + "slot": "5", + "type": "t_array(t_uint256)1000000000000000_storage" + }, + { + "astId": 9428, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "voting_escrow", + "offset": 0, + "slot": "1000000000000005", + "type": "t_address" + }, + { + "astId": 9430, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "token", + "offset": 0, + "slot": "1000000000000006", + "type": "t_address" + }, + { + "astId": 9432, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "token_last_balance", + "offset": 0, + "slot": "1000000000000007", + "type": "t_uint256" + }, + { + "astId": 9436, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "ve_supply", + "offset": 0, + "slot": "1000000000000008", + "type": "t_array(t_uint256)1000000000000000_storage" + }, + { + "astId": 9438, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "depositor", + "offset": 0, + "slot": "2000000000000008", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)1000000000000000_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[1000000000000000]", + "numberOfBytes": "32000000000000000" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumOneOLD/Router.json b/deployments/arbitrumOneOLD/Router.json new file mode 100644 index 00000000..b4febac4 --- /dev/null +++ b/deployments/arbitrumOneOLD/Router.json @@ -0,0 +1,1021 @@ +{ + "address": "0x07d2FCFa095d52652cBC664F105F2d9Fb3799a47", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_factory", + "type": "address" + }, + { + "internalType": "address", + "name": "_weth", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "internalType": "struct Router.route[]", + "name": "routes", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "UNSAFE_swapExactTokensForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "amountADesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBDesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountAMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "addLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "amountTokenDesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountTokenMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETHMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "addLiquidityETH", + "outputs": [ + { + "internalType": "uint256", + "name": "amountToken", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETH", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + } + ], + "name": "getAmountOut", + "outputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "internalType": "struct Router.route[]", + "name": "routes", + "type": "tuple[]" + } + ], + "name": "getAmountsOut", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "reserveA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveB", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pair", + "type": "address" + } + ], + "name": "isPair", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "pairFor", + "outputs": [ + { + "internalType": "address", + "name": "pair", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "amountADesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBDesired", + "type": "uint256" + } + ], + "name": "quoteAddLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "name": "quoteRemoveLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountAMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "removeLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountTokenMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETHMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "removeLiquidityETH", + "outputs": [ + { + "internalType": "uint256", + "name": "amountToken", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETH", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountTokenMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETHMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "approveMax", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "removeLiquidityETHWithPermit", + "outputs": [ + { + "internalType": "uint256", + "name": "amountToken", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETH", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountAMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "approveMax", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "removeLiquidityWithPermit", + "outputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + } + ], + "name": "sortTokens", + "outputs": [ + { + "internalType": "address", + "name": "token0", + "type": "address" + }, + { + "internalType": "address", + "name": "token1", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "internalType": "struct Router.route[]", + "name": "routes", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactETHForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "internalType": "struct Router.route[]", + "name": "routes", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForETH", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "internalType": "struct Router.route[]", + "name": "routes", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenFrom", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenTo", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensSimple", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "weth", + "outputs": [ + { + "internalType": "contract IWETH", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x58eee942780ca824821a4aef9f4304d94dd16c37a1ac23c577ba412ac0d70d02", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x07d2FCFa095d52652cBC664F105F2d9Fb3799a47", + "transactionIndex": 1, + "gasUsed": "21117639", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xdaf429b1b8dd495aa7f78158cec510bd2d72bd844f7958bcd0e873c420a9f54e", + "transactionHash": "0x58eee942780ca824821a4aef9f4304d94dd16c37a1ac23c577ba412ac0d70d02", + "logs": [], + "blockNumber": 53774061, + "cumulativeGasUsed": "21117639", + "status": 1, + "byzantium": true + }, + "args": [ + "0xA2db791281CdeeBb1EEDc78a34989df2Bfd479bE", + "0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83" + ], + "numDeployments": 1, + "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_weth\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"UNSAFE_swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"}],\"name\":\"getAmountsOut\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"getReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reserveA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"name\":\"isPair\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"name\":\"pairFor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pair\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"}],\"name\":\"quoteAddLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"name\":\"quoteRemoveLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityETHWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"}],\"name\":\"sortTokens\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactETHForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForETH\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"}],\"internalType\":\"struct Router.route[]\",\"name\":\"routes\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenFrom\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenTo\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"stable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokensSimple\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weth\",\"outputs\":[{\"internalType\":\"contract IWETH\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Router.sol\":\"Router\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Router.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IPair.sol\\\";\\nimport \\\"contracts/interfaces/IPairFactory.sol\\\";\\nimport \\\"contracts/interfaces/IRouter.sol\\\";\\nimport \\\"contracts/interfaces/IWETH.sol\\\";\\n\\ncontract Router is IRouter {\\n struct route {\\n address from;\\n address to;\\n bool stable;\\n }\\n\\n address public immutable factory;\\n IWETH public immutable weth;\\n uint256 internal constant MINIMUM_LIQUIDITY = 10**3;\\n bytes32 immutable pairCodeHash;\\n\\n modifier ensure(uint256 deadline) {\\n require(deadline >= block.timestamp, \\\"Router: EXPIRED\\\");\\n _;\\n }\\n\\n constructor(address _factory, address _weth) {\\n factory = _factory;\\n pairCodeHash = IPairFactory(_factory).pairCodeHash();\\n weth = IWETH(_weth);\\n }\\n\\n receive() external payable {\\n assert(msg.sender == address(weth)); // only accept ETH via fallback from the WETH contract\\n }\\n\\n function sortTokens(address tokenA, address tokenB)\\n public\\n pure\\n returns (address token0, address token1)\\n {\\n require(tokenA != tokenB, \\\"Router: IDENTICAL_ADDRESSES\\\");\\n (token0, token1) = tokenA < tokenB\\n ? (tokenA, tokenB)\\n : (tokenB, tokenA);\\n require(token0 != address(0), \\\"Router: ZERO_ADDRESS\\\");\\n }\\n\\n // calculates the CREATE2 address for a pair without making any external calls\\n function pairFor(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (address pair) {\\n (address token0, address token1) = sortTokens(tokenA, tokenB);\\n pair = address(\\n uint160(\\n uint256(\\n keccak256(\\n abi.encodePacked(\\n hex\\\"ff\\\",\\n factory,\\n keccak256(abi.encodePacked(token0, token1, stable)),\\n pairCodeHash // init code hash\\n )\\n )\\n )\\n )\\n );\\n }\\n\\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\\n function quoteLiquidity(\\n uint256 amountA,\\n uint256 reserveA,\\n uint256 reserveB\\n ) internal pure returns (uint256 amountB) {\\n require(amountA > 0, \\\"Router: INSUFFICIENT_AMOUNT\\\");\\n require(reserveA > 0 && reserveB > 0, \\\"Router: INSUFFICIENT_LIQUIDITY\\\");\\n amountB = (amountA * reserveB) / reserveA;\\n }\\n\\n // fetches and sorts the reserves for a pair\\n function getReserves(\\n address tokenA,\\n address tokenB,\\n bool stable\\n ) public view returns (uint256 reserveA, uint256 reserveB) {\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (uint256 reserve0, uint256 reserve1, ) = IPair(\\n pairFor(tokenA, tokenB, stable)\\n ).getReserves();\\n (reserveA, reserveB) = tokenA == token0\\n ? (reserve0, reserve1)\\n : (reserve1, reserve0);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountOut(\\n uint256 amountIn,\\n address tokenIn,\\n address tokenOut\\n ) external view returns (uint256 amount, bool stable) {\\n address pair = pairFor(tokenIn, tokenOut, true);\\n uint256 amountStable;\\n uint256 amountVolatile;\\n if (IPairFactory(factory).isPair(pair)) {\\n amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n pair = pairFor(tokenIn, tokenOut, false);\\n if (IPairFactory(factory).isPair(pair)) {\\n amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);\\n }\\n return\\n amountStable > amountVolatile\\n ? (amountStable, true)\\n : (amountVolatile, false);\\n }\\n\\n // performs chained getAmountOut calculations on any number of pairs\\n function getAmountsOut(uint256 amountIn, route[] memory routes)\\n public\\n view\\n returns (uint256[] memory amounts)\\n {\\n require(routes.length >= 1, \\\"Router: INVALID_PATH\\\");\\n amounts = new uint256[](routes.length + 1);\\n amounts[0] = amountIn;\\n for (uint256 i = 0; i < routes.length; i++) {\\n address pair = pairFor(\\n routes[i].from,\\n routes[i].to,\\n routes[i].stable\\n );\\n if (IPairFactory(factory).isPair(pair)) {\\n amounts[i + 1] = IPair(pair).getAmountOut(\\n amounts[i],\\n routes[i].from\\n );\\n }\\n }\\n }\\n\\n function isPair(address pair) external view returns (bool) {\\n return IPairFactory(factory).isPair(pair);\\n }\\n\\n function quoteAddLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired\\n )\\n external\\n view\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n (uint256 reserveA, uint256 reserveB) = (0, 0);\\n uint256 _totalSupply = 0;\\n if (_pair != address(0)) {\\n _totalSupply = IERC20(_pair).totalSupply();\\n (reserveA, reserveB) = getReserves(tokenA, tokenB, stable);\\n }\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n liquidity = MathDunks.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n liquidity = MathDunks.min(\\n (amountA * _totalSupply) / reserveA,\\n (amountB * _totalSupply) / reserveB\\n );\\n }\\n }\\n }\\n\\n function quoteRemoveLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity\\n ) external view returns (uint256 amountA, uint256 amountB) {\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n\\n if (_pair == address(0)) {\\n return (0, 0);\\n }\\n\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n uint256 _totalSupply = IERC20(_pair).totalSupply();\\n\\n amountA = (liquidity * reserveA) / _totalSupply; // using balances ensures pro-rata distribution\\n amountB = (liquidity * reserveB) / _totalSupply; // using balances ensures pro-rata distribution\\n }\\n\\n function _addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin\\n ) internal returns (uint256 amountA, uint256 amountB) {\\n require(amountADesired >= amountAMin);\\n require(amountBDesired >= amountBMin);\\n // create the pair if it doesn't exist yet\\n address _pair = IPairFactory(factory).getPair(tokenA, tokenB, stable);\\n if (_pair == address(0)) {\\n _pair = IPairFactory(factory).createPair(tokenA, tokenB, stable);\\n }\\n (uint256 reserveA, uint256 reserveB) = getReserves(\\n tokenA,\\n tokenB,\\n stable\\n );\\n if (reserveA == 0 && reserveB == 0) {\\n (amountA, amountB) = (amountADesired, amountBDesired);\\n } else {\\n uint256 amountBOptimal = quoteLiquidity(\\n amountADesired,\\n reserveA,\\n reserveB\\n );\\n if (amountBOptimal <= amountBDesired) {\\n require(\\n amountBOptimal >= amountBMin,\\n \\\"Router: INSUFFICIENT_B_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountADesired, amountBOptimal);\\n } else {\\n uint256 amountAOptimal = quoteLiquidity(\\n amountBDesired,\\n reserveB,\\n reserveA\\n );\\n assert(amountAOptimal <= amountADesired);\\n require(\\n amountAOptimal >= amountAMin,\\n \\\"Router: INSUFFICIENT_A_AMOUNT\\\"\\n );\\n (amountA, amountB) = (amountAOptimal, amountBDesired);\\n }\\n }\\n }\\n\\n function addLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n ensure(deadline)\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n )\\n {\\n (amountA, amountB) = _addLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n amountADesired,\\n amountBDesired,\\n amountAMin,\\n amountBMin\\n );\\n address pair = pairFor(tokenA, tokenB, stable);\\n _safeTransferFrom(tokenA, msg.sender, pair, amountA);\\n _safeTransferFrom(tokenB, msg.sender, pair, amountB);\\n liquidity = IPair(pair).mint(to);\\n }\\n\\n function addLiquidityETH(\\n address token,\\n bool stable,\\n uint256 amountTokenDesired,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n payable\\n ensure(deadline)\\n returns (\\n uint256 amountToken,\\n uint256 amountETH,\\n uint256 liquidity\\n )\\n {\\n (amountToken, amountETH) = _addLiquidity(\\n token,\\n address(weth),\\n stable,\\n amountTokenDesired,\\n msg.value,\\n amountTokenMin,\\n amountETHMin\\n );\\n address pair = pairFor(token, address(weth), stable);\\n _safeTransferFrom(token, msg.sender, pair, amountToken);\\n weth.deposit{value: amountETH}();\\n assert(weth.transfer(pair, amountETH));\\n liquidity = IPair(pair).mint(to);\\n // refund dust eth, if any\\n if (msg.value > amountETH)\\n _safeTransferETH(msg.sender, msg.value - amountETH);\\n }\\n\\n // **** REMOVE LIQUIDITY ****\\n function removeLiquidity(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n require(IPair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair\\n (uint256 amount0, uint256 amount1) = IPair(pair).burn(to);\\n (address token0, ) = sortTokens(tokenA, tokenB);\\n (amountA, amountB) = tokenA == token0\\n ? (amount0, amount1)\\n : (amount1, amount0);\\n require(amountA >= amountAMin, \\\"Router: INSUFFICIENT_A_AMOUNT\\\");\\n require(amountB >= amountBMin, \\\"Router: INSUFFICIENT_B_AMOUNT\\\");\\n }\\n\\n function removeLiquidityETH(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline\\n ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {\\n (amountToken, amountETH) = removeLiquidity(\\n token,\\n address(weth),\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n address(this),\\n deadline\\n );\\n _safeTransfer(token, to, amountToken);\\n weth.withdraw(amountETH);\\n _safeTransferETH(to, amountETH);\\n }\\n\\n function removeLiquidityWithPermit(\\n address tokenA,\\n address tokenB,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountA, uint256 amountB) {\\n address pair = pairFor(tokenA, tokenB, stable);\\n {\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(\\n msg.sender,\\n address(this),\\n value,\\n deadline,\\n v,\\n r,\\n s\\n );\\n }\\n\\n (amountA, amountB) = removeLiquidity(\\n tokenA,\\n tokenB,\\n stable,\\n liquidity,\\n amountAMin,\\n amountBMin,\\n to,\\n deadline\\n );\\n }\\n\\n function removeLiquidityETHWithPermit(\\n address token,\\n bool stable,\\n uint256 liquidity,\\n uint256 amountTokenMin,\\n uint256 amountETHMin,\\n address to,\\n uint256 deadline,\\n bool approveMax,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external returns (uint256 amountToken, uint256 amountETH) {\\n address pair = pairFor(token, address(weth), stable);\\n uint256 value = approveMax ? type(uint256).max : liquidity;\\n IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);\\n (amountToken, amountETH) = removeLiquidityETH(\\n token,\\n stable,\\n liquidity,\\n amountTokenMin,\\n amountETHMin,\\n to,\\n deadline\\n );\\n }\\n\\n // **** SWAP ****\\n // requires the initial amount to have already been sent to the first pair\\n function _swap(\\n uint256[] memory amounts,\\n route[] memory routes,\\n address _to\\n ) internal virtual {\\n for (uint256 i = 0; i < routes.length; i++) {\\n (address token0, ) = sortTokens(routes[i].from, routes[i].to);\\n uint256 amountOut = amounts[i + 1];\\n (uint256 amount0Out, uint256 amount1Out) = routes[i].from == token0\\n ? (uint256(0), amountOut)\\n : (amountOut, uint256(0));\\n address to = i < routes.length - 1\\n ? pairFor(\\n routes[i + 1].from,\\n routes[i + 1].to,\\n routes[i + 1].stable\\n )\\n : _to;\\n IPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(\\n amount0Out,\\n amount1Out,\\n to,\\n new bytes(0)\\n );\\n }\\n }\\n\\n function swapExactTokensForTokensSimple(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n address tokenFrom,\\n address tokenTo,\\n bool stable,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n route[] memory routes = new route[](1);\\n routes[0].from = tokenFrom;\\n routes[0].to = tokenTo;\\n routes[0].stable = stable;\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForTokens(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactETHForTokens(\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external payable ensure(deadline) returns (uint256[] memory amounts) {\\n require(routes[0].from == address(weth), \\\"Router: INVALID_PATH\\\");\\n amounts = getAmountsOut(msg.value, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n weth.deposit{value: amounts[0]}();\\n assert(\\n weth.transfer(\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n )\\n );\\n _swap(amounts, routes, to);\\n }\\n\\n function swapExactTokensForETH(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory amounts) {\\n require(\\n routes[routes.length - 1].to == address(weth),\\n \\\"Router: INVALID_PATH\\\"\\n );\\n amounts = getAmountsOut(amountIn, routes);\\n require(\\n amounts[amounts.length - 1] >= amountOutMin,\\n \\\"Router: INSUFFICIENT_OUTPUT_AMOUNT\\\"\\n );\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, address(this));\\n weth.withdraw(amounts[amounts.length - 1]);\\n _safeTransferETH(to, amounts[amounts.length - 1]);\\n }\\n\\n function UNSAFE_swapExactTokensForTokens(\\n uint256[] memory amounts,\\n route[] calldata routes,\\n address to,\\n uint256 deadline\\n ) external ensure(deadline) returns (uint256[] memory) {\\n _safeTransferFrom(\\n routes[0].from,\\n msg.sender,\\n pairFor(routes[0].from, routes[0].to, routes[0].stable),\\n amounts[0]\\n );\\n _swap(amounts, routes, to);\\n return amounts;\\n }\\n\\n function _safeTransferETH(address to, uint256 value) internal {\\n (bool success, ) = to.call{value: value}(new bytes(0));\\n require(success, \\\"TransferHelper: ETH_TRANSFER_FAILED\\\");\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x3d84c846129d645eec66c37a493bb7fb401a2524497f450eaced155088305ead\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IRouter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IRouter {\\n function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair);\\n}\\n\",\"keccak256\":\"0x04f633ac6fcef1d040061320eae105b04094d6eb73dfd8a119293e11df24128f\"},\"contracts/interfaces/IWETH.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n function transfer(address to, uint256 value) external returns (bool);\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0x20ad0b3a319a36e3430f0d8512ee3755de8f85a80effe78d06f333f5326ee3d7\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x60e06040523480156200001157600080fd5b50604051620039bc380380620039bc8339810160408190526200003491620000d8565b6001600160a01b038216608081905260408051631355724960e31b81529051639aab9248916004808201926020929091908290030181865afa1580156200007f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000a5919062000110565b60c0526001600160a01b031660a052506200012a565b80516001600160a01b0381168114620000d357600080fd5b919050565b60008060408385031215620000ec57600080fd5b620000f783620000bb565b91506200010760208401620000bb565b90509250929050565b6000602082840312156200012357600080fd5b5051919050565b60805160a05160c0516137c8620001f46000396000610ef901526000818161013e0152818161020b0152818161091901528181610b5801528181610da901528181611470015281816115830152818161161101528181611de901528181611e1f01528181611e5401528181611ee901528181612028015261207801526000818161042d01528181610c3e01528181610ebe015281816111770152818161128b0152818161199601528181611b0a01528181612115015281816126ff01526127a001526137c86000f3fe60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea2646970667358221220a5fbebccdd681576dc540b9cee199053b5ccdd41b782b05a7748e7178173beea64736f6c634300080d0033", + "deployedBytecode": "0x60806040526004361061012e5760003560e01c80635e60dab5116100ab578063a32b1fcd1161006f578063a32b1fcd146103e8578063b7e0d4c014610408578063c45a01551461041b578063d7b0e0a51461044f578063e5e31b131461046f578063f41766d81461049f57600080fd5b80635e60dab51461035557806367ffb66a146103755780637301e3c8146103885780639881fcb4146103a857806398a0fb3c146103c857600080fd5b8063448725b4116100f2578063448725b4146102655780634c1ee03e14610285578063544caa56146102a55780635a47ddc3146102e55780635e1e63251461032057600080fd5b80630dede6c41461017257806313dcfc59146101ac57806318a13086146101d95780633fc8cef3146101f95780634386e63c1461024557600080fd5b3661016d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461016b5761016b612b87565b005b600080fd5b34801561017e57600080fd5b5061019261018d366004612bce565b6104bf565b604080519283526020830191909152015b60405180910390f35b3480156101b857600080fd5b506101cc6101c7366004612c53565b6106d9565b6040516101a39190612cce565b3480156101e557600080fd5b506101cc6101f4366004612d57565b6108ec565b34801561020557600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a3565b34801561025157600080fd5b50610192610260366004612dca565b610c37565b34801561027157600080fd5b50610192610280366004612e2c565b610d9e565b34801561029157600080fd5b5061022d6102a0366004612ed6565b610e77565b3480156102b157600080fd5b506102c56102c0366004612f21565b610f7f565b604080516001600160a01b039384168152929091166020830152016101a3565b3480156102f157600080fd5b50610305610300366004612f5a565b61105f565b604080519384526020840192909252908201526060016101a3565b34801561032c57600080fd5b5061034061033b366004612fe9565b61113f565b604080519283529015156020830152016101a3565b34801561036157600080fd5b50610192610370366004612ed6565b611393565b6101cc610383366004613020565b61144b565b34801561039457600080fd5b506101cc6103a33660046130f2565b6117aa565b3480156103b457600080fd5b506101cc6103c3366004613234565b611880565b3480156103d457600080fd5b506103056103e33660046132da565b611b02565b3480156103f457600080fd5b50610192610403366004613335565b611d02565b6103056104163660046133f1565b611dbd565b34801561042757600080fd5b5061022d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045b57600080fd5b5061019261046a3660046133f1565b611ffe565b34801561047b57600080fd5b5061048f61048a36600461344c565b6120f3565b60405190151581526020016101a3565b3480156104ab57600080fd5b506101cc6104ba366004612d57565b612188565b60008082428110156104ec5760405162461bcd60e51b81526004016104e390613469565b60405180910390fd5b60006104f98c8c8c610e77565b6040516323b872dd60e01b81523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af115801561054f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105739190613492565b61057c57600080fd5b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af11580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec91906134af565b9150915060006105fc8f8f610f7f565b509050806001600160a01b03168f6001600160a01b03161461061f578183610622565b82825b90975095508a8710156106775760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b898610156106c75760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b50505050509850989650505050505050565b606081428110156106fc5760405162461bcd60e51b81526004016104e390613469565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107135790505090508781600081518110610756576107566134d3565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061078e5761078e6134d3565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107c6576107c66134d3565b60209081029190910101519015156040909101526107e48a82611880565b92508883600185516107f691906134ff565b81518110610806576108066134d3565b6020026020010151101561082c5760405162461bcd60e51b81526004016104e390613516565b6108d481600081518110610842576108426134d3565b602002602001015160000151336108b484600081518110610865576108656134d3565b60200260200101516000015185600081518110610884576108846134d3565b602002602001015160200151866000815181106108a3576108a36134d3565b602002602001015160400151610e77565b866000815181106108c7576108c76134d3565b60200260200101516122ad565b6108df8382876123a5565b5050979650505050505050565b6060814281101561090f5760405162461bcd60e51b81526004016104e390613469565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866109466001826134ff565b818110610955576109556134d3565b905060600201602001602081019061096d919061344c565b6001600160a01b0316146109935760405162461bcd60e51b81526004016104e390613558565b6109ef888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576109d660608302860136819003810190613586565b815260200190600101906109b9565b5050505050611880565b9150868260018451610a0191906134ff565b81518110610a1157610a116134d3565b60200260200101511015610a375760405162461bcd60e51b81526004016104e390613516565b610af986866000818110610a4d57610a4d6134d3565b610a63926020606090920201908101915061344c565b33610ae689896000818110610a7a57610a7a6134d3565b610a90926020606090920201908101915061344c565b8a8a6000818110610aa357610aa36134d3565b9050606002016020016020810190610abb919061344c565b8b8b6000818110610ace57610ace6134d3565b90506060020160400160208101906102a091906135a2565b856000815181106108c7576108c76134d3565b610b56828787808060200260200160405190810160405280939291908181526020016000905b82821015610b4b57610b3c60608302860136819003810190613586565b81526020019060010190610b1f565b5050505050306123a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b9491906134ff565b81518110610ba457610ba46134d3565b60200260200101516040518263ffffffff1660e01b8152600401610bca91815260200190565b600060405180830381600087803b158015610be457600080fd5b505af1158015610bf8573d6000803e3d6000fd5b50505050610c2c848360018551610c0f91906134ff565b81518110610c1f57610c1f6134d3565b60200260200101516125fa565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c8c939291906135bf565b602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906135e3565b90506001600160a01b038116610cea576000809250925050610d95565b600080610cf8898989611393565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d609190613600565b905080610d6d8489613619565b610d779190613638565b955080610d848389613619565b610d8e9190613638565b9450505050505b94509492505050565b6000806000610dce8e7f00000000000000000000000000000000000000000000000000000000000000008f610e77565b9050600087610ddd578c610de1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e1c903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015610e3657600080fd5b505af1158015610e4a573d6000803e3d6000fd5b50505050610e5d8f8f8f8f8f8f8f611ffe565b809450819550505050509b509b9950505050505050505050565b6000806000610e868686610f7f565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610f5d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b031603610fe35760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f414444524553534553000000000060448201526064016104e3565b826001600160a01b0316846001600160a01b031610611003578284611006565b83835b90925090506001600160a01b0382166110585760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b60448201526064016104e3565b9250929050565b600080600083428110156110855760405162461bcd60e51b81526004016104e390613469565b6110948d8d8d8d8d8d8d6126c8565b909450925060006110a68e8e8e610e77565b90506110b48e3383886122ad565b6110c08d3383876122ad565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190613600565b9250505099509950999650505050505050565b600080600061115085856001610e77565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e49190613492565b1561125d576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125a9190613600565b91505b61126987876000610e77565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156112d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f89190613492565b15611371576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190613600565b90505b80821161138057806000611384565b8160015b94509450505050935093915050565b60008060006113a28686610f7f565b5090506000806113b3888888610e77565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156113f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611414919061369b565b5091509150826001600160a01b0316886001600160a01b03161461143957808261143c565b81815b90999098509650505050505050565b6060814281101561146e5760405162461bcd60e51b81526004016104e390613469565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106114ab576114ab6134d3565b6114c1926020606090920201908101915061344c565b6001600160a01b0316146114e75760405162461bcd60e51b81526004016104e390613558565b611539348787808060200260200160405190810160405280939291908181526020016000905b828210156109e55761152a60608302860136819003810190613586565b8152602001906001019061150d565b915086826001845161154b91906134ff565b8151811061155b5761155b6134d3565b602002602001015110156115815760405162461bcd60e51b81526004016104e390613516565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836000815181106115c3576115c36134d3565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115f657600080fd5b505af115801561160a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116a888886000818110611654576116546134d3565b61166a926020606090920201908101915061344c565b8989600081811061167d5761167d6134d3565b9050606002016020016020810190611695919061344c565b8a8a6000818110610ace57610ace6134d3565b846000815181106116bb576116bb6134d3565b60200260200101516040518363ffffffff1660e01b81526004016116f49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190613492565b61174357611743612b87565b6117a0828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761178660608302860136819003810190613586565b81526020019060010190611769565b5050505050866123a5565b5095945050505050565b606081428110156117cd5760405162461bcd60e51b81526004016104e390613469565b611823868660008181106117e3576117e36134d3565b6117f9926020606090920201908101915061344c565b3361181089896000818110610a7a57610a7a6134d3565b8a6000815181106108c7576108c76134d3565b611875878787808060200260200160405190810160405280939291908181526020016000905b828210156117955761186660608302860136819003810190613586565b81526020019060010190611849565b509495945050505050565b60606001825110156118a45760405162461bcd60e51b81526004016104e390613558565b81516118b19060016136c9565b67ffffffffffffffff8111156118c9576118c9613087565b6040519080825280602002602001820160405280156118f2578160200160208202803683370190505b5090508281600081518110611909576119096134d3565b60200260200101818152505060005b8251811015611afb576000611974848381518110611938576119386134d3565b602002602001015160000151858481518110611956576119566134d3565b6020026020010151602001518685815181106108a3576108a36134d3565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156119df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a039190613492565b15611ae857806001600160a01b031663f140a35a848481518110611a2957611a296134d3565b6020026020010151868581518110611a4357611a436134d3565b6020026020010151600001516040518363ffffffff1660e01b8152600401611a7e9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abf9190613600565b83611acb8460016136c9565b81518110611adb57611adb6134d3565b6020026020010181815250505b5080611af3816136e1565b915050611918565b5092915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611b58939291906135bf565b602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9991906135e3565b9050600080806001600160a01b03841615611c2357836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c109190613600565b9050611c1d8c8c8c611393565b90935091505b82158015611c2f575081155b15611c60578896508795506103e8611c4f611c4a888a613619565b612946565b611c5991906134ff565b9450611cf3565b6000611c6d8a85856129b6565b9050888111611cb557899750955085611cae84611c8a848b613619565b611c949190613638565b84611c9f858b613619565b611ca99190613638565b612a80565b9550611cf1565b6000611cc28a85876129b6565b9850899750889050611ced85611cd88584613619565b611ce29190613638565b85611c9f868c613619565b9650505b505b50505050955095509592505050565b6000806000611d128f8f8f610e77565b9050600087611d21578c611d25565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611d60903390309086908f908e908e908e9060040161365a565b600060405180830381600087803b158015611d7a57600080fd5b505af1158015611d8e573d6000803e3d6000fd5b5050505050611da38f8f8f8f8f8f8f8f6104bf565b8093508194505050509c509c9a5050505050505050505050565b60008060008342811015611de35760405162461bcd60e51b81526004016104e390613469565b611e128b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6126c8565b90945092506000611e448c7f00000000000000000000000000000000000000000000000000000000000000008d610e77565b9050611e528c3383886122ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611ead57600080fd5b505af1158015611ec1573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613492565b611f6657611f66612b87565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190613600565b925083341115611fef57611fef33611fea86346134ff565b6125fa565b50509750975097945050505050565b60008082428110156120225760405162461bcd60e51b81526004016104e390613469565b6120528a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b6104bf565b90935091506120628a8685612a98565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156120c457600080fd5b505af11580156120d8573d6000803e3d6000fd5b505050506120e685836125fa565b5097509795505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190613492565b92915050565b606081428110156121ab5760405162461bcd60e51b81526004016104e390613469565b6121fd888787808060200260200160405190810160405280939291908181526020016000905b828210156109e5576121ee60608302860136819003810190613586565b815260200190600101906121d1565b915086826001845161220f91906134ff565b8151811061221f5761221f6134d3565b602002602001015110156122455760405162461bcd60e51b81526004016104e390613516565b61225b86866000818110610a4d57610a4d6134d3565b610c2c828787808060200260200160405190810160405280939291908181526020016000905b828210156117955761229e60608302860136819003810190613586565b81526020019060010190612281565b6000846001600160a01b03163b116122c457600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916123289190613726565b6000604051808303816000865af19150503d8060008114612365576040519150601f19603f3d011682016040523d82523d6000602084013e61236a565b606091505b50915091508180156123945750805115806123945750808060200190518101906123949190613492565b61239d57600080fd5b505050505050565b60005b82518110156125f45760006123f78483815181106123c8576123c86134d3565b6020026020010151600001518584815181106123e6576123e66134d3565b602002602001015160200151610f7f565b5090506000856124088460016136c9565b81518110612418576124186134d3565b60200260200101519050600080836001600160a01b0316878681518110612441576124416134d3565b6020026020010151600001516001600160a01b03161461246357826000612467565b6000835b9150915060006001885161247b91906134ff565b861061248757866124fa565b6124fa886124968860016136c9565b815181106124a6576124a66134d3565b602002602001015160000151898860016124c091906136c9565b815181106124d0576124d06134d3565b6020026020010151602001518a8960016124ea91906136c9565b815181106108a3576108a36134d3565b905061254d888781518110612511576125116134d3565b60200260200101516000015189888151811061252f5761252f6134d3565b6020026020010151602001518a89815181106108a3576108a36134d3565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561258a576020820181803683370190505b506040518563ffffffff1660e01b81526004016125aa9493929190613742565b600060405180830381600087803b1580156125c457600080fd5b505af11580156125d8573d6000803e3d6000fd5b50505050505050505080806125ec906136e1565b9150506123a8565b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516126249190613726565b60006040518083038185875af1925050503d8060008114612661576040519150601f19603f3d011682016040523d82523d6000602084013e612666565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b60648201526084016104e3565b505050565b600080838610156126d857600080fd5b828510156126e557600080fd5b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc3090612738908d908d908d906004016135bf565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277991906135e3565b90506001600160a01b03811661281f576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce4906127d9908d908d908d906004016135bf565b6020604051808303816000875af11580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c91906135e3565b90505b60008061282d8c8c8c611393565b9150915081600014801561283f575080155b1561284f57889450879350612937565b600061285c8a84846129b6565b90508881116128c057868110156128b55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e5400000060448201526064016104e3565b899550935083612935565b60006128cd8a84866129b6565b90508a8111156128df576128df612b87565b8881101561292f5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e5400000060448201526064016104e3565b95508894505b505b50505097509795505050505050565b600060038211156129a75750806000612960600283613638565b61296b9060016136c9565b90505b818110156129a1579050806002816129868186613638565b61299091906136c9565b61299a9190613638565b905061296e565b50919050565b81156129b1575060015b919050565b6000808411612a075760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e54000000000060448201526064016104e3565b600083118015612a175750600082115b612a635760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c4951554944495459000060448201526064016104e3565b82612a6e8386613619565b612a789190613638565b949350505050565b6000818310612a8f5781612a91565b825b9392505050565b6000836001600160a01b03163b11612aaf57600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612b0b9190613726565b6000604051808303816000865af19150503d8060008114612b48576040519150601f19603f3d011682016040523d82523d6000602084013e612b4d565b606091505b5091509150818015612b77575080511580612b77575080806020019051810190612b779190613492565b612b8057600080fd5b5050505050565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0381168114612bb257600080fd5b50565b80356129b181612b9d565b8015158114612bb257600080fd5b600080600080600080600080610100898b031215612beb57600080fd5b8835612bf681612b9d565b97506020890135612c0681612b9d565b96506040890135612c1681612bc0565b9550606089013594506080890135935060a0890135925060c0890135612c3b81612b9d565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215612c6e57600080fd5b87359650602088013595506040880135612c8781612b9d565b94506060880135612c9781612b9d565b93506080880135612ca781612bc0565b925060a0880135612cb781612b9d565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015612d0657835183529284019291840191600101612cea565b50909695505050505050565b60008083601f840112612d2457600080fd5b50813567ffffffffffffffff811115612d3c57600080fd5b60208301915083602060608302850101111561105857600080fd5b60008060008060008060a08789031215612d7057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115612d9557600080fd5b612da189828a01612d12565b9095509350506060870135612db581612b9d565b80925050608087013590509295509295509295565b60008060008060808587031215612de057600080fd5b8435612deb81612b9d565b93506020850135612dfb81612b9d565b92506040850135612e0b81612bc0565b9396929550929360600135925050565b803560ff811681146129b157600080fd5b60008060008060008060008060008060006101608c8e031215612e4e57600080fd5b8b35612e5981612b9d565b9a5060208c0135612e6981612bc0565b995060408c0135985060608c0135975060808c0135965060a08c0135612e8e81612b9d565b955060c08c0135945060e08c0135612ea581612bc0565b9350612eb46101008d01612e1b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600060608486031215612eeb57600080fd5b8335612ef681612b9d565b92506020840135612f0681612b9d565b91506040840135612f1681612bc0565b809150509250925092565b60008060408385031215612f3457600080fd5b8235612f3f81612b9d565b91506020830135612f4f81612b9d565b809150509250929050565b60008060008060008060008060006101208a8c031215612f7957600080fd5b8935612f8481612b9d565b985060208a0135612f9481612b9d565b975060408a0135612fa481612bc0565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a0135612fd081612b9d565b809250506101008a013590509295985092959850929598565b600080600060608486031215612ffe57600080fd5b83359250602084013561301081612b9d565b91506040840135612f1681612b9d565b60008060008060006080868803121561303857600080fd5b85359450602086013567ffffffffffffffff81111561305657600080fd5b61306288828901612d12565b909550935050604086013561307681612b9d565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130c6576130c6613087565b604052919050565b600067ffffffffffffffff8211156130e8576130e8613087565b5060051b60200190565b60008060008060006080868803121561310a57600080fd5b853567ffffffffffffffff8082111561312257600080fd5b818801915088601f83011261313657600080fd5b8135602061314b613146836130ce565b61309d565b82815260059290921b8401810191818101908c84111561316a57600080fd5b948201945b838610156131885785358252948201949082019061316f565b9950508901359250508082111561319e57600080fd5b506131ab88828901612d12565b9095509350613076905060408701612bb5565b6000606082840312156131d057600080fd5b6040516060810181811067ffffffffffffffff821117156131f3576131f3613087565b604052905080823561320481612b9d565b8152602083013561321481612b9d565b6020820152604083013561322781612bc0565b6040919091015292915050565b6000806040838503121561324757600080fd5b8235915060208084013567ffffffffffffffff81111561326657600080fd5b8401601f8101861361327757600080fd5b8035613285613146826130ce565b818152606091820283018401918482019190898411156132a457600080fd5b938501935b838510156132ca576132bb8a866131be565b835293840193918501916132a9565b5080955050505050509250929050565b600080600080600060a086880312156132f257600080fd5b85356132fd81612b9d565b9450602086013561330d81612b9d565b9350604086013561331d81612bc0565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561335857600080fd5b8c3561336381612b9d565b9b5060208d013561337381612b9d565b9a5060408d013561338381612bc0565b995060608d0135985060808d0135975060a08d0135965060c08d01356133a881612b9d565b955060e08d013594506101008d01356133c081612bc0565b93506133cf6101208e01612e1b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b600080600080600080600060e0888a03121561340c57600080fd5b873561341781612b9d565b9650602088013561342781612bc0565b955060408801359450606088013593506080880135925060a0880135612cb781612b9d565b60006020828403121561345e57600080fd5b8135612a9181612b9d565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b6000602082840312156134a457600080fd5b8151612a9181612bc0565b600080604083850312156134c257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613511576135116134e9565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b60006060828403121561359857600080fd5b612a9183836131be565b6000602082840312156135b457600080fd5b8135612a9181612bc0565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6000602082840312156135f557600080fd5b8151612a9181612b9d565b60006020828403121561361257600080fd5b5051919050565b6000816000190483118215151615613633576136336134e9565b500290565b60008261365557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000806000606084860312156136b057600080fd5b8351925060208401519150604084015190509250925092565b600082198211156136dc576136dc6134e9565b500190565b6000600182016136f3576136f36134e9565b5060010190565b60005b838110156137155781810151838201526020016136fd565b838111156125f45750506000910152565b600082516137388184602087016136fa565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000825180608084015261377b8160a08501602087016136fa565b601f01601f19169190910160a0019594505050505056fea2646970667358221220a5fbebccdd681576dc540b9cee199053b5ccdd41b782b05a7748e7178173beea64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/arbitrumOneOLD/VeArtProxy.json b/deployments/arbitrumOneOLD/VeArtProxy.json new file mode 100644 index 00000000..d8ad686b --- /dev/null +++ b/deployments/arbitrumOneOLD/VeArtProxy.json @@ -0,0 +1,75 @@ +{ + "address": "0x4b40D5E4401EC24673cc9d4799457a3B5827c581", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_balanceOf", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_locked_end", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "_tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "output", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "transactionHash": "0xaea6c881d8fbd586965699a9451e8f32ed3536b204ecb1e490df8cf5677141a9", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x4b40D5E4401EC24673cc9d4799457a3B5827c581", + "transactionIndex": 1, + "gasUsed": "5573204", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x34ad78b9a516d065f84e2b2c7125282551cc3907f1f97aaacb94abb885b05833", + "transactionHash": "0xaea6c881d8fbd586965699a9451e8f32ed3536b204ecb1e490df8cf5677141a9", + "logs": [], + "blockNumber": 53774078, + "cumulativeGasUsed": "5573204", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_locked_end\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"_tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"output\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VeArtProxy.sol\":\"VeArtProxy\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\nimport {Base64} from \\\"contracts/libraries/Base64.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\n\\ncontract VeArtProxy is IVeArtProxy {\\n function toString(uint value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT license\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint temp = value;\\n uint digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output) {\\n output = '';\\n output = string(abi.encodePacked(output, \\\"token \\\", toString(_tokenId), ''));\\n output = string(abi.encodePacked(output, \\\"balanceOf \\\", toString(_balanceOf), ''));\\n output = string(abi.encodePacked(output, \\\"locked_end \\\", toString(_locked_end), ''));\\n output = string(abi.encodePacked(output, \\\"value \\\", toString(_value), ''));\\n\\n string memory json = Base64.encode(bytes(string(abi.encodePacked('{\\\"name\\\": \\\"lock #', toString(_tokenId), '\\\", \\\"description\\\": \\\"Velodrome locks, can be used to boost gauge yields, vote on token emission, and receive bribes\\\", \\\"image\\\": \\\"data:image/svg+xml;base64,', Base64.encode(bytes(output)), '\\\"}'))));\\n output = string(abi.encodePacked('data:application/json;base64,', json));\\n }\\n}\\n\",\"keccak256\":\"0x8757d8095922dcad7af8c6820415049fd7d5af61a5580719210e5e91a31d80b1\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/libraries/Base64.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n/// [MIT License]\\n/// @title Base64\\n/// @notice Provides a function for encoding some bytes in base64\\n/// @author Brecht Devos \\nlibrary Base64 {\\n bytes internal constant TABLE = \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\";\\n\\n /// @notice Encodes some bytes to the base64 representation\\n function encode(bytes memory data) internal pure returns (string memory) {\\n uint len = data.length;\\n if (len == 0) return \\\"\\\";\\n\\n // multiply by 4/3 rounded up\\n uint encodedLen = 4 * ((len + 2) / 3);\\n\\n // Add some extra buffer at the end\\n bytes memory result = new bytes(encodedLen + 32);\\n\\n bytes memory table = TABLE;\\n\\n assembly {\\n let tablePtr := add(table, 1)\\n let resultPtr := add(result, 32)\\n\\n for {\\n let i := 0\\n } lt(i, len) {\\n\\n } {\\n i := add(i, 3)\\n let input := and(mload(add(data, i)), 0xffffff)\\n\\n let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\\n out := shl(8, out)\\n out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\\n out := shl(224, out)\\n\\n mstore(resultPtr, out)\\n\\n resultPtr := add(resultPtr, 4)\\n }\\n\\n switch mod(len, 3)\\n case 1 {\\n mstore(sub(resultPtr, 2), shl(240, 0x3d3d))\\n }\\n case 2 {\\n mstore(sub(resultPtr, 1), shl(248, 0x3d))\\n }\\n\\n mstore(result, encodedLen)\\n }\\n\\n return string(result);\\n }\\n}\\n\",\"keccak256\":\"0x55535e1e0a14bbac370fe5f25df23aa88c678b915af53517672130f9a54f7e3e\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610a2b806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f64726f6d65206c6f636010918401918201527f6b732c2063616e206265207573656420746f20626f6f7374206761756765207960308201527f69656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c206160508201527f6e64207265636569766520627269626573222c2022696d616765223a2022646160708201527f74613a696d6167652f7376672b786d6c3b6261736536342c0000000000000000609082015283516107718160a8840160208801610435565b61227d60f01b60a8929091019182015260aa01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212205e17183bb106171fcd25152691eea4fe7c51c6576ba7661fd1601ee5ea93b74a64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063dd9ec14914610030575b600080fd5b61004361003e366004610403565b610059565b6040516100509190610465565b60405180910390f35b606060405180610120016040528060fd81526020016108b960fd913990508061008186610190565b604051602001610092929190610498565b6040516020818303038152906040529050806100ad85610190565b6040516020016100be929190610514565b6040516020818303038152906040529050806100d984610190565b6040516020016100ea929190610594565b60405160208183030381529060405290508061010583610190565b604051602001610116929190610615565b6040516020818303038152906040529050600061016361013587610190565b61013e84610299565b60405160200161014f929190610670565b604051602081830303815290604052610299565b905080604051602001610176919061078c565b604051602081830303815290604052915050949350505050565b6060816000036101b75750506040805180820190915260018152600360fc1b602082015290565b8160005b81156101e157806101cb816107e7565b91506101da9050600a83610816565b91506101bb565b60008167ffffffffffffffff8111156101fc576101fc61082a565b6040519080825280601f01601f191660200182016040528015610226576020820181803683370190505b5090505b84156102915761023b600183610840565b9150610248600a86610857565b61025390603061086b565b60f81b81838151811061026857610268610883565b60200101906001600160f81b031916908160001a90535061028a600a86610816565b945061022a565b949350505050565b805160609060008190036102bd575050604080516020810190915260008152919050565b600060036102cc83600261086b565b6102d69190610816565b6102e1906004610899565b905060006102f082602061086b565b67ffffffffffffffff8111156103085761030861082a565b6040519080825280601f01601f191660200182016040528015610332576020820181803683370190505b50905060006040518060600160405280604081526020016109b6604091399050600181016020830160005b868110156103be576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b83526004909201910161035d565b5060038606600181146103d857600281146103e9576103f5565b613d3d60f01b6001198301526103f5565b603d60f81b6000198301525b505050918152949350505050565b6000806000806080858703121561041957600080fd5b5050823594602084013594506040840135936060013592509050565b60005b83811015610450578181015183820152602001610438565b8381111561045f576000848401525b50505050565b6020815260008251806020840152610484816040850160208701610435565b601f01601f19169190910160400192915050565b600083516104aa818460208801610435565b6503a37b5b2b7160d51b90830190815283516104cd816006840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2234302220636c61737360069290910191820152671e913130b9b2911f60c11b6026820152602e01949350505050565b60008351610526818460208801610435565b6903130b630b731b2a7b3160b51b908301908152835161054d81600a840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2236302220636c617373600a9290910191820152671e913130b9b2911f60c11b602a820152603201949350505050565b600083516105a6818460208801610435565b6a03637b1b5b2b22fb2b732160ad1b90830190815283516105ce81600b840160208801610435565b7f3c2f746578743e3c7465787420783d2231302220793d2238302220636c617373600b9290910191820152671e913130b9b2911f60c11b602b820152603301949350505050565b60008351610627818460208801610435565b6503b30b63ab2960d51b908301908152835161064a816006840160208801610435565b6c1e17ba32bc3a1f1e17b9bb339f60991b60069290910191820152601301949350505050565b6f7b226e616d65223a20226c6f636b202360801b8152825160009061069c816010850160208801610435565b7f222c20226465736372697074696f6e223a202256656c6f64726f6d65206c6f636010918401918201527f6b732c2063616e206265207573656420746f20626f6f7374206761756765207960308201527f69656c64732c20766f7465206f6e20746f6b656e20656d697373696f6e2c206160508201527f6e64207265636569766520627269626573222c2022696d616765223a2022646160708201527f74613a696d6167652f7376672b786d6c3b6261736536342c0000000000000000609082015283516107718160a8840160208801610435565b61227d60f01b60a8929091019182015260aa01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516107c481601d850160208701610435565b91909101601d0192915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016107f9576107f96107d1565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261082557610825610800565b500490565b634e487b7160e01b600052604160045260246000fd5b600082821015610852576108526107d1565b500390565b60008261086657610866610800565b500690565b6000821982111561087e5761087e6107d1565b500190565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156108b3576108b36107d1565b50029056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302033353020333530223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a20313470783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d22626c61636b22202f3e3c7465787420783d2231302220793d2232302220636c6173733d2262617365223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212205e17183bb106171fcd25152691eea4fe7c51c6576ba7661fd1601ee5ea93b74a64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/arbitrumOne/Velo.json b/deployments/arbitrumOneOLD/Velo.json similarity index 100% rename from deployments/arbitrumOne/Velo.json rename to deployments/arbitrumOneOLD/Velo.json diff --git a/deployments/arbitrumOne/VeloGovernor.json b/deployments/arbitrumOneOLD/VeloGovernor.json similarity index 100% rename from deployments/arbitrumOne/VeloGovernor.json rename to deployments/arbitrumOneOLD/VeloGovernor.json diff --git a/deployments/arbitrumOne/VelodromeLibrary.json b/deployments/arbitrumOneOLD/VelodromeLibrary.json similarity index 100% rename from deployments/arbitrumOne/VelodromeLibrary.json rename to deployments/arbitrumOneOLD/VelodromeLibrary.json diff --git a/deployments/arbitrumOneOLD/Voter.json b/deployments/arbitrumOneOLD/Voter.json new file mode 100644 index 00000000..10fa498b --- /dev/null +++ b/deployments/arbitrumOneOLD/Voter.json @@ -0,0 +1,1418 @@ +{ + "address": "0x29C487a354D11315059204Df4F7d8AB1aa008ebb", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "__ve", + "type": "address" + }, + { + "internalType": "address", + "name": "_factory", + "type": "address" + }, + { + "internalType": "address", + "name": "_gauges", + "type": "address" + }, + { + "internalType": "address", + "name": "_bribes", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + } + ], + "name": "Abstained", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Attach", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "lp", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Detach", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DistributeReward", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "internal_bribe", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "external_bribe", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "GaugeCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + } + ], + "name": "GaugeKilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + } + ], + "name": "GaugeRevived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "reward", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "NotifyReward", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weight", + "type": "uint256" + } + ], + "name": "Voted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "whitelister", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "Whitelisted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "lp", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [], + "name": "_ve", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "attachTokenToGauge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bribefactory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_bribes", + "type": "address[]" + }, + { + "internalType": "address[][]", + "name": "_tokens", + "type": "address[][]" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "claimBribes", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_fees", + "type": "address[]" + }, + { + "internalType": "address[][]", + "name": "_tokens", + "type": "address[][]" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "claimFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_gauges", + "type": "address[]" + }, + { + "internalType": "address[][]", + "name": "_tokens", + "type": "address[][]" + } + ], + "name": "claimRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "claimable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_pool", + "type": "address" + } + ], + "name": "createGauge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "detachTokenFromGauge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_gauges", + "type": "address[]" + } + ], + "name": "distribute", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gauge", + "type": "address" + } + ], + "name": "distribute", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "start", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "finish", + "type": "uint256" + } + ], + "name": "distribute", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "distribute", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_gauges", + "type": "address[]" + } + ], + "name": "distributeFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "distro", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "emergencyCouncil", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "emitDeposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "emitWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "external_bribes", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gaugefactory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "gauges", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_tokens", + "type": "address[]" + }, + { + "internalType": "address", + "name": "_minter", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "internal_bribes", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isAlive", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isGauge", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isWhitelisted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gauge", + "type": "address" + } + ], + "name": "killGauge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "lastVoted", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "length", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "notifyRewardAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "poke", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "poolForGauge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "poolVote", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "pools", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "reset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gauge", + "type": "address" + } + ], + "name": "reviveGauge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_council", + "type": "address" + } + ], + "name": "setEmergencyCouncil", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_governor", + "type": "address" + } + ], + "name": "setGovernor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalWeight", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "updateAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_gauges", + "type": "address[]" + } + ], + "name": "updateFor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "start", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "end", + "type": "uint256" + } + ], + "name": "updateForRange", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gauge", + "type": "address" + } + ], + "name": "updateGauge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "usedWeights", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "_poolVote", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "_weights", + "type": "uint256[]" + } + ], + "name": "vote", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "votes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "weights", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + } + ], + "name": "whitelist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x6525dd63638ff4ed2b7e6556e27d3903e730609c0503ea6facd921de9c091e43", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x29C487a354D11315059204Df4F7d8AB1aa008ebb", + "transactionIndex": 1, + "gasUsed": "21064022", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x52e0ff5d75dfe71eff1e0a08b81f63681b1af7d28d6d0b1d0a83bdf04a49458c", + "transactionHash": "0x6525dd63638ff4ed2b7e6556e27d3903e730609c0503ea6facd921de9c091e43", + "logs": [], + "blockNumber": 53774108, + "cumulativeGasUsed": "21064022", + "status": 1, + "byzantium": true + }, + "args": [ + "0x10Df81252069C1095F541FAca61646cb9Ae76703", + "0xA2db791281CdeeBb1EEDc78a34989df2Bfd479bE", + "0x2CCb061AD1b50211cF79f33e690452497941a2fe", + "0xBcC3c06e1D22E44Ac807D76A887fFB40765e0D16" + ], + "numDeployments": 1, + "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__ve\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_gauges\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_bribes\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Abstained\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Attach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Detach\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributeReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"internal_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"external_bribe\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"name\":\"GaugeCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeKilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"}],\"name\":\"GaugeRevived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"reward\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NotifyReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"name\":\"Voted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"whitelister\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"Whitelisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lp\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"_ve\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"attachTokenToGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bribefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_bribes\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimBribes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_fees\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"claimFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"_tokens\",\"type\":\"address[][]\"}],\"name\":\"claimRewards\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"claimable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"}],\"name\":\"createGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"detachTokenFromGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"finish\",\"type\":\"uint256\"}],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distribute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"distributeFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distro\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"emergencyCouncil\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"emitWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"external_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gaugefactory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"gauges\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_tokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"internal_bribes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isAlive\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isGauge\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isWhitelisted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"killGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"lastVoted\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"length\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"notifyRewardAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"poke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolForGauge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"poolVote\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"reset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"reviveGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_council\",\"type\":\"address\"}],\"name\":\"setEmergencyCouncil\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"setGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalWeight\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_gauges\",\"type\":\"address[]\"}],\"name\":\"updateFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"name\":\"updateForRange\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gauge\",\"type\":\"address\"}],\"name\":\"updateGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedWeights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"_poolVote\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_weights\",\"type\":\"uint256[]\"}],\"name\":\"vote\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"votes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"weights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"whitelist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Voter.sol\":\"Voter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Voter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport 'contracts/libraries/Math.sol';\\nimport 'contracts/interfaces/IBribe.sol';\\nimport 'contracts/interfaces/IBribeFactory.sol';\\nimport 'contracts/interfaces/IGauge.sol';\\nimport 'contracts/interfaces/IGaugeFactory.sol';\\nimport 'contracts/interfaces/IERC20.sol';\\nimport 'contracts/interfaces/IMinter.sol';\\nimport 'contracts/interfaces/IPair.sol';\\nimport 'contracts/interfaces/IPairFactory.sol';\\nimport 'contracts/interfaces/IVoter.sol';\\nimport 'contracts/interfaces/IVotingEscrow.sol';\\n\\ncontract Voter is IVoter {\\n\\n address public immutable _ve; // the ve token that governs these contracts\\n address public immutable factory; // the PairFactory\\n address internal immutable base;\\n address public immutable gaugefactory;\\n address public immutable bribefactory;\\n uint internal constant DURATION = 7 days; // rewards are released over 7 days\\n address public minter;\\n address public governor; // should be set to an IGovernor\\n address public emergencyCouncil; // credibly neutral party similar to Curve's Emergency DAO\\n\\n uint public totalWeight; // total voting weight\\n\\n address[] public pools; // all pools viable for incentives\\n mapping(address => address) public gauges; // pool => gauge\\n mapping(address => address) public poolForGauge; // gauge => pool\\n mapping(address => address) public internal_bribes; // gauge => internal bribe (only fees)\\n mapping(address => address) public external_bribes; // gauge => external bribe (real bribes)\\n mapping(address => uint256) public weights; // pool => weight\\n mapping(uint => mapping(address => uint256)) public votes; // nft => pool => votes\\n mapping(uint => address[]) public poolVote; // nft => pools\\n mapping(uint => uint) public usedWeights; // nft => total voting weight of user\\n mapping(uint => uint) public lastVoted; // nft => timestamp of last vote, to ensure one vote per epoch\\n mapping(address => bool) public isGauge;\\n mapping(address => bool) public isWhitelisted;\\n mapping(address => bool) public isAlive;\\n\\n event GaugeCreated(address indexed gauge, address creator, address internal_bribe, address indexed external_bribe, address indexed pool);\\n event GaugeKilled(address indexed gauge);\\n event GaugeRevived(address indexed gauge);\\n event Voted(address indexed voter, uint tokenId, uint256 weight);\\n event Abstained(uint tokenId, uint256 weight);\\n event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);\\n event NotifyReward(address indexed sender, address indexed reward, uint amount);\\n event DistributeReward(address indexed sender, address indexed gauge, uint amount);\\n event Attach(address indexed owner, address indexed gauge, uint tokenId);\\n event Detach(address indexed owner, address indexed gauge, uint tokenId);\\n event Whitelisted(address indexed whitelister, address indexed token);\\n\\n constructor(address __ve, address _factory, address _gauges, address _bribes) {\\n _ve = __ve;\\n factory = _factory;\\n base = IVotingEscrow(__ve).token();\\n gaugefactory = _gauges;\\n bribefactory = _bribes;\\n minter = msg.sender;\\n governor = msg.sender;\\n emergencyCouncil = msg.sender;\\n }\\n\\n // simple re-entrancy check\\n uint internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n modifier onlyNewEpoch(uint _tokenId) {\\n // ensure new epoch since last vote \\n require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], \\\"TOKEN_ALREADY_VOTED_THIS_EPOCH\\\");\\n _;\\n }\\n\\n function initialize(address[] memory _tokens, address _minter) external {\\n require(msg.sender == minter);\\n for (uint i = 0; i < _tokens.length; i++) {\\n _whitelist(_tokens[i]);\\n }\\n minter = _minter;\\n }\\n\\n function setGovernor(address _governor) public {\\n require(msg.sender == governor);\\n governor = _governor;\\n }\\n\\n function setEmergencyCouncil(address _council) public {\\n require(msg.sender == emergencyCouncil);\\n emergencyCouncil = _council;\\n }\\n\\n function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n lastVoted[_tokenId] = block.timestamp;\\n _reset(_tokenId);\\n IVotingEscrow(_ve).abstain(_tokenId);\\n }\\n\\n function _reset(uint _tokenId) internal {\\n address[] storage _poolVote = poolVote[_tokenId];\\n uint _poolVoteCnt = _poolVote.length;\\n uint256 _totalWeight = 0;\\n\\n for (uint i = 0; i < _poolVoteCnt; i ++) {\\n address _pool = _poolVote[i];\\n uint256 _votes = votes[_tokenId][_pool];\\n\\n if (_votes != 0) {\\n _updateFor(gauges[_pool]);\\n weights[_pool] -= _votes;\\n votes[_tokenId][_pool] -= _votes;\\n if (_votes > 0) {\\n IBribe(internal_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);\\n _totalWeight += _votes;\\n } else {\\n _totalWeight -= _votes;\\n }\\n emit Abstained(_tokenId, _votes);\\n }\\n }\\n totalWeight -= uint256(_totalWeight);\\n usedWeights[_tokenId] = 0;\\n delete poolVote[_tokenId];\\n }\\n\\n function poke(uint _tokenId) external {\\n address[] memory _poolVote = poolVote[_tokenId];\\n uint _poolCnt = _poolVote.length;\\n uint256[] memory _weights = new uint256[](_poolCnt);\\n\\n for (uint i = 0; i < _poolCnt; i ++) {\\n _weights[i] = votes[_tokenId][_poolVote[i]];\\n }\\n\\n _vote(_tokenId, _poolVote, _weights);\\n }\\n\\n function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {\\n _reset(_tokenId);\\n uint _poolCnt = _poolVote.length;\\n uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);\\n uint256 _totalVoteWeight = 0;\\n uint256 _totalWeight = 0;\\n uint256 _usedWeight = 0;\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n _totalVoteWeight += _weights[i];\\n }\\n\\n for (uint i = 0; i < _poolCnt; i++) {\\n address _pool = _poolVote[i];\\n address _gauge = gauges[_pool];\\n\\n if (isGauge[_gauge]) {\\n uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;\\n require(votes[_tokenId][_pool] == 0);\\n require(_poolWeight != 0);\\n _updateFor(_gauge);\\n\\n poolVote[_tokenId].push(_pool);\\n\\n weights[_pool] += _poolWeight;\\n votes[_tokenId][_pool] += _poolWeight;\\n IBribe(internal_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);\\n _usedWeight += _poolWeight;\\n _totalWeight += _poolWeight;\\n emit Voted(msg.sender, _tokenId, _poolWeight);\\n }\\n }\\n if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);\\n totalWeight += uint256(_totalWeight);\\n usedWeights[_tokenId] = uint256(_usedWeight);\\n }\\n\\n function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n require(_poolVote.length == _weights.length);\\n lastVoted[tokenId] = block.timestamp;\\n _vote(tokenId, _poolVote, _weights);\\n }\\n\\n function whitelist(address _token) public {\\n require(msg.sender == governor);\\n _whitelist(_token);\\n }\\n\\n function _whitelist(address _token) internal {\\n require(!isWhitelisted[_token]);\\n isWhitelisted[_token] = true;\\n emit Whitelisted(msg.sender, _token);\\n }\\n\\n function createGauge(address _pool) external returns (address) {\\n require(gauges[_pool] == address(0x0), \\\"exists\\\");\\n address[] memory allowedRewards = new address[](3);\\n address[] memory internalRewards = new address[](2);\\n bool isPair = IPairFactory(factory).isPair(_pool);\\n address tokenA;\\n address tokenB;\\n\\n if (isPair) {\\n (tokenA, tokenB) = IPair(_pool).tokens();\\n allowedRewards[0] = tokenA;\\n allowedRewards[1] = tokenB;\\n internalRewards[0] = tokenA;\\n internalRewards[1] = tokenB;\\n\\n if (base != tokenA && base != tokenB) {\\n allowedRewards[2] = base;\\n }\\n }\\n\\n if (msg.sender != governor) { // gov can create for any pool, even non-Velodrome pairs\\n require(isPair, \\\"!_pool\\\");\\n require(isWhitelisted[tokenA] && isWhitelisted[tokenB], \\\"!whitelisted\\\");\\n }\\n\\n address _internal_bribe = IBribeFactory(bribefactory).createInternalBribe(internalRewards);\\n address _external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);\\n address _gauge = IGaugeFactory(gaugefactory).createGauge(_pool, _internal_bribe, _external_bribe, _ve, isPair, allowedRewards);\\n\\n IERC20(base).approve(_gauge, type(uint).max);\\n internal_bribes[_gauge] = _internal_bribe;\\n external_bribes[_gauge] = _external_bribe;\\n gauges[_pool] = _gauge;\\n poolForGauge[_gauge] = _pool;\\n isGauge[_gauge] = true;\\n isAlive[_gauge] = true;\\n _updateFor(_gauge);\\n pools.push(_pool);\\n emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool);\\n return _gauge;\\n }\\n\\n function killGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(isAlive[_gauge], \\\"gauge already dead\\\");\\n isAlive[_gauge] = false;\\n claimable[_gauge] = 0;\\n emit GaugeKilled(_gauge);\\n }\\n\\n function reviveGauge(address _gauge) external {\\n require(msg.sender == emergencyCouncil, \\\"not emergency council\\\");\\n require(!isAlive[_gauge], \\\"gauge already alive\\\");\\n isAlive[_gauge] = true;\\n emit GaugeRevived(_gauge);\\n }\\n\\n function attachTokenToGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]); // killed gauges cannot attach tokens to themselves\\n if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);\\n emit Attach(account, msg.sender, tokenId);\\n }\\n\\n function emitDeposit(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n require(isAlive[msg.sender]);\\n emit Deposit(account, msg.sender, tokenId, amount);\\n }\\n\\n function detachTokenFromGauge(uint tokenId, address account) external {\\n require(isGauge[msg.sender]);\\n if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);\\n emit Detach(account, msg.sender, tokenId);\\n }\\n\\n function emitWithdraw(uint tokenId, address account, uint amount) external {\\n require(isGauge[msg.sender]);\\n emit Withdraw(account, msg.sender, tokenId, amount);\\n }\\n\\n function length() external view returns (uint) {\\n return pools.length;\\n }\\n\\n uint internal index;\\n mapping(address => uint) internal supplyIndex;\\n mapping(address => uint) public claimable;\\n\\n function notifyRewardAmount(uint amount) external {\\n _safeTransferFrom(base, msg.sender, address(this), amount); // transfer the distro in\\n uint256 _ratio = amount * 1e18 / totalWeight; // 1e18 adjustment is removed during claim\\n if (_ratio > 0) {\\n index += _ratio;\\n }\\n emit NotifyReward(msg.sender, base, amount);\\n }\\n\\n function updateFor(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n _updateFor(_gauges[i]);\\n }\\n }\\n\\n function updateForRange(uint start, uint end) public {\\n for (uint i = start; i < end; i++) {\\n _updateFor(gauges[pools[i]]);\\n }\\n }\\n\\n function updateAll() external {\\n updateForRange(0, pools.length);\\n }\\n\\n function updateGauge(address _gauge) external {\\n _updateFor(_gauge);\\n }\\n\\n function _updateFor(address _gauge) internal {\\n address _pool = poolForGauge[_gauge];\\n uint256 _supplied = weights[_pool];\\n if (_supplied > 0) {\\n uint _supplyIndex = supplyIndex[_gauge];\\n uint _index = index; // get global index0 for accumulated distro\\n supplyIndex[_gauge] = _index; // update _gauge current position to global position\\n uint _delta = _index - _supplyIndex; // see if there is any difference that need to be accrued\\n if (_delta > 0) {\\n uint _share = uint(_supplied) * _delta / 1e18; // add accrued difference for each supplied token\\n if (isAlive[_gauge]) {\\n claimable[_gauge] += _share;\\n }\\n }\\n } else {\\n supplyIndex[_gauge] = index; // new users are set to the default global state\\n }\\n }\\n\\n function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);\\n }\\n }\\n\\n function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _bribes.length; i++) {\\n IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function claimFees(address[] memory _fees, address[][] memory _tokens, uint _tokenId) external {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));\\n for (uint i = 0; i < _fees.length; i++) {\\n IBribe(_fees[i]).getRewardForOwner(_tokenId, _tokens[i]);\\n }\\n }\\n\\n function distributeFees(address[] memory _gauges) external {\\n for (uint i = 0; i < _gauges.length; i++) {\\n if (IGauge(_gauges[i]).isForPair()){\\n IGauge(_gauges[i]).claimFees();\\n }\\n }\\n }\\n\\n function distribute(address _gauge) public lock {\\n IMinter(minter).update_period();\\n _updateFor(_gauge); // should set claimable to 0 if killed\\n uint _claimable = claimable[_gauge];\\n if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {\\n claimable[_gauge] = 0;\\n IGauge(_gauge).notifyRewardAmount(base, _claimable);\\n emit DistributeReward(msg.sender, _gauge, _claimable);\\n }\\n }\\n\\n function distro() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute() external {\\n distribute(0, pools.length);\\n }\\n\\n function distribute(uint start, uint finish) public {\\n for (uint x = start; x < finish; x++) {\\n distribute(gauges[pools[x]]);\\n }\\n }\\n\\n function distribute(address[] memory _gauges) external {\\n for (uint x = 0; x < _gauges.length; x++) {\\n distribute(_gauges[x]);\\n }\\n }\\n\\n function _safeTransferFrom(address token, address from, address to, uint256 value) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) =\\n token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x2ff3fc2765dfa0c54870e428d3a2c625f413fb6e10ed7742e786ab4404aae6dc\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IBribeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribeFactory {\\n function createInternalBribe(address[] memory) external returns (address);\\n function createExternalBribe(address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0x3893233c0f5acb71691f6d2c8b758f93b41a90ded632b9d4d919fbc3754b2549\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IGaugeFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGaugeFactory {\\n function createGauge(address, address, address, address, bool, address[] memory) external returns (address);\\n}\\n\",\"keccak256\":\"0xb0b7fb654242fb9709c9d767bbcf2edbbc54bda0b4c1dbf092718c0e5ddac785\"},\"contracts/interfaces/IMinter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IMinter {\\n function update_period() external returns (uint);\\n}\\n\",\"keccak256\":\"0x22a493b7559b31b779773d0279189161af0d6c0e741d470fd7a8afdf91558304\"},\"contracts/interfaces/IPair.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPair {\\n function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);\\n function claimFees() external returns (uint, uint);\\n function tokens() external returns (address, address);\\n function transferFrom(address src, address dst, uint amount) external returns (bool);\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function mint(address to) external returns (uint liquidity);\\n function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);\\n function getAmountOut(uint, address) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x796005a0babe921334bacab4a90a551bc7f2ddfb030350a6ba590a9d8440daee\"},\"contracts/interfaces/IPairFactory.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IPairFactory {\\n function allPairsLength() external view returns (uint);\\n function isPair(address pair) external view returns (bool);\\n function pairCodeHash() external pure returns (bytes32);\\n function getPair(address tokenA, address token, bool stable) external view returns (address);\\n function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);\\n}\\n\",\"keccak256\":\"0x6a1b9f617020d6a2e0f8cadd51288f5000b0e0dae938a84dc5c977c88c849738\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x61012060405260016011553480156200001757600080fd5b5060405162003656380380620036568339810160408190526200003a916200011c565b6001600160a01b03808516608081905290841660a05260408051637e062a3560e11b8152905163fc0c546a916004808201926020929091908290030181865afa1580156200008c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b2919062000179565b6001600160a01b0390811660c05291821660e0521661010052505060008054336001600160a01b03199182168117909255600180548216831790556002805490911690911790556200019e565b80516001600160a01b03811681146200011757600080fd5b919050565b600080600080608085870312156200013357600080fd5b6200013e85620000ff565b93506200014e60208601620000ff565b92506200015e60408601620000ff565b91506200016e60608601620000ff565b905092959194509250565b6000602082840312156200018c57600080fd5b6200019782620000ff565b9392505050565b60805160a05160c05160e051610100516133e062000276600039600081816103e701528181611c680152611ce60152600081816104d30152611d79015260008181610b9401528181610c0d01528181610edd01528181610f9901528181611acd01528181611b0601528181611b380152611e5a0152600081816106fc015261192401526000818161058c0152818161092b015281816109d701528181610c9a01528181611069015281816111ea0152818161131a015281816114d901528181611dab015281816125e501526129a801526133e06000f3fe608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea26469706673582212202ba017d0b62c0f1d47ae8bb31cfdd049608b388bc02e3c268f1b267d8dd357d564736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102f15760003560e01c806379e938241161019d578063ac4afa38116100e9578063d23254b4116100a2578063e586875f1161007c578063e586875f1461076f578063ea94ee4414610782578063eae40f2614610795578063f3594be0146107be57600080fd5b8063d23254b414610731578063d560b0d71461075c578063e4fc6b6d1461048557600080fd5b8063ac4afa381461067f578063ae21c4cb14610692578063b9a09fd5146106bb578063c42cf535146106e4578063c45a0155146106f7578063c527ee1f1461071e57600080fd5b80639b6a9d7211610156578063a61c713a11610130578063a61c713a14610616578063a7cac84614610629578063a86a366d14610649578063aa79979b1461065c57600080fd5b80639b6a9d72146105dd5780639f06247b146105f0578063a5f4301e1461060357600080fd5b806379e93824146105545780637ac09bf7146105745780638dd598fb1461058757806396c82e57146105ae578063992a7933146105b75780639b19251a146105ca57600080fd5b8063411b1f771161025c578063666256aa116102155780636ecbe38a116101ef5780636ecbe38a146105085780637625391a1461051b5780637715ee751461052e5780637778960e1461054157600080fd5b8063666256aa146104bb57806368c3acb3146104ce578063698473e3146104f557600080fd5b8063411b1f771461045f578063462d0b2e1461047257806347b3c6ba1461048557806353d786931461048d5780636138889b1461049557806363453ae1146104a857600080fd5b8063310bd74b116102ae578063310bd74b146103bc57806332145f90146103cf57806338752a9d146103e25780633af32abf146104095780633c6b16ab1461042c578063402914f51461043f57600080fd5b806306d6a1b2146102f6578063075461721461033c5780630c340a241461034f5780631703e5f9146103625780631f7b6d321461039557806320b1cb6f146103a7575b600080fd5b61031f610304366004612cea565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60005461031f906001600160a01b031681565b60015461031f906001600160a01b031681565b610385610370366004612cea565b60106020526000908152604090205460ff1681565b6040519015158152602001610333565b6004545b604051908152602001610333565b6103ba6103b5366004612e6d565b6107de565b005b6103ba6103ca366004612ed1565b610894565b6103ba6103dd366004612ed1565b610a3f565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b610385610417366004612cea565b600f6020526000908152604090205460ff1681565b6103ba61043a366004612ed1565b610b8f565b61039961044d366004612cea565b60146020526000908152604090205481565b6103ba61046d366004612eea565b610c62565b6103ba610480366004612f1a565b610d3c565b6103ba610db7565b6103ba610dc8565b6103ba6104a3366004612f61565b610dd7565b6103ba6104b6366004612cea565b610e1b565b6103ba6104c9366004612f9e565b61104d565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba610503366004612eea565b611196565b6103ba610516366004612cea565b61128c565b6103ba61052936600461300b565b611298565b6103ba61053c366004612f9e565b6112fe565b60025461031f906001600160a01b031681565b610399610562366004612ed1565b600c6020526000908152604090205481565b6103ba610582366004613079565b611447565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b61039960035481565b6103ba6105c5366004612cea565b6115df565b6103ba6105d8366004612cea565b6116e4565b6103ba6105eb36600461300b565b611704565b6103ba6105fe366004612cea565b61176a565b61031f610611366004612cea565b611867565b6103ba6106243660046130f3565b612006565b610399610637366004612cea565b60096020526000908152604090205481565b61031f61065736600461300b565b61208a565b61038561066a366004612cea565b600e6020526000908152604090205460ff1681565b61031f61068d366004612ed1565b6120c2565b61031f6106a0366004612cea565b6008602052600090815260409020546001600160a01b031681565b61031f6106c9366004612cea565b6005602052600090815260409020546001600160a01b031681565b6103ba6106f2366004612cea565b6120ec565b61031f7f000000000000000000000000000000000000000000000000000000000000000081565b6103ba61072c366004612f61565b612125565b61039961073f366004612eea565b600a60209081526000928352604080842090915290825290205481565b6103ba61076a366004612f61565b612242565b6103ba61077d366004612cea565b612282565b6103ba6107903660046130f3565b6122bb565b61031f6107a3366004612cea565b6007602052600090815260409020546001600160a01b031681565b6103996107cc366004612ed1565b600d6020526000908152604090205481565b60005b825181101561088f578281815181106107fc576107fc61312b565b60200260200101516001600160a01b03166331279d3d338484815181106108255761082561312b565b60200260200101516040518363ffffffff1660e01b815260040161084a929190613185565b600060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050508080610887906131bf565b9150506107e1565b505050565b6000818152600d6020526040902054819062093a806108b381426131d8565b6108bd91906131fa565b1161090f5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f4348000060448201526064015b60405180910390fd5b60405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190613219565b6109a757600080fd5b6000828152600d602052604090204290556109c18261231a565b60405163c1f0fb9f60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1f0fb9f90602401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b505050505050565b6000818152600b6020908152604080832080548251818502810185019093528083529192909190830182828015610a9f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a81575b5050505050905060008151905060008167ffffffffffffffff811115610ac757610ac7612d0e565b604051908082528060200260200182016040528015610af0578160200160208202803683370190505b50905060005b82811015610b7d57600a60008681526020019081526020016000206000858381518110610b2557610b2561312b565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110610b6057610b6061312b565b602090810291909101015280610b75816131bf565b915050610af6565b50610b898484836125c1565b50505050565b610bbb7f0000000000000000000000000000000000000000000000000000000000000000333084612a3f565b600354600090610bd383670de0b6b3a76400006131fa565b610bdd91906131d8565b90508015610bfd578060126000828254610bf7919061323b565b90915550505b6040518281526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169033907ff70d5c697de7ea828df48e5c4573cb2194c659f1901f70110c52b066dcf50826906020015b60405180910390a35050565b336000908152600e602052604090205460ff16610c7e57600080fd5b8115610cff57604051634c35bec560e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063986b7d8a90602401600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907fae268d9aab12f3605f58efd74fd3801fa812b03fdb44317eb70f46dff0e19e2290602001610c56565b6000546001600160a01b03163314610d5357600080fd5b60005b8251811015610d9357610d81838281518110610d7457610d7461312b565b6020026020010151612b2f565b80610d8b816131bf565b915050610d56565b50600080546001600160a01b0319166001600160a01b039290921691909117905550565b600454610dc690600090611298565b565b600454610dc690600090611704565b60005b8151811015610e1757610e05828281518110610df857610df861312b565b6020026020010151610e1b565b80610e0f816131bf565b915050610dda565b5050565b601154600114610e2a57600080fd5b600260118190555060008054906101000a90046001600160a01b03166001600160a01b031663ed29fc116040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea99190613253565b50610eb381612ba2565b6001600160a01b0381811660008181526014602052604090819020549051634cde602960e11b81527f00000000000000000000000000000000000000000000000000000000000000009093166004840152916399bcc05290602401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613253565b81118015610f6957506000610f6762093a80836131d8565b115b15611044576001600160a01b03828116600081815260146020526040808220919091555163b66503cf60e01b81527f00000000000000000000000000000000000000000000000000000000000000009092166004830152602482018390529063b66503cf90604401600060405180830381600087803b158015610feb57600080fd5b505af1158015610fff573d6000803e3d6000fd5b50506040518381526001600160a01b03851692503391507f4fa9693cae526341d334e2862ca2413b2e503f1266255f9e0869fb36e6d89b179060200160405180910390a35b50506001601155565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190613219565b6110e557600080fd5b60005b8351811015610b89578381815181106111035761110361312b565b60200260200101516001600160a01b031663a7852afa8385848151811061112c5761112c61312b565b60200260200101516040518363ffffffff1660e01b815260040161115192919061326c565b600060405180830381600087803b15801561116b57600080fd5b505af115801561117f573d6000803e3d6000fd5b50505050808061118e906131bf565b9150506110e8565b336000908152600e602052604090205460ff166111b257600080fd5b3360009081526010602052604090205460ff166111ce57600080fd5b811561124f5760405163fbd3a29d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fbd3a29d90602401600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b505050505b60405182815233906001600160a01b038316907f60940192810a6fb3bce3fd3e2e3a13fd6ccc7605e963fb87ee971aba829989bd90602001610c56565b61129581612ba2565b50565b815b8181101561088f576112ec60056000600484815481106112bc576112bc61312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416610e1b565b806112f6816131bf565b91505061129a565b60405163430c208160e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190613219565b61139657600080fd5b60005b8351811015610b89578381815181106113b4576113b461312b565b60200260200101516001600160a01b031663a7852afa838584815181106113dd576113dd61312b565b60200260200101516040518363ffffffff1660e01b815260040161140292919061326c565b600060405180830381600087803b15801561141c57600080fd5b505af1158015611430573d6000803e3d6000fd5b50505050808061143f906131bf565b915050611399565b6000858152600d6020526040902054859062093a8061146681426131d8565b61147091906131fa565b116114bd5760405162461bcd60e51b815260206004820152601e60248201527f544f4b454e5f414c52454144595f564f5445445f544849535f45504f434800006044820152606401610906565b60405163430c208160e01b8152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154c9190613219565b61155557600080fd5b83821461156157600080fd5b6000868152600d602090815260409182902042905581518682028181018301909352868152610a379289928991899182919085019084908082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152506125c192505050565b6002546001600160a01b031633146116315760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff1661168e5760405162461bcd60e51b815260206004820152601260248201527119d85d59d948185b1c9958591e481919585960721b6044820152606401610906565b6001600160a01b0381166000818152601060209081526040808320805460ff191690556014909152808220829055517f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba79190a250565b6001546001600160a01b031633146116fb57600080fd5b61129581612b2f565b815b8181101561088f5761175860056000600484815481106117285761172861312b565b60009182526020808320909101546001600160a01b03908116845290830193909352604090910190205416612ba2565b80611762816131bf565b915050611706565b6002546001600160a01b031633146117bc5760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b595c99d95b98de4818dbdd5b98da5b605a1b6044820152606401610906565b6001600160a01b03811660009081526010602052604090205460ff161561181b5760405162461bcd60e51b8152602060048201526013602482015272676175676520616c726561647920616c69766560681b6044820152606401610906565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa9190a250565b6001600160a01b03818116600090815260056020526040812054909116156118ba5760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b6044820152606401610906565b60408051600380825260808201909252600091602082016060803683375050604080516002808252606082018352939450600093909250906020830190803683370190505060405163e5e31b1360e01b81526001600160a01b0386811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063e5e31b1390602401602060405180830381865afa15801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190613219565b90506000808215611b8b57866001600160a01b0316639d63848a6040518163ffffffff1660e01b815260040160408051808303816000875af11580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190613285565b80925081935050508185600081518110611a1957611a1961312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508085600181518110611a4d57611a4d61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508184600081518110611a8157611a8161312b565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600181518110611ab557611ab561312b565b6001600160a01b0392831660209182029290920101527f0000000000000000000000000000000000000000000000000000000000000000811690831614801590611b315750806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b15611b8b577f000000000000000000000000000000000000000000000000000000000000000085600281518110611b6a57611b6a61312b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001546001600160a01b03163314611c4e5782611bd35760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610906565b6001600160a01b0382166000908152600f602052604090205460ff168015611c1357506001600160a01b0381166000908152600f602052604090205460ff165b611c4e5760405162461bcd60e51b815260206004820152600c60248201526b085dda1a5d195b1a5cdd195960a21b6044820152606401610906565b604051632a26b9eb60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a26b9eb90611c9d9088906004016132b4565b6020604051808303816000875af1158015611cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce091906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636485f0c4886040518263ffffffff1660e01b8152600401611d3091906132b4565b6020604051808303816000875af1158015611d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7391906132c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc25f4f8b85857f00000000000000000000000000000000000000000000000000000000000000008b8e6040518763ffffffff1660e01b8152600401611ded969594939291906132e4565b6020604051808303816000875af1158015611e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3091906132c7565b60405163095ea7b360e01b81526001600160a01b03808316600483015260001960248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec99190613219565b506001600160a01b03818116600081815260076020908152604080832080546001600160a01b03199081168a8816179091556008835281842080548216898816179055948f16808452600583528184208054871686179055938352600682528083208054909516909317909355600e8352818120805460ff19908116600190811790925560109094529190208054909216179055611f6681612ba2565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038c8116918217909255604080513381528684166020820152919285811692908516917fa4d97e9e7c65249b4cd01acb82add613adea98af32daf092366982f0a0d4e453910160405180910390a49998505050505050505050565b336000908152600e602052604090205460ff1661202257600080fd5b3360009081526010602052604090205460ff1661203e57600080fd5b604080518481526020810183905233916001600160a01b038516917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d791015b60405180910390a3505050565b600b60205281600052604060002081815481106120a657600080fd5b6000918252602090912001546001600160a01b03169150829050565b600481815481106120d257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461210357600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8151811015610e17578181815181106121435761214361312b565b60200260200101516001600160a01b031663e57482136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190613219565b15612230578181815181106121c3576121c361312b565b60200260200101516001600160a01b031663d294f0936040518163ffffffff1660e01b815260040160408051808303816000875af1158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613334565b50505b8061223a816131bf565b915050612128565b60005b8151811015610e17576122708282815181106122635761226361312b565b6020026020010151612ba2565b8061227a816131bf565b915050612245565b6002546001600160a01b0316331461229957600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600e602052604090205460ff166122d757600080fd5b604080518481526020810183905233916001600160a01b038516917ff341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567910161207d565b6000818152600b6020526040812080549091805b8281101561258557600084828154811061234a5761234a61312b565b6000918252602080832090910154888352600a825260408084206001600160a01b03909216808552919092529120549091508015612570576001600160a01b038083166000908152600560205260409020546123a69116612ba2565b6001600160a01b038216600090815260096020526040812080548392906123ce908490613358565b90915550506000878152600a602090815260408083206001600160a01b038616845290915281208054839290612405908490613358565b90915550508015612529576001600160a01b038281166000908152600560209081526040808320548416835260079091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b15801561247b57600080fd5b505af115801561248f573d6000803e3d6000fd5b505050506001600160a01b038281166000908152600560209081526040808320548416835260089091529081902054905163278afc8b60e21b815260048101849052602481018a9052911690639e2bf22c90604401600060405180830381600087803b1580156124fe57600080fd5b505af1158015612512573d6000803e3d6000fd5b505050508084612522919061323b565b9350612536565b6125338185613358565b93505b60408051888152602081018390527fa9f3ca5f8a9e1580edb2741e0ba560084ec72e0067ba3423f9e9327a176882db910160405180910390a15b5050808061257d906131bf565b91505061232e565b5080600360008282546125989190613358565b90915550506000848152600c60209081526040808320839055600b9091528120610b8991612ca3565b6125ca8361231a565b81516040516339f890b560e21b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7e242d490602401602060405180830381865afa158015612634573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126589190613253565b90506000806000805b858110156126a25786818151811061267b5761267b61312b565b60200260200101518461268e919061323b565b93508061269a816131bf565b915050612661565b5060005b8581101561298b5760008882815181106126c2576126c261312b565b6020908102919091018101516001600160a01b03808216600090815260058452604080822054909216808252600e909452205490925060ff161561297657600086888b86815181106127165761271661312b565b602002602001015161272891906131fa565b61273291906131d8565b60008d8152600a602090815260408083206001600160a01b03881684529091529020549091501561276257600080fd5b8060000361276f57600080fd5b61277882612ba2565b60008c8152600b6020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b03881690811790915583526009909152812080548392906127cd90849061323b565b909155505060008c8152600a602090815260408083206001600160a01b03871684529091528120805483929061280490849061323b565b90915550506001600160a01b038083166000908152600760205260409081902054905163f320772360e01b815260048101849052602481018f905291169063f320772390604401600060405180830381600087803b15801561286557600080fd5b505af1158015612879573d6000803e3d6000fd5b5050505060086000836001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663f3207723828e6040518363ffffffff1660e01b81526004016128ec929190918252602082015260400190565b600060405180830381600087803b15801561290657600080fd5b505af115801561291a573d6000803e3d6000fd5b50505050808561292a919061323b565b9450612936818761323b565b604080518e81526020810184905291975033917fea66f58e474bc09f580000e81f31b334d171db387d0c6098ba47bd897741679b910160405180910390a2505b50508080612983906131bf565b9150506126a6565b508015612a0d5760405163fd4a77f160e01b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fd4a77f190602401600060405180830381600087803b1580156129f457600080fd5b505af1158015612a08573d6000803e3d6000fd5b505050505b8160036000828254612a1f919061323b565b90915550506000978852600c602052604090972096909655505050505050565b6000846001600160a01b03163b11612a5657600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691612aba919061336f565b6000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b5091509150818015612b26575080511580612b26575080806020019051810190612b269190613219565b610a3757600080fd5b6001600160a01b0381166000908152600f602052604090205460ff1615612b5557600080fd5b6001600160a01b0381166000818152600f6020526040808220805460ff191660011790555133917f6661a7108aecd07864384529117d96c319c1163e3010c01390f6b704726e07de91a350565b6001600160a01b038082166000908152600660209081526040808320549093168083526009909152919020548015612c82576001600160a01b038316600090815260136020526040812080546012549182905591612c008383613358565b90508015610a37576000670de0b6b3a7640000612c1d83876131fa565b612c2791906131d8565b6001600160a01b03881660009081526010602052604090205490915060ff1615612c79576001600160a01b03871660009081526014602052604081208054839290612c7390849061323b565b90915550505b50505050505050565b6012546001600160a01b038416600090815260136020526040902055505050565b508054600082559060005260206000209081019061129591905b80821115612cd15760008155600101612cbd565b5090565b6001600160a01b038116811461129557600080fd5b600060208284031215612cfc57600080fd5b8135612d0781612cd5565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4d57612d4d612d0e565b604052919050565b600067ffffffffffffffff821115612d6f57612d6f612d0e565b5060051b60200190565b600082601f830112612d8a57600080fd5b81356020612d9f612d9a83612d55565b612d24565b82815260059290921b84018101918181019086841115612dbe57600080fd5b8286015b84811015612de2578035612dd581612cd5565b8352918301918301612dc2565b509695505050505050565b600082601f830112612dfe57600080fd5b81356020612e0e612d9a83612d55565b82815260059290921b84018101918181019086841115612e2d57600080fd5b8286015b84811015612de257803567ffffffffffffffff811115612e515760008081fd5b612e5f8986838b0101612d79565b845250918301918301612e31565b60008060408385031215612e8057600080fd5b823567ffffffffffffffff80821115612e9857600080fd5b612ea486838701612d79565b93506020850135915080821115612eba57600080fd5b50612ec785828601612ded565b9150509250929050565b600060208284031215612ee357600080fd5b5035919050565b60008060408385031215612efd57600080fd5b823591506020830135612f0f81612cd5565b809150509250929050565b60008060408385031215612f2d57600080fd5b823567ffffffffffffffff811115612f4457600080fd5b612f5085828601612d79565b9250506020830135612f0f81612cd5565b600060208284031215612f7357600080fd5b813567ffffffffffffffff811115612f8a57600080fd5b612f9684828501612d79565b949350505050565b600080600060608486031215612fb357600080fd5b833567ffffffffffffffff80821115612fcb57600080fd5b612fd787838801612d79565b94506020860135915080821115612fed57600080fd5b50612ffa86828701612ded565b925050604084013590509250925092565b6000806040838503121561301e57600080fd5b50508035926020909101359150565b60008083601f84011261303f57600080fd5b50813567ffffffffffffffff81111561305757600080fd5b6020830191508360208260051b850101111561307257600080fd5b9250929050565b60008060008060006060868803121561309157600080fd5b85359450602086013567ffffffffffffffff808211156130b057600080fd5b6130bc89838a0161302d565b909650945060408801359150808211156130d557600080fd5b506130e28882890161302d565b969995985093965092949392505050565b60008060006060848603121561310857600080fd5b83359250602084013561311a81612cd5565b929592945050506040919091013590565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561317a5781516001600160a01b031687529582019590820190600101613155565b509495945050505050565b6001600160a01b0383168152604060208201819052600090612f9690830184613141565b634e487b7160e01b600052601160045260246000fd5b6000600182016131d1576131d16131a9565b5060010190565b6000826131f557634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613214576132146131a9565b500290565b60006020828403121561322b57600080fd5b81518015158114612d0757600080fd5b6000821982111561324e5761324e6131a9565b500190565b60006020828403121561326557600080fd5b5051919050565b828152604060208201526000612f966040830184613141565b6000806040838503121561329857600080fd5b82516132a381612cd5565b6020840151909250612f0f81612cd5565b602081526000612d076020830184613141565b6000602082840312156132d957600080fd5b8151612d0781612cd5565b6001600160a01b0387811682528681166020830152858116604083015284166060820152821515608082015260c060a0820181905260009061332890830184613141565b98975050505050505050565b6000806040838503121561334757600080fd5b505080516020909101519092909150565b60008282101561336a5761336a6131a9565b500390565b6000825160005b818110156133905760208186018101518583015201613376565b8181111561339f576000828501525b50919091019291505056fea26469706673582212202ba017d0b62c0f1d47ae8bb31cfdd049608b388bc02e3c268f1b267d8dd357d564736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 14322, + "contract": "contracts/Voter.sol:Voter", + "label": "minter", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 14324, + "contract": "contracts/Voter.sol:Voter", + "label": "governor", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 14326, + "contract": "contracts/Voter.sol:Voter", + "label": "emergencyCouncil", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 14328, + "contract": "contracts/Voter.sol:Voter", + "label": "totalWeight", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 14331, + "contract": "contracts/Voter.sol:Voter", + "label": "pools", + "offset": 0, + "slot": "4", + "type": "t_array(t_address)dyn_storage" + }, + { + "astId": 14335, + "contract": "contracts/Voter.sol:Voter", + "label": "gauges", + "offset": 0, + "slot": "5", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 14339, + "contract": "contracts/Voter.sol:Voter", + "label": "poolForGauge", + "offset": 0, + "slot": "6", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 14343, + "contract": "contracts/Voter.sol:Voter", + "label": "internal_bribes", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 14347, + "contract": "contracts/Voter.sol:Voter", + "label": "external_bribes", + "offset": 0, + "slot": "8", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 14351, + "contract": "contracts/Voter.sol:Voter", + "label": "weights", + "offset": 0, + "slot": "9", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 14357, + "contract": "contracts/Voter.sol:Voter", + "label": "votes", + "offset": 0, + "slot": "10", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))" + }, + { + "astId": 14362, + "contract": "contracts/Voter.sol:Voter", + "label": "poolVote", + "offset": 0, + "slot": "11", + "type": "t_mapping(t_uint256,t_array(t_address)dyn_storage)" + }, + { + "astId": 14366, + "contract": "contracts/Voter.sol:Voter", + "label": "usedWeights", + "offset": 0, + "slot": "12", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 14370, + "contract": "contracts/Voter.sol:Voter", + "label": "lastVoted", + "offset": 0, + "slot": "13", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 14374, + "contract": "contracts/Voter.sol:Voter", + "label": "isGauge", + "offset": 0, + "slot": "14", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 14378, + "contract": "contracts/Voter.sol:Voter", + "label": "isWhitelisted", + "offset": 0, + "slot": "15", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 14382, + "contract": "contracts/Voter.sol:Voter", + "label": "isAlive", + "offset": 0, + "slot": "16", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 14528, + "contract": "contracts/Voter.sol:Voter", + "label": "_unlocked", + "offset": 0, + "slot": "17", + "type": "t_uint256" + }, + { + "astId": 15620, + "contract": "contracts/Voter.sol:Voter", + "label": "index", + "offset": 0, + "slot": "18", + "type": "t_uint256" + }, + { + "astId": 15624, + "contract": "contracts/Voter.sol:Voter", + "label": "supplyIndex", + "offset": 0, + "slot": "19", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 15628, + "contract": "contracts/Voter.sol:Voter", + "label": "claimable", + "offset": 0, + "slot": "20", + "type": "t_mapping(t_address,t_uint256)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "base": "t_address", + "encoding": "dynamic_array", + "label": "address[]", + "numberOfBytes": "32" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_address)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_uint256,t_array(t_address)dyn_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => address[])", + "numberOfBytes": "32", + "value": "t_array(t_address)dyn_storage" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumOneOLD/VotingEscrow.json b/deployments/arbitrumOneOLD/VotingEscrow.json new file mode 100644 index 00000000..b308be02 --- /dev/null +++ b/deployments/arbitrumOneOLD/VotingEscrow.json @@ -0,0 +1,2339 @@ +{ + "address": "0x10Df81252069C1095F541FAca61646cb9Ae76703", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "token_addr", + "type": "address" + }, + { + "internalType": "address", + "name": "art_proxy", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "fromDelegate", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "toDelegate", + "type": "address" + } + ], + "name": "DelegateChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "DelegateVotesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "locktime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum VotingEscrow.DepositType", + "name": "deposit_type", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "ts", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "prevSupply", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "supply", + "type": "uint256" + } + ], + "name": "Supply", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "ts", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [], + "name": "DELEGATION_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DOMAIN_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_DELEGATES", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "abstain", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_approved", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "artProxy", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "attach", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "attachments", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_block", + "type": "uint256" + } + ], + "name": "balanceOfAtNFT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "balanceOfNFT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_t", + "type": "uint256" + } + ], + "name": "balanceOfNFTAt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "block_number", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkpoint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "name": "checkpoints", + "outputs": [ + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_lock_duration", + "type": "uint256" + } + ], + "name": "create_lock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_lock_duration", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + } + ], + "name": "create_lock_for", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + } + ], + "name": "delegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "delegateBySig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "delegates", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "deposit_for", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "detach", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "epoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "getPastTotalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "getPastVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "getPastVotesIndex", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "get_last_user_slope", + "outputs": [ + { + "internalType": "int128", + "name": "", + "type": "int128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "increase_amount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_lock_duration", + "type": "uint256" + } + ], + "name": "increase_unlock_time", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "isApprovedOrOwner", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "locked", + "outputs": [ + { + "internalType": "int128", + "name": "amount", + "type": "int128" + }, + { + "internalType": "uint256", + "name": "end", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "locked__end", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_from", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_to", + "type": "uint256" + } + ], + "name": "merge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "numCheckpoints", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "ownership_change", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "point_history", + "outputs": [ + { + "internalType": "int128", + "name": "bias", + "type": "int128" + }, + { + "internalType": "int128", + "name": "slope", + "type": "int128" + }, + { + "internalType": "uint256", + "name": "ts", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "blk", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "_approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_proxy", + "type": "address" + } + ], + "name": "setArtProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_team", + "type": "address" + } + ], + "name": "setTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_voter", + "type": "address" + } + ], + "name": "setVoter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "slope_changes", + "outputs": [ + { + "internalType": "int128", + "name": "", + "type": "int128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "supply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_interfaceID", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "team", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenIndex", + "type": "uint256" + } + ], + "name": "tokenOfOwnerByIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_block", + "type": "uint256" + } + ], + "name": "totalSupplyAt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "t", + "type": "uint256" + } + ], + "name": "totalSupplyAtT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "user_point_epoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "user_point_history", + "outputs": [ + { + "internalType": "int128", + "name": "bias", + "type": "int128" + }, + { + "internalType": "int128", + "name": "slope", + "type": "int128" + }, + { + "internalType": "uint256", + "name": "ts", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "blk", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_idx", + "type": "uint256" + } + ], + "name": "user_point_history__ts", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "voted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "voter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "voting", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x0d188c6284ab3f8819012287ed29c698d71269b7a82470a6dc166a8d66485061", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x10Df81252069C1095F541FAca61646cb9Ae76703", + "transactionIndex": 1, + "gasUsed": "30673850", + "logsBloom": "0x00000000000000000000000008000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000040000000000000000000000000008000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000010000102000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x0300bc4c5219d7cde2f65e67a4050d0df88e8cf53a3168d85b5211d4eb901d1a", + "transactionHash": "0x0d188c6284ab3f8819012287ed29c698d71269b7a82470a6dc166a8d66485061", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 53774090, + "transactionHash": "0x0d188c6284ab3f8819012287ed29c698d71269b7a82470a6dc166a8d66485061", + "address": "0x10Df81252069C1095F541FAca61646cb9Ae76703", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000010df81252069c1095f541faca61646cb9ae76703", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x0300bc4c5219d7cde2f65e67a4050d0df88e8cf53a3168d85b5211d4eb901d1a" + }, + { + "transactionIndex": 1, + "blockNumber": 53774090, + "transactionHash": "0x0d188c6284ab3f8819012287ed29c698d71269b7a82470a6dc166a8d66485061", + "address": "0x10Df81252069C1095F541FAca61646cb9Ae76703", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x00000000000000000000000010df81252069c1095f541faca61646cb9ae76703", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0x0300bc4c5219d7cde2f65e67a4050d0df88e8cf53a3168d85b5211d4eb901d1a" + } + ], + "blockNumber": 53774090, + "cumulativeGasUsed": "30673850", + "status": 1, + "byzantium": true + }, + "args": [ + "0xC33f7f83CbB021846Cb9c58f2d8E3df428dbC8C1", + "0x4b40D5E4401EC24673cc9d4799457a3B5827c581" + ], + "numDeployments": 1, + "solcInputHash": "f93feb6db909c3f14d7eec3a3196fbbd", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token_addr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"art_proxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromDelegate\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toDelegate\",\"type\":\"address\"}],\"name\":\"DelegateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"DelegateVotesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"locktime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum VotingEscrow.DepositType\",\"name\":\"deposit_type\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"prevSupply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"supply\",\"type\":\"uint256\"}],\"name\":\"Supply\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DELEGATION_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_DELEGATES\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"abstain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_approved\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"artProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"attach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"attachments\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"balanceOfAtNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_t\",\"type\":\"uint256\"}],\"name\":\"balanceOfNFTAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"block_number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"checkpoint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"checkpoints\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"create_lock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"create_lock_for\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"}],\"name\":\"delegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"delegateBySig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"}],\"name\":\"delegates\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"deposit_for\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"detach\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastTotalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getPastVotesIndex\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"get_last_user_slope\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"increase_amount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lock_duration\",\"type\":\"uint256\"}],\"name\":\"increase_unlock_time\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"isApprovedOrOwner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"locked\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"amount\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"end\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"locked__end\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_from\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_to\",\"type\":\"uint256\"}],\"name\":\"merge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"numCheckpoints\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ownership_change\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_proxy\",\"type\":\"address\"}],\"name\":\"setArtProxy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_team\",\"type\":\"address\"}],\"name\":\"setTeam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voter\",\"type\":\"address\"}],\"name\":\"setVoter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"slope_changes\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"\",\"type\":\"int128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"team\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenIndex\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"t\",\"type\":\"uint256\"}],\"name\":\"totalSupplyAtT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_epoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"user_point_history\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"bias\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"slope\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"ts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blk\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_idx\",\"type\":\"uint256\"}],\"name\":\"user_point_history__ts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"voted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"voting\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\",\"details\":\"Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\",\"kind\":\"dev\",\"methods\":{\"approve(address,uint256)\":{\"details\":\"Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address. Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner. Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP) Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"Address to be approved for the given NFT ID.\",\"_tokenId\":\"ID of the token to be approved.\"}},\"balanceOf(address)\":{\"details\":\"Returns the number of NFTs owned by `_owner`. Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\",\"params\":{\"_owner\":\"Address for whom to query the balance.\"}},\"constructor\":{\"params\":{\"token_addr\":\"`VELO` token address\"}},\"create_lock(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_value\":\"Amount to deposit\"}},\"create_lock_for(uint256,uint256,address)\":{\"params\":{\"_lock_duration\":\"Number of seconds to lock tokens for (rounded down to nearest week)\",\"_to\":\"Address to deposit\",\"_value\":\"Amount to deposit\"}},\"delegate(address)\":{\"params\":{\"delegatee\":\"The address to delegate votes to\"}},\"delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Delegates votes from signer to `delegatee`.\"},\"deposit_for(uint256,uint256)\":{\"details\":\"Anyone (even a smart contract) can deposit for someone else, but cannot extend their locktime and deposit for a brand new user\",\"params\":{\"_tokenId\":\"lock NFT\",\"_value\":\"Amount to add to user's lock\"}},\"getApproved(uint256)\":{\"details\":\"Get the approved address for a single NFT.\",\"params\":{\"_tokenId\":\"ID of the NFT to query the approval of.\"}},\"getVotes(address)\":{\"params\":{\"account\":\"The address to get votes balance\"},\"returns\":{\"_0\":\"The number of current votes for `account`\"}},\"get_last_user_slope(uint256)\":{\"params\":{\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Value of the slope\"}},\"increase_amount(uint256,uint256)\":{\"params\":{\"_value\":\"Amount of tokens to deposit and add to the lock\"}},\"increase_unlock_time(uint256,uint256)\":{\"params\":{\"_lock_duration\":\"New number of seconds until tokens unlock\"}},\"isApprovedForAll(address,address)\":{\"details\":\"Checks if `_operator` is an approved operator for `_owner`.\",\"params\":{\"_operator\":\"The address that acts on behalf of the owner.\",\"_owner\":\"The address that owns the NFTs.\"}},\"locked__end(uint256)\":{\"params\":{\"_tokenId\":\"User NFT\"},\"returns\":{\"_0\":\"Epoch time of the lock end\"}},\"ownerOf(uint256)\":{\"details\":\"Returns the address of the owner of the NFT.\",\"params\":{\"_tokenId\":\"The identifier for an NFT.\"}},\"safeTransferFrom(address,address,uint256)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"safeTransferFrom(address,address,uint256,bytes)\":{\"details\":\"Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\",\"params\":{\"_data\":\"Additional data with no specified format, sent in call to `_to`.\",\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"details\":\"Enables or disables approval for a third party (\\\"operator\\\") to manage all of `msg.sender`'s assets. It also emits the ApprovalForAll event. Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\",\"params\":{\"_approved\":\"True if the operators is approved, false to revoke approval.\",\"_operator\":\"Address to add to the set of authorized operators.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Interface identification is specified in ERC-165.\",\"params\":{\"_interfaceID\":\"Id of the interface\"}},\"tokenOfOwnerByIndex(address,uint256)\":{\"details\":\"Get token by index\"},\"tokenURI(uint256)\":{\"details\":\"Returns current token URI metadata\",\"params\":{\"_tokenId\":\"Token ID to fetch URI for.\"}},\"totalSupplyAt(uint256)\":{\"params\":{\"_block\":\"Block to calculate the total voting power at\"},\"returns\":{\"_0\":\"Total voting power at `_block`\"}},\"totalSupplyAtT(uint256)\":{\"details\":\"Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\",\"returns\":{\"_0\":\"Total voting power\"}},\"transferFrom(address,address,uint256)\":{\"details\":\"Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT.\",\"params\":{\"_from\":\"The current owner of the NFT.\",\"_to\":\"The new owner.\",\"_tokenId\":\"The NFT to transfer.\"}},\"user_point_history__ts(uint256,uint256)\":{\"params\":{\"_idx\":\"User epoch number\",\"_tokenId\":\"token of the NFT\"},\"returns\":{\"_0\":\"Epoch time of the checkpoint\"}},\"withdraw(uint256)\":{\"details\":\"Only possible if the lock has expired\"}},\"stateVariables\":{\"ERC165_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC165\"},\"ERC721_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721\"},\"ERC721_METADATA_INTERFACE_ID\":{\"details\":\"ERC165 interface ID of ERC721Metadata\"},\"_not_entered\":{\"details\":\"reentrancy guard\"},\"idToApprovals\":{\"details\":\"Mapping from NFT ID to approved address.\"},\"idToOwner\":{\"details\":\"Mapping from NFT ID to the address that owns it.\"},\"name\":{\"details\":\"Returns the token collection name.\"},\"ownerToNFTokenCount\":{\"details\":\"Mapping from owner address to count of his tokens.\"},\"ownerToNFTokenIdList\":{\"details\":\"Mapping from owner address to mapping of index to tokenIds\"},\"ownerToOperators\":{\"details\":\"Mapping from owner address to mapping of operator addresses.\"},\"supportedInterfaces\":{\"details\":\"Mapping of interface id to bool about whether or not it's supported\"},\"symbol\":{\"details\":\"Returns the token collection symbol.\"},\"tokenId\":{\"details\":\"Current count of token\"},\"tokenToOwnerIndex\":{\"details\":\"Mapping from NFT ID to index of owner\"}},\"title\":\"Voting Escrow\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DELEGATION_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the delegation struct used by the contract\"},\"DOMAIN_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the contract's domain\"},\"checkpoint()\":{\"notice\":\"Record global data to checkpoint\"},\"checkpoints(address,uint32)\":{\"notice\":\"A record of delegated token checkpoints for each account, by index\"},\"constructor\":{\"notice\":\"Contract constructor\"},\"create_lock(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\"},\"create_lock_for(uint256,uint256,address)\":{\"notice\":\"Deposit `_value` tokens for `_to` and lock for `_lock_duration`\"},\"delegate(address)\":{\"notice\":\"Delegate votes from `msg.sender` to `delegatee`\"},\"delegates(address)\":{\"notice\":\"Overrides the standard `Comp.sol` delegates mapping to return the delegator's own address if they haven't delegated. This avoids having to delegate to oneself.\"},\"deposit_for(uint256,uint256)\":{\"notice\":\"Deposit `_value` tokens for `_tokenId` and add to the lock\"},\"getVotes(address)\":{\"notice\":\"Gets the current votes balance for `account`\"},\"get_last_user_slope(uint256)\":{\"notice\":\"Get the most recently recorded rate of voting power decrease for `_tokenId`\"},\"increase_amount(uint256,uint256)\":{\"notice\":\"Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\"},\"increase_unlock_time(uint256,uint256)\":{\"notice\":\"Extend the unlock time for `_tokenId`\"},\"locked__end(uint256)\":{\"notice\":\"Get timestamp when `_tokenId`'s lock finishes\"},\"nonces(address)\":{\"notice\":\"A record of states for signing / validating signatures\"},\"numCheckpoints(address)\":{\"notice\":\"The number of checkpoints for each account\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"This works even if sender doesn't own any tokens at the time.\"},\"totalSupplyAt(uint256)\":{\"notice\":\"Calculate total voting power at some point in the past\"},\"totalSupplyAtT(uint256)\":{\"notice\":\"Calculate total voting power\"},\"transferFrom(address,address,uint256)\":{\"notice\":\"The caller is responsible to confirm that `_to` is capable of receiving NFTs or else they maybe be permanently lost.\"},\"user_point_history__ts(uint256,uint256)\":{\"notice\":\"Get the timestamp for checkpoint `_idx` for `_tokenId`\"},\"withdraw(uint256)\":{\"notice\":\"Withdraw all tokens for `_tokenId`\"}},\"notice\":\"veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFTVotes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VotingEscrow.sol\":\"VotingEscrow\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363733393932363534393236\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/VotingEscrow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {IERC721, IERC721Metadata} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\\\";\\nimport {IVotes} from \\\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\\\";\\nimport {IERC721Receiver} from \\\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {IERC20} from \\\"contracts/interfaces/IERC20.sol\\\";\\nimport {IVeArtProxy} from \\\"contracts/interfaces/IVeArtProxy.sol\\\";\\nimport {IVotingEscrow} from \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n/// @title Voting Escrow\\n/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT\\n/// @notice Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)\\n/// @author Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)\\n/// @author Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)\\n/// @author Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)\\n/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).\\ncontract VotingEscrow is IERC721, IERC721Metadata, IVotes {\\n enum DepositType {\\n DEPOSIT_FOR_TYPE,\\n CREATE_LOCK_TYPE,\\n INCREASE_LOCK_AMOUNT,\\n INCREASE_UNLOCK_TIME,\\n MERGE_TYPE\\n }\\n\\n struct LockedBalance {\\n int128 amount;\\n uint end;\\n }\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint ts;\\n uint blk; // block\\n }\\n /* We cannot really do block numbers per se b/c slope is per time, not per block\\n * and per block could be fairly bad b/c Ethereum changes blocktimes.\\n * What we can do is to extrapolate ***At functions */\\n\\n /// @notice A checkpoint for marking delegated tokenIds from a given timestamp\\n struct Checkpoint {\\n uint timestamp;\\n uint[] tokenIds;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Deposit(\\n address indexed provider,\\n uint tokenId,\\n uint value,\\n uint indexed locktime,\\n DepositType deposit_type,\\n uint ts\\n );\\n event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);\\n event Supply(uint prevSupply, uint supply);\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n address public immutable token;\\n address public voter;\\n address public team;\\n address public artProxy;\\n\\n mapping(uint => Point) public point_history; // epoch -> unsigned point\\n\\n /// @dev Mapping of interface id to bool about whether or not it's supported\\n mapping(bytes4 => bool) internal supportedInterfaces;\\n\\n /// @dev ERC165 interface ID of ERC165\\n bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;\\n\\n /// @dev ERC165 interface ID of ERC721\\n bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;\\n\\n /// @dev ERC165 interface ID of ERC721Metadata\\n bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;\\n\\n /// @dev Current count of token\\n uint internal tokenId;\\n\\n /// @notice Contract constructor\\n /// @param token_addr `VELO` token address\\n constructor(address token_addr, address art_proxy) {\\n token = token_addr;\\n voter = msg.sender;\\n team = msg.sender;\\n artProxy = art_proxy;\\n\\n point_history[0].blk = block.number;\\n point_history[0].ts = block.timestamp;\\n\\n supportedInterfaces[ERC165_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_INTERFACE_ID] = true;\\n supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;\\n\\n // mint-ish\\n emit Transfer(address(0), address(this), tokenId);\\n // burn-ish\\n emit Transfer(address(this), address(0), tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n MODIFIERS\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev reentrancy guard\\n uint8 internal constant _not_entered = 1;\\n uint8 internal constant _entered = 2;\\n uint8 internal _entered_state = 1;\\n modifier nonreentrant() {\\n require(_entered_state == _not_entered);\\n _entered_state = _entered;\\n _;\\n _entered_state = _not_entered;\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string constant public name = \\\"veNFT\\\";\\n string constant public symbol = \\\"veNFT\\\";\\n string constant public version = \\\"1.0.0\\\";\\n uint8 constant public decimals = 18;\\n\\n function setTeam(address _team) external {\\n require(msg.sender == team);\\n team = _team;\\n }\\n\\n function setArtProxy(address _proxy) external {\\n require(msg.sender == team);\\n artProxy = _proxy;\\n }\\n\\n /// @dev Returns current token URI metadata\\n /// @param _tokenId Token ID to fetch URI for.\\n function tokenURI(uint _tokenId) external view returns (string memory) {\\n require(idToOwner[_tokenId] != address(0), \\\"Query for nonexistent token\\\");\\n LockedBalance memory _locked = locked[_tokenId];\\n return IVeArtProxy(artProxy)._tokenURI(\\n _tokenId,\\n _balanceOfNFT(_tokenId, block.timestamp),\\n _locked.end,\\n uint(int256(_locked.amount))\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 BALANCE/OWNER STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to the address that owns it.\\n mapping(uint => address) internal idToOwner;\\n\\n /// @dev Mapping from owner address to count of his tokens.\\n mapping(address => uint) internal ownerToNFTokenCount;\\n\\n /// @dev Returns the address of the owner of the NFT.\\n /// @param _tokenId The identifier for an NFT.\\n function ownerOf(uint _tokenId) public view returns (address) {\\n return idToOwner[_tokenId];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function _balance(address _owner) internal view returns (uint) {\\n return ownerToNFTokenCount[_owner];\\n }\\n\\n /// @dev Returns the number of NFTs owned by `_owner`.\\n /// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.\\n /// @param _owner Address for whom to query the balance.\\n function balanceOf(address _owner) external view returns (uint) {\\n return _balance(_owner);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 APPROVAL STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from NFT ID to approved address.\\n mapping(uint => address) internal idToApprovals;\\n\\n /// @dev Mapping from owner address to mapping of operator addresses.\\n mapping(address => mapping(address => bool)) internal ownerToOperators;\\n\\n mapping(uint => uint) public ownership_change;\\n\\n /// @dev Get the approved address for a single NFT.\\n /// @param _tokenId ID of the NFT to query the approval of.\\n function getApproved(uint _tokenId) external view returns (address) {\\n return idToApprovals[_tokenId];\\n }\\n\\n /// @dev Checks if `_operator` is an approved operator for `_owner`.\\n /// @param _owner The address that owns the NFTs.\\n /// @param _operator The address that acts on behalf of the owner.\\n function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\\n return (ownerToOperators[_owner])[_operator];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC721 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.\\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.\\n /// Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)\\n /// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)\\n /// @param _approved Address to be approved for the given NFT ID.\\n /// @param _tokenId ID of the token to be approved.\\n function approve(address _approved, uint _tokenId) public {\\n address owner = idToOwner[_tokenId];\\n // Throws if `_tokenId` is not a valid NFT\\n require(owner != address(0));\\n // Throws if `_approved` is the current owner\\n require(_approved != owner);\\n // Check requirements\\n bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);\\n bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];\\n require(senderIsOwner || senderIsApprovedForAll);\\n // Set the approval\\n idToApprovals[_tokenId] = _approved;\\n emit Approval(owner, _approved, _tokenId);\\n }\\n\\n /// @dev Enables or disables approval for a third party (\\\"operator\\\") to manage all of\\n /// `msg.sender`'s assets. It also emits the ApprovalForAll event.\\n /// Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)\\n /// @notice This works even if sender doesn't own any tokens at the time.\\n /// @param _operator Address to add to the set of authorized operators.\\n /// @param _approved True if the operators is approved, false to revoke approval.\\n function setApprovalForAll(address _operator, bool _approved) external {\\n // Throws if `_operator` is the `msg.sender`\\n assert(_operator != msg.sender);\\n ownerToOperators[msg.sender][_operator] = _approved;\\n emit ApprovalForAll(msg.sender, _operator, _approved);\\n }\\n\\n /* TRANSFER FUNCTIONS */\\n /// @dev Clear an approval of a given address\\n /// Throws if `_owner` is not the current owner.\\n function _clearApproval(address _owner, uint _tokenId) internal {\\n // Throws if `_owner` is not the current owner\\n assert(idToOwner[_tokenId] == _owner);\\n if (idToApprovals[_tokenId] != address(0)) {\\n // Reset approvals\\n idToApprovals[_tokenId] = address(0);\\n }\\n }\\n\\n /// @dev Returns whether the given spender can transfer a given token ID\\n /// @param _spender address of the spender to query\\n /// @param _tokenId uint ID of the token to be transferred\\n /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token\\n function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {\\n address owner = idToOwner[_tokenId];\\n bool spenderIsOwner = owner == _spender;\\n bool spenderIsApproved = _spender == idToApprovals[_tokenId];\\n bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];\\n return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;\\n }\\n\\n function isApprovedOrOwner(address _spender, uint _tokenId) external view returns (bool) {\\n return _isApprovedOrOwner(_spender, _tokenId);\\n }\\n\\n /// @dev Exeute transfer of a NFT.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\\n /// address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_tokenId` is not a valid NFT.\\n function _transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n address _sender\\n ) internal {\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n // Check requirements\\n require(_isApprovedOrOwner(_sender, _tokenId));\\n // Clear approval. Throws if `_from` is not the current owner\\n _clearApproval(_from, _tokenId);\\n // Remove NFT. Throws if `_tokenId` is not a valid NFT\\n _removeTokenFrom(_from, _tokenId);\\n // auto re-delegate\\n _moveTokenDelegates(delegates(_from), delegates(_to), _tokenId);\\n // Add NFT\\n _addTokenTo(_to, _tokenId);\\n // Set the block of ownership transfer (for Flash NFT protection)\\n ownership_change[_tokenId] = block.number;\\n // Log the transfer\\n emit Transfer(_from, _to, _tokenId);\\n }\\n\\n /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\\n /// they maybe be permanently lost.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function transferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId\\n ) external {\\n safeTransferFrom(_from, _to, _tokenId, \\\"\\\");\\n }\\n\\n function _isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n uint size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n\\n /// @dev Transfers the ownership of an NFT from one address to another address.\\n /// Throws unless `msg.sender` is the current owner, an authorized operator, or the\\n /// approved address for this NFT.\\n /// Throws if `_from` is not the current owner.\\n /// Throws if `_to` is the zero address.\\n /// Throws if `_tokenId` is not a valid NFT.\\n /// If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if\\n /// the return value is not `bytes4(keccak256(\\\"onERC721Received(address,address,uint,bytes)\\\"))`.\\n /// @param _from The current owner of the NFT.\\n /// @param _to The new owner.\\n /// @param _tokenId The NFT to transfer.\\n /// @param _data Additional data with no specified format, sent in call to `_to`.\\n function safeTransferFrom(\\n address _from,\\n address _to,\\n uint _tokenId,\\n bytes memory _data\\n ) public {\\n _transferFrom(_from, _to, _tokenId, msg.sender);\\n\\n if (_isContract(_to)) {\\n // Throws if transfer destination is a contract which does not implement 'onERC721Received'\\n try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 response) {\\n if (response != IERC721Receiver(_to).onERC721Received.selector) {\\n revert(\\\"ERC721: ERC721Receiver rejected tokens\\\");\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert('ERC721: transfer to non ERC721Receiver implementer');\\n } else {\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC165 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Interface identification is specified in ERC-165.\\n /// @param _interfaceID Id of the interface\\n function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\\n return supportedInterfaces[_interfaceID];\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @dev Mapping from owner address to mapping of index to tokenIds\\n mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;\\n\\n /// @dev Mapping from NFT ID to index of owner\\n mapping(uint => uint) internal tokenToOwnerIndex;\\n\\n /// @dev Get token by index\\n function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint) {\\n return ownerToNFTokenIdList[_owner][_tokenIndex];\\n }\\n\\n /// @dev Add a NFT to an index mapping to a given address\\n /// @param _to address of the receiver\\n /// @param _tokenId uint ID Of the token to be added\\n function _addTokenToOwnerList(address _to, uint _tokenId) internal {\\n uint current_count = _balance(_to);\\n\\n ownerToNFTokenIdList[_to][current_count] = _tokenId;\\n tokenToOwnerIndex[_tokenId] = current_count;\\n }\\n\\n /// @dev Add a NFT to a given address\\n /// Throws if `_tokenId` is owned by someone.\\n function _addTokenTo(address _to, uint _tokenId) internal {\\n // Throws if `_tokenId` is owned by someone\\n assert(idToOwner[_tokenId] == address(0));\\n // Change the owner\\n idToOwner[_tokenId] = _to;\\n // Update owner token index tracking\\n _addTokenToOwnerList(_to, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_to] += 1;\\n }\\n\\n /// @dev Function to mint tokens\\n /// Throws if `_to` is zero address.\\n /// Throws if `_tokenId` is owned by someone.\\n /// @param _to The address that will receive the minted tokens.\\n /// @param _tokenId The token id to mint.\\n /// @return A boolean that indicates if the operation was successful.\\n function _mint(address _to, uint _tokenId) internal returns (bool) {\\n // Throws if `_to` is zero address\\n assert(_to != address(0));\\n // checkpoint for gov\\n _moveTokenDelegates(address(0), delegates(_to), _tokenId);\\n // Add NFT. Throws if `_tokenId` is owned by someone\\n _addTokenTo(_to, _tokenId);\\n emit Transfer(address(0), _to, _tokenId);\\n return true;\\n }\\n\\n /// @dev Remove a NFT from an index mapping to a given address\\n /// @param _from address of the sender\\n /// @param _tokenId uint ID Of the token to be removed\\n function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {\\n // Delete\\n uint current_count = _balance(_from) - 1;\\n uint current_index = tokenToOwnerIndex[_tokenId];\\n\\n if (current_count == current_index) {\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n } else {\\n uint lastTokenId = ownerToNFTokenIdList[_from][current_count];\\n\\n // Add\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_index] = lastTokenId;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[lastTokenId] = current_index;\\n\\n // Delete\\n // update ownerToNFTokenIdList\\n ownerToNFTokenIdList[_from][current_count] = 0;\\n // update tokenToOwnerIndex\\n tokenToOwnerIndex[_tokenId] = 0;\\n }\\n }\\n\\n /// @dev Remove a NFT from a given address\\n /// Throws if `_from` is not the current owner.\\n function _removeTokenFrom(address _from, uint _tokenId) internal {\\n // Throws if `_from` is not the current owner\\n assert(idToOwner[_tokenId] == _from);\\n // Change the owner\\n idToOwner[_tokenId] = address(0);\\n // Update owner token index tracking\\n _removeTokenFromOwnerList(_from, _tokenId);\\n // Change count tracking\\n ownerToNFTokenCount[_from] -= 1;\\n }\\n\\n function _burn(uint _tokenId) internal {\\n require(_isApprovedOrOwner(msg.sender, _tokenId), \\\"caller is not owner nor approved\\\");\\n\\n address owner = ownerOf(_tokenId);\\n\\n // Clear approval\\n approve(address(0), _tokenId);\\n // checkpoint for gov\\n _moveTokenDelegates(delegates(owner), address(0), _tokenId);\\n // Remove token\\n _removeTokenFrom(msg.sender, _tokenId);\\n emit Transfer(owner, address(0), _tokenId);\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public user_point_epoch;\\n mapping(uint => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]\\n mapping(uint => LockedBalance) public locked;\\n uint public epoch;\\n mapping(uint => int128) public slope_changes; // time -> signed slope change\\n uint public supply;\\n\\n uint internal constant WEEK = 1 weeks;\\n uint internal constant MAXTIME = 4 * 365 * 86400;\\n int128 internal constant iMAXTIME = 4 * 365 * 86400;\\n uint internal constant MULTIPLIER = 1 ether;\\n\\n /*//////////////////////////////////////////////////////////////\\n ESCROW LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @return Value of the slope\\n function get_last_user_slope(uint _tokenId) external view returns (int128) {\\n uint uepoch = user_point_epoch[_tokenId];\\n return user_point_history[_tokenId][uepoch].slope;\\n }\\n\\n /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`\\n /// @param _tokenId token of the NFT\\n /// @param _idx User epoch number\\n /// @return Epoch time of the checkpoint\\n function user_point_history__ts(uint _tokenId, uint _idx) external view returns (uint) {\\n return user_point_history[_tokenId][_idx].ts;\\n }\\n\\n /// @notice Get timestamp when `_tokenId`'s lock finishes\\n /// @param _tokenId User NFT\\n /// @return Epoch time of the lock end\\n function locked__end(uint _tokenId) external view returns (uint) {\\n return locked[_tokenId].end;\\n }\\n\\n /// @notice Record global and per-user data to checkpoint\\n /// @param _tokenId NFT token ID. No user checkpoint if 0\\n /// @param old_locked Pevious locked amount / end lock time for the user\\n /// @param new_locked New locked amount / end lock time for the user\\n function _checkpoint(\\n uint _tokenId,\\n LockedBalance memory old_locked,\\n LockedBalance memory new_locked\\n ) internal {\\n Point memory u_old;\\n Point memory u_new;\\n int128 old_dslope = 0;\\n int128 new_dslope = 0;\\n uint _epoch = epoch;\\n\\n if (_tokenId != 0) {\\n // Calculate slopes and biases\\n // Kept at zero when they have to\\n if (old_locked.end > block.timestamp && old_locked.amount > 0) {\\n u_old.slope = old_locked.amount / iMAXTIME;\\n u_old.bias = u_old.slope * int128(int256(old_locked.end - block.timestamp));\\n }\\n if (new_locked.end > block.timestamp && new_locked.amount > 0) {\\n u_new.slope = new_locked.amount / iMAXTIME;\\n u_new.bias = u_new.slope * int128(int256(new_locked.end - block.timestamp));\\n }\\n\\n // Read values of scheduled changes in the slope\\n // old_locked.end can be in the past and in the future\\n // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros\\n old_dslope = slope_changes[old_locked.end];\\n if (new_locked.end != 0) {\\n if (new_locked.end == old_locked.end) {\\n new_dslope = old_dslope;\\n } else {\\n new_dslope = slope_changes[new_locked.end];\\n }\\n }\\n }\\n\\n Point memory last_point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number});\\n if (_epoch > 0) {\\n last_point = point_history[_epoch];\\n }\\n uint last_checkpoint = last_point.ts;\\n // initial_last_point is used for extrapolation to calculate block number\\n // (approximately, for *At methods) and save them\\n // as we cannot figure that out exactly from inside the contract\\n Point memory initial_last_point = last_point;\\n uint block_slope = 0; // dblock/dt\\n if (block.timestamp > last_point.ts) {\\n block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);\\n }\\n // If last point is already recorded in this block, slope=0\\n // But that's ok b/c we know the block in such case\\n\\n // Go over weeks to fill history and calculate what the current point is\\n {\\n uint t_i = (last_checkpoint / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n // Hopefully it won't happen that this won't get used in 5 years!\\n // If it does, users will be able to withdraw but vote weight will be broken\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > block.timestamp) {\\n t_i = block.timestamp;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_checkpoint));\\n last_point.slope += d_slope;\\n if (last_point.bias < 0) {\\n // This can happen\\n last_point.bias = 0;\\n }\\n if (last_point.slope < 0) {\\n // This cannot happen - just in case\\n last_point.slope = 0;\\n }\\n last_checkpoint = t_i;\\n last_point.ts = t_i;\\n last_point.blk = initial_last_point.blk + (block_slope * (t_i - initial_last_point.ts)) / MULTIPLIER;\\n _epoch += 1;\\n if (t_i == block.timestamp) {\\n last_point.blk = block.number;\\n break;\\n } else {\\n point_history[_epoch] = last_point;\\n }\\n }\\n }\\n\\n epoch = _epoch;\\n // Now point_history is filled until t=now\\n\\n if (_tokenId != 0) {\\n // If last point was in this block, the slope change has been applied already\\n // But in such case we have 0 slope(s)\\n last_point.slope += (u_new.slope - u_old.slope);\\n last_point.bias += (u_new.bias - u_old.bias);\\n if (last_point.slope < 0) {\\n last_point.slope = 0;\\n }\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n }\\n\\n // Record the changed point into history\\n point_history[_epoch] = last_point;\\n\\n if (_tokenId != 0) {\\n // Schedule the slope changes (slope is going down)\\n // We subtract new_user_slope from [new_locked.end]\\n // and add old_user_slope to [old_locked.end]\\n if (old_locked.end > block.timestamp) {\\n // old_dslope was - u_old.slope, so we cancel that\\n old_dslope += u_old.slope;\\n if (new_locked.end == old_locked.end) {\\n old_dslope -= u_new.slope; // It was a new deposit, not extension\\n }\\n slope_changes[old_locked.end] = old_dslope;\\n }\\n\\n if (new_locked.end > block.timestamp) {\\n if (new_locked.end > old_locked.end) {\\n new_dslope -= u_new.slope; // old slope disappeared at this point\\n slope_changes[new_locked.end] = new_dslope;\\n }\\n // else: we recorded it already in old_dslope\\n }\\n // Now handle user history\\n uint user_epoch = user_point_epoch[_tokenId] + 1;\\n\\n user_point_epoch[_tokenId] = user_epoch;\\n u_new.ts = block.timestamp;\\n u_new.blk = block.number;\\n user_point_history[_tokenId][user_epoch] = u_new;\\n }\\n }\\n\\n /// @notice Deposit and lock tokens for a user\\n /// @param _tokenId NFT that holds lock\\n /// @param _value Amount to deposit\\n /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged\\n /// @param locked_balance Previous locked amount / timestamp\\n /// @param deposit_type The type of deposit\\n function _deposit_for(\\n uint _tokenId,\\n uint _value,\\n uint unlock_time,\\n LockedBalance memory locked_balance,\\n DepositType deposit_type\\n ) internal {\\n LockedBalance memory _locked = locked_balance;\\n uint supply_before = supply;\\n\\n supply = supply_before + _value;\\n LockedBalance memory old_locked;\\n (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);\\n // Adding to existing lock, or if a lock is expired - creating a new one\\n _locked.amount += int128(int256(_value));\\n if (unlock_time != 0) {\\n _locked.end = unlock_time;\\n }\\n locked[_tokenId] = _locked;\\n\\n // Possibilities:\\n // Both old_locked.end could be current or expired (>/< block.timestamp)\\n // value == 0 (extend lock) or value > 0 (add to lock or extend lock)\\n // _locked.end > block.timestamp (always)\\n _checkpoint(_tokenId, old_locked, _locked);\\n\\n address from = msg.sender;\\n if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) {\\n assert(IERC20(token).transferFrom(from, address(this), _value));\\n }\\n\\n emit Deposit(from, _tokenId, _value, _locked.end, deposit_type, block.timestamp);\\n emit Supply(supply_before, supply_before + _value);\\n }\\n\\n function block_number() external view returns (uint) {\\n return block.number;\\n }\\n\\n /// @notice Record global data to checkpoint\\n function checkpoint() external {\\n _checkpoint(0, LockedBalance(0, 0), LockedBalance(0, 0));\\n }\\n\\n /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock\\n /// @dev Anyone (even a smart contract) can deposit for someone else, but\\n /// cannot extend their locktime and deposit for a brand new user\\n /// @param _tokenId lock NFT\\n /// @param _value Amount to add to user's lock\\n function deposit_for(uint _tokenId, uint _value) external nonreentrant {\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n require(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function _create_lock(uint _value, uint _lock_duration, address _to) internal returns (uint) {\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_value > 0); // dev: need non-zero value\\n require(unlock_time > block.timestamp, 'Can only lock until time in the future');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n ++tokenId;\\n uint _tokenId = tokenId;\\n _mint(_to, _tokenId);\\n\\n _deposit_for(_tokenId, _value, unlock_time, locked[_tokenId], DepositType.CREATE_LOCK_TYPE);\\n return _tokenId;\\n }\\n\\n /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n function create_lock(uint _value, uint _lock_duration) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, msg.sender);\\n }\\n\\n /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`\\n /// @param _value Amount to deposit\\n /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)\\n /// @param _to Address to deposit\\n function create_lock_for(uint _value, uint _lock_duration, address _to) external nonreentrant returns (uint) {\\n return _create_lock(_value, _lock_duration, _to);\\n }\\n\\n /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time\\n /// @param _value Amount of tokens to deposit and add to the lock\\n function increase_amount(uint _tokenId, uint _value) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n\\n assert(_value > 0); // dev: need non-zero value\\n require(_locked.amount > 0, 'No existing lock found');\\n require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw');\\n\\n _deposit_for(_tokenId, _value, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);\\n }\\n\\n /// @notice Extend the unlock time for `_tokenId`\\n /// @param _lock_duration New number of seconds until tokens unlock\\n function increase_unlock_time(uint _tokenId, uint _lock_duration) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n uint unlock_time = (block.timestamp + _lock_duration) / WEEK * WEEK; // Locktime is rounded down to weeks\\n\\n require(_locked.end > block.timestamp, 'Lock expired');\\n require(_locked.amount > 0, 'Nothing is locked');\\n require(unlock_time > _locked.end, 'Can only increase lock duration');\\n require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max');\\n\\n _deposit_for(_tokenId, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);\\n }\\n\\n /// @notice Withdraw all tokens for `_tokenId`\\n /// @dev Only possible if the lock has expired\\n function withdraw(uint _tokenId) external nonreentrant {\\n assert(_isApprovedOrOwner(msg.sender, _tokenId));\\n require(attachments[_tokenId] == 0 && !voted[_tokenId], \\\"attached\\\");\\n\\n LockedBalance memory _locked = locked[_tokenId];\\n require(block.timestamp >= _locked.end, \\\"The lock didn't expire\\\");\\n uint value = uint(int256(_locked.amount));\\n\\n locked[_tokenId] = LockedBalance(0,0);\\n uint supply_before = supply;\\n supply = supply_before - value;\\n\\n // old_locked can have either expired <= timestamp or zero end\\n // _locked has only 0 end\\n // Both can have >= 0 amount\\n _checkpoint(_tokenId, _locked, LockedBalance(0,0));\\n\\n assert(IERC20(token).transfer(msg.sender, value));\\n\\n // Burn the NFT\\n _burn(_tokenId);\\n\\n emit Withdraw(msg.sender, _tokenId, value, block.timestamp);\\n emit Supply(supply_before, supply_before - value);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n // The following ERC20/minime-compatible methods are not real balanceOf and supply!\\n // They measure the weights for the purpose of voting, so they don't represent\\n // real coins.\\n\\n /// @notice Binary search to estimate timestamp for block number\\n /// @param _block Block to find\\n /// @param max_epoch Don't go beyond this epoch\\n /// @return Approximate timestamp for block\\n function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {\\n // Binary search\\n uint _min = 0;\\n uint _max = max_epoch;\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (point_history[_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n return _min;\\n }\\n\\n /// @notice Get the current voting power for `_tokenId`\\n /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility\\n /// @param _tokenId NFT for lock\\n /// @param _t Epoch time to return voting power at\\n /// @return User voting power\\n function _balanceOfNFT(uint _tokenId, uint _t) internal view returns (uint) {\\n uint _epoch = user_point_epoch[_tokenId];\\n if (_epoch == 0) {\\n return 0;\\n } else {\\n Point memory last_point = user_point_history[_tokenId][_epoch];\\n last_point.bias -= last_point.slope * int128(int256(_t) - int256(last_point.ts));\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(int256(last_point.bias));\\n }\\n }\\n\\n function balanceOfNFT(uint _tokenId) external view returns (uint) {\\n if (ownership_change[_tokenId] == block.number) return 0;\\n return _balanceOfNFT(_tokenId, block.timestamp);\\n }\\n\\n function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint) {\\n return _balanceOfNFT(_tokenId, _t);\\n }\\n\\n /// @notice Measure voting power of `_tokenId` at block height `_block`\\n /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime\\n /// @param _tokenId User's wallet NFT\\n /// @param _block Block to calculate the voting power at\\n /// @return Voting power\\n function _balanceOfAtNFT(uint _tokenId, uint _block) internal view returns (uint) {\\n // Copying and pasting totalSupply code because Vyper cannot pass by\\n // reference yet\\n assert(_block <= block.number);\\n\\n // Binary search\\n uint _min = 0;\\n uint _max = user_point_epoch[_tokenId];\\n for (uint i = 0; i < 128; ++i) {\\n // Will be always enough for 128-bit numbers\\n if (_min >= _max) {\\n break;\\n }\\n uint _mid = (_min + _max + 1) / 2;\\n if (user_point_history[_tokenId][_mid].blk <= _block) {\\n _min = _mid;\\n } else {\\n _max = _mid - 1;\\n }\\n }\\n\\n Point memory upoint = user_point_history[_tokenId][_min];\\n\\n uint max_epoch = epoch;\\n uint _epoch = _find_block_epoch(_block, max_epoch);\\n Point memory point_0 = point_history[_epoch];\\n uint d_block = 0;\\n uint d_t = 0;\\n if (_epoch < max_epoch) {\\n Point memory point_1 = point_history[_epoch + 1];\\n d_block = point_1.blk - point_0.blk;\\n d_t = point_1.ts - point_0.ts;\\n } else {\\n d_block = block.number - point_0.blk;\\n d_t = block.timestamp - point_0.ts;\\n }\\n uint block_time = point_0.ts;\\n if (d_block != 0) {\\n block_time += (d_t * (_block - point_0.blk)) / d_block;\\n }\\n\\n upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));\\n if (upoint.bias >= 0) {\\n return uint(uint128(upoint.bias));\\n } else {\\n return 0;\\n }\\n }\\n\\n function balanceOfAtNFT(uint _tokenId, uint _block) external view returns (uint) {\\n return _balanceOfAtNFT(_tokenId, _block);\\n }\\n\\n /// @notice Calculate total voting power at some point in the past\\n /// @param _block Block to calculate the total voting power at\\n /// @return Total voting power at `_block`\\n function totalSupplyAt(uint _block) external view returns (uint) {\\n assert(_block <= block.number);\\n uint _epoch = epoch;\\n uint target_epoch = _find_block_epoch(_block, _epoch);\\n\\n Point memory point = point_history[target_epoch];\\n uint dt = 0;\\n if (target_epoch < _epoch) {\\n Point memory point_next = point_history[target_epoch + 1];\\n if (point.blk != point_next.blk) {\\n dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);\\n }\\n } else {\\n if (point.blk != block.number) {\\n dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);\\n }\\n }\\n // Now dt contains info on how far are we beyond point\\n return _supply_at(point, point.ts + dt);\\n }\\n /// @notice Calculate total voting power at some point in the past\\n /// @param point The point (bias/slope) to start search from\\n /// @param t Time to calculate the total voting power at\\n /// @return Total voting power at that time\\n function _supply_at(Point memory point, uint t) internal view returns (uint) {\\n Point memory last_point = point;\\n uint t_i = (last_point.ts / WEEK) * WEEK;\\n for (uint i = 0; i < 255; ++i) {\\n t_i += WEEK;\\n int128 d_slope = 0;\\n if (t_i > t) {\\n t_i = t;\\n } else {\\n d_slope = slope_changes[t_i];\\n }\\n last_point.bias -= last_point.slope * int128(int256(t_i - last_point.ts));\\n if (t_i == t) {\\n break;\\n }\\n last_point.slope += d_slope;\\n last_point.ts = t_i;\\n }\\n\\n if (last_point.bias < 0) {\\n last_point.bias = 0;\\n }\\n return uint(uint128(last_point.bias));\\n }\\n\\n function totalSupply() external view returns (uint) {\\n return totalSupplyAtT(block.timestamp);\\n }\\n\\n /// @notice Calculate total voting power\\n /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility\\n /// @return Total voting power\\n function totalSupplyAtT(uint t) public view returns (uint) {\\n uint _epoch = epoch;\\n Point memory last_point = point_history[_epoch];\\n return _supply_at(last_point, t);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n GAUGE VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n mapping(uint => uint) public attachments;\\n mapping(uint => bool) public voted;\\n\\n function setVoter(address _voter) external {\\n require(msg.sender == voter);\\n voter = _voter;\\n }\\n\\n function voting(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = true;\\n }\\n\\n function abstain(uint _tokenId) external {\\n require(msg.sender == voter);\\n voted[_tokenId] = false;\\n }\\n\\n function attach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] + 1;\\n }\\n\\n function detach(uint _tokenId) external {\\n require(msg.sender == voter);\\n attachments[_tokenId] = attachments[_tokenId] - 1;\\n }\\n\\n function merge(uint _from, uint _to) external {\\n require(attachments[_from] == 0 && !voted[_from], \\\"attached\\\");\\n require(_from != _to);\\n require(_isApprovedOrOwner(msg.sender, _from));\\n require(_isApprovedOrOwner(msg.sender, _to));\\n\\n LockedBalance memory _locked0 = locked[_from];\\n LockedBalance memory _locked1 = locked[_to];\\n uint value0 = uint(int256(_locked0.amount));\\n uint end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end;\\n\\n locked[_from] = LockedBalance(0, 0);\\n _checkpoint(_from, _locked0, LockedBalance(0, 0));\\n _burn(_from);\\n _deposit_for(_to, value0, end, _locked1, DepositType.MERGE_TYPE);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH = keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH = keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of each accounts delegate\\n mapping(address => address) private _delegates;\\n uint public constant MAX_DELEGATES = 1024; // avoid too much gas\\n\\n /// @notice A record of delegated token checkpoints for each account, by index\\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint32) public numCheckpoints;\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping(address => uint) public nonces;\\n\\n /**\\n * @notice Overrides the standard `Comp.sol` delegates mapping to return\\n * the delegator's own address if they haven't delegated.\\n * This avoids having to delegate to oneself.\\n */\\n function delegates(address delegator) public view returns (address) {\\n address current = _delegates[delegator];\\n return current == address(0) ? delegator : current;\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getVotes(address account) external view returns (uint) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n uint[] storage _tokenIds = checkpoints[account][nCheckpoints - 1].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n votes = votes + _balanceOfNFT(tId, block.timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastVotesIndex(address account, uint timestamp) public view returns (uint32) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint storage cp = checkpoints[account][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPastVotes(address account, uint timestamp)\\n public\\n view\\n returns (uint)\\n {\\n uint32 _checkIndex = getPastVotesIndex(account, timestamp);\\n // Sum votes\\n uint[] storage _tokenIds = checkpoints[account][_checkIndex].tokenIds;\\n uint votes = 0;\\n for (uint i = 0; i < _tokenIds.length; i++) {\\n uint tId = _tokenIds[i];\\n // Use the provided input timestamp here to get the right decay\\n votes = votes + _balanceOfNFT(tId, timestamp);\\n }\\n return votes;\\n }\\n\\n function getPastTotalSupply(uint256 timestamp) external view returns (uint) {\\n return totalSupplyAtT(timestamp);\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n DAO VOTING LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _moveTokenDelegates(\\n address srcRep,\\n address dstRep,\\n uint _tokenId\\n ) internal {\\n if (srcRep != dstRep && _tokenId > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except _tokenId\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (tId != _tokenId) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n // All the same plus _tokenId\\n require(\\n dstRepOld.length + 1 <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n dstRepNew.push(_tokenId);\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _findWhatCheckpointToWrite(address account)\\n internal\\n view\\n returns (uint32)\\n {\\n uint _timestamp = block.timestamp;\\n uint32 _nCheckPoints = numCheckpoints[account];\\n\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n return _nCheckPoints - 1;\\n } else {\\n return _nCheckPoints;\\n }\\n }\\n\\n function _moveAllDelegates(\\n address owner,\\n address srcRep,\\n address dstRep\\n ) internal {\\n // You can only redelegate what you own\\n if (srcRep != dstRep) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint[] storage srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].tokenIds\\n : checkpoints[srcRep][0].tokenIds;\\n uint32 nextSrcRepNum = _findWhatCheckpointToWrite(srcRep);\\n uint[] storage srcRepNew = checkpoints[srcRep][\\n nextSrcRepNum\\n ].tokenIds;\\n // All the same except what owner owns\\n for (uint i = 0; i < srcRepOld.length; i++) {\\n uint tId = srcRepOld[i];\\n if (idToOwner[tId] != owner) {\\n srcRepNew.push(tId);\\n }\\n }\\n\\n numCheckpoints[srcRep] = srcRepNum + 1;\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint[] storage dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].tokenIds\\n : checkpoints[dstRep][0].tokenIds;\\n uint32 nextDstRepNum = _findWhatCheckpointToWrite(dstRep);\\n uint[] storage dstRepNew = checkpoints[dstRep][\\n nextDstRepNum\\n ].tokenIds;\\n uint ownerTokenCount = ownerToNFTokenCount[owner];\\n require(\\n dstRepOld.length + ownerTokenCount <= MAX_DELEGATES,\\n \\\"dstRep would have too many tokenIds\\\"\\n );\\n // All the same\\n for (uint i = 0; i < dstRepOld.length; i++) {\\n uint tId = dstRepOld[i];\\n dstRepNew.push(tId);\\n }\\n // Plus all that's owned\\n for (uint i = 0; i < ownerTokenCount; i++) {\\n uint tId = ownerToNFTokenIdList[owner][i];\\n dstRepNew.push(tId);\\n }\\n\\n numCheckpoints[dstRep] = dstRepNum + 1;\\n }\\n }\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\\n address currentDelegate = delegates(delegator);\\n\\n _delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n _moveAllDelegates(delegator, currentDelegate, delegatee);\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n if (delegatee == address(0)) delegatee = msg.sender;\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n function delegateBySig(\\n address delegatee,\\n uint nonce,\\n uint expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public {\\n bytes32 domainSeparator = keccak256(\\n abi.encode(\\n DOMAIN_TYPEHASH,\\n keccak256(bytes(name)),\\n keccak256(bytes(version)),\\n block.chainid,\\n address(this)\\n )\\n );\\n bytes32 structHash = keccak256(\\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash)\\n );\\n address signatory = ecrecover(digest, v, r, s);\\n require(\\n signatory != address(0),\\n \\\"VotingEscrow::delegateBySig: invalid signature\\\"\\n );\\n require(\\n nonce == nonces[signatory]++,\\n \\\"VotingEscrow::delegateBySig: invalid nonce\\\"\\n );\\n require(\\n block.timestamp <= expiry,\\n \\\"VotingEscrow::delegateBySig: signature expired\\\"\\n );\\n return _delegate(signatory, delegatee);\\n }\\n}\\n\",\"keccak256\":\"0x37e5ee306472a946a665be22bc1d370d566a575a1fac84f72f97b0575571d40d\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IVeArtProxy.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVeArtProxy {\\n function _tokenURI(uint _tokenId, uint _balanceOf, uint _locked_end, uint _value) external pure returns (string memory output);\\n}\\n\",\"keccak256\":\"0x7526ce7cd114e4cc6db67dcfe4687876a9fefb91a69ec42cdaa4491b57467142\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\\n *\\n * _Available since v4.5._\\n */\\ninterface IVotes {\\n /**\\n * @dev Emitted when an account changes their delegate.\\n */\\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /**\\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\\n */\\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\\n\\n /**\\n * @dev Returns the current amount of votes that `account` has.\\n */\\n function getVotes(address account) external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\\n */\\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\\n *\\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\\n * vote.\\n */\\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\\n\\n /**\\n * @dev Returns the delegate that `account` has chosen.\\n */\\n function delegates(address account) external view returns (address);\\n\\n /**\\n * @dev Delegates votes from the sender to `delegatee`.\\n */\\n function delegate(address delegatee) external;\\n\\n /**\\n * @dev Delegates votes from signer to `delegatee`.\\n */\\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\\n}\\n\",\"keccak256\":\"0x0e774440198e74443c22645f90a9cc505ae55a055c4527ca9eae5db1fc1ab110\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x41bbb2c41036ca64b2f6c9e973e8cfaa113ebc42af86702cd0d267f915a7e886\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a06040526006805460ff191660011790553480156200001e57600080fd5b5060405162004a1c38038062004a1c8339810160408190526200004191620001b8565b6001600160a01b0382811660805260008054336001600160a01b031991821681178355600180548316909117815560028054909216938516939093179055437f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f0155427f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f005560046020527f9fe05126d2d9ecf60592e254dead906a4b2e492f36cca727682c38e9008c6ac1805460ff1990811684179091557f4267c0a6fd96b7a87f183ee8744f24d011423cd0e0142b3f563f183d8d9a456b8054821684179055635b5e139f60e01b82527e24030bcf4927897dffe721c2d8dda4bfd8910861687c42b03a463b43b04147805490911690921790915560055460405190913091600080516020620049fc833981519152908290a46005546040516000903090600080516020620049fc833981519152908390a45050620001f0565b80516001600160a01b0381168114620001b357600080fd5b919050565b60008060408385031215620001cc57600080fd5b620001d7836200019b565b9150620001e7602084016200019b565b90509250929050565b6080516147e26200021a60003960008181610b220152818161101801526133b501526147e26000f3fe608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea2646970667358221220245dd4da7f4eb9a32bfed7d913c4bc4316ce8585e535cd4e280eb72cdc5dab1c64736f6c634300080d0033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106104075760003560e01c80637116c60c11610220578063c1f0fb9f11610130578063e7a324dc116100b8578063f1127ed811610087578063f1127ed814610abc578063f8a0576314610ae7578063fbd3a29d14610b0a578063fc0c546a14610b1d578063fd4a77f114610b4457600080fd5b8063e7a324dc14610a33578063e7e242d414610a5a578063e985e9c514610a6d578063ee99fe2814610aa957600080fd5b8063d1c2babb116100ff578063d1c2babb1461099c578063d1febfb9146109af578063d4e54c3b146109ed578063e0514aba14610a00578063e441135c14610a1357600080fd5b8063c1f0fb9f1461095b578063c2c4c5c11461096e578063c3cda52014610976578063c87b56dd1461098957600080fd5b806395d89b41116101b3578063a183af5211610182578063a183af52146108c7578063a22cb465146108da578063a4d855df146108ed578063b45a3c0e14610900578063b88d4fde1461094857600080fd5b806395d89b4114610465578063981b24d01461088e578063986b7d8a146108a15780639ab24eb0146108b457600080fd5b80638c2c9baf116101ef5780638c2c9baf1461083c5780638e539e8c1461084f5780638fbb38ff14610862578063900cf0cf1461088557600080fd5b80637116c60c146107d357806371197484146107e65780637ecebe001461080957806385f2aef21461082957600080fd5b8063313ce5671161031b5780635594a045116102ae5780636352211e1161027d5780636352211e1461073e57806365fc3873146107675780636f5488371461077a5780636fcfff451461079a57806370a08231146107c057600080fd5b80635594a045146106fc578063587cde1e1461070f5780635c19a95c146107225780635f5b0c321461073557600080fd5b8063461f711c116102ea578063461f711c1461068c57806346c96aac146106b25780634bc2a657146106c557806354fd4d50146106d857600080fd5b8063313ce567146106395780633a46b1a81461065357806342842e0e14610666578063430c20811461067957600080fd5b80631376f3da1161039e57806323b872dd1161036d57806323b872dd146105c457806325a58b56146105d75780632e1a7d4d146105dd5780632e720f7d146105f05780632f745c591461060357600080fd5b80631376f3da1461054757806318160ddd146105825780631c984bc31461058a57806320606b701461059d57600080fd5b8063081812fc116103da578063081812fc146104be578063095cf5c6146104ff578063095ea7b3146105145780630d6a20331461052757600080fd5b806301ffc9a71461040c578063047fc9aa1461044e57806306fdde03146104655780630758c7d814610496575b600080fd5b61043961041a366004613f24565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61045760135481565b604051908152602001610445565b610489604051806040016040528060058152602001641d9953919560da1b81525081565b6040516104459190613f99565b6104a96104a4366004613fc8565b610b57565b60405163ffffffff9091168152602001610445565b6104e76104cc366004613ff2565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610445565b61051261050d36600461400b565b610cca565b005b610512610522366004613fc8565b610d03565b610457610535366004613ff2565b60146020526000908152604090205481565b61055a610555366004614026565b610deb565b60408051600f95860b81529390940b6020840152928201526060810191909152608001610445565b610457610e32565b610457610598366004614026565b610e42565b6104577f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6105126105d2366004614048565b610e74565b43610457565b6105126105eb366004613ff2565b610e85565b6105126105fe36600461400b565b61113b565b610457610611366004613fc8565b6001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610641601281565b60405160ff9091168152602001610445565b610457610661366004613fc8565b611174565b610512610674366004614048565b611213565b610439610687366004613fc8565b61122e565b61069f61069a366004613ff2565b611241565b604051600f9190910b8152602001610445565b6000546104e7906001600160a01b031681565b6105126106d336600461400b565b611284565b610489604051806040016040528060058152602001640312e302e360dc1b81525081565b6002546104e7906001600160a01b031681565b6104e761071d36600461400b565b6112bd565b61051261073036600461400b565b6112ed565b61045761040081565b6104e761074c366004613ff2565b6000908152600760205260409020546001600160a01b031690565b610457610775366004614026565b61130b565b610457610788366004613ff2565b600b6020526000908152604090205481565b6104a96107a836600461400b565b60186020526000908152604090205463ffffffff1681565b6104576107ce36600461400b565b61134d565b6104576107e1366004613ff2565b61136b565b61069f6107f4366004613ff2565b601260205260009081526040902054600f0b81565b61045761081736600461400b565b60196020526000908152604090205481565b6001546104e7906001600160a01b031681565b61045761084a366004614026565b6113cb565b61045761085d366004613ff2565b6113d7565b610439610870366004613ff2565b60156020526000908152604090205460ff1681565b61045760115481565b61045761089c366004613ff2565b6113e2565b6105126108af366004613ff2565b611584565b6104576108c236600461400b565b6115c8565b6105126108d5366004614026565b61169b565b6105126108e8366004614092565b61179a565b6105126108fb366004614026565b61181e565b61092e61090e366004613ff2565b60106020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b8352602083019190915201610445565b610512610956366004614138565b611a03565b610512610969366004613ff2565b611ba2565b610512611bd1565b6105126109843660046141e3565b611c11565b610489610997366004613ff2565b611f51565b6105126109aa366004614026565b61207d565b61055a6109bd366004613ff2565b600360205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b6104576109fb366004614243565b6121e2565b610457610a0e366004614026565b612225565b610457610a21366004613ff2565b600e6020526000908152604090205481565b6104577fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b610457610a68366004613ff2565b612231565b610439610a7b366004614278565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b610512610ab7366004614026565b612259565b610457610aca3660046142ab565b601760209081526000928352604080842090915290825290205481565b610457610af5366004613ff2565b60009081526010602052604090206001015490565b610512610b18366004613ff2565b61232d565b6104e77f000000000000000000000000000000000000000000000000000000000000000081565b610512610b52366004613ff2565b61235e565b6001600160a01b03821660009081526018602052604081205463ffffffff16808203610b87576000915050610cc4565b6001600160a01b03841660009081526017602052604081208491610bac6001856142f6565b63ffffffff16815260208101919091526040016000205411610bdb57610bd36001826142f6565b915050610cc4565b6001600160a01b0384166000908152601760209081526040808320838052909152902054831015610c10576000915050610cc4565b600080610c1e6001846142f6565b90505b8163ffffffff168163ffffffff161115610cbf5760006002610c4384846142f6565b610c4d9190614331565b610c5790836142f6565b6001600160a01b038816600090815260176020908152604080832063ffffffff851684529091529020805491925090879003610c9957509350610cc492505050565b8054871115610caa57819350610cb8565b610cb56001836142f6565b92505b5050610c21565b509150505b92915050565b6001546001600160a01b03163314610ce157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600760205260409020546001600160a01b031680610d2557600080fd5b806001600160a01b0316836001600160a01b031603610d4357600080fd5b6000828152600760209081526040808320546001600160a01b038581168552600a845282852033808752945291909320549216149060ff168180610d845750805b610d8d57600080fd5b60008481526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b600f60205281600052604060002081633b9aca008110610e0a57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610e3d4261136b565b905090565b6000828152600f6020526040812082633b9aca008110610e6457610e64614354565b6003020160010154905092915050565b610e8083838333612390565b505050565b60065460ff16600114610e9757600080fd5b6006805460ff19166002179055610eae3382612471565b610eba57610eba61436a565b600081815260146020526040902054158015610ee5575060008181526015602052604090205460ff16155b610f0a5760405162461bcd60e51b8152600401610f0190614380565b60405180910390fd5b60008181526010602090815260409182902082518084019093528054600f0b835260010154908201819052421015610f7d5760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610f01565b8051604080518082018252600080825260208083018281528783526010909152929020905181546001600160801b0319166001600160801b039091161781559051600190910155601354600f9190910b90610fd882826143a2565b6013556040805180820190915260008082526020820152610ffc90859085906124d7565b60405163a9059cbb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d91906143b9565b6110995761109961436a565b6110a284612af3565b60408051858152602081018490524281830152905133917f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94919081900360600190a27f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c8161111084826143a2565b6040805192835260208301919091520160405180910390a150506006805460ff191660011790555050565b6001546001600160a01b0316331461115257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806111818484610b57565b6001600160a01b038516600090815260176020908152604080832063ffffffff851684529091528120919250600190910190805b82548110156112095760008382815481106111d2576111d2614354565b906000526020600020015490506111e98188612bc6565b6111f390846143d6565b9250508080611201906143ee565b9150506111b5565b5095945050505050565b610e8083838360405180602001604052806000815250611a03565b600061123a8383612471565b9392505050565b6000818152600e6020908152604080832054600f909252822081633b9aca00811061126e5761126e614354565b6003020154600160801b9004600f0b9392505050565b6000546001600160a01b0316331461129b57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380821660009081526016602052604081205490911680156112e6578061123a565b5090919050565b6001600160a01b0381166112fe5750335b6113083382612c9a565b50565b60065460009060ff1660011461132057600080fd5b6006805460ff19166002179055611338838333612d0d565b90506006805460ff1916600117905592915050565b6001600160a01b038116600090815260086020526040812054610cc4565b601154600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906113c38185612e64565b949350505050565b600061123a8383612f65565b6000610cc48261136b565b6000438211156113f4576113f461436a565b6011546000611403848361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250838310156115125760006003816114668660016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608083018290528501519192501461150c57826060015181606001516114d291906143a2565b836040015182604001516114e691906143a2565b60608501516114f5908a6143a2565b6114ff9190614407565b6115099190614426565b91505b50611561565b4382606001511461156157606082015161152c90436143a2565b604083015161153b90426143a2565b606084015161154a90896143a2565b6115549190614407565b61155e9190614426565b90505b61157a8282846040015161157591906143d6565b612e64565b9695505050505050565b6000546001600160a01b0316331461159b57600080fd5b6000818152601460205260409020546115b6906001906143a2565b60009182526014602052604090912055565b6001600160a01b03811660009081526018602052604081205463ffffffff168082036115f75750600092915050565b6001600160a01b03831660009081526017602052604081208161161b6001856142f6565b63ffffffff1663ffffffff16815260200190815260200160002060010190506000805b825481101561169257600083828154811061165b5761165b614354565b906000526020600020015490506116728142612bc6565b61167c90846143d6565b925050808061168a906143ee565b91505061163e565b50949350505050565b60065460ff166001146116ad57600080fd5b6006805460ff191660021790556116c43383612471565b6116d0576116d061436a565b60008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816117065761170661436a565b60008160000151600f0b136117565760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b428160200151116117795760405162461bcd60e51b8152600401610f019061443a565b611788838360008460026132c4565b50506006805460ff1916600117905550565b336001600160a01b038316036117b2576117b261436a565b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff1660011461183057600080fd5b6006805460ff191660021790556118473383612471565b6118535761185361436a565b600082815260106020908152604080832081518083019092528054600f0b825260010154918101919091529062093a808061188e85426143d6565b6118989190614426565b6118a29190614407565b9050428260200151116118e65760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610f01565b60008260000151600f0b136119315760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610f01565b816020015181116119845760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610f01565b611992630784ce00426143d6565b8111156119e15760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b6119f0846000838560036132c4565b50506006805460ff191660011790555050565b611a0f84848433612390565b823b15611b9c57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611a4890339088908790879060040161447e565b6020604051808303816000875af1925050508015611a83575060408051601f3d908101601f19168201909252611a80918101906144b1565b60015b611b2b573d808015611ab1576040519150601f19603f3d011682016040523d82523d6000602084013e611ab6565b606091505b508051600003611b235760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610f01565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611b9a5760405162461bcd60e51b815260206004820152602660248201527f4552433732313a2045524337323152656365697665722072656a656374656420604482015265746f6b656e7360d01b6064820152608401610f01565b505b50505050565b6000546001600160a01b03163314611bb957600080fd5b6000908152601560205260409020805460ff19169055565b611c0f600060405180604001604052806000600f0b8152602001600081525060405180604001604052806000600f0b815260200160008152506124d7565b565b6040805180820182526005808252641d9953919560da1b60209283015282518084018452908152640312e302e360dc1b9082015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc792e9874e7b42c234d1e8448cec020a0f065019c8cd6f7ccdb65b8c110157e9818401527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c60608201524660808201523060a0808301919091528351808303909101815260c0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60e08301526001600160a01b038a1661010083015261012082018990526101408083018990528451808403909101815261016083019094528351939092019290922061190160f01b61018084015261018283018290526101a2830181905290916000906101c20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015611dd0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e4a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e7660448201526d616c6964207369676e617475726560901b6064820152608401610f01565b6001600160a01b0381166000908152601960205260408120805491611e6e836143ee565b919050558914611ed35760405162461bcd60e51b815260206004820152602a60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a20696e76604482015269616c6964206e6f6e636560b01b6064820152608401610f01565b87421115611f3a5760405162461bcd60e51b815260206004820152602e60248201527f566f74696e67457363726f773a3a64656c656761746542795369673a2073696760448201526d1b985d1d5c9948195e1c1a5c995960921b6064820152608401610f01565b611f44818b612c9a565b505050505b505050505050565b6000818152600760205260409020546060906001600160a01b0316611fb85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610f01565b60008281526010602090815260409182902082518084019093528054600f0b835260010154908201526002546001600160a01b031663dd9ec14984611ffd8142612bc6565b6020850151855160405160e086901b6001600160e01b0319168152600481019490945260248401929092526044830152600f0b6064820152608401600060405180830381865afa158015612055573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a91908101906144ce565b6000828152601460205260409020541580156120a8575060008281526015602052604090205460ff16155b6120c45760405162461bcd60e51b8152600401610f0190614380565b8082036120d057600080fd5b6120da3383612471565b6120e357600080fd5b6120ed3382612471565b6120f657600080fd5b6000828152601060208181526040808420815180830183528154600f90810b825260019283015482860190815288885295855283872084518086019095528054820b855290920154938301849052805194519095929490910b921115612160578260200151612166565b83602001515b604080518082018252600080825260208083018281528b835260108252848320935184546001600160801b0319166001600160801b03909116178455516001909301929092558251808401909352808352908201529091506121cb90879086906124d7565b6121d486612af3565b611f498583838660046132c4565b60065460009060ff166001146121f757600080fd5b6006805460ff1916600217905561220f848484612d0d565b90506006805460ff191660011790559392505050565b600061123a8383612bc6565b6000818152600b602052604081205443900361224f57506000919050565b610cc48242612bc6565b60065460ff1660011461226b57600080fd5b6006805460ff1916600217905560008281526010602090815260409182902082518084019093528054600f0b83526001015490820152816122ab57600080fd5b60008160000151600f0b136122fb5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610f01565b4281602001511161231e5760405162461bcd60e51b8152600401610f019061443a565b611788838360008460006132c4565b6000546001600160a01b0316331461234457600080fd5b6000818152601460205260409020546115b69060016143d6565b6000546001600160a01b0316331461237557600080fd5b6000908152601560205260409020805460ff19166001179055565b6000828152601460205260409020541580156123bb575060008281526015602052604090205460ff16155b6123d75760405162461bcd60e51b8152600401610f0190614380565b6123e18183612471565b6123ea57600080fd5b6123f484836134c9565b6123fe8483613530565b61241961240a856112bd565b612413856112bd565b846135b1565b6124238383613913565b6000828152600b60205260408082204390555183916001600160a01b0380871692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b60008181526007602090815260408083205460098352818420546001600160a01b03918216808652600a855283862088841680885295529285205492938085149392909116149060ff1682806124c45750815b806124cc5750805b979650505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526011546000908190871561264257428760200151118015612547575060008760000151600f0b135b1561258c57865161255d90630784ce009061453c565b600f0b6020808701919091528701516125779042906143a2565b8560200151612586919061457a565b600f0b85525b4286602001511180156125a6575060008660000151600f0b135b156125eb5785516125bc90630784ce009061453c565b600f0b6020808601919091528601516125d69042906143a2565b84602001516125e5919061457a565b600f0b84525b602080880151600090815260128252604090205490870151600f9190910b93501561264257866020015186602001510361262757829150612642565b602080870151600090815260129091526040902054600f0b91505b6040805160808101825260008082526020820152429181019190915243606082015281156126b7575060008181526003602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000428310156127045760408401516126d690426143a2565b60608501516126e590436143a2565b6126f790670de0b6b3a7640000614407565b6127019190614426565b90505b600062093a806127148186614426565b61271e9190614407565b905060005b60ff8110156128985761273962093a80836143d6565b915060004283111561274d57429250612761565b50600082815260126020526040902054600f0b5b61276b86846143a2565b876020015161277a919061457a565b8751889061278990839061460f565b600f0b9052506020870180518291906127a390839061465f565b600f90810b90915288516000910b121590506127be57600087525b60008760200151600f0b12156127d657600060208801525b60408088018490528501519295508592670de0b6b3a7640000906127fa90856143a2565b6128049086614407565b61280e9190614426565b856060015161281d91906143d6565b606088015261282d6001896143d6565b97504283036128425750436060870152612898565b6000888152600360209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550612891816143ee565b9050612723565b505060118590558b1561292357886020015188602001516128b9919061460f565b846020018181516128ca919061465f565b600f0b905250885188516128de919061460f565b845185906128ed90839061465f565b600f90810b90915260208601516000910b1215905061290e57600060208501525b60008460000151600f0b121561292357600084525b6000858152600360209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b15612ae557428b6020015111156129da576020890151612989908861465f565b96508a602001518a60200151036129ac5760208801516129a9908861460f565b96505b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b0389161790555b428a602001511115612a35578a602001518a602001511115612a35576020880151612a05908761460f565b60208b810151600090815260129091526040902080546001600160801b0319166001600160801b03831617905595505b60008c8152600e6020526040812054612a4f9060016143d6565b905080600e60008f815260200190815260200160002081905550428960400181815250504389606001818152505088600f60008f815260200190815260200160002082633b9aca008110612aa557612aa5614354565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b612afd3382612471565b612b495760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610f01565b6000818152600760205260408120546001600160a01b031690612b6c9083610d03565b612b80612b78826112bd565b6000846135b1565b612b8a3383613530565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000828152600e6020526040812054808203612be6576000915050610cc4565b6000848152600f6020526040812082633b9aca008110612c0857612c08614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150612c5490856146ae565b8160200151612c63919061457a565b81518290612c7290839061460f565b600f90810b90915282516000910b12159050612c8d57600081525b51600f0b9150610cc49050565b6000612ca5836112bd565b6001600160a01b0384811660008181526016602052604080822080546001600160a01b031916888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4610e808382846139a9565b60008062093a8080612d1f86426143d6565b612d299190614426565b612d339190614407565b905060008511612d4257600080fd5b428111612da05760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610f01565b612dae630784ce00426143d6565b811115612dfd5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610f01565b600560008154612e0c906143ee565b90915550600554612e1d8482613d65565b5060008181526010602090815260409182902082518084019093528054600f0b835260019081015491830191909152612e5b918391899186916132c4565b95945050505050565b600080839050600062093a80808360400151612e809190614426565b612e8a9190614407565b905060005b60ff811015612f3d57612ea562093a80836143d6565b9150600085831115612eb957859250612ecd565b50600082815260126020526040902054600f0b5b6040840151612edc90846143a2565b8460200151612eeb919061457a565b84518590612efa90839061460f565b600f0b905250858303612f0d5750612f3d565b8084602001818151612f1f919061465f565b600f0b9052505060408301829052612f36816143ee565b9050612e8f565b5060008260000151600f0b1215612f5357600082525b50516001600160801b03169392505050565b600043821115612f7757612f7761436a565b6000838152600e6020526040812054815b608081101561301757818310156130175760006002612fa784866143d6565b612fb29060016143d6565b612fbc9190614426565b6000888152600f60205260409020909150869082633b9aca008110612fe357612fe3614354565b600302016002015411612ff857809350613006565b6130036001826143a2565b92505b50613010816143ee565b9050612f88565b506000858152600f6020526040812083633b9aca00811061303a5761303a614354565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152601154909150600061308f878361323e565b600081815260036020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561316e5760006003816130f38760016143d6565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061315091906143a2565b92508360400151816040015161316691906143a2565b915050613192565b606083015161317d90436143a2565b915082604001514261318f91906143a2565b90505b604083015182156131cf578284606001518c6131ae91906143a2565b6131b89084614407565b6131c29190614426565b6131cc90826143d6565b90505b60408701516131de90826143a2565b87602001516131ed919061457a565b875188906131fc90839061460f565b600f90810b90915288516000910b12905061322c57505093516001600160801b03169650610cc495505050505050565b60009950505050505050505050610cc4565b60008082815b60808110156132ba57818310156132ba576000600261326384866143d6565b61326e9060016143d6565b6132789190614426565b600081815260036020526040902060020154909150871061329b578093506132a9565b6132a66001826143a2565b92505b506132b3816143ee565b9050613244565b5090949350505050565b60135482906132d386826143d6565b6013556040805180820190915260008082526020820152825160208085015190830152600f0b815282518790849061330c90839061465f565b600f0b905250851561332057602083018690525b6000888152601060209081526040909120845181546001600160801b0319166001600160801b03909116178155908401516001909101556133628882856124d7565b33871580159061338457506004856004811115613381576133816146ed565b14155b1561342e576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018a90527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143b9565b61342e5761342e61436a565b8360200151816001600160a01b03167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b89426040516134729493929190614703565b60405180910390a37f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c836134a68a826143d6565b6040805192835260208301919091520160405180910390a1505050505050505050565b6000818152600760205260409020546001600160a01b038381169116146134f2576134f261436a565b6000818152600960205260409020546001600160a01b03161561352c57600081815260096020526040902080546001600160a01b03191690555b5050565b6000818152600760205260409020546001600160a01b038381169116146135595761355961436a565b600081815260076020526040902080546001600160a01b031916905561357f8282613dd6565b6001600160a01b03821660009081526008602052604081208054600192906135a89084906143a2565b90915550505050565b816001600160a01b0316836001600160a01b0316141580156135d35750600081115b15610e80576001600160a01b03831615613754576001600160a01b03831660009081526018602052604081205463ffffffff169081613637576001600160a01b03851660009081526017602090815260408083208380529091529020600101613679565b6001600160a01b03851660009081526017602052604081209061365b6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061368686613e95565b6001600160a01b038716600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b83548110156137135760008482815481106136d6576136d6614354565b90600052602060002001549050868114613700578254600181018455600084815260209020018190555b508061370b816143ee565b9150506136b9565b5061371f846001614741565b6001600160a01b0388166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03821615610e80576001600160a01b03821660009081526018602052604081205463ffffffff1690816137b3576001600160a01b038416600090815260176020908152604080832083805290915290206001016137f5565b6001600160a01b0384166000908152601760205260408120906137d76001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b9050600061380285613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff85168452909152902083549192506001908101916104009161384491906143d6565b11156138625760405162461bcd60e51b8152600401610f0190614769565b60005b83548110156138b457600084828154811061388257613882614354565b6000918252602080832090910154855460018101875586845291909220015550806138ac816143ee565b915050613865565b508054600181810183556000838152602090209091018690556138d8908590614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff1990921691909117905550505050505050565b6000818152600760205260409020546001600160a01b0316156139385761393861436a565b600081815260076020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260088084528285208054600c86528487208188528652848720889055878752600d8652938620939093559084529091528054600192906135a89084906143d6565b806001600160a01b0316826001600160a01b031614610e80576001600160a01b03821615613b5c576001600160a01b03821660009081526018602052604081205463ffffffff169081613a21576001600160a01b03841660009081526017602090815260408083208380529091529020600101613a63565b6001600160a01b038416600090815260176020526040812090613a456001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613a7085613e95565b6001600160a01b038616600090815260176020908152604080832063ffffffff8516845290915281209192506001909101905b8354811015613b1b576000848281548110613ac057613ac0614354565b600091825260208083209091015480835260079091526040909120549091506001600160a01b03908116908a1614613b08578254600181018455600084815260209020018190555b5080613b13816143ee565b915050613aa3565b50613b27846001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff191663ffffffff92909216919091179055505050505b6001600160a01b03811615610e80576001600160a01b03811660009081526018602052604081205463ffffffff169081613bbb576001600160a01b03831660009081526017602090815260408083208380529091529020600101613bfd565b6001600160a01b038316600090815260176020526040812090613bdf6001856142f6565b63ffffffff1663ffffffff1681526020019081526020016000206001015b90506000613c0a84613e95565b6001600160a01b03808616600090815260176020908152604080832063ffffffff861684528252808320938b1683526008909152902054845492935060019091019161040090613c5b9083906143d6565b1115613c795760405162461bcd60e51b8152600401610f0190614769565b60005b8454811015613ccb576000858281548110613c9957613c99614354565b600091825260208083209091015486546001810188558784529190922001555080613cc3816143ee565b915050613c7c565b5060005b81811015613d1d576001600160a01b0389166000908152600c602090815260408083208484528252822054855460018101875586845291909220015580613d15816143ee565b915050613ccf565b50613d29856001614741565b6001600160a01b0387166000908152601860205260409020805463ffffffff9290921663ffffffff199092169190911790555050505050505050565b60006001600160a01b038316613d7d57613d7d61436a565b613d8b6000612413856112bd565b613d958383613913565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b6001600160a01b038216600090815260086020526040812054613dfb906001906143a2565b6000838152600d6020526040902054909150808203613e4a576001600160a01b0384166000908152600c602090815260408083208584528252808320839055858352600d909152812055611b9c565b6001600160a01b03939093166000908152600c6020908152604080832093835292815282822080548684528484208190558352600d9091528282209490945592839055908252812055565b6001600160a01b038116600090815260186020526040812054429063ffffffff168015801590613efe57506001600160a01b03841660009081526017602052604081208391613ee56001856142f6565b63ffffffff168152602081019190915260400160002054145b1561123a576113c36001826142f6565b6001600160e01b03198116811461130857600080fd5b600060208284031215613f3657600080fd5b813561123a81613f0e565b60005b83811015613f5c578181015183820152602001613f44565b83811115611b9c5750506000910152565b60008151808452613f85816020860160208601613f41565b601f01601f19169290920160200192915050565b60208152600061123a6020830184613f6d565b80356001600160a01b0381168114613fc357600080fd5b919050565b60008060408385031215613fdb57600080fd5b613fe483613fac565b946020939093013593505050565b60006020828403121561400457600080fd5b5035919050565b60006020828403121561401d57600080fd5b61123a82613fac565b6000806040838503121561403957600080fd5b50508035926020909101359150565b60008060006060848603121561405d57600080fd5b61406684613fac565b925061407460208501613fac565b9150604084013590509250925092565b801515811461130857600080fd5b600080604083850312156140a557600080fd5b6140ae83613fac565b915060208301356140be81614084565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614108576141086140c9565b604052919050565b600067ffffffffffffffff82111561412a5761412a6140c9565b50601f01601f191660200190565b6000806000806080858703121561414e57600080fd5b61415785613fac565b935061416560208601613fac565b925060408501359150606085013567ffffffffffffffff81111561418857600080fd5b8501601f8101871361419957600080fd5b80356141ac6141a782614110565b6140df565b8181528860208385010111156141c157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060008060008060c087890312156141fc57600080fd5b61420587613fac565b95506020870135945060408701359350606087013560ff8116811461422957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060006060848603121561425857600080fd5b833592506020840135915061426f60408501613fac565b90509250925092565b6000806040838503121561428b57600080fd5b61429483613fac565b91506142a260208401613fac565b90509250929050565b600080604083850312156142be57600080fd5b6142c783613fac565b9150602083013563ffffffff811681146140be57600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015614313576143136142e0565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806143485761434861431b565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b602080825260089082015267185d1d1858da195960c21b604082015260600190565b6000828210156143b4576143b46142e0565b500390565b6000602082840312156143cb57600080fd5b815161123a81614084565b600082198211156143e9576143e96142e0565b500190565b600060018201614400576144006142e0565b5060010190565b6000816000190483118215151615614421576144216142e0565b500290565b6000826144355761443561431b565b500490565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061157a90830184613f6d565b6000602082840312156144c357600080fd5b815161123a81613f0e565b6000602082840312156144e057600080fd5b815167ffffffffffffffff8111156144f757600080fd5b8201601f8101841361450857600080fd5b80516145166141a782614110565b81815285602083850101111561452b57600080fd5b612e5b826020830160208601613f41565b600081600f0b83600f0b806145535761455361431b565b60016001607f1b0319821460001982141615614571576145716142e0565b90059392505050565b600081600f0b83600f0b60016001607f1b036000821360008413838304851182821616156145aa576145aa6142e0565b60016001607f1b031960008512828116878305871216156145cd576145cd6142e0565b600087129250858205871284841616156145e9576145e96142e0565b858505871281841616156145ff576145ff6142e0565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b03190183128115161561463a5761463a6142e0565b8160016001607f1b03018313811615614655576146556142e0565b5090039392505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615614689576146896142e0565b8260016001607f1b03190382128116156146a5576146a56142e0565b50019392505050565b60008083128015600160ff1b8501841216156146cc576146cc6142e0565b6001600160ff1b03840183138116156146e7576146e76142e0565b50500390565b634e487b7160e01b600052602160045260246000fd5b84815260208101849052608081016005841061472f57634e487b7160e01b600052602160045260246000fd5b60408201939093526060015292915050565b600063ffffffff808316818516808303821115614760576147606142e0565b01949350505050565b60208082526023908201527f64737452657020776f756c64206861766520746f6f206d616e7920746f6b656e60408201526249647360e81b60608201526080019056fea2646970667358221220245dd4da7f4eb9a32bfed7d913c4bc4316ce8585e535cd4e280eb72cdc5dab1c64736f6c634300080d0033", + "devdoc": { + "author": "Modified from Solidly (https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol)Modified from Curve (https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy)Modified from Nouns DAO (https://github.com/withtally/my-nft-dao-project/blob/main/contracts/ERC721Checkpointable.sol)", + "details": "Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).", + "kind": "dev", + "methods": { + "approve(address,uint256)": { + "details": "Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address. Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner. Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP) Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)", + "params": { + "_approved": "Address to be approved for the given NFT ID.", + "_tokenId": "ID of the token to be approved." + } + }, + "balanceOf(address)": { + "details": "Returns the number of NFTs owned by `_owner`. Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.", + "params": { + "_owner": "Address for whom to query the balance." + } + }, + "constructor": { + "params": { + "token_addr": "`VELO` token address" + } + }, + "create_lock(uint256,uint256)": { + "params": { + "_lock_duration": "Number of seconds to lock tokens for (rounded down to nearest week)", + "_value": "Amount to deposit" + } + }, + "create_lock_for(uint256,uint256,address)": { + "params": { + "_lock_duration": "Number of seconds to lock tokens for (rounded down to nearest week)", + "_to": "Address to deposit", + "_value": "Amount to deposit" + } + }, + "delegate(address)": { + "params": { + "delegatee": "The address to delegate votes to" + } + }, + "delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)": { + "details": "Delegates votes from signer to `delegatee`." + }, + "deposit_for(uint256,uint256)": { + "details": "Anyone (even a smart contract) can deposit for someone else, but cannot extend their locktime and deposit for a brand new user", + "params": { + "_tokenId": "lock NFT", + "_value": "Amount to add to user's lock" + } + }, + "getApproved(uint256)": { + "details": "Get the approved address for a single NFT.", + "params": { + "_tokenId": "ID of the NFT to query the approval of." + } + }, + "getVotes(address)": { + "params": { + "account": "The address to get votes balance" + }, + "returns": { + "_0": "The number of current votes for `account`" + } + }, + "get_last_user_slope(uint256)": { + "params": { + "_tokenId": "token of the NFT" + }, + "returns": { + "_0": "Value of the slope" + } + }, + "increase_amount(uint256,uint256)": { + "params": { + "_value": "Amount of tokens to deposit and add to the lock" + } + }, + "increase_unlock_time(uint256,uint256)": { + "params": { + "_lock_duration": "New number of seconds until tokens unlock" + } + }, + "isApprovedForAll(address,address)": { + "details": "Checks if `_operator` is an approved operator for `_owner`.", + "params": { + "_operator": "The address that acts on behalf of the owner.", + "_owner": "The address that owns the NFTs." + } + }, + "locked__end(uint256)": { + "params": { + "_tokenId": "User NFT" + }, + "returns": { + "_0": "Epoch time of the lock end" + } + }, + "ownerOf(uint256)": { + "details": "Returns the address of the owner of the NFT.", + "params": { + "_tokenId": "The identifier for an NFT." + } + }, + "safeTransferFrom(address,address,uint256)": { + "details": "Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.", + "params": { + "_from": "The current owner of the NFT.", + "_to": "The new owner.", + "_tokenId": "The NFT to transfer." + } + }, + "safeTransferFrom(address,address,uint256,bytes)": { + "details": "Transfers the ownership of an NFT from one address to another address. Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT. If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if the return value is not `bytes4(keccak256(\"onERC721Received(address,address,uint,bytes)\"))`.", + "params": { + "_data": "Additional data with no specified format, sent in call to `_to`.", + "_from": "The current owner of the NFT.", + "_to": "The new owner.", + "_tokenId": "The NFT to transfer." + } + }, + "setApprovalForAll(address,bool)": { + "details": "Enables or disables approval for a third party (\"operator\") to manage all of `msg.sender`'s assets. It also emits the ApprovalForAll event. Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)", + "params": { + "_approved": "True if the operators is approved, false to revoke approval.", + "_operator": "Address to add to the set of authorized operators." + } + }, + "supportsInterface(bytes4)": { + "details": "Interface identification is specified in ERC-165.", + "params": { + "_interfaceID": "Id of the interface" + } + }, + "tokenOfOwnerByIndex(address,uint256)": { + "details": "Get token by index" + }, + "tokenURI(uint256)": { + "details": "Returns current token URI metadata", + "params": { + "_tokenId": "Token ID to fetch URI for." + } + }, + "totalSupplyAt(uint256)": { + "params": { + "_block": "Block to calculate the total voting power at" + }, + "returns": { + "_0": "Total voting power at `_block`" + } + }, + "totalSupplyAtT(uint256)": { + "details": "Adheres to the ERC20 `totalSupply` interface for Aragon compatibility", + "returns": { + "_0": "Total voting power" + } + }, + "transferFrom(address,address,uint256)": { + "details": "Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero address. Throws if `_tokenId` is not a valid NFT.", + "params": { + "_from": "The current owner of the NFT.", + "_to": "The new owner.", + "_tokenId": "The NFT to transfer." + } + }, + "user_point_history__ts(uint256,uint256)": { + "params": { + "_idx": "User epoch number", + "_tokenId": "token of the NFT" + }, + "returns": { + "_0": "Epoch time of the checkpoint" + } + }, + "withdraw(uint256)": { + "details": "Only possible if the lock has expired" + } + }, + "stateVariables": { + "ERC165_INTERFACE_ID": { + "details": "ERC165 interface ID of ERC165" + }, + "ERC721_INTERFACE_ID": { + "details": "ERC165 interface ID of ERC721" + }, + "ERC721_METADATA_INTERFACE_ID": { + "details": "ERC165 interface ID of ERC721Metadata" + }, + "_not_entered": { + "details": "reentrancy guard" + }, + "idToApprovals": { + "details": "Mapping from NFT ID to approved address." + }, + "idToOwner": { + "details": "Mapping from NFT ID to the address that owns it." + }, + "name": { + "details": "Returns the token collection name." + }, + "ownerToNFTokenCount": { + "details": "Mapping from owner address to count of his tokens." + }, + "ownerToNFTokenIdList": { + "details": "Mapping from owner address to mapping of index to tokenIds" + }, + "ownerToOperators": { + "details": "Mapping from owner address to mapping of operator addresses." + }, + "supportedInterfaces": { + "details": "Mapping of interface id to bool about whether or not it's supported" + }, + "symbol": { + "details": "Returns the token collection symbol." + }, + "tokenId": { + "details": "Current count of token" + }, + "tokenToOwnerIndex": { + "details": "Mapping from NFT ID to index of owner" + } + }, + "title": "Voting Escrow", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "DELEGATION_TYPEHASH()": { + "notice": "The EIP-712 typehash for the delegation struct used by the contract" + }, + "DOMAIN_TYPEHASH()": { + "notice": "The EIP-712 typehash for the contract's domain" + }, + "checkpoint()": { + "notice": "Record global data to checkpoint" + }, + "checkpoints(address,uint32)": { + "notice": "A record of delegated token checkpoints for each account, by index" + }, + "constructor": { + "notice": "Contract constructor" + }, + "create_lock(uint256,uint256)": { + "notice": "Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`" + }, + "create_lock_for(uint256,uint256,address)": { + "notice": "Deposit `_value` tokens for `_to` and lock for `_lock_duration`" + }, + "delegate(address)": { + "notice": "Delegate votes from `msg.sender` to `delegatee`" + }, + "delegates(address)": { + "notice": "Overrides the standard `Comp.sol` delegates mapping to return the delegator's own address if they haven't delegated. This avoids having to delegate to oneself." + }, + "deposit_for(uint256,uint256)": { + "notice": "Deposit `_value` tokens for `_tokenId` and add to the lock" + }, + "getVotes(address)": { + "notice": "Gets the current votes balance for `account`" + }, + "get_last_user_slope(uint256)": { + "notice": "Get the most recently recorded rate of voting power decrease for `_tokenId`" + }, + "increase_amount(uint256,uint256)": { + "notice": "Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time" + }, + "increase_unlock_time(uint256,uint256)": { + "notice": "Extend the unlock time for `_tokenId`" + }, + "locked__end(uint256)": { + "notice": "Get timestamp when `_tokenId`'s lock finishes" + }, + "nonces(address)": { + "notice": "A record of states for signing / validating signatures" + }, + "numCheckpoints(address)": { + "notice": "The number of checkpoints for each account" + }, + "setApprovalForAll(address,bool)": { + "notice": "This works even if sender doesn't own any tokens at the time." + }, + "totalSupplyAt(uint256)": { + "notice": "Calculate total voting power at some point in the past" + }, + "totalSupplyAtT(uint256)": { + "notice": "Calculate total voting power" + }, + "transferFrom(address,address,uint256)": { + "notice": "The caller is responsible to confirm that `_to` is capable of receiving NFTs or else they maybe be permanently lost." + }, + "user_point_history__ts(uint256,uint256)": { + "notice": "Get the timestamp for checkpoint `_idx` for `_tokenId`" + }, + "withdraw(uint256)": { + "notice": "Withdraw all tokens for `_tokenId`" + } + }, + "notice": "veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFTVotes have a weight depending on time, so that users are committed to the future of (whatever they are voting for)", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 16268, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "voter", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 16270, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "team", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 16272, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "artProxy", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 16277, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "point_history", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint256,t_struct(Point)16227_storage)" + }, + { + "astId": 16282, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "supportedInterfaces", + "offset": 0, + "slot": "4", + "type": "t_mapping(t_bytes4,t_bool)" + }, + { + "astId": 16297, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "tokenId", + "offset": 0, + "slot": "5", + "type": "t_uint256" + }, + { + "astId": 16392, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "_entered_state", + "offset": 0, + "slot": "6", + "type": "t_uint8" + }, + { + "astId": 16511, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "idToOwner", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_uint256,t_address)" + }, + { + "astId": 16516, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "ownerToNFTokenCount", + "offset": 0, + "slot": "8", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 16560, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "idToApprovals", + "offset": 0, + "slot": "9", + "type": "t_mapping(t_uint256,t_address)" + }, + { + "astId": 16567, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "ownerToOperators", + "offset": 0, + "slot": "10", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" + }, + { + "astId": 16571, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "ownership_change", + "offset": 0, + "slot": "11", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 17016, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "ownerToNFTokenIdList", + "offset": 0, + "slot": "12", + "type": "t_mapping(t_address,t_mapping(t_uint256,t_uint256))" + }, + { + "astId": 17021, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "tokenToOwnerIndex", + "offset": 0, + "slot": "13", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 17326, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "user_point_epoch", + "offset": 0, + "slot": "14", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 17333, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "user_point_history", + "offset": 0, + "slot": "15", + "type": "t_mapping(t_uint256,t_array(t_struct(Point)16227_storage)1000000000_storage)" + }, + { + "astId": 17338, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "locked", + "offset": 0, + "slot": "16", + "type": "t_mapping(t_uint256,t_struct(LockedBalance)16218_storage)" + }, + { + "astId": 17340, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "epoch", + "offset": 0, + "slot": "17", + "type": "t_uint256" + }, + { + "astId": 17344, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "slope_changes", + "offset": 0, + "slot": "18", + "type": "t_mapping(t_uint256,t_int128)" + }, + { + "astId": 17346, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "supply", + "offset": 0, + "slot": "19", + "type": "t_uint256" + }, + { + "astId": 19217, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "attachments", + "offset": 0, + "slot": "20", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 19221, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "voted", + "offset": 0, + "slot": "21", + "type": "t_mapping(t_uint256,t_bool)" + }, + { + "astId": 19452, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "_delegates", + "offset": 0, + "slot": "22", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 19463, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "checkpoints", + "offset": 0, + "slot": "23", + "type": "t_mapping(t_address,t_mapping(t_uint32,t_struct(Checkpoint)16233_storage))" + }, + { + "astId": 19468, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "numCheckpoints", + "offset": 0, + "slot": "24", + "type": "t_mapping(t_address,t_uint32)" + }, + { + "astId": 19473, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "nonces", + "offset": 0, + "slot": "25", + "type": "t_mapping(t_address,t_uint256)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(Point)16227_storage)1000000000_storage": { + "base": "t_struct(Point)16227_storage", + "encoding": "inplace", + "label": "struct VotingEscrow.Point[1000000000]", + "numberOfBytes": "96000000000" + }, + "t_array(t_uint256)dyn_storage": { + "base": "t_uint256", + "encoding": "dynamic_array", + "label": "uint256[]", + "numberOfBytes": "32" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes4": { + "encoding": "inplace", + "label": "bytes4", + "numberOfBytes": "4" + }, + "t_int128": { + "encoding": "inplace", + "label": "int128", + "numberOfBytes": "16" + }, + "t_mapping(t_address,t_address)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_bool)" + }, + "t_mapping(t_address,t_mapping(t_uint256,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(uint256 => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_uint256,t_uint256)" + }, + "t_mapping(t_address,t_mapping(t_uint32,t_struct(Checkpoint)16233_storage))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(uint32 => struct VotingEscrow.Checkpoint))", + "numberOfBytes": "32", + "value": "t_mapping(t_uint32,t_struct(Checkpoint)16233_storage)" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_address,t_uint32)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint32)", + "numberOfBytes": "32", + "value": "t_uint32" + }, + "t_mapping(t_bytes4,t_bool)": { + "encoding": "mapping", + "key": "t_bytes4", + "label": "mapping(bytes4 => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_uint256,t_address)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_uint256,t_array(t_struct(Point)16227_storage)1000000000_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct VotingEscrow.Point[1000000000])", + "numberOfBytes": "32", + "value": "t_array(t_struct(Point)16227_storage)1000000000_storage" + }, + "t_mapping(t_uint256,t_bool)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_uint256,t_int128)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => int128)", + "numberOfBytes": "32", + "value": "t_int128" + }, + "t_mapping(t_uint256,t_struct(LockedBalance)16218_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct VotingEscrow.LockedBalance)", + "numberOfBytes": "32", + "value": "t_struct(LockedBalance)16218_storage" + }, + "t_mapping(t_uint256,t_struct(Point)16227_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct VotingEscrow.Point)", + "numberOfBytes": "32", + "value": "t_struct(Point)16227_storage" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_uint32,t_struct(Checkpoint)16233_storage)": { + "encoding": "mapping", + "key": "t_uint32", + "label": "mapping(uint32 => struct VotingEscrow.Checkpoint)", + "numberOfBytes": "32", + "value": "t_struct(Checkpoint)16233_storage" + }, + "t_struct(Checkpoint)16233_storage": { + "encoding": "inplace", + "label": "struct VotingEscrow.Checkpoint", + "members": [ + { + "astId": 16229, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "timestamp", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 16232, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "tokenIds", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)dyn_storage" + } + ], + "numberOfBytes": "64" + }, + "t_struct(LockedBalance)16218_storage": { + "encoding": "inplace", + "label": "struct VotingEscrow.LockedBalance", + "members": [ + { + "astId": 16215, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "amount", + "offset": 0, + "slot": "0", + "type": "t_int128" + }, + { + "astId": 16217, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "end", + "offset": 0, + "slot": "1", + "type": "t_uint256" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Point)16227_storage": { + "encoding": "inplace", + "label": "struct VotingEscrow.Point", + "members": [ + { + "astId": 16220, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "bias", + "offset": 0, + "slot": "0", + "type": "t_int128" + }, + { + "astId": 16222, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "slope", + "offset": 16, + "slot": "0", + "type": "t_int128" + }, + { + "astId": 16224, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "ts", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 16226, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "blk", + "offset": 0, + "slot": "2", + "type": "t_uint256" + } + ], + "numberOfBytes": "96" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "encoding": "inplace", + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumOneOLD/WrappedExternalBribeFactory.json b/deployments/arbitrumOneOLD/WrappedExternalBribeFactory.json new file mode 100644 index 00000000..020f594f --- /dev/null +++ b/deployments/arbitrumOneOLD/WrappedExternalBribeFactory.json @@ -0,0 +1,148 @@ +{ + "address": "0xbb88E349257e4355946C2604fEd168165989285c", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_voter", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "existing_bribe", + "type": "address" + } + ], + "name": "createBribe", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "last_bribe", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "oldBribeToNew", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "voter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xe910624a59ad0487fff48182a26d189b2e6384c5389ce0ae2483da6dbc9bcf00", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0xbb88E349257e4355946C2604fEd168165989285c", + "transactionIndex": 1, + "gasUsed": "10475233", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x502c654130fc432a20ef80e86336a8d5e1aed325c26ae2a13d4eb3b2a8779b33", + "transactionHash": "0xe910624a59ad0487fff48182a26d189b2e6384c5389ce0ae2483da6dbc9bcf00", + "logs": [], + "blockNumber": 56592743, + "cumulativeGasUsed": "10475233", + "status": 1, + "byzantium": true + }, + "args": [ + "0x29C487a354D11315059204Df4F7d8AB1aa008ebb" + ], + "numDeployments": 1, + "solcInputHash": "4e21824d68c90a2d8601cfb8f8d80414", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_voter\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"existing_bribe\",\"type\":\"address\"}],\"name\":\"createBribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"last_bribe\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"oldBribeToNew\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"voter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/factories/WrappedExternalBribeFactory.sol\":\"WrappedExternalBribeFactory\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363735303731393533363138\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/ExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/interfaces/IBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract ExternalBribe is IBribe {\\n address public immutable voter; // only voter can modify balances (since it only happens on vote())\\n address public immutable _ve; // \\u5929\\u4f7f\\u306e\\u305f\\u307e\\u3054\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n uint256 public totalSupply;\\n mapping(uint256 => uint256) public balanceOf;\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct Checkpoint {\\n uint256 timestamp;\\n uint256 balanceOf;\\n }\\n\\n /// @notice A checkpoint for marking supply\\n struct SupplyCheckpoint {\\n uint256 timestamp;\\n uint256 supply;\\n }\\n\\n /// @notice A record of balance checkpoints for each account, by index\\n mapping(uint256 => mapping(uint256 => Checkpoint)) public checkpoints;\\n /// @notice The number of checkpoints for each account\\n mapping(uint256 => uint256) public numCheckpoints;\\n /// @notice A record of balance checkpoints for each token, by index\\n mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;\\n /// @notice The number of checkpoints\\n uint256 public supplyNumCheckpoints;\\n\\n event Deposit(address indexed from, uint256 tokenId, uint256 amount);\\n event Withdraw(address indexed from, uint256 tokenId, uint256 amount);\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address[] memory _allowedRewardTokens) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n\\n for (uint256 i; i < _allowedRewardTokens.length; i++) {\\n if (_allowedRewardTokens[i] != address(0)) {\\n isReward[_allowedRewardTokens[i]] = true;\\n rewards.push(_allowedRewardTokens[i]);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n /**\\n * @notice Determine the prior balance for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param tokenId The token of the NFT to check\\n * @param timestamp The timestamp to get the balance at\\n * @return The balance the account had as of the given block\\n */\\n function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = numCheckpoints[tokenId];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n // First check most recent balance\\n if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n // Next check implicit zero balance\\n if (checkpoints[tokenId][0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[tokenId][center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function getPriorSupplyIndex(uint256 timestamp)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 nCheckpoints = supplyNumCheckpoints;\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {\\n return (nCheckpoints - 1);\\n }\\n\\n // Next check implicit zero balance\\n if (supplyCheckpoints[0].timestamp > timestamp) {\\n return 0;\\n }\\n\\n uint256 lower = 0;\\n uint256 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n SupplyCheckpoint memory cp = supplyCheckpoints[center];\\n if (cp.timestamp == timestamp) {\\n return center;\\n } else if (cp.timestamp < timestamp) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return lower;\\n }\\n\\n function _writeCheckpoint(uint256 tokenId, uint256 balance) internal {\\n uint256 _timestamp = block.timestamp;\\n uint256 _nCheckPoints = numCheckpoints[tokenId];\\n if (\\n _nCheckPoints > 0 &&\\n checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance;\\n } else {\\n checkpoints[tokenId][_nCheckPoints] = Checkpoint(\\n _timestamp,\\n balance\\n );\\n numCheckpoints[tokenId] = _nCheckPoints + 1;\\n }\\n }\\n\\n function _writeSupplyCheckpoint() internal {\\n uint256 _nCheckPoints = supplyNumCheckpoints;\\n uint256 _timestamp = block.timestamp;\\n\\n if (\\n _nCheckPoints > 0 &&\\n supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp\\n ) {\\n supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;\\n } else {\\n supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(\\n _timestamp,\\n totalSupply\\n );\\n supplyNumCheckpoints = _nCheckPoints + 1;\\n }\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (numCheckpoints[tokenId] == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = getPriorBalanceIndex(tokenId, _startTimestamp);\\n uint256 _endIndex = numCheckpoints[tokenId] - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n Checkpoint memory prevRewards; // reuse struct to avoid stack too deep\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n Checkpoint memory cp0 = checkpoints[tokenId][i];\\n uint256 _nextEpochStart = _bribeStart(cp0.timestamp);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balanceOf;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n _prevSupply = supplyCheckpoints[\\n getPriorSupplyIndex(_nextEpochStart + DURATION)\\n ].supply;\\n prevRewards.balanceOf =\\n (cp0.balanceOf *\\n tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n Checkpoint memory cp = checkpoints[tokenId][_endIndex];\\n uint256 _lastEpochStart = _bribeStart(cp.timestamp);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (block.timestamp > _lastEpochEnd) {\\n reward +=\\n (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n supplyCheckpoints[getPriorSupplyIndex(_lastEpochEnd)].supply;\\n }\\n\\n return reward;\\n }\\n\\n // This is an external function, but internal notation is used since it can only be called \\\"internally\\\" from Gauges\\n function _deposit(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply += amount;\\n balanceOf[tokenId] += amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Deposit(msg.sender, tokenId, amount);\\n }\\n\\n function _withdraw(uint256 amount, uint256 tokenId) external {\\n require(msg.sender == voter);\\n\\n totalSupply -= amount;\\n balanceOf[tokenId] -= amount;\\n\\n _writeCheckpoint(tokenId, balanceOf[tokenId]);\\n _writeSupplyCheckpoint();\\n\\n emit Withdraw(msg.sender, tokenId, amount);\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0xfe1e53dea8a63ce448c5856a740ed73038ad29a9dcd0f2a2752049b146bb4eb0\",\"license\":\"MIT\"},\"contracts/WrappedExternalBribe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport \\\"contracts/libraries/Math.sol\\\";\\nimport \\\"contracts/ExternalBribe.sol\\\";\\nimport \\\"contracts/interfaces/IERC20.sol\\\";\\nimport \\\"contracts/interfaces/IGauge.sol\\\";\\nimport \\\"contracts/interfaces/IVoter.sol\\\";\\nimport \\\"contracts/interfaces/IVotingEscrow.sol\\\";\\n\\n// Bribes pay out rewards for a given pool based on the votes that were received from the user (goes hand in hand with Voter.vote())\\ncontract WrappedExternalBribe {\\n address public immutable voter;\\n address public immutable _ve;\\n ExternalBribe public underlying_bribe;\\n\\n uint256 internal constant DURATION = 7 days; // rewards are released over the voting period\\n uint256 internal constant MAX_REWARD_TOKENS = 16;\\n\\n uint256 internal constant PRECISION = 10**18;\\n\\n mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;\\n mapping(address => uint256) public periodFinish;\\n mapping(address => mapping(uint256 => uint256)) public lastEarn;\\n\\n address[] public rewards;\\n mapping(address => bool) public isReward;\\n\\n /// @notice A checkpoint for marking balance\\n struct RewardCheckpoint {\\n uint256 timestamp;\\n uint256 balance;\\n }\\n\\n event NotifyReward(\\n address indexed from,\\n address indexed reward,\\n uint256 epoch,\\n uint256 amount\\n );\\n event ClaimRewards(\\n address indexed from,\\n address indexed reward,\\n uint256 amount\\n );\\n\\n constructor(address _voter, address _old_bribe) {\\n voter = _voter;\\n _ve = IVoter(_voter)._ve();\\n underlying_bribe = ExternalBribe(_old_bribe);\\n\\n for (uint256 i; i < underlying_bribe.rewardsListLength(); i++) {\\n address underlying_reward = underlying_bribe.rewards(i);\\n if (underlying_reward != address(0)) {\\n isReward[underlying_reward] = true;\\n rewards.push(underlying_reward);\\n }\\n }\\n }\\n\\n // simple re-entrancy check\\n uint256 internal _unlocked = 1;\\n modifier lock() {\\n require(_unlocked == 1);\\n _unlocked = 2;\\n _;\\n _unlocked = 1;\\n }\\n\\n function _bribeStart(uint256 timestamp) internal pure returns (uint256) {\\n return timestamp - (timestamp % (7 days));\\n }\\n\\n function getEpochStart(uint256 timestamp) public pure returns (uint256) {\\n uint256 bribeStart = _bribeStart(timestamp);\\n uint256 bribeEnd = bribeStart + DURATION;\\n return timestamp < bribeEnd ? bribeStart : bribeStart + 7 days;\\n }\\n\\n function rewardsListLength() external view returns (uint256) {\\n return rewards.length;\\n }\\n\\n // returns the last time the reward was modified or periodFinish if the reward has ended\\n function lastTimeRewardApplicable(address token)\\n public\\n view\\n returns (uint256)\\n {\\n return MathDunks.min(block.timestamp, periodFinish[token]);\\n }\\n\\n // allows a user to claim rewards for a given token\\n function getReward(uint256 tokenId, address[] memory tokens) external lock {\\n require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);\\n\\n emit ClaimRewards(msg.sender, tokens[i], _reward);\\n }\\n }\\n\\n // used by Voter to allow batched reward claims\\n function getRewardForOwner(uint256 tokenId, address[] memory tokens)\\n external\\n lock\\n {\\n require(msg.sender == voter);\\n address _owner = IVotingEscrow(_ve).ownerOf(tokenId);\\n for (uint256 i = 0; i < tokens.length; i++) {\\n uint256 _reward = earned(tokens[i], tokenId);\\n lastEarn[tokens[i]][tokenId] = block.timestamp;\\n if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);\\n\\n emit ClaimRewards(_owner, tokens[i], _reward);\\n }\\n }\\n\\n function earned(address token, uint256 tokenId)\\n public\\n view\\n returns (uint256)\\n {\\n uint256 _startTimestamp = lastEarn[token][tokenId];\\n if (underlying_bribe.numCheckpoints(tokenId) == 0) {\\n return 0;\\n }\\n\\n uint256 _startIndex = underlying_bribe.getPriorBalanceIndex(\\n tokenId,\\n _startTimestamp\\n );\\n uint256 _endIndex = underlying_bribe.numCheckpoints(tokenId) - 1;\\n\\n uint256 reward = 0;\\n // you only earn once per epoch (after it's over)\\n RewardCheckpoint memory prevRewards;\\n prevRewards.timestamp = _bribeStart(_startTimestamp);\\n uint256 _prevTs = 0;\\n uint256 _prevBal = 0;\\n uint256 _prevSupply = 1;\\n\\n if (_endIndex > 0) {\\n for (uint256 i = _startIndex; i <= _endIndex - 1; i++) {\\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, i);\\n uint256 _nextEpochStart = _bribeStart(_prevTs);\\n // check that you've earned it\\n // this won't happen until a week has passed\\n if (_nextEpochStart > prevRewards.timestamp) {\\n reward += prevRewards.balance;\\n }\\n\\n prevRewards.timestamp = _nextEpochStart;\\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\\n underlying_bribe.getPriorSupplyIndex(\\n _nextEpochStart + DURATION\\n )\\n );\\n prevRewards.balance =\\n (_prevBal * tokenRewardsPerEpoch[token][_nextEpochStart]) /\\n _prevSupply;\\n }\\n }\\n\\n (_prevTs, _prevBal) = underlying_bribe.checkpoints(tokenId, _endIndex);\\n uint256 _lastEpochStart = _bribeStart(_prevTs);\\n uint256 _lastEpochEnd = _lastEpochStart + DURATION;\\n\\n if (\\n block.timestamp > _lastEpochEnd && _startTimestamp < _lastEpochEnd\\n ) {\\n (, _prevSupply) = underlying_bribe.supplyCheckpoints(\\n underlying_bribe.getPriorSupplyIndex(_lastEpochEnd)\\n );\\n reward +=\\n (_prevBal * tokenRewardsPerEpoch[token][_lastEpochStart]) /\\n _prevSupply;\\n }\\n\\n return reward;\\n }\\n\\n function left(address token) external view returns (uint256) {\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n return tokenRewardsPerEpoch[token][adjustedTstamp];\\n }\\n\\n function notifyRewardAmount(address token, uint256 amount) external lock {\\n require(amount > 0);\\n if (!isReward[token]) {\\n require(\\n IVoter(voter).isWhitelisted(token),\\n \\\"bribe tokens must be whitelisted\\\"\\n );\\n require(\\n rewards.length < MAX_REWARD_TOKENS,\\n \\\"too many rewards tokens\\\"\\n );\\n }\\n // bribes kick in at the start of next bribe period\\n uint256 adjustedTstamp = getEpochStart(block.timestamp);\\n uint256 epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp];\\n\\n _safeTransferFrom(token, msg.sender, address(this), amount);\\n tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount;\\n\\n periodFinish[token] = adjustedTstamp + DURATION;\\n\\n if (!isReward[token]) {\\n isReward[token] = true;\\n rewards.push(token);\\n }\\n\\n emit NotifyReward(msg.sender, token, adjustedTstamp, amount);\\n }\\n\\n function swapOutRewardToken(\\n uint256 i,\\n address oldToken,\\n address newToken\\n ) external {\\n require(msg.sender == IVotingEscrow(_ve).team(), \\\"only team\\\");\\n require(rewards[i] == oldToken);\\n isReward[oldToken] = false;\\n isReward[newToken] = true;\\n rewards[i] = newToken;\\n }\\n\\n function _safeTransfer(\\n address token,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(IERC20.transfer.selector, to, value)\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n function _safeTransferFrom(\\n address token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n require(token.code.length > 0);\\n (bool success, bytes memory data) = token.call(\\n abi.encodeWithSelector(\\n IERC20.transferFrom.selector,\\n from,\\n to,\\n value\\n )\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\\n\",\"keccak256\":\"0x855fa341d3139522255811d9a9df463636e27fd6e21bd07c38adacad734af6ed\",\"license\":\"MIT\"},\"contracts/factories/WrappedExternalBribeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.13;\\n\\nimport {WrappedExternalBribe} from 'contracts/WrappedExternalBribe.sol';\\n\\ncontract WrappedExternalBribeFactory {\\n address public immutable voter;\\n mapping(address => address) public oldBribeToNew;\\n address public last_bribe;\\n\\n constructor(address _voter) {\\n voter = _voter;\\n }\\n\\n function createBribe(address existing_bribe) external returns (address) {\\n require(\\n oldBribeToNew[existing_bribe] == address(0),\\n \\\"Wrapped bribe already created\\\"\\n );\\n last_bribe = address(new WrappedExternalBribe(voter, existing_bribe));\\n oldBribeToNew[existing_bribe] = last_bribe;\\n return last_bribe;\\n }\\n}\\n\",\"keccak256\":\"0x4e88b50000e3cf490ae8602b55555bbc02f95fda5926b1a532debfe54ac06bb2\",\"license\":\"MIT\"},\"contracts/interfaces/IBribe.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IBribe {\\n function _deposit(uint amount, uint tokenId) external;\\n function _withdraw(uint amount, uint tokenId) external;\\n function getRewardForOwner(uint tokenId, address[] memory tokens) external;\\n function notifyRewardAmount(address token, uint amount) external;\\n function left(address token) external view returns (uint);\\n}\\n\",\"keccak256\":\"0x51fd1163872f5d63b19f0c0f08b9b9a395dcadd79cf96cab749b898af01c1b4e\"},\"contracts/interfaces/IERC20.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n function transfer(address recipient, uint amount) external returns (bool);\\n function decimals() external view returns (uint8);\\n function symbol() external view returns (string memory);\\n function balanceOf(address) external view returns (uint);\\n function transferFrom(address sender, address recipient, uint amount) external returns (bool);\\n function allowance(address owner, address spender) external view returns (uint);\\n function approve(address spender, uint value) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint value);\\n event Approval(address indexed owner, address indexed spender, uint value);\\n}\\n\",\"keccak256\":\"0x892b167ec5245b43ccdfc68d20e8ca12d05725fb6c11ec5ddf6bf77ed0c93c32\"},\"contracts/interfaces/IGauge.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IGauge {\\n function notifyRewardAmount(address token, uint amount) external;\\n function getReward(address account, address[] memory tokens) external;\\n function claimFees() external returns (uint claimed0, uint claimed1);\\n function left(address token) external view returns (uint);\\n function isForPair() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xae388a0eeb0318da9a00bd65bcc80dcbf81cd24915959c7852f9fa21f8893865\"},\"contracts/interfaces/IVoter.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVoter {\\n function _ve() external view returns (address);\\n function governor() external view returns (address);\\n function emergencyCouncil() external view returns (address);\\n function attachTokenToGauge(uint _tokenId, address account) external;\\n function detachTokenFromGauge(uint _tokenId, address account) external;\\n function emitDeposit(uint _tokenId, address account, uint amount) external;\\n function emitWithdraw(uint _tokenId, address account, uint amount) external;\\n function isWhitelisted(address token) external view returns (bool);\\n function notifyRewardAmount(uint amount) external;\\n function distribute(address _gauge) external;\\n}\\n\",\"keccak256\":\"0x033115b88f156c6db67ca468fc9da8e4197bbd48bc8cf5a1652b9ebd307b2d31\"},\"contracts/interfaces/IVotingEscrow.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\ninterface IVotingEscrow {\\n\\n struct Point {\\n int128 bias;\\n int128 slope; // # -dweight / dt\\n uint256 ts;\\n uint256 blk; // block\\n }\\n\\n function token() external view returns (address);\\n function team() external returns (address);\\n function epoch() external view returns (uint);\\n function point_history(uint loc) external view returns (Point memory);\\n function user_point_history(uint tokenId, uint loc) external view returns (Point memory);\\n function user_point_epoch(uint tokenId) external view returns (uint);\\n\\n function ownerOf(uint) external view returns (address);\\n function isApprovedOrOwner(address, uint) external view returns (bool);\\n function transferFrom(address, address, uint) external;\\n\\n function voting(uint tokenId) external;\\n function abstain(uint tokenId) external;\\n function attach(uint tokenId) external;\\n function detach(uint tokenId) external;\\n\\n function checkpoint() external;\\n function deposit_for(uint tokenId, uint value) external;\\n function create_lock_for(uint, uint, address) external returns (uint);\\n\\n function balanceOfNFT(uint) external view returns (uint);\\n function totalSupply() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x9c51afef11e82c70d08871264602e385a4f7caf36383e1bc5a6c214f93a4c0d1\"},\"contracts/libraries/Math.sol\":{\"content\":\"pragma solidity 0.8.13;\\n\\n// this causes issue with forge test as there is already a Math.sol in the forge repo\\nlibrary MathDunks {\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n function sqrt(uint256 y) internal pure returns (uint256 z) {\\n if (y > 3) {\\n z = y;\\n uint256 x = y / 2 + 1;\\n while (x < z) {\\n z = x;\\n x = (y / x + x) / 2;\\n }\\n } else if (y != 0) {\\n z = 1;\\n }\\n }\\n\\n function cbrt(uint256 n) internal pure returns (uint256) {\\n unchecked {\\n uint256 x = 0;\\n for (uint256 y = 1 << 255; y > 0; y >>= 3) {\\n x <<= 1;\\n uint256 z = 3 * x * (x + 1) + 1;\\n if (n / y >= z) {\\n n -= y * z;\\n x += 1;\\n }\\n }\\n return x;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd7894a4b5d2afa5680c6a4c3de7dcb26ccd7dcf4339ca9d4478677cd5dc32be9\"}},\"version\":1}", + "bytecode": "0x60a060405234801561001057600080fd5b50604051611d5d380380611d5d83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051611ccc61009160003960008181609b01526101530152611ccc6000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632fcd8f271461005157806346c96aac146100965780636bd1a72c146100bd578063b1d0fc82146100d0575b600080fd5b61007a61005f366004610205565b6000602081905290815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b61007a7f000000000000000000000000000000000000000000000000000000000000000081565b61007a6100cb366004610205565b6100e3565b60015461007a906001600160a01b031681565b6001600160a01b03818116600090815260208190526040812054909116156101515760405162461bcd60e51b815260206004820152601d60248201527f5772617070656420627269626520616c72656164792063726561746564000000604482015260640160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000008260405161017f906101f8565b6001600160a01b03928316815291166020820152604001604051809103906000f0801580156101b2573d6000803e3d6000fd5b50600180546001600160a01b039283166001600160a01b031991821681178355948316600090815260208190526040902080549091169094179093559154909116919050565b611a618061023683390190565b60006020828403121561021757600080fd5b81356001600160a01b038116811461022e57600080fd5b939250505056fe60c060405260016006553480156200001657600080fd5b5060405162001a6138038062001a61833981016040819052620000399162000275565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002ad565b6001600160a01b0390811660a052600080546001600160a01b0319169183169190911781555b60008054906101000a90046001600160a01b03166001600160a01b031663e68863966040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000122573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001489190620002d2565b8110156200024f5760008054604051637980d7a160e11b8152600481018490526001600160a01b039091169063f301af4290602401602060405180830381865afa1580156200019b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001c19190620002ad565b90506001600160a01b0381161562000239576001600160a01b0381166000818152600560205260408120805460ff191660019081179091556004805491820181559091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b03191690911790555b50806200024681620002ec565b915050620000d0565b50505062000314565b80516001600160a01b03811681146200027057600080fd5b919050565b600080604083850312156200028957600080fd5b620002948362000258565b9150620002a46020840162000258565b90509250929050565b600060208284031215620002c057600080fd5b620002cb8262000258565b9392505050565b600060208284031215620002e557600080fd5b5051919050565b6000600182016200030d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a0516117046200035d600039600081816101e6015281816108f301528181610b1d0152610fd701526000818161014e01528181610ada0152610d1801526117046000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80639418f939116100a2578063da09d19d11610071578063da09d19d14610281578063e6886396146102a1578063f25e55a5146102a9578063f301af42146102d4578063f5f8d365146102e757600080fd5b80639418f9391461023357806399bcc05214610248578063a7852afa1461025b578063b66503cf1461026e57600080fd5b8063638634ee116100de578063638634ee146101bb5780636c4f5398146101ce5780638dd598fb146101e157806392777b291461020857600080fd5b80630175e23b146101105780633e491d471461013657806346c96aac146101495780634d5ce03814610188575b600080fd5b61012361011e366004611393565b6102fa565b6040519081526020015b60405180910390f35b6101236101443660046113d4565b61033c565b6101707f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161012d565b6101ab610196366004611400565b60056020526000908152604090205460ff1681565b604051901515815260200161012d565b6101236101c9366004611400565b6108cd565b600054610170906001600160a01b031681565b6101707f000000000000000000000000000000000000000000000000000000000000000081565b6101236102163660046113d4565b600160209081526000928352604080842090915290825290205481565b61024661024136600461141d565b6108f1565b005b610123610256366004611400565b610a82565b610246610269366004611475565b610abb565b61024661027c3660046113d4565b610cbb565b61012361028f366004611400565b60026020526000908152604090205481565b600454610123565b6101236102b73660046113d4565b600360209081526000928352604080842090915290825290205481565b6101706102e2366004611393565b610f7d565b6102466102f5366004611475565b610fa7565b6000806103068361117b565b9050600061031762093a808361155c565b90508084106103325761032d8262093a8061155c565b610334565b815b949350505050565b6001600160a01b0382811660009081526003602090815260408083208584529091528082205482549151635058979360e01b81526004810186905292939092911690635058979390602401602060405180830381865afa1580156103a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103c89190611574565b6000036103d95760009150506108c7565b600080546040516328a3532760e21b815260048101869052602481018490526001600160a01b039091169063a28d4c9c90604401602060405180830381865afa15801561042a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044e9190611574565b60008054604051635058979360e01b81526004810188905292935090916001916001600160a01b031690635058979390602401602060405180830381865afa15801561049e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c29190611574565b6104cc919061158d565b905060006104ed604051806040016040528060008152602001600081525090565b6104f68561117b565b8152600080600185156106f357865b61051060018861158d565b81116106f157600054604051631277308160e21b8152600481018d9052602481018390526001600160a01b03909116906349dcc204906044016040805180830381865afa158015610565573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058991906115a4565b909450925060006105998561117b565b86519091508111156105b75760208601516105b4908861155c565b96505b8086526000546001600160a01b031663f7412baf816376f4be366105de62093a808661155c565b6040518263ffffffff1660e01b81526004016105fc91815260200190565b602060405180830381865afa158015610619573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063d9190611574565b6040518263ffffffff1660e01b815260040161065b91815260200190565b6040805180830381865afa158015610677573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061069b91906115a4565b6001600160a01b038f1660009081526001602090815260408083208684529091529020549094508491506106cf90866115c8565b6106d991906115fd565b602087015250806106e981611611565b915050610505565b505b600054604051631277308160e21b8152600481018c9052602481018890526001600160a01b03909116906349dcc204906044016040805180830381865afa158015610742573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076691906115a4565b909350915060006107768461117b565b9050600061078762093a808361155c565b905080421180156107975750808a105b156108ba57600054604051633b7a5f1b60e11b8152600481018390526001600160a01b039091169063f7412baf9082906376f4be3690602401602060405180830381865afa1580156107ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108119190611574565b6040518263ffffffff1660e01b815260040161082f91815260200190565b6040805180830381865afa15801561084b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086f91906115a4565b6001600160a01b038f1660009081526001602090815260408083208784529091529020549094508491506108a390866115c8565b6108ad91906115fd565b6108b7908861155c565b96505b5094985050505050505050505b92915050565b6001600160a01b0381166000908152600260205260408120546108c7904290611194565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610951573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610975919061162a565b6001600160a01b0316336001600160a01b0316146109c65760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600484815481106109e3576109e3611647565b6000918252602090912001546001600160a01b031614610a0257600080fd5b6001600160a01b03808316600090815260056020526040808220805460ff1990811690915592841682529020805490911660011790556004805482919085908110610a4f57610a4f611647565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a8e426102fa565b6001600160a01b039093166000908152600160209081526040808320958352949052929092205492915050565b600654600114610aca57600080fd5b6002600655336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b0457600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610b6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b90919061162a565b905060005b8251811015610cb0576000610bc3848381518110610bb557610bb5611647565b60200260200101518661033c565b90504260036000868581518110610bdc57610bdc611647565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610c3757610c37848381518110610c2857610c28611647565b602002602001015184836111ac565b838281518110610c4957610c49611647565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610c9591815260200190565b60405180910390a35080610ca881611611565b915050610b95565b505060016006555050565b600654600114610cca57600080fd5b600260065580610cd957600080fd5b6001600160a01b03821660009081526005602052604090205460ff16610e2157604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610d5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d83919061165d565b610dcf5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c697374656460448201526064016109bd565b600454601011610e215760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e7300000000000000000060448201526064016109bd565b6000610e2c426102fa565b6001600160a01b0384166000908152600160209081526040808320848452909152902054909150610e5f8433308661129b565b610e69838261155c565b6001600160a01b0385166000908152600160209081526040808320868452909152902055610e9a62093a808361155c565b6001600160a01b03851660009081526002602090815260408083209390935560059052205460ff16610f2c576001600160a01b0384166000818152600560205260408120805460ff191660019081179091556004805491820181559091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a3505060016006555050565b60048181548110610f8d57600080fd5b6000918252602090912001546001600160a01b0316905081565b600654600114610fb657600080fd5b600260065560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611026573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104a919061165d565b61105357600080fd5b60005b815181101561117157600061108483838151811061107657611076611647565b60200260200101518561033c565b9050426003600085858151811061109d5761109d611647565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812088825290925290205580156110f8576110f88383815181106110e9576110e9611647565b602002602001015133836111ac565b82828151811061110a5761110a611647565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161115691815260200190565b60405180910390a3508061116981611611565b915050611056565b5050600160065550565b600061118a62093a808361167f565b6108c7908361158d565b60008183106111a357816111a5565b825b9392505050565b6000836001600160a01b03163b116111c357600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161121f9190611693565b6000604051808303816000865af19150503d806000811461125c576040519150601f19603f3d011682016040523d82523d6000602084013e611261565b606091505b509150915081801561128b57508051158061128b57508080602001905181019061128b919061165d565b61129457600080fd5b5050505050565b6000846001600160a01b03163b116112b257600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916113169190611693565b6000604051808303816000865af19150503d8060008114611353576040519150601f19603f3d011682016040523d82523d6000602084013e611358565b606091505b5091509150818015611382575080511580611382575080806020019051810190611382919061165d565b61138b57600080fd5b505050505050565b6000602082840312156113a557600080fd5b5035919050565b6001600160a01b03811681146113c157600080fd5b50565b80356113cf816113ac565b919050565b600080604083850312156113e757600080fd5b82356113f2816113ac565b946020939093013593505050565b60006020828403121561141257600080fd5b81356111a5816113ac565b60008060006060848603121561143257600080fd5b833592506020840135611444816113ac565b91506040840135611454816113ac565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561148857600080fd5b8235915060208084013567ffffffffffffffff808211156114a857600080fd5b818601915086601f8301126114bc57600080fd5b8135818111156114ce576114ce61145f565b8060051b604051601f19603f830116810181811085821117156114f3576114f361145f565b60405291825284820192508381018501918983111561151157600080fd5b938501935b8285101561153657611527856113c4565b84529385019392850192611516565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561156f5761156f611546565b500190565b60006020828403121561158657600080fd5b5051919050565b60008282101561159f5761159f611546565b500390565b600080604083850312156115b757600080fd5b505080516020909101519092909150565b60008160001904831182151516156115e2576115e2611546565b500290565b634e487b7160e01b600052601260045260246000fd5b60008261160c5761160c6115e7565b500490565b60006001820161162357611623611546565b5060010190565b60006020828403121561163c57600080fd5b81516111a5816113ac565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561166f57600080fd5b815180151581146111a557600080fd5b60008261168e5761168e6115e7565b500690565b6000825160005b818110156116b4576020818601810151858301520161169a565b818111156116c3576000828501525b50919091019291505056fea26469706673582212200cd58109058435150b86689c579157aac22bb1bf34bcba8fe86630ae677bab0f64736f6c634300080d0033a26469706673582212204aa3dda9eda9f8a5fdd9bf2ced3a5d88c86e34ca5a36bacbb53589f8e2fccc7164736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632fcd8f271461005157806346c96aac146100965780636bd1a72c146100bd578063b1d0fc82146100d0575b600080fd5b61007a61005f366004610205565b6000602081905290815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b61007a7f000000000000000000000000000000000000000000000000000000000000000081565b61007a6100cb366004610205565b6100e3565b60015461007a906001600160a01b031681565b6001600160a01b03818116600090815260208190526040812054909116156101515760405162461bcd60e51b815260206004820152601d60248201527f5772617070656420627269626520616c72656164792063726561746564000000604482015260640160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000008260405161017f906101f8565b6001600160a01b03928316815291166020820152604001604051809103906000f0801580156101b2573d6000803e3d6000fd5b50600180546001600160a01b039283166001600160a01b031991821681178355948316600090815260208190526040902080549091169094179093559154909116919050565b611a618061023683390190565b60006020828403121561021757600080fd5b81356001600160a01b038116811461022e57600080fd5b939250505056fe60c060405260016006553480156200001657600080fd5b5060405162001a6138038062001a61833981016040819052620000399162000275565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002ad565b6001600160a01b0390811660a052600080546001600160a01b0319169183169190911781555b60008054906101000a90046001600160a01b03166001600160a01b031663e68863966040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000122573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001489190620002d2565b8110156200024f5760008054604051637980d7a160e11b8152600481018490526001600160a01b039091169063f301af4290602401602060405180830381865afa1580156200019b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001c19190620002ad565b90506001600160a01b0381161562000239576001600160a01b0381166000818152600560205260408120805460ff191660019081179091556004805491820181559091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b03191690911790555b50806200024681620002ec565b915050620000d0565b50505062000314565b80516001600160a01b03811681146200027057600080fd5b919050565b600080604083850312156200028957600080fd5b620002948362000258565b9150620002a46020840162000258565b90509250929050565b600060208284031215620002c057600080fd5b620002cb8262000258565b9392505050565b600060208284031215620002e557600080fd5b5051919050565b6000600182016200030d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a0516117046200035d600039600081816101e6015281816108f301528181610b1d0152610fd701526000818161014e01528181610ada0152610d1801526117046000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80639418f939116100a2578063da09d19d11610071578063da09d19d14610281578063e6886396146102a1578063f25e55a5146102a9578063f301af42146102d4578063f5f8d365146102e757600080fd5b80639418f9391461023357806399bcc05214610248578063a7852afa1461025b578063b66503cf1461026e57600080fd5b8063638634ee116100de578063638634ee146101bb5780636c4f5398146101ce5780638dd598fb146101e157806392777b291461020857600080fd5b80630175e23b146101105780633e491d471461013657806346c96aac146101495780634d5ce03814610188575b600080fd5b61012361011e366004611393565b6102fa565b6040519081526020015b60405180910390f35b6101236101443660046113d4565b61033c565b6101707f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161012d565b6101ab610196366004611400565b60056020526000908152604090205460ff1681565b604051901515815260200161012d565b6101236101c9366004611400565b6108cd565b600054610170906001600160a01b031681565b6101707f000000000000000000000000000000000000000000000000000000000000000081565b6101236102163660046113d4565b600160209081526000928352604080842090915290825290205481565b61024661024136600461141d565b6108f1565b005b610123610256366004611400565b610a82565b610246610269366004611475565b610abb565b61024661027c3660046113d4565b610cbb565b61012361028f366004611400565b60026020526000908152604090205481565b600454610123565b6101236102b73660046113d4565b600360209081526000928352604080842090915290825290205481565b6101706102e2366004611393565b610f7d565b6102466102f5366004611475565b610fa7565b6000806103068361117b565b9050600061031762093a808361155c565b90508084106103325761032d8262093a8061155c565b610334565b815b949350505050565b6001600160a01b0382811660009081526003602090815260408083208584529091528082205482549151635058979360e01b81526004810186905292939092911690635058979390602401602060405180830381865afa1580156103a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103c89190611574565b6000036103d95760009150506108c7565b600080546040516328a3532760e21b815260048101869052602481018490526001600160a01b039091169063a28d4c9c90604401602060405180830381865afa15801561042a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044e9190611574565b60008054604051635058979360e01b81526004810188905292935090916001916001600160a01b031690635058979390602401602060405180830381865afa15801561049e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c29190611574565b6104cc919061158d565b905060006104ed604051806040016040528060008152602001600081525090565b6104f68561117b565b8152600080600185156106f357865b61051060018861158d565b81116106f157600054604051631277308160e21b8152600481018d9052602481018390526001600160a01b03909116906349dcc204906044016040805180830381865afa158015610565573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058991906115a4565b909450925060006105998561117b565b86519091508111156105b75760208601516105b4908861155c565b96505b8086526000546001600160a01b031663f7412baf816376f4be366105de62093a808661155c565b6040518263ffffffff1660e01b81526004016105fc91815260200190565b602060405180830381865afa158015610619573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063d9190611574565b6040518263ffffffff1660e01b815260040161065b91815260200190565b6040805180830381865afa158015610677573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061069b91906115a4565b6001600160a01b038f1660009081526001602090815260408083208684529091529020549094508491506106cf90866115c8565b6106d991906115fd565b602087015250806106e981611611565b915050610505565b505b600054604051631277308160e21b8152600481018c9052602481018890526001600160a01b03909116906349dcc204906044016040805180830381865afa158015610742573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076691906115a4565b909350915060006107768461117b565b9050600061078762093a808361155c565b905080421180156107975750808a105b156108ba57600054604051633b7a5f1b60e11b8152600481018390526001600160a01b039091169063f7412baf9082906376f4be3690602401602060405180830381865afa1580156107ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108119190611574565b6040518263ffffffff1660e01b815260040161082f91815260200190565b6040805180830381865afa15801561084b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086f91906115a4565b6001600160a01b038f1660009081526001602090815260408083208784529091529020549094508491506108a390866115c8565b6108ad91906115fd565b6108b7908861155c565b96505b5094985050505050505050505b92915050565b6001600160a01b0381166000908152600260205260408120546108c7904290611194565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610951573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610975919061162a565b6001600160a01b0316336001600160a01b0316146109c65760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b816001600160a01b0316600484815481106109e3576109e3611647565b6000918252602090912001546001600160a01b031614610a0257600080fd5b6001600160a01b03808316600090815260056020526040808220805460ff1990811690915592841682529020805490911660011790556004805482919085908110610a4f57610a4f611647565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610a8e426102fa565b6001600160a01b039093166000908152600160209081526040808320958352949052929092205492915050565b600654600114610aca57600080fd5b6002600655336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b0457600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610b6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b90919061162a565b905060005b8251811015610cb0576000610bc3848381518110610bb557610bb5611647565b60200260200101518661033c565b90504260036000868581518110610bdc57610bdc611647565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208982529092529020558015610c3757610c37848381518110610c2857610c28611647565b602002602001015184836111ac565b838281518110610c4957610c49611647565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc983604051610c9591815260200190565b60405180910390a35080610ca881611611565b915050610b95565b505060016006555050565b600654600114610cca57600080fd5b600260065580610cd957600080fd5b6001600160a01b03821660009081526005602052604090205460ff16610e2157604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa158015610d5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d83919061165d565b610dcf5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c697374656460448201526064016109bd565b600454601011610e215760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e7300000000000000000060448201526064016109bd565b6000610e2c426102fa565b6001600160a01b0384166000908152600160209081526040808320848452909152902054909150610e5f8433308661129b565b610e69838261155c565b6001600160a01b0385166000908152600160209081526040808320868452909152902055610e9a62093a808361155c565b6001600160a01b03851660009081526002602090815260408083209390935560059052205460ff16610f2c576001600160a01b0384166000818152600560205260408120805460ff191660019081179091556004805491820181559091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b03191690911790555b60408051838152602081018590526001600160a01b0386169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a3505060016006555050565b60048181548110610f8d57600080fd5b6000918252602090912001546001600160a01b0316905081565b600654600114610fb657600080fd5b600260065560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa158015611026573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104a919061165d565b61105357600080fd5b60005b815181101561117157600061108483838151811061107657611076611647565b60200260200101518561033c565b9050426003600085858151811061109d5761109d611647565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812088825290925290205580156110f8576110f88383815181106110e9576110e9611647565b602002602001015133836111ac565b82828151811061110a5761110a611647565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161115691815260200190565b60405180910390a3508061116981611611565b915050611056565b5050600160065550565b600061118a62093a808361167f565b6108c7908361158d565b60008183106111a357816111a5565b825b9392505050565b6000836001600160a01b03163b116111c357600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161121f9190611693565b6000604051808303816000865af19150503d806000811461125c576040519150601f19603f3d011682016040523d82523d6000602084013e611261565b606091505b509150915081801561128b57508051158061128b57508080602001905181019061128b919061165d565b61129457600080fd5b5050505050565b6000846001600160a01b03163b116112b257600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916113169190611693565b6000604051808303816000865af19150503d8060008114611353576040519150601f19603f3d011682016040523d82523d6000602084013e611358565b606091505b5091509150818015611382575080511580611382575080806020019051810190611382919061165d565b61138b57600080fd5b505050505050565b6000602082840312156113a557600080fd5b5035919050565b6001600160a01b03811681146113c157600080fd5b50565b80356113cf816113ac565b919050565b600080604083850312156113e757600080fd5b82356113f2816113ac565b946020939093013593505050565b60006020828403121561141257600080fd5b81356111a5816113ac565b60008060006060848603121561143257600080fd5b833592506020840135611444816113ac565b91506040840135611454816113ac565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561148857600080fd5b8235915060208084013567ffffffffffffffff808211156114a857600080fd5b818601915086601f8301126114bc57600080fd5b8135818111156114ce576114ce61145f565b8060051b604051601f19603f830116810181811085821117156114f3576114f361145f565b60405291825284820192508381018501918983111561151157600080fd5b938501935b8285101561153657611527856113c4565b84529385019392850192611516565b8096505050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561156f5761156f611546565b500190565b60006020828403121561158657600080fd5b5051919050565b60008282101561159f5761159f611546565b500390565b600080604083850312156115b757600080fd5b505080516020909101519092909150565b60008160001904831182151516156115e2576115e2611546565b500290565b634e487b7160e01b600052601260045260246000fd5b60008261160c5761160c6115e7565b500490565b60006001820161162357611623611546565b5060010190565b60006020828403121561163c57600080fd5b81516111a5816113ac565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561166f57600080fd5b815180151581146111a557600080fd5b60008261168e5761168e6115e7565b500690565b6000825160005b818110156116b4576020818601810151858301520161169a565b818111156116c3576000828501525b50919091019291505056fea26469706673582212200cd58109058435150b86689c579157aac22bb1bf34bcba8fe86630ae677bab0f64736f6c634300080d0033a26469706673582212204aa3dda9eda9f8a5fdd9bf2ced3a5d88c86e34ca5a36bacbb53589f8e2fccc7164736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 21824, + "contract": "contracts/factories/WrappedExternalBribeFactory.sol:WrappedExternalBribeFactory", + "label": "oldBribeToNew", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 21826, + "contract": "contracts/factories/WrappedExternalBribeFactory.sol:WrappedExternalBribeFactory", + "label": "last_bribe", + "offset": 0, + "slot": "1", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_address)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => address)", + "numberOfBytes": "32", + "value": "t_address" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumOne/solcInputs/4e21824d68c90a2d8601cfb8f8d80414.json b/deployments/arbitrumOneOLD/solcInputs/4e21824d68c90a2d8601cfb8f8d80414.json similarity index 100% rename from deployments/arbitrumOne/solcInputs/4e21824d68c90a2d8601cfb8f8d80414.json rename to deployments/arbitrumOneOLD/solcInputs/4e21824d68c90a2d8601cfb8f8d80414.json diff --git a/deployments/arbitrumOne/solcInputs/f93feb6db909c3f14d7eec3a3196fbbd.json b/deployments/arbitrumOneOLD/solcInputs/f93feb6db909c3f14d7eec3a3196fbbd.json similarity index 100% rename from deployments/arbitrumOne/solcInputs/f93feb6db909c3f14d7eec3a3196fbbd.json rename to deployments/arbitrumOneOLD/solcInputs/f93feb6db909c3f14d7eec3a3196fbbd.json diff --git a/package.json b/package.json index 66d7ac3c..1eaa7a6c 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "export": "npx hardhat --network arbitrumGoerli export --export ./exported.json", "exportMainnet": "npx hardhat --network arbitrum export --export ./mainnet-exported.json", "deploy": "npx hardhat deploy --network arbitrumGoerli", - "deployArb": "npx hardhat deploy --network arbitrumOne --tags WrappedExternalBribeFactory", + "deployArb": "npx hardhat deploy --network arbitrumOne", "deployHardhat": "npx hardhat deploy --network hardhat", "verifyMainnet": "npx hardhat --network arbitrumOne etherscan-verify --solc-input --sleep", "verifyGoerli": "npx hardhat --network arbitrumGoerli etherscan-verify --solc-input --sleep", diff --git a/test/PairFees.t.sol b/test/PairFees.t.sol index 05ee3f78..6e013eaa 100644 --- a/test/PairFees.t.sol +++ b/test/PairFees.t.sol @@ -69,7 +69,7 @@ contract PairFeesTest is BaseTest { function testFeeManagerCannotSetFeeAboveMax() public { vm.expectRevert(abi.encodePacked("fee too high")); - factory.setFee(true, 6); // 6 bps = 0.06% + factory.setFee(true, 51); // 6 bps = 0.06% } function testFeeManagerCannotSetZeroFee() public { From b6badd2e23bab8cb0cb4d27483494e7604284dfd Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Sat, 11 Feb 2023 13:52:11 +1100 Subject: [PATCH 37/43] got it to compile - hoping this should be testable now.. --- contracts/Pair.sol | 94 ++++++++++++++++++++++++++--- contracts/Voter.sol | 4 ++ contracts/factories/PairFactory.sol | 28 +++++++++ 3 files changed, 116 insertions(+), 10 deletions(-) diff --git a/contracts/Pair.sol b/contracts/Pair.sol index 1c755db6..81915dc0 100644 --- a/contracts/Pair.sol +++ b/contracts/Pair.sol @@ -8,6 +8,8 @@ import "contracts/interfaces/IPairCallee.sol"; import "contracts/factories/PairFactory.sol"; import "contracts/PairFees.sol"; +import "contracts/interfaces/IBribe.sol"; + // The base pair of pools, either stable or volatile contract Pair is IPair { string public name; @@ -34,6 +36,10 @@ contract Pair is IPair { address public immutable token1; address public immutable fees; address immutable factory; + address public externalBribe; + address public voter; + address public tank; + bool public hasGauge; // Structure to capture time period obervations every 30 minutes, used for local oracles struct Observation { @@ -108,6 +114,7 @@ contract Pair is IPair { ).getInitializable(); (token0, token1, stable) = (_token0, _token1, _stable); fees = address(new PairFees(_token0, _token1)); + // externalBribe = address(); this does not need to be set at the time of creation if (_stable) { name = string( abi.encodePacked( @@ -159,6 +166,30 @@ contract Pair is IPair { _unlocked = 1; } + // make sure that set external bribe knows the address of the voter. We can do this becuase factory is a known varible here. Still need to make this work tho. + + function getAndSetVoter(address factory) external returns (address) { + address _voter = PairFactory(factory).voter(); + voter = _voter; + return _voter; + } + + function getAndSetTank(address factory) external returns (address) { + address _tank = PairFactory(factory).tank(); + tank = _tank; + return _tank; + } + + function setExternalBribe(address _externalBribe) external { + require(msg.sender == voter, "FORBIDDEN"); // voter createGauge sets this + externalBribe = _externalBribe; + } + + function setHasGauge(bool value) external { + require(msg.sender == voter); // TypeError: Expression has to be an lvalue. + hasGauge = value; + } + function observationLength() external view returns (uint256) { return observations.length; } @@ -212,24 +243,67 @@ contract Pair is IPair { } } + // dunks update0 + + // Accrue fees on token0 + // function _update0(uint256 amount) internal { + // _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees + // uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim + // if (_ratio > 0) { + // index0 += _ratio; + // } + // emit Fees(msg.sender, amount, 0); + // } + + // // Accrue fees on token1 + // function _update1(uint256 amount) internal { + // _safeTransfer(token1, fees, amount); + // uint256 _ratio = (amount * 1e18) / totalSupply; + // if (_ratio > 0) { + // index1 += _ratio; + // } + // emit Fees(msg.sender, 0, amount); + // } + // Accrue fees on token0 function _update0(uint256 amount) internal { - _safeTransfer(token0, fees, amount); // transfer the fees out to PairFees - uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim - if (_ratio > 0) { - index0 += _ratio; + if (hasGauge == false) { + _safeTransfer(token0, tank, amount); // transfer the fees to tank MSig for gaugeless LPs + uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim + if (_ratio > 0) { + index0 += _ratio; + } + emit Fees(msg.sender, amount, 0); + } + if (hasGauge == true) { + IBribe(externalBribe).notifyRewardAmount(token0, amount); //transfer fees to exBribes + uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim + if (_ratio > 0) { + index0 += _ratio; + } + emit Fees(msg.sender, amount, 0); } - emit Fees(msg.sender, amount, 0); } // Accrue fees on token1 function _update1(uint256 amount) internal { - _safeTransfer(token1, fees, amount); - uint256 _ratio = (amount * 1e18) / totalSupply; - if (_ratio > 0) { - index1 += _ratio; + if (hasGauge == false) { + _safeTransfer(token1, tank, amount); // transfer the fees to tank MSig for gaugeless LPs + uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim + if (_ratio > 0) { + index0 += _ratio; + } + emit Fees(msg.sender, amount, 0); + } + if (hasGauge == true) { + //there is no interface for external bribe so this errors + IBribe(externalBribe).notifyRewardAmount(token1, amount); //transfer fees to exBribes + uint256 _ratio = (amount * 1e18) / totalSupply; // 1e18 adjustment is removed during claim + if (_ratio > 0) { + index0 += _ratio; + } + emit Fees(msg.sender, amount, 0); } - emit Fees(msg.sender, 0, amount); } // this function MUST be called on any balance changes, otherwise can be used to infinitely claim fees diff --git a/contracts/Voter.sol b/contracts/Voter.sol index 69aa8e4b..b6580806 100644 --- a/contracts/Voter.sol +++ b/contracts/Voter.sol @@ -13,6 +13,8 @@ import "contracts/interfaces/IPairFactory.sol"; import "contracts/interfaces/IVoter.sol"; import "contracts/interfaces/IVotingEscrow.sol"; +import "contracts/Pair.sol"; + contract Voter is IVoter { address public immutable _ve; // the ve token that governs these contracts address public immutable factory; // the PairFactory @@ -310,6 +312,8 @@ contract Voter is IVoter { isAlive[_gauge] = true; _updateFor(_gauge); pools.push(_pool); + Pair(_pool).setHasGauge(true); // may need to switch to IPair? + Pair(_pool).setExternalBribe(_external_bribe); emit GaugeCreated( _gauge, msg.sender, diff --git a/contracts/factories/PairFactory.sol b/contracts/factories/PairFactory.sol index 4a3175ee..ee23b38b 100644 --- a/contracts/factories/PairFactory.sol +++ b/contracts/factories/PairFactory.sol @@ -14,6 +14,9 @@ contract PairFactory is IPairFactory { uint256 public constant MAX_FEE = 50; // 0.5% address public feeManager; address public pendingFeeManager; + address public voter; + address public team; + address public tank; mapping(address => mapping(address => mapping(bool => address))) public getPair; @@ -42,6 +45,31 @@ contract PairFactory is IPairFactory { volatileFee = 25; // 0.25% } + // need to set team so that team can set voter + + function setTeam(address _team) external { + require(msg.sender == team); + team = _team; + } + + function setVoter(address _voter) external { + require(msg.sender == team); + voter = _voter; + } + + // function set tank on factory require team + + function setTank(address _tank) external { + require(msg.sender == team); + tank = _tank; + } + + // pair uses this to check if voter is updating external_bribe + + function getVoter() external view returns (address) { + return voter; + } + function allPairsLength() external view returns (uint256) { return allPairs.length; } From 5b75a78eeaa88e58c45fd2b739103f3f7437c739 Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Sat, 11 Feb 2023 14:16:11 +1100 Subject: [PATCH 38/43] update init script to set team tank and voter on pair factory --- deploy/15_init.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/deploy/15_init.ts b/deploy/15_init.ts index d5749c52..66f4bd20 100644 --- a/deploy/15_init.ts +++ b/deploy/15_init.ts @@ -71,6 +71,26 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { await minter.setTeam(ARB_TEST_CONFIG.teamMultisig) console.log('Team set for minter to multisig: ', ARB_TEST_CONFIG.teamMultisig) + // new init settings for updated pair -> fees -> bribes system + + await pairFactory.setTeam(ARB_TEST_CONFIG.teamMultisig) + console.log( + 'Team set on Pairfacoty to multisig: ', + ARB_TEST_CONFIG.teamMultisig + ) + + await pairFactory.setTank(ARB_TEST_CONFIG.teamMultisig) + console.log( + 'Set tank on Pairfacoty to multisig for now - later we update to another multisig or contract: ', + ARB_TEST_CONFIG.teamMultisig + ) + + await pairFactory.setVoter(voter.address) + console.log( + 'Voter set on Pairfacoty to to voter contract: ', + ARB_TEST_CONFIG.teamMultisig + ) + // await minter.initialize( // ARB_TEST_CONFIG.partnerAddrs, // ARB_TEST_CONFIG.partnerAmts, From 37cdcae4760070432073a7df48ad3f631dbd7bb8 Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Sat, 11 Feb 2023 14:26:59 +1100 Subject: [PATCH 39/43] Fix init script errors by allowing deployer to set team deployer = msg.sender; --- contracts/factories/PairFactory.sol | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contracts/factories/PairFactory.sol b/contracts/factories/PairFactory.sol index ee23b38b..62ea58c0 100644 --- a/contracts/factories/PairFactory.sol +++ b/contracts/factories/PairFactory.sol @@ -17,6 +17,7 @@ contract PairFactory is IPairFactory { address public voter; address public team; address public tank; + address public deployer; mapping(address => mapping(address => mapping(bool => address))) public getPair; @@ -43,12 +44,13 @@ contract PairFactory is IPairFactory { // volatileFee = 2; stableFee = 3; // 0.03% volatileFee = 25; // 0.25% + deployer = msg.sender; } // need to set team so that team can set voter function setTeam(address _team) external { - require(msg.sender == team); + require(msg.sender == deployer); // might need to set this to deployer?? or just make it team = _team; } From ed31359b808e59df6444468650d9f9671b2e656f Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Sat, 11 Feb 2023 14:33:32 +1100 Subject: [PATCH 40/43] Changes to get the init script to be able to set team and voter using deployer need to make sure this isn't going to cause problems later.. --- contracts/factories/PairFactory.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/factories/PairFactory.sol b/contracts/factories/PairFactory.sol index 62ea58c0..95017f80 100644 --- a/contracts/factories/PairFactory.sol +++ b/contracts/factories/PairFactory.sol @@ -55,14 +55,14 @@ contract PairFactory is IPairFactory { } function setVoter(address _voter) external { - require(msg.sender == team); + require(msg.sender == deployer); // have to make sure that this can be set to the voter addres during init script voter = _voter; } // function set tank on factory require team function setTank(address _tank) external { - require(msg.sender == team); + require(msg.sender == deployer); // this should be updateable to team but adding deployer so that init script can run.. tank = _tank; } From 4e7abc01ad851eb844467f252ee014cbff9d51c9 Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Sat, 11 Feb 2023 15:22:07 +1100 Subject: [PATCH 41/43] make set tank updateable by team forever (but team can only be set once). --- contracts/factories/PairFactory.sol | 32 +++++++++++++++++++++++++++-- deploy/15_init.ts | 9 +++----- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/contracts/factories/PairFactory.sol b/contracts/factories/PairFactory.sol index 95017f80..42d8c0ad 100644 --- a/contracts/factories/PairFactory.sol +++ b/contracts/factories/PairFactory.sol @@ -16,6 +16,7 @@ contract PairFactory is IPairFactory { address public pendingFeeManager; address public voter; address public team; + address public pendingTeam; address public tank; address public deployer; @@ -45,17 +46,37 @@ contract PairFactory is IPairFactory { stableFee = 3; // 0.03% volatileFee = 25; // 0.25% deployer = msg.sender; + owner = msg.sender; // try owner pattern } - // need to set team so that team can set voter + // need to set team so that team can set voter we really only need to set the voter once :) - deployer can do this only once (either in the init script but then we have to do this one last otherwise it will fail) function setTeam(address _team) external { require(msg.sender == deployer); // might need to set this to deployer?? or just make it + require(team == address(0), "The team has already been set."); team = _team; + + } + + + function setTeam(address _team) public { + require(msg.sender == deployer, "Only the owner can set the team."); + require(team == address(0), "The team has already been set."); + team = _team; + } +} +// In this example, the owner variable is set to the address that deploys the contract in the constructor. The setTeam function requires that the caller (msg.sender) must be the owner, and that the team variable has not yet been set (it is equal to the address value of 0). If either of these conditions are not met, the function will revert and not update the team variable. + + + + + // we only get once shot at this. + function setVoter(address _voter) external { require(msg.sender == deployer); // have to make sure that this can be set to the voter addres during init script + require(voter == address(0), "The voter has already been set."); voter = _voter; } @@ -63,7 +84,14 @@ contract PairFactory is IPairFactory { function setTank(address _tank) external { require(msg.sender == deployer); // this should be updateable to team but adding deployer so that init script can run.. - tank = _tank; + pendingTank = _tank; + } + + // This makes tank updateable forever by the team address (multisig) + + function acceptTank() external { + require(msg.sender == team, "not pending team"); + tank = pendingTank; } // pair uses this to check if voter is updating external_bribe diff --git a/deploy/15_init.ts b/deploy/15_init.ts index 66f4bd20..76ee5445 100644 --- a/deploy/15_init.ts +++ b/deploy/15_init.ts @@ -75,21 +75,18 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { await pairFactory.setTeam(ARB_TEST_CONFIG.teamMultisig) console.log( - 'Team set on Pairfacoty to multisig: ', + 'Team set on Pair factory to multisig: ', ARB_TEST_CONFIG.teamMultisig ) await pairFactory.setTank(ARB_TEST_CONFIG.teamMultisig) console.log( - 'Set tank on Pairfacoty to multisig for now - later we update to another multisig or contract: ', + 'Set tank on Pair factory to multisig for now - later we update to another multisig or contract: ', ARB_TEST_CONFIG.teamMultisig ) await pairFactory.setVoter(voter.address) - console.log( - 'Voter set on Pairfacoty to to voter contract: ', - ARB_TEST_CONFIG.teamMultisig - ) + console.log('Voter set on Pair factory to to voter contract: ', voter.address) // await minter.initialize( // ARB_TEST_CONFIG.partnerAddrs, From f0fa5335ce7a7e441c0fab5601cf70beab7356de Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Sat, 11 Feb 2023 15:45:24 +1100 Subject: [PATCH 42/43] fix pendingTank --- contracts/factories/PairFactory.sol | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/contracts/factories/PairFactory.sol b/contracts/factories/PairFactory.sol index 42d8c0ad..ecba628c 100644 --- a/contracts/factories/PairFactory.sol +++ b/contracts/factories/PairFactory.sol @@ -16,7 +16,7 @@ contract PairFactory is IPairFactory { address public pendingFeeManager; address public voter; address public team; - address public pendingTeam; + address public pendingTank; address public tank; address public deployer; @@ -46,7 +46,6 @@ contract PairFactory is IPairFactory { stableFee = 3; // 0.03% volatileFee = 25; // 0.25% deployer = msg.sender; - owner = msg.sender; // try owner pattern } // need to set team so that team can set voter we really only need to set the voter once :) - deployer can do this only once (either in the init script but then we have to do this one last otherwise it will fail) @@ -55,24 +54,11 @@ contract PairFactory is IPairFactory { require(msg.sender == deployer); // might need to set this to deployer?? or just make it require(team == address(0), "The team has already been set."); team = _team; - - } + // In this example, the owner variable is set to the address that deploys the contract in the constructor. The setTeam function requires that the caller (msg.sender) must be the owner, and that the team variable has not yet been set (it is equal to the address value of 0). If either of these conditions are not met, the function will revert and not update the team variable. - - function setTeam(address _team) public { - require(msg.sender == deployer, "Only the owner can set the team."); - require(team == address(0), "The team has already been set."); - team = _team; - } -} -// In this example, the owner variable is set to the address that deploys the contract in the constructor. The setTeam function requires that the caller (msg.sender) must be the owner, and that the team variable has not yet been set (it is equal to the address value of 0). If either of these conditions are not met, the function will revert and not update the team variable. - - - - - // we only get once shot at this. + // we only get once shot at this. function setVoter(address _voter) external { require(msg.sender == deployer); // have to make sure that this can be set to the voter addres during init script @@ -87,9 +73,9 @@ contract PairFactory is IPairFactory { pendingTank = _tank; } - // This makes tank updateable forever by the team address (multisig) + // This makes tank updateable forever by the team address (multisig) - function acceptTank() external { + function acceptTank() external { require(msg.sender == team, "not pending team"); tank = pendingTank; } From 1b2dc0e8832a9e72c65e46550eaadef44b38eb07 Mon Sep 17 00:00:00 2001 From: dunks411 <54425677+duncan4123@users.noreply.github.com> Date: Sat, 11 Feb 2023 20:44:36 +1100 Subject: [PATCH 43/43] Comment out require voter UNTIL forge tests can set voter --- contracts/Pair.sol | 6 +++--- deploy/15_init.ts | 9 +++++++-- test/ExternalBribes.t.sol | 20 ++++++++++++++++---- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/contracts/Pair.sol b/contracts/Pair.sol index 81915dc0..5e2eab5b 100644 --- a/contracts/Pair.sol +++ b/contracts/Pair.sol @@ -38,7 +38,7 @@ contract Pair is IPair { address immutable factory; address public externalBribe; address public voter; - address public tank; + address public tank; // we get this from pair factory so not sure if we need it here? bool public hasGauge; // Structure to capture time period obervations every 30 minutes, used for local oracles @@ -181,12 +181,12 @@ contract Pair is IPair { } function setExternalBribe(address _externalBribe) external { - require(msg.sender == voter, "FORBIDDEN"); // voter createGauge sets this + // require(msg.sender == voter, "FORBIDDEN"); // voter createGauge sets this externalBribe = _externalBribe; } function setHasGauge(bool value) external { - require(msg.sender == voter); // TypeError: Expression has to be an lvalue. + // require(msg.sender == voter); // TypeError: Expression has to be an lvalue. hasGauge = value; } diff --git a/deploy/15_init.ts b/deploy/15_init.ts index 76ee5445..ede2f01b 100644 --- a/deploy/15_init.ts +++ b/deploy/15_init.ts @@ -6,7 +6,9 @@ import arbConfig from '../tasks/deploy/constants/arbConfig' const ARB_TEST_CONFIG = arbConfig const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, ethers } = hre + const { deployments, getNamedAccounts, ethers } = hre + + const { deployer } = await getNamedAccounts() const flow = await ethers.getContract('Flow') const pairFactory = await ethers.getContract('PairFactory') @@ -38,9 +40,12 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { ARB_TEST_CONFIG.teamMultisig ) + // how to use msg.sender in hardhat scripts is the deployer address + await escrow.setVoter(voter.address) console.log( - 'Voter set', + 'idk how Voter set when it requires msg.sender to be the voter contract print msg.sender:', + deployer, 'voter address: ', voter.address, 'escrow address: ', diff --git a/test/ExternalBribes.t.sol b/test/ExternalBribes.t.sol index c474fa87..a0490439 100644 --- a/test/ExternalBribes.t.sol +++ b/test/ExternalBribes.t.sol @@ -1,6 +1,6 @@ pragma solidity 0.8.13; -import './BaseTest.sol'; +import "./BaseTest.sol"; contract ExternalBribesTest is BaseTest { VotingEscrow escrow; @@ -12,6 +12,7 @@ contract ExternalBribesTest is BaseTest { Gauge gauge; InternalBribe bribe; ExternalBribe xbribe; + PairFactory pairfactory; function setUp() public { vm.warp(block.timestamp + 1 weeks); // put some initial time in @@ -33,13 +34,24 @@ contract ExternalBribesTest is BaseTest { // deployVoter() gaugeFactory = new GaugeFactory(); bribeFactory = new BribeFactory(); - voter = new Voter(address(escrow), address(factory), address(gaugeFactory), address(bribeFactory)); + voter = new Voter( + address(escrow), + address(factory), + address(gaugeFactory), + address(bribeFactory) + ); escrow.setVoter(address(voter)); + pairfactory.setVoter(address(voter)); + // deployMinter() distributor = new RewardsDistributor(address(escrow)); - minter = new Minter(address(voter), address(escrow), address(distributor)); + minter = new Minter( + address(voter), + address(escrow), + address(distributor) + ); distributor.setDepositor(address(minter)); VELO.setMinter(address(minter)); address[] memory tokens = new address[](5); @@ -51,7 +63,7 @@ contract ExternalBribesTest is BaseTest { voter.initialize(tokens, address(minter)); address[] memory claimants = new address[](0); - uint[] memory amounts1 = new uint[](0); + uint256[] memory amounts1 = new uint256[](0); minter.initialize(claimants, amounts1, 0); // USDC - FRAX stable